From 98ee997bf3e060c561841934e94105b8b659d35a Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 24 Oct 2020 21:59:10 -0500 Subject: [PATCH 001/143] update pipeline versioning --- .../PostPublish.ps1 | 0 .../deployment-pipeline.yml | 75 ++++--- IW4MAdmin.sln | 6 +- RunPublishPre.cmd | 7 - RunPublishRelease.cmd | 7 - azure-pipelines.yml | 190 ------------------ 6 files changed, 53 insertions(+), 232 deletions(-) rename PostPublish.ps1 => DeploymentFiles/PostPublish.ps1 (100%) rename pre-release-pipeline.yaml => DeploymentFiles/deployment-pipeline.yml (69%) delete mode 100644 RunPublishPre.cmd delete mode 100644 RunPublishRelease.cmd delete mode 100644 azure-pipelines.yml diff --git a/PostPublish.ps1 b/DeploymentFiles/PostPublish.ps1 similarity index 100% rename from PostPublish.ps1 rename to DeploymentFiles/PostPublish.ps1 diff --git a/pre-release-pipeline.yaml b/DeploymentFiles/deployment-pipeline.yml similarity index 69% rename from pre-release-pipeline.yaml rename to DeploymentFiles/deployment-pipeline.yml index 857320c7..042c957d 100644 --- a/pre-release-pipeline.yaml +++ b/DeploymentFiles/deployment-pipeline.yml @@ -1,8 +1,11 @@ +name: '$(Date:yyyy.MM.dd)$(Rev:.r)' + trigger: batch: true branches: include: - release/pre + - master pr: none @@ -12,110 +15,130 @@ pool: variables: solution: 'IW4MAdmin.sln' buildPlatform: 'Any CPU' - buildConfiguration: 'Prerelease' outputFolder: '$(Build.ArtifactStagingDirectory)\Publish\$(buildConfiguration)' + releaseType: verified + buildConfiguration: Stable steps: -- task: NuGetToolInstaller@1 +- task: PowerShell@2 + displayName: 'Setup Pre-Release configuration' + condition: eq(variables['Build.SourceBranch'], 'refs/heads/release/pre') + inputs: + targetType: 'inline' + script: | + echo '##vso[task.setvariable variable=releaseType]prerelease' + echo '##vso[task.setvariable variable=buildConfiguration]Prerelease' + failOnStderr: true - task: NuGetCommand@2 + displayName: 'Restore nuget packages' inputs: restoreSolution: '$(solution)' - task: PowerShell@2 + displayName: 'Preload external resources' inputs: targetType: 'inline' script: | + Write-Host 'Build Configuration is $(buildConfiguration), Release Type is $(releaseType)' md -Force lib\open-iconic\font\css wget https://raw.githubusercontent.com/iconic/open-iconic/master/font/css/open-iconic-bootstrap.scss -o lib\open-iconic\font\css\open-iconic-bootstrap.scss failOnStderr: true workingDirectory: '$(Build.Repository.LocalPath)\WebfrontCore\wwwroot' -- task: projectversionasvariable@1 - inputs: - path: '$(Build.Repository.LocalPath)\Application\Application.csproj' - - task: VSBuild@1 + displayName: 'Build projects' inputs: solution: '$(solution)' - msbuildArgs: '/p:DeployOnBuild=false /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)" /p:Version=$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' + msbuildArgs: '/p:DeployOnBuild=false /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)" /p:Version=$(Build.BuildNumber)' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' - task: DotNetCoreCLI@2 + displayName: 'Publish projects' inputs: command: 'publish' publishWebProjects: false projects: | **/WebfrontCore.csproj **/Application.csproj - arguments: '-c $(buildConfiguration) -o $(outputFolder) /p:Version=$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' + arguments: '-c $(buildConfiguration) -o $(outputFolder) /p:Version=$(Build.BuildNumber)' zipAfterPublish: false modifyOutputPath: false - task: PowerShell@2 + displayName: 'Run publish script 1' inputs: - targetType: 'inline' - script: 'wget https://raidmax.org/downloads/dos2unix.exe' - failOnStderr: true - workingDirectory: '$(Build.Repository.LocalPath)\Application\BuildScripts' - -- task: PowerShell@2 - inputs: - filePath: 'PostPublish.ps1' + filePath: 'DeploymentFiles/PostPublish.ps1' arguments: '$(outputFolder)' failOnStderr: true workingDirectory: '$(Build.Repository.LocalPath)' - task: BatchScript@1 + displayName: 'Run publish script 2' inputs: filename: 'Application\BuildScripts\PostPublish.bat' workingFolder: '$(Build.Repository.LocalPath)' arguments: '$(outputFolder)' failOnStandardError: true +- task: PowerShell@2 + displayName: 'Download dos2unix for line endings' + inputs: + targetType: 'inline' + script: 'wget https://raidmax.org/downloads/dos2unix.exe' + failOnStderr: true + workingDirectory: '$(Build.Repository.LocalPath)\Application\BuildScripts' + - task: CmdLine@2 + displayName: 'Convert Linux start script line endings' inputs: script: | echo changing to encoding for linux start script dos2unix $(outputFolder)\StartIW4MAdmin.sh echo creating website version filename - @echo IW4MAdmin-$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId) > $(Build.ArtifactStagingDirectory)\version_prerelease.txt + @echo IW4MAdmin-$(Build.BuildNumber) > $(Build.ArtifactStagingDirectory)\version_$(releaseType).txt workingDirectory: '$(Build.Repository.LocalPath)\Application\BuildScripts' - task: CopyFiles@2 + displayName: 'Move script plugins into publish directory' inputs: SourceFolder: '$(Build.Repository.LocalPath)\Plugins\ScriptPlugins' Contents: '*.js' TargetFolder: '$(outputFolder)\Plugins' - task: CopyFiles@2 + displayName: 'Move binary plugins into publish directory' inputs: SourceFolder: '$(Build.Repository.LocalPath)\BUILD\Plugins\' Contents: '*.dll' TargetFolder: '$(outputFolder)\Plugins' - task: CmdLine@2 + displayName: 'Move webfront resources into publish directory' inputs: script: 'xcopy /s /y /f wwwroot $(outputFolder)\wwwroot' workingDirectory: '$(Build.Repository.LocalPath)\BUILD\Plugins' failOnStderr: true - task: CmdLine@2 + displayName: 'Move gamescript files into publish directory' inputs: script: 'echo d | xcopy /s /y /f GameFiles $(outputFolder)\GameFiles' workingDirectory: '$(Build.Repository.LocalPath)' failOnStderr: true - task: ArchiveFiles@2 + displayName: 'Generate final zip file' inputs: rootFolderOrFile: '$(outputFolder)' includeRootFolder: false archiveType: 'zip' - archiveFile: '$(Build.ArtifactStagingDirectory)/IW4MAdmin-$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId).zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/IW4MAdmin-$(Build.BuildNumber).zip' replaceExistingArchive: true - task: FtpUpload@2 + displayName: 'Upload zip file to website' inputs: credentialsOption: 'inputs' serverUrl: '$(FTPUrl)' @@ -130,13 +153,14 @@ steps: trustSSL: false - task: FtpUpload@2 + displayName: 'Upload version info to website' inputs: credentialsOption: 'inputs' serverUrl: '$(FTPUrl)' username: '$(FTPUsername)' password: '$(FTPPassword)' rootDirectory: '$(Build.ArtifactStagingDirectory)' - filePatterns: 'version_prerelease.txt' + filePatterns: 'version_$(releaseType).txt' remoteDirectory: 'IW4MAdmin' clean: false cleanContents: false @@ -144,27 +168,29 @@ steps: trustSSL: false - task: GitHubRelease@1 + displayName: 'Make GitHub release' inputs: gitHubConnection: 'github.com_RaidMax' repositoryName: 'RaidMax/IW4M-Admin' action: 'create' target: '$(Build.SourceVersion)' tagSource: 'userSpecifiedTag' - tag: '$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId)' - title: 'Version $(Version.Major).$(Version.Minor) $(buildConfiguration) Feature $(Version.Build) Build $(Build.BuildId)' + tag: '$(Build.BuildNumber)-$(releaseType)' + title: 'IW4MAdmin $(Build.BuildNumber) ($(releaseType))' assets: '$(Build.ArtifactStagingDirectory)/*.zip' - isPreRelease: true + isPreRelease: eq(variables['Build.SourceBranch'], 'refs/heads/release/pre') releaseNotesSource: 'inline' releaseNotesInline: 'todo' changeLogCompareToRelease: 'lastNonDraftRelease' changeLogType: 'commitBased' - task: PowerShell@2 + displayName: 'Update master version' inputs: targetType: 'inline' script: | $payload = @{ - 'current-version-prerelease' = '$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' + 'current-version-$(releaseType)' = '$(Build.BuildNumber)' 'jwt-secret' = '$(JWTSecret)' } | ConvertTo-Json @@ -179,7 +205,8 @@ steps: Invoke-RestMethod @params - task: PublishPipelineArtifact@1 + displayName: 'Publish artifact for analysis' inputs: targetPath: '$(outputFolder)' artifact: 'IW4MAdmin.$(buildConfiguration)' - publishLocation: 'pipeline' \ No newline at end of file + publishLocation: 'pipeline' diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 0a60a118..6190d1e4 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -8,11 +8,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject GameFiles\IW4x\userraw\scripts\_commands.gsc = GameFiles\IW4x\userraw\scripts\_commands.gsc GameFiles\IW4x\userraw\scripts\_customcallbacks.gsc = GameFiles\IW4x\userraw\scripts\_customcallbacks.gsc - PostPublish.ps1 = PostPublish.ps1 - pre-release-pipeline.yaml = pre-release-pipeline.yaml + DeploymentFiles\deployment-pipeline.yml = DeploymentFiles\deployment-pipeline.yml + DeploymentFiles\PostPublish.ps1 = DeploymentFiles\PostPublish.ps1 README.md = README.md - RunPublishPre.cmd = RunPublishPre.cmd - RunPublishRelease.cmd = RunPublishRelease.cmd version.txt = version.txt EndProjectSection EndProject diff --git a/RunPublishPre.cmd b/RunPublishPre.cmd deleted file mode 100644 index 59f6de3f..00000000 --- a/RunPublishPre.cmd +++ /dev/null @@ -1,7 +0,0 @@ -dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease -dotnet publish Application/Application.csproj -c Prerelease -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease -dotnet publish GameLogServer/GameLogServer.pyproj -c Release -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease\GameLogServer -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat" -msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=PreRelease /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\GameLogServer\ -cd "X:\IW4MAdmin\DEPLOY\" -PowerShell ".\upload_prerelease.ps1" \ No newline at end of file diff --git a/RunPublishRelease.cmd b/RunPublishRelease.cmd deleted file mode 100644 index 6af19fd4..00000000 --- a/RunPublishRelease.cmd +++ /dev/null @@ -1,7 +0,0 @@ -dotnet publish WebfrontCore/WebfrontCore.csproj -c Release -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\Windows /p:PublishProfile=sTABLE -dotnet publish Application/Application.csproj -c Release -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\Windows /p:PublishProfile=Stable -dotnet publish GameLogServer/GameLogServer.pyproj -c Release -f netcoreapp3.0 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease\GameLogServer -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat" -msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=Stable /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\GameLogServer\ -cd "X:\IW4MAdmin\DEPLOY\" -PowerShell ".\upload_release.ps1" \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 99af8947..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,190 +0,0 @@ -trigger: - batch: true - branches: - include: - - releases/* - - 2.4-pr - paths: - exclude: - - azure-pipelines.yml - - Master/* - -pr: none - -pool: - vmImage: 'windows-latest' - -variables: - solution: 'IW4MAdmin.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Prerelease' - outputFolder: '$(Build.ArtifactStagingDirectory)\Publish\$(buildConfiguration)' - -steps: -- task: NuGetToolInstaller@1 - -- task: NuGetCommand@2 - inputs: - restoreSolution: '$(solution)' - -- task: PowerShell@2 - inputs: - targetType: 'inline' - script: | - md -Force lib\open-iconic\font\css - wget https://raw.githubusercontent.com/iconic/open-iconic/master/font/css/open-iconic-bootstrap.scss -o lib\open-iconic\font\css\open-iconic-bootstrap.scss - failOnStderr: true - workingDirectory: '$(Build.Repository.LocalPath)\WebfrontCore\wwwroot' - -- task: projectversionasvariable@1 - inputs: - path: '$(Build.Repository.LocalPath)\Application\Application.csproj' - -- task: VSBuild@1 - inputs: - solution: '$(solution)' - msbuildArgs: '/p:DeployOnBuild=false /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)" /p:Version=$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' - platform: '$(buildPlatform)' - configuration: '$(buildConfiguration)' - -- task: DotNetCoreCLI@2 - inputs: - command: 'publish' - publishWebProjects: false - projects: | - **/WebfrontCore.csproj - **/Application.csproj - arguments: '-c $(buildConfiguration) -o $(outputFolder) /p:Version=$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' - zipAfterPublish: false - modifyOutputPath: false - -- task: PowerShell@2 - inputs: - targetType: 'inline' - script: 'wget https://raidmax.org/downloads/dos2unix.exe' - failOnStderr: true - workingDirectory: '$(Build.Repository.LocalPath)\Application\BuildScripts' - -- task: PowerShell@2 - inputs: - filePath: 'PostPublish.ps1' - arguments: '$(outputFolder)' - failOnStderr: true - workingDirectory: '$(Build.Repository.LocalPath)' - -- task: BatchScript@1 - inputs: - filename: 'Application\BuildScripts\PostPublish.bat' - workingFolder: '$(Build.Repository.LocalPath)' - arguments: '$(outputFolder)' - failOnStandardError: true - -- task: CmdLine@2 - inputs: - script: | - echo changing to encoding for linux start script - dos2unix $(outputFolder)\StartIW4MAdmin.sh - echo creating website version filename - @echo IW4MAdmin-$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId) > $(Build.ArtifactStagingDirectory)\version_prerelease.txt - workingDirectory: '$(Build.Repository.LocalPath)\Application\BuildScripts' - -- task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.Repository.LocalPath)\Plugins\ScriptPlugins' - Contents: '*.js' - TargetFolder: '$(outputFolder)\Plugins' - -- task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.Repository.LocalPath)\BUILD\Plugins\' - Contents: '*.dll' - TargetFolder: '$(outputFolder)\Plugins' - -- task: CmdLine@2 - inputs: - script: 'xcopy /s /y /f wwwroot $(outputFolder)\wwwroot' - workingDirectory: '$(Build.Repository.LocalPath)\BUILD\Plugins' - failOnStderr: true - -- task: CmdLine@2 - inputs: - script: 'echo d | xcopy /s /y /f GameFiles $(outputFolder)\GameFiles' - workingDirectory: '$(Build.Repository.LocalPath)' - failOnStderr: true - -- task: ArchiveFiles@2 - inputs: - rootFolderOrFile: '$(outputFolder)' - includeRootFolder: false - archiveType: 'zip' - archiveFile: '$(Build.ArtifactStagingDirectory)/IW4MAdmin-$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId).zip' - replaceExistingArchive: true - -- task: FtpUpload@2 - inputs: - credentialsOption: 'inputs' - serverUrl: '$(FTPUrl)' - username: '$(FTPUsername)' - password: '$(FTPPassword)' - rootDirectory: '$(Build.ArtifactStagingDirectory)' - filePatterns: '*.zip' - remoteDirectory: 'IW4MAdmin/Download' - clean: false - cleanContents: false - preservePaths: false - trustSSL: false - -- task: FtpUpload@2 - inputs: - credentialsOption: 'inputs' - serverUrl: '$(FTPUrl)' - username: '$(FTPUsername)' - password: '$(FTPPassword)' - rootDirectory: '$(Build.ArtifactStagingDirectory)' - filePatterns: 'version_prerelease.txt' - remoteDirectory: 'IW4MAdmin' - clean: false - cleanContents: false - preservePaths: false - trustSSL: false - -- task: GitHubRelease@1 - inputs: - gitHubConnection: 'github.com_RaidMax' - repositoryName: 'RaidMax/IW4M-Admin' - action: 'create' - target: '$(Build.SourceVersion)' - tagSource: 'userSpecifiedTag' - tag: '$(Version.Major).$(Version.Minor)-$(buildConfiguration)$(Version.Build)b$(Build.BuildId)' - title: 'Version $(Version.Major).$(Version.Minor) $(buildConfiguration) Feature $(Version.Build) Build $(Build.BuildId)' - assets: '$(Build.ArtifactStagingDirectory)/*.zip' - isPreRelease: true - releaseNotesSource: 'inline' - releaseNotesInline: 'todo' - changeLogCompareToRelease: 'lastNonDraftRelease' - changeLogType: 'commitBased' - -- task: PowerShell@2 - inputs: - targetType: 'inline' - script: | - $payload = @{ - 'current-version-prerelease' = '$(Version.Major).$(Version.Minor).$(Version.Build).$(Build.BuildId)' - 'jwt-secret' = '$(JWTSecret)' - } | ConvertTo-Json - - - $params = @{ - Uri = 'http://api.raidmax.org:5000/version' - Method = 'POST' - Body = $payload - ContentType = 'application/json' - } - - Invoke-RestMethod @params - -- task: PublishPipelineArtifact@1 - inputs: - targetPath: '$(outputFolder)' - artifact: 'IW4MAdmin.$(buildConfiguration)' - publishLocation: 'pipeline' \ No newline at end of file From 84189cf136d7a437537ad347bf694b7312945508 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 31 Oct 2020 09:18:37 -0500 Subject: [PATCH 002/143] fix issue with T5 status response parsing --- DeploymentFiles/deployment-pipeline.yml | 4 +++- Plugins/ScriptPlugins/ParserRektT5M.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/DeploymentFiles/deployment-pipeline.yml b/DeploymentFiles/deployment-pipeline.yml index 042c957d..b9391784 100644 --- a/DeploymentFiles/deployment-pipeline.yml +++ b/DeploymentFiles/deployment-pipeline.yml @@ -18,6 +18,7 @@ variables: outputFolder: '$(Build.ArtifactStagingDirectory)\Publish\$(buildConfiguration)' releaseType: verified buildConfiguration: Stable + isPreRelease: false steps: - task: PowerShell@2 @@ -28,6 +29,7 @@ steps: script: | echo '##vso[task.setvariable variable=releaseType]prerelease' echo '##vso[task.setvariable variable=buildConfiguration]Prerelease' + echo '##vso[task.setvariable variable=isPreRelease]true' failOnStderr: true - task: NuGetCommand@2 @@ -178,7 +180,7 @@ steps: tag: '$(Build.BuildNumber)-$(releaseType)' title: 'IW4MAdmin $(Build.BuildNumber) ($(releaseType))' assets: '$(Build.ArtifactStagingDirectory)/*.zip' - isPreRelease: eq(variables['Build.SourceBranch'], 'refs/heads/release/pre') + isPreRelease: $(isPreRelease) releaseNotesSource: 'inline' releaseNotesInline: 'todo' changeLogCompareToRelease: 'lastNonDraftRelease' diff --git a/Plugins/ScriptPlugins/ParserRektT5M.js b/Plugins/ScriptPlugins/ParserRektT5M.js index aa1e441a..a9ce84ec 100644 --- a/Plugins/ScriptPlugins/ParserRektT5M.js +++ b/Plugins/ScriptPlugins/ParserRektT5M.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.2, + version: 0.3, name: 'RektT5m Parser', isParser: true, @@ -16,7 +16,7 @@ var plugin = { eventParser.Configuration.GameDirectory = 'data'; - rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xff\x01print'; + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xff\x01print\n'; rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}'; rconParser.Configuration.CommandPrefixes.RConGetInfo = undefined; From e76976799bf86c204e70576019aa5912c62182a0 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Tue, 3 Nov 2020 20:04:11 -0600 Subject: [PATCH 003/143] fix issue with partial matches for map load command --- SharedLibraryCore/Commands/NativeCommands.cs | 2 +- Tests/ApplicationTests/CommandTests.cs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index e3f4e97b..9d47a2cf 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -875,7 +875,7 @@ namespace SharedLibraryCore.Commands E.Owner.Broadcast(_translationLookup["COMMANDS_MAP_SUCCESS"].FormatExt(foundMap.Alias)); await Task.Delay(delay); - await E.Owner.LoadMap(newMap); + await E.Owner.LoadMap(foundMap?.Name ?? newMap); } } diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index 2bcc6c48..fc73a2cc 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -606,6 +606,25 @@ namespace ApplicationTests A.CallTo(() => rconParser.ExecuteCommandAsync(A.Ignored, A.Ignored)) .MustHaveHappened(); } + + [Test] + public async Task Test_LoadMap_FindsMapName_FromPartialAlias() + { + var cmd = serviceProvider.GetRequiredService(); + var server = serviceProvider.GetRequiredService(); + var rconParser = serviceProvider.GetRequiredService(); + server.Maps.Add(new Map() + { + Name = "mp_test", + Alias = "test" + }); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, server.Maps.First().Name, server); + + await cmd.ExecuteAsync(gameEvent); + + A.CallTo(() => rconParser.ExecuteCommandAsync(A.Ignored, A.That.Contains(server.Maps[0].Name))) + .MustHaveHappened(); + } #endregion } } From fd7bd7e0da0e23d8cf7375f4182b46f7e8e1ca57 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 7 Nov 2020 10:40:58 -0600 Subject: [PATCH 004/143] partial support of IW6x until the game log is implemented --- Application/IW4MServer.cs | 9 ++- Application/RCon/RConConnection.cs | 94 +++++++++++++++++------ Application/RconParsers/BaseRConParser.cs | 17 +++- IW4MAdmin.sln | 1 + Plugins/ScriptPlugins/ParserIW6x.js | 43 +++++++++++ SharedLibraryCore/RCon/StaticHelpers.cs | 15 +++- SharedLibraryCore/Server.cs | 2 +- 7 files changed, 149 insertions(+), 32 deletions(-) create mode 100644 Plugins/ScriptPlugins/ParserIW6x.js diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 1b5f02a6..f3f8de0c 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -972,7 +972,7 @@ namespace IW4MAdmin if (!string.IsNullOrEmpty(svRunning.Value) && svRunning.Value != "1") { - throw new ServerException(loc["SERVER_ERROR_NOT_RUNNING"]); + throw new ServerException(loc["SERVER_ERROR_NOT_RUNNING"].FormatExt(this.ToString())); } var infoResponse = RconParser.Configuration.CommandPrefixes.RConGetInfo != null ? await this.GetInfoAsync() : null; @@ -1042,9 +1042,10 @@ namespace IW4MAdmin } if (needsRestart) - { - Logger.WriteWarning("Game log file not properly initialized, restarting map..."); - await this.ExecuteCommandAsync("map_restart"); + { + // disabling this for the time being + /*Logger.WriteWarning("Game log file not properly initialized, restarting map..."); + await this.ExecuteCommandAsync("map_restart");*/ } // this DVAR isn't set until the a map is loaded diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index ca131f4c..8dbadbb3 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -49,9 +49,11 @@ namespace IW4MAdmin.Application.RCon var connectionState = ActiveQueries[this.Endpoint]; -#if DEBUG == true - _log.WriteDebug($"Waiting for semaphore to be released [{this.Endpoint}]"); -#endif + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Waiting for semaphore to be released [{this.Endpoint}]"); + } + // enter the semaphore so only one query is sent at a time per server. await connectionState.OnComplete.WaitAsync(); @@ -64,10 +66,11 @@ namespace IW4MAdmin.Application.RCon connectionState.LastQuery = DateTime.Now; -#if DEBUG == true - _log.WriteDebug($"Semaphore has been released [{this.Endpoint}]"); - _log.WriteDebug($"Query [{this.Endpoint},{type.ToString()},{parameters}]"); -#endif + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Semaphore has been released [{Endpoint}]"); + _log.WriteDebug($"Query [{Endpoint},{type},{parameters}]"); + } byte[] payload = null; bool waitForResponse = config.WaitForResponse; @@ -133,6 +136,7 @@ namespace IW4MAdmin.Application.RCon connectionState.OnReceivedData.Reset(); connectionState.ConnectionAttempts++; connectionState.BytesReadPerSegment.Clear(); + bool exceptionCaught = false; #if DEBUG == true _log.WriteDebug($"Sending {payload.Length} bytes to [{this.Endpoint}] ({connectionState.ConnectionAttempts}/{StaticHelpers.AllowedConnectionFails})"); #endif @@ -150,9 +154,11 @@ namespace IW4MAdmin.Application.RCon catch { + // we want to retry with a delay if (connectionState.ConnectionAttempts < StaticHelpers.AllowedConnectionFails) { - await Task.Delay(StaticHelpers.FloodProtectionInterval); + exceptionCaught = true; + await Task.Delay(StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts)); goto retrySend; } @@ -161,7 +167,8 @@ namespace IW4MAdmin.Application.RCon finally { - if (connectionState.OnComplete.CurrentCount == 0) + // we don't want to release if we're going to retry the query + if (connectionState.OnComplete.CurrentCount == 0 && !exceptionCaught) { connectionState.OnComplete.Release(1); } @@ -170,13 +177,12 @@ namespace IW4MAdmin.Application.RCon if (response.Length == 0) { - _log.WriteWarning($"Received empty response for request [{type.ToString()}, {parameters}, {Endpoint.ToString()}]"); + _log.WriteWarning($"Received empty response for request [{type}, {parameters}, {Endpoint}]"); return new string[0]; } string responseString = type == StaticHelpers.QueryType.COMMAND_STATUS ? - ReassembleSegmentedStatus(response) : - _gameEncoding.GetString(response[0]) + '\n'; + ReassembleSegmentedStatus(response) : RecombineMessages(response); // note: not all games respond if the pasword is wrong or not set if (responseString.Contains("Invalid password") || responseString.Contains("rconpassword")) @@ -234,6 +240,35 @@ namespace IW4MAdmin.Application.RCon return string.Join("", splitStatusStrings); } + /// + /// Recombines multiple game messages into one + /// + /// + /// + private string RecombineMessages(byte[][] payload) + { + if (payload.Length == 1) + { + return _gameEncoding.GetString(payload[0]).TrimEnd('\n') + '\n'; + } + + else + { + var builder = new StringBuilder(); + for (int i = 0; i < payload.Length; i++) + { + string message = _gameEncoding.GetString(payload[i]).TrimEnd('\n') + '\n'; + if (i > 0) + { + message = message.Replace(config.CommandPrefixes.RConResponse, ""); + } + builder.Append(message); + } + builder.Append('\n'); + return builder.ToString(); + } + } + private async Task SendPayloadAsync(byte[] payload, bool waitForResponse) { var connectionState = ActiveQueries[this.Endpoint]; @@ -259,7 +294,8 @@ namespace IW4MAdmin.Application.RCon if (sendDataPending) { // the send has not been completed asyncronously - if (!await Task.Run(() => connectionState.OnSentData.Wait(StaticHelpers.SocketTimeout))) + // this really shouldn't ever happen because it's UDP + if (!await Task.Run(() => connectionState.OnSentData.Wait(StaticHelpers.SocketTimeout(1)))) { rconSocket.Close(); throw new NetworkException("Timed out sending data", rconSocket); @@ -278,7 +314,11 @@ namespace IW4MAdmin.Application.RCon if (receiveDataPending) { - if (!await Task.Run(() => connectionState.OnReceivedData.Wait(10000))) + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Waiting to asynchrously receive data on attempt #{connectionState.ConnectionAttempts}"); + } + if (!await Task.Run(() => connectionState.OnReceivedData.Wait(StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts)))) { rconSocket.Close(); throw new NetworkException("Timed out waiting for response", rconSocket); @@ -287,6 +327,11 @@ namespace IW4MAdmin.Application.RCon rconSocket.Close(); + return GetResponseData(connectionState); + } + + private byte[][] GetResponseData(ConnectionState connectionState) + { var responseList = new List(); int totalBytesRead = 0; @@ -305,9 +350,10 @@ namespace IW4MAdmin.Application.RCon private void OnDataReceived(object sender, SocketAsyncEventArgs e) { -#if DEBUG == true - _log.WriteDebug($"Read {e.BytesTransferred} bytes from {e.RemoteEndPoint.ToString()}"); -#endif + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Read {e.BytesTransferred} bytes from {e.RemoteEndPoint}"); + } // this occurs when we close the socket if (e.BytesTransferred == 0) @@ -330,9 +376,10 @@ namespace IW4MAdmin.Application.RCon if (!sock.ReceiveAsync(state.ReceiveEventArgs)) { -#if DEBUG == true - _log.WriteDebug($"Read {state.ReceiveEventArgs.BytesTransferred} synchronous bytes from {e.RemoteEndPoint.ToString()}"); -#endif + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Read {state.ReceiveEventArgs.BytesTransferred} synchronous bytes from {e.RemoteEndPoint}"); + } // we need to increment this here because the callback isn't executed if there's no pending IO state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred); ActiveQueries[this.Endpoint].OnReceivedData.Set(); @@ -354,9 +401,10 @@ namespace IW4MAdmin.Application.RCon private void OnDataSent(object sender, SocketAsyncEventArgs e) { -#if DEBUG == true - _log.WriteDebug($"Sent {e.Buffer?.Length} bytes to {e.ConnectSocket?.RemoteEndPoint?.ToString()}"); -#endif + if (Utilities.IsDevelopment) + { + _log.WriteDebug($"Sent {e.Buffer?.Length} bytes to {e.ConnectSocket?.RemoteEndPoint?.ToString()}"); + } ActiveQueries[this.Endpoint].OnSentData.Set(); } } diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index d1af19c5..d797111c 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -76,7 +76,22 @@ namespace IW4MAdmin.Application.RconParsers public async Task> GetDvarAsync(IRConConnection connection, string dvarName, T fallbackValue = default) { - string[] lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.GET_DVAR, dvarName); + string[] lineSplit; + + try + { + lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.GET_DVAR, dvarName); + } + catch + { + if (fallbackValue == null) + { + throw; + } + + lineSplit = new string[0]; + } + string response = string.Join('\n', lineSplit).TrimEnd('\0'); var match = Regex.Match(response, Configuration.Dvar.Pattern); diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 6190d1e4..c2dfee15 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -35,6 +35,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug Plugins\ScriptPlugins\ActionOnReport.js = Plugins\ScriptPlugins\ActionOnReport.js Plugins\ScriptPlugins\ParserCoD4x.js = Plugins\ScriptPlugins\ParserCoD4x.js Plugins\ScriptPlugins\ParserIW4x.js = Plugins\ScriptPlugins\ParserIW4x.js + Plugins\ScriptPlugins\ParserIW6x.js = Plugins\ScriptPlugins\ParserIW6x.js Plugins\ScriptPlugins\ParserPIW5.js = Plugins\ScriptPlugins\ParserPIW5.js Plugins\ScriptPlugins\ParserPT6.js = Plugins\ScriptPlugins\ParserPT6.js Plugins\ScriptPlugins\ParserRektT5M.js = Plugins\ScriptPlugins\ParserRektT5M.js diff --git a/Plugins/ScriptPlugins/ParserIW6x.js b/Plugins/ScriptPlugins/ParserIW6x.js new file mode 100644 index 00000000..facfedab --- /dev/null +++ b/Plugins/ScriptPlugins/ParserIW6x.js @@ -0,0 +1,43 @@ +var rconParser; +var eventParser; + +var plugin = { + author: 'Xerxes, RaidMax', + version: 0.1, + name: 'IW6x Parser', + isParser: true, + + onEventAsync: function (gameEvent, server) { + }, + + onLoadAsync: function (manager) { + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); + + rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}'; + rconParser.Configuration.CommandPrefixes.Say = 'say {0}'; + rconParser.Configuration.CommandPrefixes.Kick = 'clientkick {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; + rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n(?:latched: \\"(.+)?\\"\\n)? *(.+)$'; + rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$'; + rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *'; + rconParser.Configuration.WaitForResponse = false; + rconParser.Configuration.Status.AddMapping(102, 4); + rconParser.Configuration.Status.AddMapping(103, 5); + rconParser.Configuration.Status.AddMapping(104, 6); + + rconParser.Version = 'IW6 MP 3.15 build 2 Sat Sep 14 2013 03:58:30PM win64'; + rconParser.GameName = 4; // IW6 + eventParser.Version = 'IW6 MP 3.15 build 2 Sat Sep 14 2013 03:58:30PM win64'; + eventParser.GameName = 4; // IW6 + eventParser.Configuration.GameDirectory = 'iw6x'; + }, + + onUnloadAsync: function () { + }, + + onTickAsync: function (server) { + } +}; diff --git a/SharedLibraryCore/RCon/StaticHelpers.cs b/SharedLibraryCore/RCon/StaticHelpers.cs index eb1e7436..68625a5a 100644 --- a/SharedLibraryCore/RCon/StaticHelpers.cs +++ b/SharedLibraryCore/RCon/StaticHelpers.cs @@ -49,14 +49,23 @@ namespace SharedLibraryCore.RCon /// /// timeout in seconds to wait for a socket send or receive before giving up /// - public static readonly int SocketTimeout = 10000; + public static TimeSpan SocketTimeout(int retryAttempt) + { + return retryAttempt switch + { + 1 => TimeSpan.FromMilliseconds(550), + 2 => TimeSpan.FromMilliseconds(1000), + 3 => TimeSpan.FromMilliseconds(2000), + _ => TimeSpan.FromMilliseconds(5000), + }; + } /// /// interval in milliseconds to wait before sending the next RCon request /// - public static readonly int FloodProtectionInterval = 650; + public static readonly int FloodProtectionInterval = 750; /// /// how many failed connection attempts before aborting connection /// - public static readonly int AllowedConnectionFails = 3; + public static readonly int AllowedConnectionFails = 4; } } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 58332bb9..2428ce30 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -269,7 +269,7 @@ namespace SharedLibraryCore { try { - return (await this.GetDvarAsync("sv_customcallbacks")).Value == "1"; + return (await this.GetDvarAsync("sv_customcallbacks", "0")).Value == "1"; } catch (Exceptions.DvarException) From 570a228c9255f2717b1e9a14e5d08cc2bbd288fd Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 11 Nov 2020 17:31:26 -0600 Subject: [PATCH 005/143] refactor logging in pretty big overhaul --- .gitignore | 1 + Application/API/Master/IMasterApi.cs | 2 +- Application/Application.csproj | 5 + Application/ApplicationManager.cs | 181 ++- Application/BuildScripts/PostBuild.bat | 15 +- .../Configuration/LoggingConfiguration.json | 43 + Application/EventParsers/BaseEventParser.cs | 4 +- .../EventParsers/DynamicEventParser.cs | 1 + Application/Extensions/StartupExtensions.cs | 41 + Application/Factories/GameLogReaderFactory.cs | 5 +- .../Factories/GameServerInstanceFactory.cs | 16 +- .../Factories/RConConnectionFactory.cs | 5 +- Application/Factories/ScriptCommandFactory.cs | 14 +- Application/GameEventHandler.cs | 24 +- Application/IO/GameLogEventDetection.cs | 28 +- Application/IO/GameLogReader.cs | 8 +- Application/IO/GameLogReaderHttp.cs | 10 +- Application/IW4MServer.cs | 1035 +++++++++-------- Application/Localization/Configure.cs | 22 +- Application/Main.cs | 192 +-- .../AdministeredPenaltyResourceQueryHelper.cs | 4 +- Application/Meta/MetaRegistration.cs | 6 +- .../ReceivedPenaltyResourceQueryHelper.cs | 4 +- .../Meta/UpdatedAliasResourceQueryHelper.cs | 4 +- .../Migration/ConfigurationMigration.cs | 8 +- Application/Misc/EventProfiler.cs | 63 - Application/Misc/Logger.cs | 113 +- Application/Misc/MasterCommunication.cs | 23 +- Application/Misc/MetaService.cs | 4 +- Application/Misc/MiddlewareActionHandler.cs | 10 +- Application/Misc/PluginImporter.cs | 25 +- Application/Misc/RemoteAssemblyHandler.cs | 12 +- Application/Misc/ScriptCommand.cs | 17 +- Application/Misc/ScriptPlugin.cs | 57 +- Application/RCon/RConConnection.cs | 101 +- Application/RconParsers/BaseRConParser.cs | 14 +- Application/RconParsers/DynamicRConParser.cs | 5 +- .../AutomessageFeed/AutomessageFeed.csproj | 2 +- .../IW4ScriptCommands.csproj | 2 +- Plugins/LiveRadar/LiveRadar.csproj | 2 +- Plugins/LiveRadar/Plugin.cs | 12 +- Plugins/Login/Login.csproj | 2 +- .../ProfanityDeterment.csproj | 2 +- Plugins/ScriptPlugins/ParserIW6x.js | 2 +- .../SampleScriptPluginCommand.js | 1 + Plugins/Stats/Cheat/Detection.cs | 19 +- Plugins/Stats/Cheat/Strain.cs | 6 - Plugins/Stats/Helpers/MigrationHelper.cs | 7 + Plugins/Stats/Helpers/StatManager.cs | 56 +- Plugins/Stats/Plugin.cs | 39 +- Plugins/Stats/Stats.csproj | 4 +- Plugins/Web/StatsWeb/API/StatsController.cs | 8 +- .../Web/StatsWeb/ChatResourceQueryHelper.cs | 4 +- .../StatsWeb/Controllers/StatsController.cs | 16 +- Plugins/Web/StatsWeb/StatsWeb.csproj | 4 +- Plugins/Welcome/Welcome.csproj | 2 +- SharedLibraryCore/Command.cs | 1 + SharedLibraryCore/Commands/NativeCommands.cs | 11 +- SharedLibraryCore/Events/GameEvent.cs | 21 +- SharedLibraryCore/Exceptions/RConException.cs | 11 + SharedLibraryCore/Interfaces/ILogger.cs | 5 +- SharedLibraryCore/Interfaces/IManager.cs | 2 + SharedLibraryCore/PartialEntities/EFClient.cs | 261 +++-- SharedLibraryCore/RCon/StaticHelpers.cs | 5 +- SharedLibraryCore/Server.cs | 45 +- .../Services/ChangeHistoryService.cs | 12 +- SharedLibraryCore/Services/ClientService.cs | 272 +++-- SharedLibraryCore/SharedLibraryCore.csproj | 8 +- SharedLibraryCore/Utilities.cs | 7 +- .../ApplicationTests/BaseEventParserTests.cs | 17 +- Tests/ApplicationTests/BaseRConParserTests.cs | 9 +- Tests/ApplicationTests/CommandTests.cs | 3 - .../DependencyInjectionExtensions.cs | 20 +- Tests/ApplicationTests/IW4MServerTests.cs | 7 +- Tests/ApplicationTests/PluginTests.cs | 6 +- Tests/ApplicationTests/ServerTests.cs | 18 +- Tests/ApplicationTests/StatsTests.cs | 17 +- .../Controllers/API/ClientController.cs | 8 +- WebfrontCore/Controllers/ClientController.cs | 2 +- WebfrontCore/Controllers/HomeController.cs | 12 +- WebfrontCore/Middleware/IPWhitelist.cs | 15 +- WebfrontCore/Startup.cs | 14 +- WebfrontCore/Views/Client/Find/Index.cshtml | 2 +- .../Components/PenaltyList/_List.cshtml | 2 +- .../Views/Shared/ResponseStatusCode.cshtml | 4 +- WebfrontCore/WebfrontCore.csproj | 8 +- 86 files changed, 1603 insertions(+), 1534 deletions(-) create mode 100644 Application/Configuration/LoggingConfiguration.json create mode 100644 Application/Extensions/StartupExtensions.cs delete mode 100644 Application/Misc/EventProfiler.cs create mode 100644 Plugins/Stats/Helpers/MigrationHelper.cs create mode 100644 SharedLibraryCore/Exceptions/RConException.cs diff --git a/.gitignore b/.gitignore index f5c4f09f..f7743056 100644 --- a/.gitignore +++ b/.gitignore @@ -244,3 +244,4 @@ launchSettings.json /Tests/ApplicationTests/Files/GameEvents.json /Tests/ApplicationTests/Files/replay.json /GameLogServer/game_log_server_env +.idea/* \ No newline at end of file diff --git a/Application/API/Master/IMasterApi.cs b/Application/API/Master/IMasterApi.cs index f6a46bf2..2b99422a 100644 --- a/Application/API/Master/IMasterApi.cs +++ b/Application/API/Master/IMasterApi.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using IW4MAdmin.Application.Helpers; +using IW4MAdmin.Application.Misc; using Newtonsoft.Json; using RestEase; using SharedLibraryCore.Helpers; diff --git a/Application/Application.csproj b/Application/Application.csproj index b0ef4959..8665b750 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -21,6 +21,8 @@ IW4MAdmin.Application false + 2020.0.0.0 + 2020.0.0.0 @@ -59,6 +61,9 @@ Always + + PreserveNewest + diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 135e0256..5324bc05 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -1,5 +1,4 @@ -using IW4MAdmin.Application.API.Master; -using IW4MAdmin.Application.EventParsers; +using IW4MAdmin.Application.EventParsers; using IW4MAdmin.Application.Extensions; using IW4MAdmin.Application.Misc; using IW4MAdmin.Application.RconParsers; @@ -9,11 +8,9 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration.Validation; using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Dtos; using SharedLibraryCore.Exceptions; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; -using SharedLibraryCore.QueryHelper; using SharedLibraryCore.Services; using System; using System.Collections; @@ -24,7 +21,12 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Serilog.Context; using static SharedLibraryCore.GameEvent; +using ILogger = Microsoft.Extensions.Logging.ILogger; +using ObsoleteLogger = SharedLibraryCore.Interfaces.ILogger; namespace IW4MAdmin.Application { @@ -32,7 +34,7 @@ namespace IW4MAdmin.Application { private readonly ConcurrentBag _servers; public List Servers => _servers.OrderByDescending(s => s.ClientNum).ToList(); - public ILogger Logger => GetLogger(0); + [Obsolete] public ObsoleteLogger Logger => _serviceProvider.GetRequiredService(); public bool IsRunning { get; private set; } public bool IsInitialized { get; private set; } public DateTime StartTime { get; private set; } @@ -54,7 +56,6 @@ namespace IW4MAdmin.Application readonly PenaltyService PenaltySvc; public IConfigurationHandler ConfigHandler; readonly IPageList PageList; - private readonly Dictionary _loggers = new Dictionary(); private readonly IMetaService _metaService; private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0); private readonly CancellationTokenSource _tokenSource; @@ -68,30 +69,33 @@ namespace IW4MAdmin.Application private readonly IScriptCommandFactory _scriptCommandFactory; private readonly IMetaRegistration _metaRegistration; private readonly IScriptPluginServiceResolver _scriptPluginServiceResolver; + private readonly IServiceProvider _serviceProvider; + private readonly ChangeHistoryService _changeHistoryService; + private readonly ApplicationConfiguration _appConfig; - public ApplicationManager(ILogger logger, IMiddlewareActionHandler actionHandler, IEnumerable commands, + public ApplicationManager(ILogger logger, IMiddlewareActionHandler actionHandler, IEnumerable commands, ITranslationLookup translationLookup, IConfigurationHandler commandConfiguration, IConfigurationHandler appConfigHandler, IGameServerInstanceFactory serverInstanceFactory, IEnumerable plugins, IParserRegexFactory parserRegexFactory, IEnumerable customParserEvents, IEventHandler eventHandler, IScriptCommandFactory scriptCommandFactory, IDatabaseContextFactory contextFactory, IMetaService metaService, - IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver) + IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver, ClientService clientService, IServiceProvider serviceProvider, + ChangeHistoryService changeHistoryService, ApplicationConfiguration appConfig) { MiddlewareActionHandler = actionHandler; _servers = new ConcurrentBag(); MessageTokens = new List(); - ClientSvc = new ClientService(contextFactory); + ClientSvc = clientService; AliasSvc = new AliasService(); PenaltySvc = new PenaltyService(); ConfigHandler = appConfigHandler; StartTime = DateTime.UtcNow; PageList = new PageList(); - AdditionalEventParsers = new List() { new BaseEventParser(parserRegexFactory, logger, appConfigHandler.Configuration()) }; - AdditionalRConParsers = new List() { new BaseRConParser(parserRegexFactory) }; + AdditionalEventParsers = new List() { new BaseEventParser(parserRegexFactory, logger, _appConfig) }; + AdditionalRConParsers = new List() { new BaseRConParser(serviceProvider.GetRequiredService>(), parserRegexFactory) }; TokenAuthenticator = new TokenAuthentication(); _logger = logger; _metaService = metaService; _tokenSource = new CancellationTokenSource(); - _loggers.Add(0, logger); _commands = commands.ToList(); _translationLookup = translationLookup; _commandConfiguration = commandConfiguration; @@ -102,6 +106,9 @@ namespace IW4MAdmin.Application _scriptCommandFactory = scriptCommandFactory; _metaRegistration = metaRegistration; _scriptPluginServiceResolver = scriptPluginServiceResolver; + _serviceProvider = serviceProvider; + _changeHistoryService = changeHistoryService; + _appConfig = appConfig; Plugins = plugins; } @@ -109,10 +116,6 @@ namespace IW4MAdmin.Application public async Task ExecuteEvent(GameEvent newEvent) { -#if DEBUG == true - Logger.WriteDebug($"Entering event process for {newEvent.Id}"); -#endif - // the event has failed already if (newEvent.Failed) { @@ -124,22 +127,17 @@ namespace IW4MAdmin.Application await newEvent.Owner.ExecuteEvent(newEvent); // save the event info to the database - var changeHistorySvc = new ChangeHistoryService(); - await changeHistorySvc.Add(newEvent); - -#if DEBUG - Logger.WriteDebug($"Processed event with id {newEvent.Id}"); -#endif + await _changeHistoryService.Add(newEvent); } catch (TaskCanceledException) { - Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early"); + _logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id); } catch (OperationCanceledException) { - Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early"); + _logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id); } // this happens if a plugin requires login @@ -152,31 +150,35 @@ namespace IW4MAdmin.Application catch (NetworkException ex) { newEvent.FailReason = EventFailReason.Exception; - Logger.WriteError(ex.Message); - Logger.WriteDebug(ex.GetExceptionInfo()); + using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) + { + _logger.LogError(ex, ex.Message); + } } catch (ServerException ex) { newEvent.FailReason = EventFailReason.Exception; - Logger.WriteWarning(ex.Message); + using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) + { + _logger.LogError(ex, ex.Message); + } } catch (Exception ex) { newEvent.FailReason = EventFailReason.Exception; - Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner)); - Logger.WriteDebug(ex.GetExceptionInfo()); + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner)); + using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) + { + _logger.LogError(ex, "Unexpected exception"); + } } - skip: + skip: // tell anyone waiting for the output that we're done newEvent.Complete(); OnGameEventExecuted?.Invoke(this, newEvent); - -#if DEBUG == true - Logger.WriteDebug($"Exiting event process for {newEvent.Id}"); -#endif } public IList GetServers() @@ -226,17 +228,14 @@ namespace IW4MAdmin.Application try { await server.ProcessUpdatesAsync(_tokenSource.Token); - - if (server.Throttled) - { - await Task.Delay((int)_throttleTimeout.TotalMilliseconds, _tokenSource.Token); - } } catch (Exception e) { - Logger.WriteWarning($"Failed to update status for {server}"); - Logger.WriteDebug(e.GetExceptionInfo()); + using (LogContext.PushProperty("Server", server.ToString())) + { + _logger.LogError(e, "Failed to update status"); + } } finally @@ -245,12 +244,7 @@ namespace IW4MAdmin.Application } })); } -#if DEBUG - Logger.WriteDebug($"{runningUpdateTasks.Count} servers queued for stats updates"); - ThreadPool.GetMaxThreads(out int workerThreads, out int n); - ThreadPool.GetAvailableThreads(out int availableThreads, out int m); - Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks"); -#endif + try { await Task.Delay(ConfigHandler.Configuration().RConPollRate, _tokenSource.Token); @@ -289,8 +283,8 @@ namespace IW4MAdmin.Application catch (Exception ex) { - Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name)); - Logger.WriteDebug(ex.Message); + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name)); + _logger.LogError(ex, "Could not properly load plugin {plugin}", scriptPlugin.Name); } }; } @@ -303,32 +297,29 @@ namespace IW4MAdmin.Application catch (Exception ex) { - Logger.WriteError($"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}"); - Logger.WriteDebug(ex.GetExceptionInfo()); + _logger.LogError(ex, $"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}"); } } #endregion #region CONFIG - var config = ConfigHandler.Configuration(); - // copy over default config if it doesn't exist - if (config == null) + if (!_appConfig.Servers?.Any() ?? true) { var defaultConfig = new BaseConfigurationHandler("DefaultSettings").Configuration(); - ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate()); - var newConfig = ConfigHandler.Configuration(); + //ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate()); + //var newConfig = ConfigHandler.Configuration(); - newConfig.AutoMessages = defaultConfig.AutoMessages; - newConfig.GlobalRules = defaultConfig.GlobalRules; - newConfig.Maps = defaultConfig.Maps; - newConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames; - newConfig.QuickMessages = defaultConfig.QuickMessages; + _appConfig.AutoMessages = defaultConfig.AutoMessages; + _appConfig.GlobalRules = defaultConfig.GlobalRules; + _appConfig.Maps = defaultConfig.Maps; + _appConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames; + _appConfig.QuickMessages = defaultConfig.QuickMessages; - if (newConfig.Servers == null) + //if (newConfig.Servers == null) { - ConfigHandler.Set(newConfig); - newConfig.Servers = new ServerConfiguration[1]; + ConfigHandler.Set(_appConfig); + _appConfig.Servers = new ServerConfiguration[1]; do { @@ -343,30 +334,29 @@ namespace IW4MAdmin.Application serverConfig.AddEventParser(parser); } - newConfig.Servers = newConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray(); + _appConfig.Servers = _appConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray(); } while (Utilities.PromptBool(_translationLookup["SETUP_SERVER_SAVE"])); - config = newConfig; await ConfigHandler.Save(); } } else { - if (string.IsNullOrEmpty(config.Id)) + if (string.IsNullOrEmpty(_appConfig.Id)) { - config.Id = Guid.NewGuid().ToString(); + _appConfig.Id = Guid.NewGuid().ToString(); await ConfigHandler.Save(); } - if (string.IsNullOrEmpty(config.WebfrontBindUrl)) + if (string.IsNullOrEmpty(_appConfig.WebfrontBindUrl)) { - config.WebfrontBindUrl = "http://0.0.0.0:1624"; + _appConfig.WebfrontBindUrl = "http://0.0.0.0:1624"; await ConfigHandler.Save(); } var validator = new ApplicationConfigurationValidator(); - var validationResult = validator.Validate(config); + var validationResult = validator.Validate(_appConfig); if (!validationResult.IsValid) { @@ -377,7 +367,7 @@ namespace IW4MAdmin.Application }; } - foreach (var serverConfig in config.Servers) + foreach (var serverConfig in _appConfig.Servers) { Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig); @@ -399,13 +389,13 @@ namespace IW4MAdmin.Application } } - if (config.Servers.Length == 0) + if (_appConfig.Servers.Length == 0) { throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid"); } Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252"); + Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(_appConfig.CustomParserEncoding) ? _appConfig.CustomParserEncoding : "windows-1252"); #endregion @@ -440,8 +430,8 @@ namespace IW4MAdmin.Application // this is because I want to store the command prefix in IW4MAdminSettings, but can't easily // inject it to all the places that need it - cmdConfig.CommandPrefix = config.CommandPrefix; - cmdConfig.BroadcastCommandPrefix = config.BroadcastCommandPrefix; + cmdConfig.CommandPrefix = _appConfig.CommandPrefix; + cmdConfig.BroadcastCommandPrefix = _appConfig.BroadcastCommandPrefix; foreach (var cmd in commandsToAddToConfig) { @@ -472,6 +462,7 @@ namespace IW4MAdmin.Application } #endregion + Console.WriteLine(_translationLookup["MANAGER_COMMUNICATION_INFO"]); await InitializeServers(); } @@ -487,13 +478,17 @@ namespace IW4MAdmin.Application { // todo: this might not always be an IW4MServer var ServerInstance = _serverInstanceFactory.CreateServer(Conf, this) as IW4MServer; - await ServerInstance.Initialize(); + using (LogContext.PushProperty("Server", ServerInstance.ToString())) + { + _logger.LogInformation("Beginning server communication initialization"); + await ServerInstance.Initialize(); - _servers.Add(ServerInstance); + _servers.Add(ServerInstance); + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname.StripColors())); + _logger.LogInformation("Finishing initialization and now monitoring [{server}]", ServerInstance.Hostname, ServerInstance.ToString()); + } - Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname)); // add the start event for this server - var e = new GameEvent() { Type = GameEvent.EventType.Start, @@ -507,13 +502,11 @@ namespace IW4MAdmin.Application catch (ServerException e) { - Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]")); - - if (e.GetType() == typeof(DvarException)) + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]")); + using (LogContext.PushProperty("Server", $"{Conf.IPAddress}:{Conf.Port}")) { - Logger.WriteDebug($"{e.Message} {(e.GetType() == typeof(DvarException) ? $"({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})" : "")}"); + _logger.LogError(e, "Unexpected exception occurred during initialization"); } - lastException = e; } } @@ -548,20 +541,10 @@ namespace IW4MAdmin.Application Stop(); } - public ILogger GetLogger(long serverId) + [Obsolete] + public ObsoleteLogger GetLogger(long serverId) { - if (_loggers.ContainsKey(serverId)) - { - return _loggers[serverId]; - } - - else - { - var newLogger = new Logger($"IW4MAdmin-Server-{serverId}"); - - _loggers.Add(serverId, newLogger); - return newLogger; - } + return _serviceProvider.GetRequiredService(); } public IList GetMessageTokens() @@ -607,7 +590,7 @@ namespace IW4MAdmin.Application public IRConParser GenerateDynamicRConParser(string name) { - return new DynamicRConParser(_parserRegexFactory) + return new DynamicRConParser(_serviceProvider.GetRequiredService>(), _parserRegexFactory) { Name = name }; diff --git a/Application/BuildScripts/PostBuild.bat b/Application/BuildScripts/PostBuild.bat index 6433f9de..c3cbc996 100644 --- a/Application/BuildScripts/PostBuild.bat +++ b/Application/BuildScripts/PostBuild.bat @@ -4,24 +4,13 @@ set TargetDir=%3 set OutDir=%4 set Version=%5 -echo %Version% > "%SolutionDir%DEPLOY\version.txt" - echo Copying dependency configs copy "%SolutionDir%WebfrontCore\%OutDir%*.deps.json" "%TargetDir%" -copy "%SolutionDir%SharedLibaryCore\%OutDir%*.deps.json" "%TargetDir%" +copy "%SolutionDir%SharedLibraryCore\%OutDir%*.deps.json" "%TargetDir%" if not exist "%TargetDir%Plugins" ( echo "Making plugin dir" md "%TargetDir%Plugins" ) -xcopy /y "%SolutionDir%Build\Plugins" "%TargetDir%Plugins\" - -echo Copying plugins for publish -del %SolutionDir%BUILD\Plugins\Tests.dll -xcopy /Y "%SolutionDir%BUILD\Plugins" "%SolutionDir%Publish\Windows\Plugins\" -xcopy /Y "%SolutionDir%BUILD\Plugins" "%SolutionDir%Publish\WindowsPrerelease\Plugins\" - -echo Copying script plugins for publish -xcopy /Y "%SolutionDir%Plugins\ScriptPlugins" "%SolutionDir%Publish\Windows\Plugins\" -xcopy /Y "%SolutionDir%Plugins\ScriptPlugins" "%SolutionDir%Publish\WindowsPrerelease\Plugins\" \ No newline at end of file +xcopy /y "%SolutionDir%Build\Plugins" "%TargetDir%Plugins\" \ No newline at end of file diff --git a/Application/Configuration/LoggingConfiguration.json b/Application/Configuration/LoggingConfiguration.json new file mode 100644 index 00000000..9c4bd9fc --- /dev/null +++ b/Application/Configuration/LoggingConfiguration.json @@ -0,0 +1,43 @@ +{ + "Serilog": { + "Using": [ + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "File", + "Args": { + "path": "Log/IW4MAdmin-Application.log", + "rollingInterval": "Day", + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Destructure": [ + { + "Name": "ToMaximumDepth", + "Args": { + "maximumDestructuringDepth": 4 + } + }, + { + "Name": "ToMaximumStringLength", + "Args": { + "maximumStringLength": 1000 + } + }, + { + "Name": "ToMaximumCollectionCount", + "Args": { + "maximumCollectionCount": 24 + } + } + ] + } +} \ No newline at end of file diff --git a/Application/EventParsers/BaseEventParser.cs b/Application/EventParsers/BaseEventParser.cs index a786628e..1d81f308 100644 --- a/Application/EventParsers/BaseEventParser.cs +++ b/Application/EventParsers/BaseEventParser.cs @@ -5,7 +5,9 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.EventParsers { @@ -348,7 +350,7 @@ namespace IW4MAdmin.Application.EventParsers catch (Exception e) { - _logger.WriteWarning($"Could not handle custom event generation - {e.GetExceptionInfo()}"); + _logger.LogError(e, $"Could not handle custom event generation"); } } diff --git a/Application/EventParsers/DynamicEventParser.cs b/Application/EventParsers/DynamicEventParser.cs index 17022320..8c8c0fb3 100644 --- a/Application/EventParsers/DynamicEventParser.cs +++ b/Application/EventParsers/DynamicEventParser.cs @@ -1,5 +1,6 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.EventParsers { diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs new file mode 100644 index 00000000..614cd2fe --- /dev/null +++ b/Application/Extensions/StartupExtensions.cs @@ -0,0 +1,41 @@ +using System.IO; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Serilog; +using SharedLibraryCore; +using SharedLibraryCore.Configuration; + +namespace IW4MAdmin.Application.Extensions +{ + public static class StartupExtensions + { + private static ILogger _defaultLogger = null; + + public static IServiceCollection AddBaseLogger(this IServiceCollection services, + ApplicationConfiguration appConfig) + { + if (_defaultLogger == null) + { + var configuration = new ConfigurationBuilder() + .AddJsonFile(Path.Join(Utilities.OperatingDirectory, "Configuration", "LoggingConfiguration.json")) + .Build(); + + var loggerConfig = new LoggerConfiguration() + .ReadFrom.Configuration(configuration); + + + if (Utilities.IsDevelopment) + { + loggerConfig = loggerConfig.WriteTo.Console( + outputTemplate:"[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") + .MinimumLevel.Debug(); + } + + _defaultLogger = loggerConfig.CreateLogger(); + } + + services.AddLogging(builder => builder.AddSerilog(_defaultLogger, dispose: true)); + return services; + } + } +} \ No newline at end of file diff --git a/Application/Factories/GameLogReaderFactory.cs b/Application/Factories/GameLogReaderFactory.cs index 53854e8b..e035e012 100644 --- a/Application/Factories/GameLogReaderFactory.cs +++ b/Application/Factories/GameLogReaderFactory.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore.Interfaces; using System; +using Microsoft.Extensions.Logging; namespace IW4MAdmin.Application.Factories { @@ -19,12 +20,12 @@ namespace IW4MAdmin.Application.Factories var baseUri = logUris[0]; if (baseUri.Scheme == Uri.UriSchemeHttp) { - return new GameLogReaderHttp(logUris, eventParser, _serviceProvider.GetRequiredService()); + return new GameLogReaderHttp(logUris, eventParser, _serviceProvider.GetRequiredService>()); } else if (baseUri.Scheme == Uri.UriSchemeFile) { - return new GameLogReader(baseUri.LocalPath, eventParser, _serviceProvider.GetRequiredService()); + return new GameLogReader(baseUri.LocalPath, eventParser, _serviceProvider.GetRequiredService>()); } throw new NotImplementedException($"No log reader implemented for Uri scheme \"{baseUri.Scheme}\""); diff --git a/Application/Factories/GameServerInstanceFactory.cs b/Application/Factories/GameServerInstanceFactory.cs index 97a53257..9e91d54b 100644 --- a/Application/Factories/GameServerInstanceFactory.cs +++ b/Application/Factories/GameServerInstanceFactory.cs @@ -1,7 +1,7 @@ -using SharedLibraryCore; +using System; +using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; -using System.Collections; namespace IW4MAdmin.Application.Factories { @@ -11,21 +11,21 @@ namespace IW4MAdmin.Application.Factories internal class GameServerInstanceFactory : IGameServerInstanceFactory { private readonly ITranslationLookup _translationLookup; - private readonly IRConConnectionFactory _rconConnectionFactory; - private readonly IGameLogReaderFactory _gameLogReaderFactory; private readonly IMetaService _metaService; + private readonly IServiceProvider _serviceProvider; /// /// base constructor /// /// /// - public GameServerInstanceFactory(ITranslationLookup translationLookup, IRConConnectionFactory rconConnectionFactory, IGameLogReaderFactory gameLogReaderFactory, IMetaService metaService) + public GameServerInstanceFactory(ITranslationLookup translationLookup, + IMetaService metaService, + IServiceProvider serviceProvider) { _translationLookup = translationLookup; - _rconConnectionFactory = rconConnectionFactory; - _gameLogReaderFactory = gameLogReaderFactory; _metaService = metaService; + _serviceProvider = serviceProvider; } /// @@ -36,7 +36,7 @@ namespace IW4MAdmin.Application.Factories /// public Server CreateServer(ServerConfiguration config, IManager manager) { - return new IW4MServer(manager, config, _translationLookup, _rconConnectionFactory, _gameLogReaderFactory, _metaService); + return new IW4MServer(config, _translationLookup, _metaService, _serviceProvider); } } } diff --git a/Application/Factories/RConConnectionFactory.cs b/Application/Factories/RConConnectionFactory.cs index 1dd0d2f8..b65d2b4b 100644 --- a/Application/Factories/RConConnectionFactory.cs +++ b/Application/Factories/RConConnectionFactory.cs @@ -1,6 +1,7 @@ using IW4MAdmin.Application.RCon; using SharedLibraryCore.Interfaces; using System.Text; +using Microsoft.Extensions.Logging; namespace IW4MAdmin.Application.Factories { @@ -10,13 +11,13 @@ namespace IW4MAdmin.Application.Factories internal class RConConnectionFactory : IRConConnectionFactory { private static readonly Encoding gameEncoding = Encoding.GetEncoding("windows-1252"); - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Base constructor /// /// - public RConConnectionFactory(ILogger logger) + public RConConnectionFactory(ILogger logger) { _logger = logger; } diff --git a/Application/Factories/ScriptCommandFactory.cs b/Application/Factories/ScriptCommandFactory.cs index 8b609144..d2e3a38b 100644 --- a/Application/Factories/ScriptCommandFactory.cs +++ b/Application/Factories/ScriptCommandFactory.cs @@ -6,6 +6,8 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Database.Models.EFClient; namespace IW4MAdmin.Application.Factories @@ -15,17 +17,20 @@ namespace IW4MAdmin.Application.Factories /// public class ScriptCommandFactory : IScriptCommandFactory { - private CommandConfiguration _config; + private readonly CommandConfiguration _config; private readonly ITranslationLookup _transLookup; + private readonly IServiceProvider _serviceProvider; - public ScriptCommandFactory(CommandConfiguration config, ITranslationLookup transLookup) + public ScriptCommandFactory(CommandConfiguration config, ITranslationLookup transLookup, IServiceProvider serviceProvider) { _config = config; _transLookup = transLookup; + _serviceProvider = serviceProvider; } /// - public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, bool isTargetRequired, IEnumerable<(string, bool)> args, Action executeAction) + public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, + bool isTargetRequired, IEnumerable<(string, bool)> args, Action executeAction) { var permissionEnum = Enum.Parse(permission); var argsArray = args.Select(_arg => new CommandArgument @@ -34,7 +39,8 @@ namespace IW4MAdmin.Application.Factories Required = _arg.Item2 }).ToArray(); - return new ScriptCommand(name, alias, description, isTargetRequired, permissionEnum, argsArray, executeAction, _config, _transLookup); + return new ScriptCommand(name, alias, description, isTargetRequired, permissionEnum, argsArray, executeAction, + _config, _transLookup, _serviceProvider.GetRequiredService>()); } } } diff --git a/Application/GameEventHandler.cs b/Application/GameEventHandler.cs index 1dfc5282..45ccf8dd 100644 --- a/Application/GameEventHandler.cs +++ b/Application/GameEventHandler.cs @@ -1,19 +1,18 @@ using IW4MAdmin.Application.Misc; -using Newtonsoft.Json; using SharedLibraryCore; using SharedLibraryCore.Events; using SharedLibraryCore.Interfaces; -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application { public class GameEventHandler : IEventHandler { private readonly EventLog _eventLog; + private readonly ILogger _logger; private static readonly GameEvent.EventType[] overrideEvents = new[] { GameEvent.EventType.Connect, @@ -22,34 +21,23 @@ namespace IW4MAdmin.Application GameEvent.EventType.Stop }; - public GameEventHandler() + public GameEventHandler(ILogger logger) { _eventLog = new EventLog(); + _logger = logger; } public void HandleEvent(IManager manager, GameEvent gameEvent) { -#if DEBUG - ThreadPool.GetMaxThreads(out int workerThreads, out int n); - ThreadPool.GetAvailableThreads(out int availableThreads, out int m); - gameEvent.Owner.Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks"); - -#endif if (manager.IsRunning || overrideEvents.Contains(gameEvent.Type)) { -#if DEBUG - gameEvent.Owner.Logger.WriteDebug($"Adding event with id {gameEvent.Id}"); -#endif - EventApi.OnGameEvent(gameEvent); Task.Factory.StartNew(() => manager.ExecuteEvent(gameEvent)); } -#if DEBUG else { - gameEvent.Owner.Logger.WriteDebug($"Skipping event as we're shutting down {gameEvent.Id}"); + _logger.LogDebug("Skipping event as we're shutting down {eventId}", gameEvent.Id); } -#endif } } } diff --git a/Application/IO/GameLogEventDetection.cs b/Application/IO/GameLogEventDetection.cs index be9468a8..9a9a1f0b 100644 --- a/Application/IO/GameLogEventDetection.cs +++ b/Application/IO/GameLogEventDetection.cs @@ -3,6 +3,9 @@ using SharedLibraryCore.Interfaces; using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.IO { @@ -12,12 +15,14 @@ namespace IW4MAdmin.Application.IO private readonly Server _server; private readonly IGameLogReader _reader; private readonly bool _ignoreBots; + private readonly ILogger _logger; - public GameLogEventDetection(Server server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory) + public GameLogEventDetection(ILogger logger, Server server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory) { _reader = gameLogReaderFactory.CreateGameLogReader(gameLogUris, server.EventParser); _server = server; _ignoreBots = server?.Manager.GetApplicationSettings().Configuration().IgnoreBots ?? false; + _logger = logger; } public async Task PollForChanges() @@ -33,15 +38,17 @@ namespace IW4MAdmin.Application.IO catch (Exception e) { - _server.Logger.WriteWarning($"Failed to update log event for {_server.EndPoint}"); - _server.Logger.WriteDebug(e.GetExceptionInfo()); + using(LogContext.PushProperty("Server", _server.ToString())) + { + _logger.LogError(e, "Failed to update log event for {endpoint}", _server.EndPoint); + } } } await Task.Delay(_reader.UpdateInterval, _server.Manager.CancellationToken); } - _server.Logger.WriteDebug("Stopped polling for changes"); + _logger.LogDebug("Stopped polling for changes"); } public async Task UpdateLogEvents() @@ -68,9 +75,6 @@ namespace IW4MAdmin.Application.IO { try { -#if DEBUG - _server.Logger.WriteVerbose(gameEvent.Data); -#endif gameEvent.Owner = _server; // we don't want to add the event if ignoreBots is on and the event comes from a bot @@ -102,10 +106,14 @@ namespace IW4MAdmin.Application.IO catch (InvalidOperationException) { - if (!_ignoreBots) + if (_ignoreBots) { - _server.Logger.WriteWarning("Could not find client in client list when parsing event line"); - _server.Logger.WriteDebug(gameEvent.Data); + continue; + } + + using(LogContext.PushProperty("Server", _server.ToString())) + { + _logger.LogError("Could not find client in client list when parsing event line {data}", gameEvent.Data); } } } diff --git a/Application/IO/GameLogReader.cs b/Application/IO/GameLogReader.cs index 764de90a..d1339cd9 100644 --- a/Application/IO/GameLogReader.cs +++ b/Application/IO/GameLogReader.cs @@ -6,6 +6,8 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.IO { @@ -19,7 +21,7 @@ namespace IW4MAdmin.Application.IO public int UpdateInterval => 300; - public GameLogReader(string logFile, IEventParser parser, ILogger logger) + public GameLogReader(string logFile, IEventParser parser, ILogger logger) { _logFile = logFile; _parser = parser; @@ -73,9 +75,7 @@ namespace IW4MAdmin.Application.IO catch (Exception e) { - _logger.WriteWarning("Could not properly parse event line"); - _logger.WriteDebug(e.Message); - _logger.WriteDebug(eventLine); + _logger.LogError(e, "Could not properly parse event line {@eventLine}", eventLine); } } diff --git a/Application/IO/GameLogReaderHttp.cs b/Application/IO/GameLogReaderHttp.cs index 822861d0..5662593e 100644 --- a/Application/IO/GameLogReaderHttp.cs +++ b/Application/IO/GameLogReaderHttp.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.IO { @@ -20,7 +22,7 @@ namespace IW4MAdmin.Application.IO private readonly string _safeLogPath; private string lastKey = "next"; - public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger logger) + public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger logger) { _eventParser = parser; _logServerApi = RestClient.For(gameLogServerUris[0].ToString()); @@ -40,7 +42,7 @@ namespace IW4MAdmin.Application.IO if (!response.Success && string.IsNullOrEmpty(lastKey)) { - _logger.WriteError($"Could not get log server info of {_safeLogPath}"); + _logger.LogError("Could not get log server info of {logPath}", _safeLogPath); return events; } @@ -62,9 +64,7 @@ namespace IW4MAdmin.Application.IO catch (Exception e) { - _logger.WriteError("Could not properly parse event line from http"); - _logger.WriteDebug(e.Message); - _logger.WriteDebug(eventLine); + _logger.LogError(e, "Could not properly parse event line from http {eventLine}", eventLine); } } } diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index f3f8de0c..26e0fecb 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -12,10 +12,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; -using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Serilog.Context; using static SharedLibraryCore.Database.Models.EFClient; namespace IW4MAdmin @@ -30,37 +32,45 @@ namespace IW4MAdmin private int lastGameTime = 0; public int Id { get; private set; } + private readonly IServiceProvider _serviceProvider; - public IW4MServer(IManager mgr, ServerConfiguration cfg, ITranslationLookup lookup, - IRConConnectionFactory connectionFactory, IGameLogReaderFactory gameLogReaderFactory, IMetaService metaService) : base(cfg, mgr, connectionFactory, gameLogReaderFactory) + public IW4MServer( + ServerConfiguration serverConfiguration, + ITranslationLookup lookup, + IMetaService metaService, + IServiceProvider serviceProvider) : base(serviceProvider.GetRequiredService>(), + serviceProvider.GetRequiredService(), + serverConfiguration, + serviceProvider.GetRequiredService(), + serviceProvider.GetRequiredService(), + serviceProvider.GetRequiredService()) { _translationLookup = lookup; _metaService = metaService; + _serviceProvider = serviceProvider; } - override public async Task OnClientConnected(EFClient clientFromLog) + public override async Task OnClientConnected(EFClient clientFromLog) { - Logger.WriteDebug($"Client slot #{clientFromLog.ClientNumber} now reserved"); + ServerLogger.LogDebug("Client slot #{clientNumber} now reserved", clientFromLog.ClientNumber); EFClient client = await Manager.GetClientService().GetUnique(clientFromLog.NetworkId); // first time client is connecting to server if (client == null) { - Logger.WriteDebug($"Client {clientFromLog} first time connecting"); + ServerLogger.LogDebug("Client {client} first time connecting", clientFromLog.ToString()); clientFromLog.CurrentServer = this; client = await Manager.GetClientService().Create(clientFromLog); } - /// this is only a temporary version until the IPAddress is transmitted + // this is only a temporary version until the IPAddress is transmitted client.CurrentAlias = new EFAlias() { Name = clientFromLog.Name, IPAddress = clientFromLog.IPAddress }; - Logger.WriteInfo($"Client {client} connected..."); - // Do the player specific stuff client.ClientNumber = clientFromLog.ClientNumber; client.Score = clientFromLog.Score; @@ -69,9 +79,7 @@ namespace IW4MAdmin client.State = ClientState.Connecting; Clients[client.ClientNumber] = client; -#if DEBUG == true - Logger.WriteDebug($"End PreConnect for {client}"); -#endif + ServerLogger.LogDebug("End PreConnect for {client}", client.ToString()); var e = new GameEvent() { Origin = client, @@ -83,11 +91,14 @@ namespace IW4MAdmin return client; } - override public async Task OnClientDisconnected(EFClient client) + public override async Task OnClientDisconnected(EFClient client) { if (!GetClientsAsList().Any(_client => _client.NetworkId == client.NetworkId)) { - Logger.WriteInfo($"{client} disconnecting, but they are not connected"); + using (LogContext.PushProperty("Server", ToString())) + { + ServerLogger.LogWarning("{client} disconnecting, but they are not connected", client.ToString()); + } return; } @@ -95,7 +106,7 @@ namespace IW4MAdmin if (client.ClientNumber >= 0) { #endif - Logger.WriteInfo($"Client {client} [{client.State.ToString().ToLower()}] disconnecting..."); + ServerLogger.LogDebug("Client {@client} disconnecting...", new { client=client.ToString(), client.State }); Clients[client.ClientNumber] = null; await client.OnDisconnect(); @@ -114,124 +125,111 @@ namespace IW4MAdmin public override async Task ExecuteEvent(GameEvent E) { - if (E == null) - { - Logger.WriteError("Received NULL event"); - return; - } - - if (E.IsBlocking) - { - await E.Origin?.Lock(); - } - - bool canExecuteCommand = true; - Exception lastException = null; - - try - { - if (!await ProcessEvent(E)) - { - return; - } - - Command C = null; - if (E.Type == GameEvent.EventType.Command) - { - try - { - C = await SharedLibraryCore.Commands.CommandProcessing.ValidateCommand(E, Manager.GetApplicationSettings().Configuration()); - } - - catch (CommandException e) - { - Logger.WriteInfo(e.Message); - E.FailReason = GameEvent.EventFailReason.Invalid; - } - - if (C != null) - { - E.Extra = C; - } - } - - try - { - var loginPlugin = Manager.Plugins.FirstOrDefault(_plugin => _plugin.Name == "Login"); - - if (loginPlugin != null) - { - await loginPlugin.OnEventAsync(E, this); - } - } - - catch (AuthorizationException e) - { - E.Origin.Tell($"{loc["COMMAND_NOTAUTHORIZED"]} - {e.Message}"); - canExecuteCommand = false; - } - - // hack: this prevents commands from getting executing that 'shouldn't' be - if (E.Type == GameEvent.EventType.Command && E.Extra is Command command && - (canExecuteCommand || E.Origin?.Level == Permission.Console)) - { - await command.ExecuteAsync(E); - } - - var pluginTasks = Manager.Plugins.Where(_plugin => _plugin.Name != "Login").Select(async _plugin => - { - try - { - // we don't want to run the events on parser plugins - if (_plugin is ScriptPlugin scriptPlugin && scriptPlugin.IsParser) - { - return; - } - - using (var tokenSource = new CancellationTokenSource()) - { - tokenSource.CancelAfter(Utilities.DefaultCommandTimeout); - await (_plugin.OnEventAsync(E, this)).WithWaitCancellation(tokenSource.Token); - } - } - catch (Exception Except) - { - Logger.WriteError($"{loc["SERVER_PLUGIN_ERROR"]} [{_plugin.Name}]"); - Logger.WriteDebug(Except.GetExceptionInfo()); - } - }).ToArray(); - - if (pluginTasks.Any()) - { - await Task.WhenAny(pluginTasks); - } - } - - catch (Exception e) - { - lastException = e; - - if (E.Origin != null && E.Type == GameEvent.EventType.Command) - { - E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); - } - } - - finally + using (LogContext.PushProperty("Server", ToString())) { if (E.IsBlocking) { - E.Origin?.Unlock(); + await E.Origin?.Lock(); } - if (lastException != null) + bool canExecuteCommand = true; + + try { - bool notifyDisconnects = !Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost; - if (notifyDisconnects || (!notifyDisconnects && lastException as NetworkException == null)) + if (!await ProcessEvent(E)) { - throw lastException; + return; + } + + Command C = null; + if (E.Type == GameEvent.EventType.Command) + { + try + { + C = await SharedLibraryCore.Commands.CommandProcessing.ValidateCommand(E, Manager.GetApplicationSettings().Configuration()); + } + + catch (CommandException e) + { + ServerLogger.LogWarning(e, "Error validating command from event {@event}", E); + E.FailReason = GameEvent.EventFailReason.Invalid; + } + + if (C != null) + { + E.Extra = C; + } + } + + try + { + var loginPlugin = Manager.Plugins.FirstOrDefault(_plugin => _plugin.Name == "Login"); + + if (loginPlugin != null) + { + await loginPlugin.OnEventAsync(E, this); + } + } + + catch (AuthorizationException e) + { + E.Origin.Tell($"{loc["COMMAND_NOTAUTHORIZED"]} - {e.Message}"); + canExecuteCommand = false; + } + + // hack: this prevents commands from getting executing that 'shouldn't' be + if (E.Type == GameEvent.EventType.Command && E.Extra is Command command && + (canExecuteCommand || E.Origin?.Level == Permission.Console)) + { + ServerLogger.LogInformation("Executing command {comamnd} for {client}", command.Name, E.Origin.ToString()); + await command.ExecuteAsync(E); + } + + var pluginTasks = Manager.Plugins + .Where(_plugin => _plugin.Name != "Login") + .Select(async plugin => await CreatePluginTask(plugin, E)); + + await Task.WhenAll(pluginTasks); + } + + catch (Exception e) + { + if (E.Origin != null && E.Type == GameEvent.EventType.Command) + { + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); } } + + finally + { + if (E.IsBlocking) + { + E.Origin?.Unlock(); + } + } + } + } + + private async Task CreatePluginTask(IPlugin plugin, GameEvent gameEvent) + { + // we don't want to run the events on parser plugins + if (plugin is ScriptPlugin scriptPlugin && scriptPlugin.IsParser) + { + return; + } + + using var tokenSource = new CancellationTokenSource(); + tokenSource.CancelAfter(Utilities.DefaultCommandTimeout); + + try + { + await (plugin.OnEventAsync(gameEvent, this)).WithWaitCancellation(tokenSource.Token); + } + catch (Exception ex) + { + Console.WriteLine(loc["SERVER_PLUGIN_ERROR"]); + ServerLogger.LogError(ex, "Could not execute {methodName} for plugin {plugin}", + nameof(plugin.OnEventAsync), plugin.Name); } } @@ -240,403 +238,418 @@ namespace IW4MAdmin /// /// /// - override protected async Task ProcessEvent(GameEvent E) + protected override async Task ProcessEvent(GameEvent E) { -#if DEBUG - Logger.WriteDebug($"processing event of type {E.Type}"); -#endif - - if (E.Type == GameEvent.EventType.ConnectionLost) + using (LogContext.PushProperty("Server", ToString())) + using (LogContext.PushProperty("EventType", E.Type)) { - var exception = E.Extra as Exception; - if (!Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost) + ServerLogger.LogDebug("processing event of type {type}", E.Type); + + if (E.Type == GameEvent.EventType.ConnectionLost) { - Logger.WriteError(exception.Message); - if (exception.Data["internal_exception"] != null) + var exception = E.Extra as Exception; + ServerLogger.LogError(exception, + "Connection lost with {server}", ToString()); + + if (!Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost) { - Logger.WriteDebug($"Internal Exception: {exception.Data["internal_exception"]}"); - } - } - Logger.WriteInfo("Connection lost to server, so we are throttling the poll rate"); - Throttled = true; - } - - if (E.Type == GameEvent.EventType.ConnectionRestored) - { - if (Throttled && !Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost) - { - Logger.WriteVerbose(loc["MANAGER_CONNECTION_REST"].FormatExt($"[{IP}:{Port}]")); - } - Logger.WriteInfo("Connection restored to server, so we are no longer throttling the poll rate"); - Throttled = false; - } - - if (E.Type == GameEvent.EventType.ChangePermission) - { - var newPermission = (Permission)E.Extra; - Logger.WriteInfo($"{E.Origin} is setting {E.Target} to permission level {newPermission}"); - await Manager.GetClientService().UpdateLevel(newPermission, E.Target, E.Origin); - } - - else if (E.Type == GameEvent.EventType.Connect) - { - if (E.Origin.State != ClientState.Connected) - { - E.Origin.State = ClientState.Connected; - E.Origin.LastConnection = DateTime.UtcNow; - E.Origin.Connections += 1; - - ChatHistory.Add(new ChatInfo() - { - Name = E.Origin.Name, - Message = "CONNECTED", - Time = DateTime.UtcNow - }); - - await E.Origin.OnJoin(E.Origin.IPAddress); - } - } - - else if (E.Type == GameEvent.EventType.PreConnect) - { - // we don't want to track bots in the database at all if ignore bots is requested - if (E.Origin.IsBot && Manager.GetApplicationSettings().Configuration().IgnoreBots) - { - return false; - } - - if (E.Origin.CurrentServer == null) - { - Logger.WriteWarning($"preconnecting client {E.Origin} did not have a current server specified"); - E.Origin.CurrentServer = this; - } - - var existingClient = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin)); - - // they're already connected - if (existingClient != null && existingClient.ClientNumber == E.Origin.ClientNumber && !E.Origin.IsBot) - { - Logger.WriteWarning($"detected preconnect for {E.Origin}, but they are already connected"); - return false; - } - - // this happens for some reason rarely where the client spots get out of order - // possible a connect/reconnect game event before we get to process it here - // it appears that new games decide to switch client slots between maps (even if the clients aren't disconnecting) - // bots can have duplicate names which causes conflicting GUIDs - else if (existingClient != null && existingClient.ClientNumber != E.Origin.ClientNumber && !E.Origin.IsBot) - { - Logger.WriteWarning($"client {E.Origin} is trying to connect in client slot {E.Origin.ClientNumber}, but they are already registed in client slot {existingClient.ClientNumber}, swapping..."); - // we need to remove them so the client spots can swap - await OnClientDisconnected(Clients[existingClient.ClientNumber]); - } - - if (Clients[E.Origin.ClientNumber] == null) - { -#if DEBUG == true - Logger.WriteDebug($"Begin PreConnect for {E.Origin}"); -#endif - // we can go ahead and put them in so that they don't get re added - Clients[E.Origin.ClientNumber] = E.Origin; - try - { - E.Origin = await OnClientConnected(E.Origin); - E.Target = E.Origin; + Console.WriteLine(loc["SERVER_ERROR_COMMUNICATION"].FormatExt($"{IP}:{Port}")); } - catch (Exception ex) - { - Logger.WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {E.Origin}"); - Logger.WriteDebug(ex.GetExceptionInfo()); + Throttled = true; + } - Clients[E.Origin.ClientNumber] = null; + if (E.Type == GameEvent.EventType.ConnectionRestored) + { + ServerLogger.LogInformation( + "Connection restored with {server}", ToString()); + + if (!Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost) + { + Console.WriteLine(loc["MANAGER_CONNECTION_REST"].FormatExt($"[{IP}:{Port}]")); + } + + Throttled = false; + } + + if (E.Type == GameEvent.EventType.ChangePermission) + { + var newPermission = (Permission) E.Extra; + ServerLogger.LogInformation("{origin} is setting {target} to permission level {newPermission}", + E.Origin.ToString(), E.Target.ToString(), newPermission); + await Manager.GetClientService().UpdateLevel(newPermission, E.Target, E.Origin); + } + + else if (E.Type == GameEvent.EventType.Connect) + { + if (E.Origin.State != ClientState.Connected) + { + E.Origin.State = ClientState.Connected; + E.Origin.LastConnection = DateTime.UtcNow; + E.Origin.Connections += 1; + + ChatHistory.Add(new ChatInfo() + { + Name = E.Origin.Name, + Message = "CONNECTED", + Time = DateTime.UtcNow + }); + + await E.Origin.OnJoin(E.Origin.IPAddress); + } + } + + else if (E.Type == GameEvent.EventType.PreConnect) + { + ServerLogger.LogInformation("Detected PreConnect for {client} from {source}", E.Origin.ToString(), E.Source); + // we don't want to track bots in the database at all if ignore bots is requested + if (E.Origin.IsBot && Manager.GetApplicationSettings().Configuration().IgnoreBots) + { return false; } - if (E.Origin.Level > Permission.Moderator) + if (E.Origin.CurrentServer == null) { - E.Origin.Tell(string.Format(loc["SERVER_REPORT_COUNT"], E.Owner.Reports.Count)); + ServerLogger.LogWarning("Preconnecting client {client} did not have a current server specified", + E.Origin.ToString()); + E.Origin.CurrentServer = this; } - } - // for some reason there's still a client in the spot - else - { - Logger.WriteWarning($"{E.Origin} is connecting but {Clients[E.Origin.ClientNumber]} is currently in that client slot"); - } - } + var existingClient = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin)); - else if (E.Type == GameEvent.EventType.Flag) - { - DateTime? expires = null; - - if (E.Extra is TimeSpan ts) - { - expires = DateTime.UtcNow + ts; - } - - // todo: maybe move this to a seperate function - var newPenalty = new EFPenalty() - { - Type = EFPenalty.PenaltyType.Flag, - Expires = expires, - Offender = E.Target, - Offense = E.Data, - Punisher = E.ImpersonationOrigin ?? E.Origin, - When = DateTime.UtcNow, - Link = E.Target.AliasLink - }; - - var addedPenalty = await Manager.GetPenaltyService().Create(newPenalty); - E.Target.SetLevel(Permission.Flagged, E.Origin); - } - - else if (E.Type == GameEvent.EventType.Unflag) - { - var unflagPenalty = new EFPenalty() - { - Type = EFPenalty.PenaltyType.Unflag, - Expires = DateTime.UtcNow, - Offender = E.Target, - Offense = E.Data, - Punisher = E.ImpersonationOrigin ?? E.Origin, - When = DateTime.UtcNow, - Link = E.Target.AliasLink - }; - - E.Target.SetLevel(Permission.User, E.Origin); - await Manager.GetPenaltyService().RemoveActivePenalties(E.Target.AliasLinkId); - await Manager.GetPenaltyService().Create(unflagPenalty); - } - - else if (E.Type == GameEvent.EventType.Report) - { - Reports.Add(new Report() - { - Origin = E.Origin, - Target = E.Target, - Reason = E.Data - }); - - var newReport = new EFPenalty() - { - Type = EFPenalty.PenaltyType.Report, - Expires = DateTime.UtcNow, - Offender = E.Target, - Offense = E.Message, - Punisher = E.ImpersonationOrigin ?? E.Origin, - Active = true, - When = DateTime.UtcNow, - Link = E.Target.AliasLink - }; - - await Manager.GetPenaltyService().Create(newReport); - - int reportNum = await Manager.GetClientService().GetClientReportCount(E.Target.ClientId); - bool isAutoFlagged = await Manager.GetClientService().IsAutoFlagged(E.Target.ClientId); - - if (!E.Target.IsPrivileged() && reportNum >= REPORT_FLAG_COUNT && !isAutoFlagged) - { - E.Target.Flag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTO_FLAG_REPORT"].FormatExt(reportNum), Utilities.IW4MAdminClient(E.Owner)); - } - } - - else if (E.Type == GameEvent.EventType.TempBan) - { - await TempBan(E.Data, (TimeSpan)E.Extra, E.Target, E.ImpersonationOrigin ?? E.Origin); ; - } - - else if (E.Type == GameEvent.EventType.Ban) - { - bool isEvade = E.Extra != null ? (bool)E.Extra : false; - await Ban(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin, isEvade); - } - - else if (E.Type == GameEvent.EventType.Unban) - { - await Unban(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); - } - - else if (E.Type == GameEvent.EventType.Kick) - { - await Kick(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); - } - - else if (E.Type == GameEvent.EventType.Warn) - { - await Warn(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); - } - - else if (E.Type == GameEvent.EventType.Disconnect) - { - ChatHistory.Add(new ChatInfo() - { - Name = E.Origin.Name, - Message = "DISCONNECTED", - Time = DateTime.UtcNow - }); - - await _metaService.AddPersistentMeta("LastMapPlayed", CurrentMap.Alias, E.Origin); - await _metaService.AddPersistentMeta("LastServerPlayed", E.Owner.Hostname, E.Origin); - } - - else if (E.Type == GameEvent.EventType.PreDisconnect) - { - bool isPotentialFalseQuit = E.GameTime.HasValue && E.GameTime.Value == lastGameTime; - - if (isPotentialFalseQuit) - { - Logger.WriteInfo($"Receive predisconnect event for {E.Origin}, but it occured at game time {E.GameTime.Value}, which is the same last map change, so we're ignoring"); - return false; - } - - // predisconnect comes from minimal rcon polled players and minimal log players - // so we need to disconnect the "full" version of the client - var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin)); - - if (client == null) - { - Logger.WriteWarning($"Client {E.Origin} detected as disconnecting, but could not find them in the player list"); - return false; - } - - else if (client.State != ClientState.Unknown) - { -#if DEBUG == true - Logger.WriteDebug($"Begin PreDisconnect for {client}"); -#endif - await OnClientDisconnected(client); -#if DEBUG == true - Logger.WriteDebug($"End PreDisconnect for {client}"); -#endif - return true; - } - - else - { - Logger.WriteWarning($"Expected disconnecting client {client} to be in state {ClientState.Connected.ToString()}, but is in state {client.State}"); - return false; - } - } - - else if (E.Type == GameEvent.EventType.Update) - { -#if DEBUG == true - Logger.WriteDebug($"Begin Update for {E.Origin}"); -#endif - await OnClientUpdate(E.Origin); - } - - if (E.Type == GameEvent.EventType.Say) - { - if (E.Data?.Length > 0) - { - string message = E.Data; - if (E.Data.IsQuickMessage()) + // they're already connected + if (existingClient != null && existingClient.ClientNumber == E.Origin.ClientNumber && + !E.Origin.IsBot) { + ServerLogger.LogInformation("{client} is already connected, so we are ignoring their PreConnect", + E.Origin.ToString()); + return false; + } + + // this happens for some reason rarely where the client spots get out of order + // possible a connect/reconnect game event before we get to process it here + // it appears that new games decide to switch client slots between maps (even if the clients aren't disconnecting) + // bots can have duplicate names which causes conflicting GUIDs + else if (existingClient != null && existingClient.ClientNumber != E.Origin.ClientNumber && + !E.Origin.IsBot) + { + ServerLogger.LogWarning( + "client {client} is trying to connect in client slot {newClientSlot}, but they are already registered in client slot {oldClientSlot}, swapping...", + E.Origin.ToString(), E.Origin.ClientNumber, existingClient.ClientNumber); + // we need to remove them so the client spots can swap + await OnClientDisconnected(Clients[existingClient.ClientNumber]); + } + + if (Clients[E.Origin.ClientNumber] == null) + { + ServerLogger.LogDebug("Begin PreConnect for {origin}", E.Origin.ToString()); + // we can go ahead and put them in so that they don't get re added + Clients[E.Origin.ClientNumber] = E.Origin; try { - message = Manager.GetApplicationSettings().Configuration() - .QuickMessages - .First(_qm => _qm.Game == GameName) - .Messages[E.Data.Substring(1)]; + E.Origin = await OnClientConnected(E.Origin); + E.Target = E.Origin; } - catch + + catch (Exception ex) { - message = E.Data.Substring(1); + Console.WriteLine($"{loc["SERVER_ERROR_ADDPLAYER"]} {E.Origin}"); + ServerLogger.LogError(ex, "Could not add player {player}", E.Origin.ToString()); + Clients[E.Origin.ClientNumber] = null; + return false; + } + + if (E.Origin.Level > Permission.Moderator) + { + E.Origin.Tell(string.Format(loc["SERVER_REPORT_COUNT"], E.Owner.Reports.Count)); } } + // for some reason there's still a client in the spot + else + { + ServerLogger.LogWarning( + "{origin} is connecting but {existingClient} is currently in that client slot", + E.Origin.ToString(), Clients[E.Origin.ClientNumber].ToString()); + } + } + + else if (E.Type == GameEvent.EventType.Flag) + { + DateTime? expires = null; + + if (E.Extra is TimeSpan ts) + { + expires = DateTime.UtcNow + ts; + } + + // todo: maybe move this to a seperate function + var newPenalty = new EFPenalty() + { + Type = EFPenalty.PenaltyType.Flag, + Expires = expires, + Offender = E.Target, + Offense = E.Data, + Punisher = E.ImpersonationOrigin ?? E.Origin, + When = DateTime.UtcNow, + Link = E.Target.AliasLink + }; + + var addedPenalty = await Manager.GetPenaltyService().Create(newPenalty); + E.Target.SetLevel(Permission.Flagged, E.Origin); + } + + else if (E.Type == GameEvent.EventType.Unflag) + { + var unflagPenalty = new EFPenalty() + { + Type = EFPenalty.PenaltyType.Unflag, + Expires = DateTime.UtcNow, + Offender = E.Target, + Offense = E.Data, + Punisher = E.ImpersonationOrigin ?? E.Origin, + When = DateTime.UtcNow, + Link = E.Target.AliasLink + }; + + E.Target.SetLevel(Permission.User, E.Origin); + await Manager.GetPenaltyService().RemoveActivePenalties(E.Target.AliasLinkId); + await Manager.GetPenaltyService().Create(unflagPenalty); + } + + else if (E.Type == GameEvent.EventType.Report) + { + Reports.Add(new Report() + { + Origin = E.Origin, + Target = E.Target, + Reason = E.Data + }); + + var newReport = new EFPenalty() + { + Type = EFPenalty.PenaltyType.Report, + Expires = DateTime.UtcNow, + Offender = E.Target, + Offense = E.Message, + Punisher = E.ImpersonationOrigin ?? E.Origin, + Active = true, + When = DateTime.UtcNow, + Link = E.Target.AliasLink + }; + + await Manager.GetPenaltyService().Create(newReport); + + int reportNum = await Manager.GetClientService().GetClientReportCount(E.Target.ClientId); + bool isAutoFlagged = await Manager.GetClientService().IsAutoFlagged(E.Target.ClientId); + + if (!E.Target.IsPrivileged() && reportNum >= REPORT_FLAG_COUNT && !isAutoFlagged) + { + E.Target.Flag( + Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTO_FLAG_REPORT"] + .FormatExt(reportNum), Utilities.IW4MAdminClient(E.Owner)); + } + } + + else if (E.Type == GameEvent.EventType.TempBan) + { + await TempBan(E.Data, (TimeSpan) E.Extra, E.Target, E.ImpersonationOrigin ?? E.Origin); + ; + } + + else if (E.Type == GameEvent.EventType.Ban) + { + bool isEvade = E.Extra != null ? (bool) E.Extra : false; + await Ban(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin, isEvade); + } + + else if (E.Type == GameEvent.EventType.Unban) + { + await Unban(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); + } + + else if (E.Type == GameEvent.EventType.Kick) + { + await Kick(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); + } + + else if (E.Type == GameEvent.EventType.Warn) + { + await Warn(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); + } + + else if (E.Type == GameEvent.EventType.Disconnect) + { ChatHistory.Add(new ChatInfo() { Name = E.Origin.Name, - Message = message, - Time = DateTime.UtcNow, - IsHidden = !string.IsNullOrEmpty(GamePassword) + Message = "DISCONNECTED", + Time = DateTime.UtcNow }); + + await _metaService.AddPersistentMeta("LastMapPlayed", CurrentMap.Alias, E.Origin); + await _metaService.AddPersistentMeta("LastServerPlayed", E.Owner.Hostname, E.Origin); } - } - if (E.Type == GameEvent.EventType.MapChange) - { - Logger.WriteInfo($"New map loaded - {ClientNum} active players"); - - // iw4 doesn't log the game info - if (E.Extra == null) + else if (E.Type == GameEvent.EventType.PreDisconnect) { - var dict = await this.GetInfoAsync(new TimeSpan(0, 0, 20)); + ServerLogger.LogInformation("Detected PreDisconnect for {client} from {source}", + E.Origin.ToString(), E.Source); + bool isPotentialFalseQuit = E.GameTime.HasValue && E.GameTime.Value == lastGameTime; - if (dict == null) + if (isPotentialFalseQuit) { - Logger.WriteWarning("Map change event response doesn't have any data"); + ServerLogger.LogDebug( + "Received PreDisconnect event for {origin}, but it occured at game time {gameTime}, which is the same last map change, so we're ignoring", + E.Origin.ToString(), E.GameTime); + return false; + } + + // predisconnect comes from minimal rcon polled players and minimal log players + // so we need to disconnect the "full" version of the client + var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin)); + + if (client == null) + { + // this can happen when the status picks up the connect before the log does + ServerLogger.LogInformation( + "Ignoring PreDisconnect for {origin} because they are no longer on the client list", + E.Origin.ToString()); + return false; + } + + else if (client.State != ClientState.Unknown) + { + await OnClientDisconnected(client); + return true; } else { - Gametype = dict["gametype"]; - Hostname = dict["hostname"]; - - string mapname = dict["mapname"] ?? CurrentMap.Name; - UpdateMap(mapname); + ServerLogger.LogWarning( + "Expected disconnecting client {client} to be in state {state}, but is in state {clientState}", + client.ToString(), ClientState.Connected.ToString(), client.State); + return false; } } - else + else if (E.Type == GameEvent.EventType.Update) { - var dict = (Dictionary)E.Extra; - Gametype = dict["g_gametype"]; - Hostname = dict["sv_hostname"]; - MaxClients = int.Parse(dict["sv_maxclients"]); - - string mapname = dict["mapname"]; - UpdateMap(mapname); + ServerLogger.LogDebug("Begin Update for {origin}", E.Origin.ToString()); + await OnClientUpdate(E.Origin); } - if (E.GameTime.HasValue) + if (E.Type == GameEvent.EventType.Say) { - lastGameTime = E.GameTime.Value; + if (E.Data?.Length > 0) + { + string message = E.Data; + if (E.Data.IsQuickMessage()) + { + try + { + message = Manager.GetApplicationSettings().Configuration() + .QuickMessages + .First(_qm => _qm.Game == GameName) + .Messages[E.Data.Substring(1)]; + } + catch + { + message = E.Data.Substring(1); + } + } + + ChatHistory.Add(new ChatInfo() + { + Name = E.Origin.Name, + Message = message, + Time = DateTime.UtcNow, + IsHidden = !string.IsNullOrEmpty(GamePassword) + }); + } } - } - if (E.Type == GameEvent.EventType.MapEnd) - { - Logger.WriteInfo("Game ending..."); - - if (E.GameTime.HasValue) + if (E.Type == GameEvent.EventType.MapChange) { - lastGameTime = E.GameTime.Value; + ServerLogger.LogInformation("New map loaded - {clientCount} active players", ClientNum); + + // iw4 doesn't log the game info + if (E.Extra == null) + { + var dict = await this.GetInfoAsync(new TimeSpan(0, 0, 20)); + + if (dict == null) + { + ServerLogger.LogWarning("Map change event response doesn't have any data"); + } + + else + { + Gametype = dict["gametype"]; + Hostname = dict["hostname"]; + + string mapname = dict["mapname"] ?? CurrentMap.Name; + UpdateMap(mapname); + } + } + + else + { + var dict = (Dictionary) E.Extra; + Gametype = dict["g_gametype"]; + Hostname = dict["sv_hostname"]; + MaxClients = int.Parse(dict["sv_maxclients"]); + + string mapname = dict["mapname"]; + UpdateMap(mapname); + } + + if (E.GameTime.HasValue) + { + lastGameTime = E.GameTime.Value; + } } - } - if (E.Type == GameEvent.EventType.Tell) - { - await Tell(E.Message, E.Target); - } - - if (E.Type == GameEvent.EventType.Broadcast) - { - if (!Utilities.IsDevelopment && E.Data != null) // hides broadcast when in development mode + if (E.Type == GameEvent.EventType.MapEnd) { - await E.Owner.ExecuteCommandAsync(E.Data); - } - } + ServerLogger.LogInformation("Game ending..."); - lock (ChatHistory) - { - while (ChatHistory.Count > Math.Ceiling(ClientNum / 2.0)) + if (E.GameTime.HasValue) + { + lastGameTime = E.GameTime.Value; + } + } + + if (E.Type == GameEvent.EventType.Tell) { - ChatHistory.RemoveAt(0); + await Tell(E.Message, E.Target); } - } - // the last client hasn't fully disconnected yet - // so there will still be at least 1 client left - if (ClientNum < 2) - { - ChatHistory.Clear(); - } + if (E.Type == GameEvent.EventType.Broadcast) + { + if (!Utilities.IsDevelopment && E.Data != null) // hides broadcast when in development mode + { + await E.Owner.ExecuteCommandAsync(E.Data); + } + } - return true; + lock (ChatHistory) + { + while (ChatHistory.Count > Math.Ceiling(ClientNum / 2.0)) + { + ChatHistory.RemoveAt(0); + } + } + + // the last client hasn't fully disconnected yet + // so there will still be at least 1 client left + if (ClientNum < 2) + { + ChatHistory.Clear(); + } + + return true; + } } private async Task OnClientUpdate(EFClient origin) @@ -645,7 +658,7 @@ namespace IW4MAdmin if (client == null) { - Logger.WriteWarning($"{origin} expected to exist in client list for update, but they do not"); + ServerLogger.LogWarning("{origin} expected to exist in client list for update, but they do not", origin.ToString()); return; } @@ -664,15 +677,17 @@ namespace IW4MAdmin catch (Exception e) { - Logger.WriteWarning($"Could not execute on join for {origin}"); - Logger.WriteDebug(e.GetExceptionInfo()); + using(LogContext.PushProperty("Server", ToString())) + { + ServerLogger.LogError(e, "Could not execute on join for {origin}", origin.ToString()); + } } } else if ((client.IPAddress != null && client.State == ClientState.Disconnecting) || client.Level == Permission.Banned) { - Logger.WriteWarning($"{client} state is Unknown (probably kicked), but they are still connected. trying to kick again..."); + ServerLogger.LogWarning("{client} state is Unknown (probably kicked), but they are still connected. trying to kick again...", origin.ToString()); await client.CanConnect(client.IPAddress); } } @@ -686,9 +701,6 @@ namespace IW4MAdmin /// async Task[]> PollPlayersAsync() { -#if DEBUG - var now = DateTime.Now; -#endif var currentClients = GetClientsAsList(); var statusResponse = (await this.GetStatusAsync()); var polledClients = statusResponse.Item1.AsEnumerable(); @@ -697,9 +709,6 @@ namespace IW4MAdmin { polledClients = polledClients.Where(c => !c.IsBot); } -#if DEBUG - Logger.WriteInfo($"Polling players took {(DateTime.Now - now).TotalMilliseconds}ms"); -#endif var disconnectingClients = currentClients.Except(polledClients); var connectingClients = polledClients.Except(currentClients); var updatedClients = polledClients.Except(connectingClients).Except(disconnectingClients); @@ -763,9 +772,8 @@ namespace IW4MAdmin DateTime playerCountStart = DateTime.Now; DateTime lastCount = DateTime.Now; - override public async Task ProcessUpdatesAsync(CancellationToken cts) + public override async Task ProcessUpdatesAsync(CancellationToken cts) { - bool notifyDisconnects = !Manager.GetApplicationSettings().Configuration().IgnoreServerConnectionLost; try { if (cts.IsCancellationRequested) @@ -776,12 +784,10 @@ namespace IW4MAdmin try { -#if DEBUG - if (Manager.GetApplicationSettings().Configuration().RConPollRate == int.MaxValue) + if (Manager.GetApplicationSettings().Configuration().RConPollRate == int.MaxValue && Utilities.IsDevelopment) { return true; } -#endif var polledClients = await PollPlayersAsync(); @@ -838,7 +844,7 @@ namespace IW4MAdmin Manager.AddEvent(e); } - if (ConnectionErrors > 0) + if (Throttled) { var _event = new GameEvent() { @@ -851,14 +857,12 @@ namespace IW4MAdmin Manager.AddEvent(_event); } - ConnectionErrors = 0; LastPoll = DateTime.Now; } catch (NetworkException e) { - ConnectionErrors++; - if (ConnectionErrors == 3) + if (!Throttled) { var _event = new GameEvent() { @@ -872,6 +876,7 @@ namespace IW4MAdmin Manager.AddEvent(_event); } + return true; } @@ -916,24 +921,22 @@ namespace IW4MAdmin } // this one is ok - catch (ServerException e) + catch (Exception e) when(e is ServerException || e is RConException) { - if (e is NetworkException && !Throttled && notifyDisconnects) + using(LogContext.PushProperty("Server", ToString())) { - Logger.WriteError(loc["SERVER_ERROR_COMMUNICATION"].FormatExt($"{IP}:{Port}")); - Logger.WriteDebug(e.GetExceptionInfo()); - } - else - { - Logger.WriteError(e.Message); + ServerLogger.LogWarning(e, "Undesirable exception occured during processing updates"); } return false; } - catch (Exception E) + catch (Exception e) { - Logger.WriteError(loc["SERVER_ERROR_EXCEPTION"].FormatExt($"[{IP}:{Port}]")); - Logger.WriteDebug(E.GetExceptionInfo()); + using(LogContext.PushProperty("Server", ToString())) + { + ServerLogger.LogError(e, "Unexpected exception occured during processing updates"); + } + Console.WriteLine(loc["SERVER_ERROR_EXCEPTION"].FormatExt($"[{IP}:{Port}]")); return false; } } @@ -1077,16 +1080,21 @@ namespace IW4MAdmin IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) }; LogPath = GenerateLogPath(logInfo); + ServerLogger.LogInformation("Game log information {@logInfo}", logInfo); + if (!File.Exists(LogPath) && ServerConfig.GameLogServerUrl == null) { - Logger.WriteError(loc["SERVER_ERROR_DNE"].FormatExt(LogPath)); + Console.WriteLine(loc["SERVER_ERROR_DNE"].FormatExt(LogPath)); + ServerLogger.LogCritical("Game log path does not exist {logPath}", LogPath); throw new ServerException(loc["SERVER_ERROR_DNE"].FormatExt(LogPath)); } } - LogEvent = new GameLogEventDetection(this, GenerateUriForLog(LogPath, ServerConfig.GameLogServerUrl?.AbsoluteUri), gameLogReaderFactory); - Logger.WriteInfo($"Log file is {LogPath}"); + ServerLogger.LogInformation("Generated game log path is {logPath}", LogPath); + LogEvent = new GameLogEventDetection( _serviceProvider.GetRequiredService>(), + this, + GenerateUriForLog(LogPath, ServerConfig.GameLogServerUrl?.AbsoluteUri), gameLogReaderFactory); _ = Task.Run(() => LogEvent.PollForChanges()); @@ -1165,8 +1173,8 @@ namespace IW4MAdmin Link = targetClient.AliasLink }; - Logger.WriteDebug($"Creating warn penalty for {targetClient}"); - await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), Manager.GetLogger(0)); + ServerLogger.LogDebug("Creating warn penalty for {targetClient}", targetClient.ToString()); + await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); if (targetClient.IsIngame) { @@ -1176,6 +1184,7 @@ namespace IW4MAdmin return; } + // todo: move to translation sheet string message = $"^1{loc["SERVER_WARNING"]} ^7[^3{targetClient.Warnings}^7]: ^3{targetClient.Name}^7, {reason}"; targetClient.CurrentServer.Broadcast(message); } @@ -1198,8 +1207,8 @@ namespace IW4MAdmin Link = targetClient.AliasLink }; - Logger.WriteDebug($"Creating kick penalty for {targetClient}"); - await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), Manager.GetLogger(0)); + ServerLogger.LogDebug("Creating kick penalty for {targetClient}", targetClient.ToString()); + await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); if (targetClient.IsIngame) { @@ -1212,6 +1221,7 @@ namespace IW4MAdmin Manager.AddEvent(e); + // todo: move to translation sheet string formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"{loc["SERVER_KICK_TEXT"]} - ^5{Reason}^7"); await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); } @@ -1235,13 +1245,14 @@ namespace IW4MAdmin Link = targetClient.AliasLink }; - Logger.WriteDebug($"Creating tempban penalty for {targetClient}"); - await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), Manager.GetLogger(0)); + ServerLogger.LogDebug("Creating tempban penalty for {targetClient}", targetClient.ToString()); + await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); if (targetClient.IsIngame) { + // todo: move to translation sheet string formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"^7{loc["SERVER_TB_TEXT"]}- ^5{Reason}"); - Logger.WriteDebug($"Executing tempban kick command for {targetClient}"); + ServerLogger.LogDebug("Executing tempban kick command for {targetClient}", targetClient.ToString()); await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); } } @@ -1265,13 +1276,14 @@ namespace IW4MAdmin IsEvadedOffense = isEvade }; - Logger.WriteDebug($"Creating ban penalty for {targetClient}"); + ServerLogger.LogDebug("Creating ban penalty for {targetClient}", targetClient.ToString()); targetClient.SetLevel(Permission.Banned, originClient); - await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), Manager.GetLogger(0)); + await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); if (targetClient.IsIngame) { - Logger.WriteDebug($"Attempting to kicking newly banned client {targetClient}"); + ServerLogger.LogDebug("Attempting to kicking newly banned client {targetClient}", targetClient.ToString()); + // todo: move to translation sheet string formattedString = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"{loc["SERVER_BAN_TEXT"]} - ^5{reason} ^7{loc["SERVER_BAN_APPEAL"].FormatExt(Website)}^7"); await targetClient.CurrentServer.ExecuteCommandAsync(formattedString); } @@ -1291,6 +1303,7 @@ namespace IW4MAdmin Link = Target.AliasLink }; + ServerLogger.LogDebug("Creating unban penalty for {targetClient}", Target.ToString()); Target.SetLevel(Permission.User, Origin); await Manager.GetPenaltyService().RemoveActivePenalties(Target.AliasLink.AliasLinkId); await Manager.GetPenaltyService().Create(unbanPenalty); diff --git a/Application/Localization/Configure.cs b/Application/Localization/Configure.cs index 2a275c72..8d759fd5 100644 --- a/Application/Localization/Configure.cs +++ b/Application/Localization/Configure.cs @@ -6,15 +6,22 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; +using Microsoft.Extensions.Logging; +using SharedLibraryCore.Configuration; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Localization { - public class Configure + public static class Configure { - public static ITranslationLookup Initialize(bool useLocalTranslation, IMasterApi apiInstance, string customLocale = null) + public static ITranslationLookup Initialize(ILogger logger, IMasterApi apiInstance, ApplicationConfiguration applicationConfiguration) { - string currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale; - string[] localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json"); + var useLocalTranslation = applicationConfiguration?.UseLocalTranslations ?? true; + var customLocale = applicationConfiguration?.EnableCustomLocale ?? false + ? (applicationConfiguration.CustomLocale ?? "en-US") + : "en-US"; + var currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale; + var localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json"); if (!useLocalTranslation) { @@ -25,9 +32,10 @@ namespace IW4MAdmin.Application.Localization return localization.LocalizationIndex; } - catch (Exception) + catch (Exception ex) { // the online localization failed so will default to local files + logger.LogWarning(ex, "Could not download latest translations"); } } @@ -60,13 +68,11 @@ namespace IW4MAdmin.Application.Localization { if (!localizationDict.TryAdd(item.Key, item.Value)) { - Program.ServerManager.GetLogger(0).WriteError($"Could not add locale string {item.Key} to localization"); + logger.LogError("Could not add locale string {key} to localization", item.Key); } } } - string localizationFile = $"{Path.Join(Utilities.OperatingDirectory, "Localization")}{Path.DirectorySeparatorChar}IW4MAdmin.{currentLocale}-{currentLocale.ToUpper()}.json"; - Utilities.CurrentLocalization = new SharedLibraryCore.Localization.Layout(localizationDict) { LocalizationName = currentLocale, diff --git a/Application/Main.cs b/Application/Main.cs index 86732d3c..4d922277 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -1,7 +1,6 @@ using IW4MAdmin.Application.API.Master; using IW4MAdmin.Application.EventParsers; using IW4MAdmin.Application.Factories; -using IW4MAdmin.Application.Helpers; using IW4MAdmin.Application.Meta; using IW4MAdmin.Application.Migration; using IW4MAdmin.Application.Misc; @@ -24,6 +23,10 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using IW4MAdmin.Application.Extensions; +using IW4MAdmin.Application.Localization; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application { @@ -76,29 +79,32 @@ namespace IW4MAdmin.Application { restart: ITranslationLookup translationLookup = null; + var logger = BuildDefaultLogger(new ApplicationConfiguration()); + Utilities.DefaultLogger = logger; + logger.LogInformation("Begin IW4MAdmin startup. Version is {version} {@args}", Version, args); + try { // do any needed housekeeping file/folder migrations ConfigurationMigration.MoveConfigFolder10518(null); ConfigurationMigration.CheckDirectories(); - + logger.LogDebug("Configuring services..."); var services = ConfigureServices(args); serviceProvider = services.BuildServiceProvider(); var versionChecker = serviceProvider.GetRequiredService(); ServerManager = (ApplicationManager)serviceProvider.GetRequiredService(); translationLookup = serviceProvider.GetRequiredService(); - ServerManager.Logger.WriteInfo(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_VERSION"].FormatExt(Version)); - await versionChecker.CheckVersion(); await ServerManager.Init(); } catch (Exception e) { - string failMessage = translationLookup == null ? "Failed to initalize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; + string failMessage = translationLookup == null ? "Failed to initialize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; string exitMessage = translationLookup == null ? "Press enter to exit..." : translationLookup["MANAGER_EXIT"]; + logger.LogCritical(e, "Failed to initialize IW4MAdmin"); Console.WriteLine(failMessage); while (e.InnerException != null) @@ -131,13 +137,14 @@ namespace IW4MAdmin.Application try { - ApplicationTask = RunApplicationTasksAsync(); + ApplicationTask = RunApplicationTasksAsync(logger); await ApplicationTask; } catch (Exception e) { - string failMessage = translationLookup == null ? "Failed to initalize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; + logger.LogCritical(e, "Failed to launch IW4MAdmin"); + string failMessage = translationLookup == null ? "Failed to launch IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; Console.WriteLine($"{failMessage}: {e.GetExceptionInfo()}"); } @@ -153,7 +160,7 @@ namespace IW4MAdmin.Application /// runs the core application tasks /// /// - private static async Task RunApplicationTasksAsync() + private static async Task RunApplicationTasksAsync(ILogger logger) { var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront ? WebfrontCore.Program.Init(ServerManager, serviceProvider, ServerManager.CancellationToken) : @@ -161,7 +168,7 @@ namespace IW4MAdmin.Application // we want to run this one on a manual thread instead of letting the thread pool handle it, // because we can't exit early from waiting on console input, and it prevents us from restarting - var inputThread = new Thread(async () => await ReadConsoleInput()); + var inputThread = new Thread(async () => await ReadConsoleInput(logger)); inputThread.Start(); var tasks = new[] @@ -171,9 +178,11 @@ namespace IW4MAdmin.Application serviceProvider.GetRequiredService().RunUploadStatus(ServerManager.CancellationToken) }; + logger.LogDebug("Starting webfront and input tasks"); await Task.WhenAll(tasks); - ServerManager.Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); + logger.LogInformation("Shutdown completed successfully"); + Console.Write(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); } @@ -181,11 +190,11 @@ namespace IW4MAdmin.Application /// reads input from the console and executes entered commands on the default server /// /// - private static async Task ReadConsoleInput() + private static async Task ReadConsoleInput(ILogger logger) { if (Console.IsInputRedirected) { - ServerManager.Logger.WriteInfo("Disabling console input as it has been redirected"); + logger.LogInformation("Disabling console input as it has been redirected"); return; } @@ -221,71 +230,29 @@ namespace IW4MAdmin.Application { } } - /// - /// Configures the dependency injection services - /// - private static IServiceCollection ConfigureServices(string[] args) + private static IServiceCollection HandlePluginRegistration(ApplicationConfiguration appConfig, + IServiceCollection serviceCollection, + IMasterApi masterApi) { - var appConfigHandler = new BaseConfigurationHandler("IW4MAdminSettings"); - var appConfig = appConfigHandler.Configuration(); - var defaultLogger = new Logger("IW4MAdmin-Manager"); - - var masterUri = Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; - var apiClient = RestClient.For(masterUri); - var pluginImporter = new PluginImporter(defaultLogger, appConfig, apiClient, new RemoteAssemblyHandler(defaultLogger, appConfig)); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton(_serviceProvider => serviceCollection) - .AddSingleton(appConfigHandler as IConfigurationHandler) - .AddSingleton(new BaseConfigurationHandler("CommandConfiguration") as IConfigurationHandler) - .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService>().Configuration() ?? new ApplicationConfiguration()) - .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService>().Configuration() ?? new CommandConfiguration()) - .AddSingleton(_serviceProvider => defaultLogger) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton, ClientService>() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton, ReceivedPenaltyResourceQueryHelper>() - .AddSingleton, AdministeredPenaltyResourceQueryHelper>() - .AddSingleton, UpdatedAliasResourceQueryHelper>() - .AddSingleton, ChatResourceQueryHelper>() - .AddTransient() + var defaultLogger = BuildDefaultLogger(appConfig); + var pluginServiceProvider = new ServiceCollection() + .AddBaseLogger(appConfig) + .AddSingleton(appConfig) + .AddSingleton(masterApi) .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(apiClient) - .AddSingleton(_serviceProvider => - { - var config = _serviceProvider.GetRequiredService>().Configuration(); - return Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false, - apiInstance: _serviceProvider.GetRequiredService(), - customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US"); - }); - - if (args.Contains("serialevents")) - { - serviceCollection.AddSingleton(); - } - else - { - serviceCollection.AddSingleton(); - } + .AddSingleton() + .BuildServiceProvider(); + var pluginImporter = pluginServiceProvider.GetRequiredService(); + + // we need to register the rest client with regular collection + serviceCollection.AddSingleton(masterApi); + // register the native commands foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes() .Where(_command => _command.BaseType == typeof(Command))) { - defaultLogger.WriteInfo($"Registered native command type {commandType.Name}"); + defaultLogger.LogDebug("Registered native command type {name}", commandType.Name); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } @@ -293,14 +260,14 @@ namespace IW4MAdmin.Application var pluginImplementations = pluginImporter.DiscoverAssemblyPluginImplementations(); foreach (var pluginType in pluginImplementations.Item1) { - defaultLogger.WriteInfo($"Registered plugin type {pluginType.FullName}"); + defaultLogger.LogDebug("Registered plugin type {name}", pluginType.FullName); serviceCollection.AddSingleton(typeof(IPlugin), pluginType); } // register the plugin commands foreach (var commandType in pluginImplementations.Item2) { - defaultLogger.WriteInfo($"Registered plugin command type {commandType.FullName}"); + defaultLogger.LogDebug("Registered plugin command type {name}", commandType.FullName); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } @@ -324,5 +291,86 @@ namespace IW4MAdmin.Application return serviceCollection; } + + + /// + /// Configures the dependency injection services + /// + private static IServiceCollection ConfigureServices(string[] args) + { + // setup the static resources (config/master api/translations) + var serviceCollection = new ServiceCollection(); + var appConfigHandler = new BaseConfigurationHandler("IW4MAdminSettings"); + var appConfig = appConfigHandler.Configuration(); + var masterUri = Utilities.IsDevelopment + ? new Uri("http://127.0.0.1:8080") + : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; + var masterRestClient = RestClient.For(masterUri); + var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig); + + if (appConfig == null) + { + appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate(); + appConfigHandler.Set(appConfig); + appConfigHandler.Save(); + } + + // build the dependency list + HandlePluginRegistration(appConfig, serviceCollection, masterRestClient); + + serviceCollection + .AddBaseLogger(appConfig) + .AddSingleton(_serviceProvider => serviceCollection) + .AddSingleton((IConfigurationHandler) appConfigHandler) + .AddSingleton(new BaseConfigurationHandler("CommandConfiguration") as IConfigurationHandler) + .AddSingleton(appConfig) + .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService>().Configuration() ?? new CommandConfiguration()) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton, ClientService>() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton, ReceivedPenaltyResourceQueryHelper>() + .AddSingleton, AdministeredPenaltyResourceQueryHelper>() + .AddSingleton, UpdatedAliasResourceQueryHelper>() + .AddSingleton, ChatResourceQueryHelper>() + .AddTransient() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(translationLookup); + + if (args.Contains("serialevents")) + { + serviceCollection.AddSingleton(); + } + else + { + serviceCollection.AddSingleton(); + } + + return serviceCollection; + } + + private static ILogger BuildDefaultLogger(ApplicationConfiguration appConfig) + { + var collection = new ServiceCollection() + .AddBaseLogger(appConfig) + .BuildServiceProvider(); + + return collection.GetRequiredService>(); + } } } diff --git a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs index 1276a4a6..76d9fd76 100644 --- a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs +++ b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs @@ -1,11 +1,13 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using SharedLibraryCore.QueryHelper; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Meta { @@ -18,7 +20,7 @@ namespace IW4MAdmin.Application.Meta private readonly ILogger _logger; private readonly IDatabaseContextFactory _contextFactory; - public AdministeredPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) + public AdministeredPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) { _contextFactory = contextFactory; _logger = logger; diff --git a/Application/Meta/MetaRegistration.cs b/Application/Meta/MetaRegistration.cs index 479f87bb..7b6516e5 100644 --- a/Application/Meta/MetaRegistration.cs +++ b/Application/Meta/MetaRegistration.cs @@ -6,6 +6,8 @@ using SharedLibraryCore.QueryHelper; using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Meta { @@ -19,7 +21,7 @@ namespace IW4MAdmin.Application.Meta private readonly IResourceQueryHelper _administeredPenaltyHelper; private readonly IResourceQueryHelper _updatedAliasHelper; - public MetaRegistration(ILogger logger, IMetaService metaService, ITranslationLookup transLookup, IEntityService clientEntityService, + public MetaRegistration(ILogger logger, IMetaService metaService, ITranslationLookup transLookup, IEntityService clientEntityService, IResourceQueryHelper receivedPenaltyHelper, IResourceQueryHelper administeredPenaltyHelper, IResourceQueryHelper updatedAliasHelper) @@ -82,7 +84,7 @@ namespace IW4MAdmin.Application.Meta if (client == null) { - _logger.WriteWarning($"No client found with id {request.ClientId} when generating profile meta"); + _logger.LogWarning("No client found with id {clientId} when generating profile meta", request.ClientId); return metaList; } diff --git a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs index 82ed8f9b..de8b38bf 100644 --- a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs +++ b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs @@ -2,12 +2,14 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using SharedLibraryCore.QueryHelper; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Meta { @@ -20,7 +22,7 @@ namespace IW4MAdmin.Application.Meta private readonly ILogger _logger; private readonly IDatabaseContextFactory _contextFactory; - public ReceivedPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) + public ReceivedPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) { _contextFactory = contextFactory; _logger = logger; diff --git a/Application/Meta/UpdatedAliasResourceQueryHelper.cs b/Application/Meta/UpdatedAliasResourceQueryHelper.cs index d5ad9989..0adca9f1 100644 --- a/Application/Meta/UpdatedAliasResourceQueryHelper.cs +++ b/Application/Meta/UpdatedAliasResourceQueryHelper.cs @@ -6,6 +6,8 @@ using SharedLibraryCore.Interfaces; using SharedLibraryCore.QueryHelper; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Meta { @@ -18,7 +20,7 @@ namespace IW4MAdmin.Application.Meta private readonly ILogger _logger; private readonly IDatabaseContextFactory _contextFactory; - public UpdatedAliasResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) + public UpdatedAliasResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) { _logger = logger; _contextFactory = contextFactory; diff --git a/Application/Migration/ConfigurationMigration.cs b/Application/Migration/ConfigurationMigration.cs index d7a421b4..814344b0 100644 --- a/Application/Migration/ConfigurationMigration.cs +++ b/Application/Migration/ConfigurationMigration.cs @@ -1,11 +1,8 @@ using SharedLibraryCore; -using SharedLibraryCore.Interfaces; using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Text.RegularExpressions; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Migration { @@ -56,7 +53,6 @@ namespace IW4MAdmin.Application.Migration if (!Directory.Exists(configDirectory)) { - log?.WriteDebug($"Creating directory for configs {configDirectory}"); Directory.CreateDirectory(configDirectory); } @@ -66,7 +62,6 @@ namespace IW4MAdmin.Application.Migration foreach (var configFile in configurationFiles) { - log?.WriteDebug($"Moving config file {configFile}"); string destinationPath = Path.Join("Configuration", configFile); if (!File.Exists(destinationPath)) { @@ -77,7 +72,6 @@ namespace IW4MAdmin.Application.Migration if (!File.Exists(Path.Join("Database", "Database.db")) && File.Exists("Database.db")) { - log?.WriteDebug("Moving database file"); File.Move("Database.db", Path.Join("Database", "Database.db")); } } diff --git a/Application/Misc/EventProfiler.cs b/Application/Misc/EventProfiler.cs deleted file mode 100644 index 0b884f67..00000000 --- a/Application/Misc/EventProfiler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using SharedLibraryCore; -using SharedLibraryCore.Interfaces; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace IW4MAdmin.Application.Misc -{ - internal class EventPerformance - { - public long ExecutionTime { get; set; } - public GameEvent Event { get; set; } - public string EventInfo => $"{Event.Type}, {Event.FailReason}, {Event.IsBlocking}, {Event.Data}, {Event.Message}, {Event.Extra}"; - } - - public class DuplicateKeyComparer : IComparer where TKey : IComparable - { - public int Compare(TKey x, TKey y) - { - int result = x.CompareTo(y); - - if (result == 0) - return 1; - else - return result; - } - } - - internal class EventProfiler - { - public double AverageEventTime { get; private set; } - public double MaxEventTime => Events.Values.Last().ExecutionTime; - public double MinEventTime => Events.Values[0].ExecutionTime; - public int TotalEventCount => Events.Count; - public SortedList Events { get; private set; } = new SortedList(new DuplicateKeyComparer()); - private readonly ILogger _logger; - - public EventProfiler(ILogger logger) - { - _logger = logger; - } - - public void Profile(DateTime start, DateTime end, GameEvent gameEvent) - { - _logger.WriteDebug($"Starting profile of event {gameEvent.Id}"); - long executionTime = (long)Math.Round((end - start).TotalMilliseconds); - - var perf = new EventPerformance() - { - Event = gameEvent, - ExecutionTime = executionTime - }; - - lock (Events) - { - Events.Add(executionTime, perf); - } - - AverageEventTime = (AverageEventTime * (TotalEventCount - 1) + executionTime) / TotalEventCount; - _logger.WriteDebug($"Finished profile of event {gameEvent.Id}"); - } - } -} diff --git a/Application/Misc/Logger.cs b/Application/Misc/Logger.cs index 96cbda54..8647118f 100644 --- a/Application/Misc/Logger.cs +++ b/Application/Misc/Logger.cs @@ -1,132 +1,47 @@ -using IW4MAdmin.Application.IO; -using SharedLibraryCore; -using SharedLibraryCore.Interfaces; -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; +using System; +using Microsoft.Extensions.Logging; +using ILogger = SharedLibraryCore.Interfaces.ILogger; namespace IW4MAdmin.Application { + [Obsolete] public class Logger : ILogger { - enum LogType + private readonly Microsoft.Extensions.Logging.ILogger _logger; + + public Logger(ILogger logger) { - Verbose, - Info, - Debug, - Warning, - Error, - Assert - } - - readonly string FileName; - readonly ReaderWriterLockSlim WritingLock; - static readonly short MAX_LOG_FILES = 10; - - public Logger(string fn) - { - FileName = Path.Join(Utilities.OperatingDirectory, "Log", $"{fn}.log"); - WritingLock = new ReaderWriterLockSlim(); - RotateLogs(); - } - - ~Logger() - { - WritingLock.Dispose(); - } - - /// - /// rotates logs when log is initialized - /// - private void RotateLogs() - { - string maxLog = FileName + MAX_LOG_FILES; - - if (File.Exists(maxLog)) - { - File.Delete(maxLog); - } - - for (int i = MAX_LOG_FILES - 1; i >= 0; i--) - { - string logToMove = i == 0 ? FileName : FileName + i; - string movedLogName = FileName + (i + 1); - - if (File.Exists(logToMove)) - { - File.Move(logToMove, movedLogName); - } - } - } - - void Write(string msg, LogType type) - { - WritingLock.EnterWriteLock(); - - string stringType = type.ToString(); - msg = msg.StripColors(); - - try - { - stringType = Utilities.CurrentLocalization.LocalizationIndex[$"GLOBAL_{type.ToString().ToUpper()}"]; - } - - catch (Exception) { } - - string LogLine = $"[{DateTime.Now.ToString("MM.dd.yyy HH:mm:ss.fff")}] - {stringType}: {msg}"; - try - { -#if DEBUG - // lets keep it simple and dispose of everything quickly as logging wont be that much (relatively) - Console.WriteLine(msg); -#else - if (type == LogType.Error || type == LogType.Verbose) - { - Console.WriteLine(LogLine); - } - File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}"); -#endif - } - - catch (Exception ex) - { - Console.WriteLine("Well.. It looks like your machine can't event write to the log file. That's something else..."); - Console.WriteLine(ex.GetExceptionInfo()); - } - - WritingLock.ExitWriteLock(); + _logger = logger; } public void WriteVerbose(string msg) { - Write(msg, LogType.Verbose); + _logger.LogInformation(msg); } public void WriteDebug(string msg) { - Write(msg, LogType.Debug); + _logger.LogDebug(msg); } public void WriteError(string msg) { - Write(msg, LogType.Error); + _logger.LogError(msg); } public void WriteInfo(string msg) { - Write(msg, LogType.Info); + WriteVerbose(msg); } public void WriteWarning(string msg) { - Write(msg, LogType.Warning); + _logger.LogWarning(msg); } public void WriteAssert(bool condition, string msg) { - if (!condition) - Write(msg, LogType.Assert); + throw new NotImplementedException(); } } } diff --git a/Application/Misc/MasterCommunication.cs b/Application/Misc/MasterCommunication.cs index 60dc6891..e94b8089 100644 --- a/Application/Misc/MasterCommunication.cs +++ b/Application/Misc/MasterCommunication.cs @@ -8,6 +8,8 @@ using System; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -24,10 +26,9 @@ namespace IW4MAdmin.Application.Misc private readonly ApplicationConfiguration _appConfig; private readonly BuildNumber _fallbackVersion = BuildNumber.Parse("99.99.99.99"); private readonly int _apiVersion = 1; - private bool firstHeartBeat = true; - public MasterCommunication(ILogger logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager) + public MasterCommunication(ILogger logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager) { _logger = logger; _transLookup = translationLookup; @@ -55,13 +56,7 @@ namespace IW4MAdmin.Application.Misc catch (Exception e) { - _logger.WriteWarning(_transLookup["MANAGER_VERSION_FAIL"]); - while (e.InnerException != null) - { - e = e.InnerException; - } - - _logger.WriteDebug(e.Message); + _logger.LogWarning(e, "Unable to retrieve IW4MAdmin version information"); } if (version.CurrentVersionStable == _fallbackVersion) @@ -110,12 +105,12 @@ namespace IW4MAdmin.Application.Misc catch (System.Net.Http.HttpRequestException e) { - _logger.WriteWarning($"Could not send heartbeat - {e.Message}"); + _logger.LogWarning(e, "Could not send heartbeat"); } catch (AggregateException e) { - _logger.WriteWarning($"Could not send heartbeat - {e.Message}"); + _logger.LogWarning(e, "Could not send heartbeat"); var exceptions = e.InnerExceptions.Where(ex => ex.GetType() == typeof(ApiException)); foreach (var ex in exceptions) @@ -129,7 +124,7 @@ namespace IW4MAdmin.Application.Misc catch (ApiException e) { - _logger.WriteWarning($"Could not send heartbeat - {e.Message}"); + _logger.LogWarning(e, "Could not send heartbeat"); if (e.StatusCode == System.Net.HttpStatusCode.Unauthorized) { connected = false; @@ -138,7 +133,7 @@ namespace IW4MAdmin.Application.Misc catch (Exception e) { - _logger.WriteWarning($"Could not send heartbeat - {e.Message}"); + _logger.LogWarning(e, "Could not send heartbeat"); } @@ -202,7 +197,7 @@ namespace IW4MAdmin.Application.Misc if (response.ResponseMessage.StatusCode != System.Net.HttpStatusCode.OK) { - _logger.WriteWarning($"Response code from master is {response.ResponseMessage.StatusCode}, message is {response.StringContent}"); + _logger.LogWarning("Non success response code from master is {statusCode}, message is {message}", response.ResponseMessage.StatusCode, response.StringContent); } } } diff --git a/Application/Misc/MetaService.cs b/Application/Misc/MetaService.cs index 0f98ad7c..31a62152 100644 --- a/Application/Misc/MetaService.cs +++ b/Application/Misc/MetaService.cs @@ -7,6 +7,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -20,7 +22,7 @@ namespace IW4MAdmin.Application.Misc private readonly IDatabaseContextFactory _contextFactory; private readonly ILogger _logger; - public MetaService(ILogger logger, IDatabaseContextFactory contextFactory) + public MetaService(ILogger logger, IDatabaseContextFactory contextFactory) { _logger = logger; _metaActions = new Dictionary>(); diff --git a/Application/Misc/MiddlewareActionHandler.cs b/Application/Misc/MiddlewareActionHandler.cs index b038f23a..a3683623 100644 --- a/Application/Misc/MiddlewareActionHandler.cs +++ b/Application/Misc/MiddlewareActionHandler.cs @@ -1,8 +1,9 @@ -using SharedLibraryCore; -using SharedLibraryCore.Interfaces; +using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -11,7 +12,7 @@ namespace IW4MAdmin.Application.Misc private readonly IDictionary> _actions; private readonly ILogger _logger; - public MiddlewareActionHandler(ILogger logger) + public MiddlewareActionHandler(ILogger logger) { _actions = new Dictionary>(); _logger = logger; @@ -38,8 +39,7 @@ namespace IW4MAdmin.Application.Misc } catch (Exception e) { - _logger.WriteWarning($"Failed to invoke middleware action {name}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Failed to invoke middleware action {name}", name); } } diff --git a/Application/Misc/PluginImporter.cs b/Application/Misc/PluginImporter.cs index 29723eba..79318b40 100644 --- a/Application/Misc/PluginImporter.cs +++ b/Application/Misc/PluginImporter.cs @@ -5,11 +5,12 @@ using System.Reflection; using SharedLibraryCore.Interfaces; using System.Linq; using SharedLibraryCore; -using IW4MAdmin.Application.Misc; using IW4MAdmin.Application.API.Master; +using Microsoft.Extensions.Logging; using SharedLibraryCore.Configuration; +using ILogger = Microsoft.Extensions.Logging.ILogger; -namespace IW4MAdmin.Application.Helpers +namespace IW4MAdmin.Application.Misc { /// /// implementation of IPluginImporter @@ -24,7 +25,7 @@ namespace IW4MAdmin.Application.Helpers private readonly IMasterApi _masterApi; private readonly ApplicationConfiguration _appConfig; - public PluginImporter(ILogger logger, ApplicationConfiguration appConfig, IMasterApi masterApi, IRemoteAssemblyHandler remoteAssemblyHandler) + public PluginImporter(ILogger logger, ApplicationConfiguration appConfig, IMasterApi masterApi, IRemoteAssemblyHandler remoteAssemblyHandler) { _logger = logger; _masterApi = masterApi; @@ -44,14 +45,14 @@ namespace IW4MAdmin.Application.Helpers { var scriptPluginFiles = Directory.GetFiles(pluginDir, "*.js").AsEnumerable().Union(GetRemoteScripts()); - _logger.WriteInfo($"Discovered {scriptPluginFiles.Count()} potential script plugins"); + _logger.LogDebug("Discovered {count} potential script plugins", scriptPluginFiles.Count()); if (scriptPluginFiles.Count() > 0) { foreach (string fileName in scriptPluginFiles) { - _logger.WriteInfo($"Discovered script plugin {fileName}"); - var plugin = new ScriptPlugin(fileName); + _logger.LogDebug("Discovered script plugin {fileName}", fileName); + var plugin = new ScriptPlugin(_logger, fileName); yield return plugin; } } @@ -71,7 +72,7 @@ namespace IW4MAdmin.Application.Helpers if (Directory.Exists(pluginDir)) { var dllFileNames = Directory.GetFiles(pluginDir, "*.dll"); - _logger.WriteInfo($"Discovered {dllFileNames.Length} potential plugin assemblies"); + _logger.LogDebug("Discovered {count} potential plugin assemblies", dllFileNames.Length); if (dllFileNames.Length > 0) { @@ -84,13 +85,13 @@ namespace IW4MAdmin.Application.Helpers .SelectMany(_asm => _asm.GetTypes()) .Where(_assemblyType => _assemblyType.GetInterface(nameof(IPlugin), false) != null); - _logger.WriteInfo($"Discovered {pluginTypes.Count()} plugin implementations"); + _logger.LogDebug("Discovered {count} plugin implementations", pluginTypes.Count()); commandTypes = assemblies .SelectMany(_asm => _asm.GetTypes()) .Where(_assemblyType => _assemblyType.IsClass && _assemblyType.BaseType == typeof(Command)); - _logger.WriteInfo($"Discovered {commandTypes.Count()} plugin commands"); + _logger.LogDebug("Discovered {count} plugin commands", commandTypes.Count()); } } @@ -109,8 +110,7 @@ namespace IW4MAdmin.Application.Helpers catch (Exception ex) { - _logger.WriteWarning("Could not load remote assemblies"); - _logger.WriteDebug(ex.GetExceptionInfo()); + _logger.LogWarning(ex, "Could not load remote assemblies"); return Enumerable.Empty(); } } @@ -127,8 +127,7 @@ namespace IW4MAdmin.Application.Helpers catch (Exception ex) { - _logger.WriteWarning("Could not load remote assemblies"); - _logger.WriteDebug(ex.GetExceptionInfo()); + _logger.LogWarning(ex,"Could not load remote scripts"); return Enumerable.Empty(); } } diff --git a/Application/Misc/RemoteAssemblyHandler.cs b/Application/Misc/RemoteAssemblyHandler.cs index 1733495c..f2214d99 100644 --- a/Application/Misc/RemoteAssemblyHandler.cs +++ b/Application/Misc/RemoteAssemblyHandler.cs @@ -1,5 +1,4 @@ -using SharedLibraryCore; -using SharedLibraryCore.Configuration; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; @@ -7,6 +6,8 @@ using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -20,7 +21,7 @@ namespace IW4MAdmin.Application.Misc private readonly ApplicationConfiguration _appconfig; private readonly ILogger _logger; - public RemoteAssemblyHandler(ILogger logger, ApplicationConfiguration appconfig) + public RemoteAssemblyHandler(ILogger logger, ApplicationConfiguration appconfig) { _appconfig = appconfig; _logger = logger; @@ -41,7 +42,7 @@ namespace IW4MAdmin.Application.Misc { if (string.IsNullOrEmpty(_appconfig.Id) || string.IsNullOrWhiteSpace(_appconfig.SubscriptionId)) { - _logger.WriteWarning($"{nameof(_appconfig.Id)} and {nameof(_appconfig.SubscriptionId)} must be provided to attempt loading remote assemblies/scripts"); + _logger.LogWarning($"{nameof(_appconfig.Id)} and {nameof(_appconfig.SubscriptionId)} must be provided to attempt loading remote assemblies/scripts"); return new byte[0][]; } @@ -63,8 +64,7 @@ namespace IW4MAdmin.Application.Misc catch (CryptographicException ex) { - _logger.WriteError("Could not obtain remote plugin assemblies"); - _logger.WriteDebug(ex.GetExceptionInfo()); + _logger.LogError(ex, "Could not decrypt remote plugin assemblies"); } return decryptedContent; diff --git a/Application/Misc/ScriptCommand.cs b/Application/Misc/ScriptCommand.cs index 6f181bba..b4fe43a1 100644 --- a/Application/Misc/ScriptCommand.cs +++ b/Application/Misc/ScriptCommand.cs @@ -4,7 +4,9 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Database.Models.EFClient; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -14,13 +16,15 @@ namespace IW4MAdmin.Application.Misc public class ScriptCommand : Command { private readonly Action _executeAction; + private readonly ILogger _logger; public ScriptCommand(string name, string alias, string description, bool isTargetRequired, Permission permission, - CommandArgument[] args, Action executeAction, CommandConfiguration config, ITranslationLookup layout) + CommandArgument[] args, Action executeAction, CommandConfiguration config, ITranslationLookup layout, ILogger logger) : base(config, layout) { _executeAction = executeAction; + _logger = logger; Name = name; Alias = alias; Description = description; @@ -29,14 +33,21 @@ namespace IW4MAdmin.Application.Misc Arguments = args; } - public override Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent e) { if (_executeAction == null) { throw new InvalidOperationException($"No execute action defined for command \"{Name}\""); } - return Task.Run(() => _executeAction(E)); + try + { + await Task.Run(() => _executeAction(e)); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to execute ScriptCommand action for command {command} {@event}", Name, e); + } } } } diff --git a/Application/Misc/ScriptPlugin.cs b/Application/Misc/ScriptPlugin.cs index c8dd97da..4075cac3 100644 --- a/Application/Misc/ScriptPlugin.cs +++ b/Application/Misc/ScriptPlugin.cs @@ -1,4 +1,5 @@ -using Jint; +using System; +using Jint; using Jint.Native; using Jint.Runtime; using Microsoft.CSharp.RuntimeBinder; @@ -12,6 +13,9 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.Misc { @@ -39,9 +43,11 @@ namespace IW4MAdmin.Application.Misc private readonly SemaphoreSlim _onProcessing; private bool successfullyLoaded; private readonly List _registeredCommandNames; + private readonly ILogger _logger; - public ScriptPlugin(string filename, string workingDirectory = null) + public ScriptPlugin(ILogger logger, string filename, string workingDirectory = null) { + _logger = logger; _fileName = filename; Watcher = new FileSystemWatcher() { @@ -84,7 +90,7 @@ namespace IW4MAdmin.Application.Misc foreach (string commandName in _registeredCommandNames) { - manager.GetLogger(0).WriteDebug($"Removing plugin registered command \"{commandName}\""); + _logger.LogDebug("Removing plugin registered command {command}", commandName); manager.RemoveCommandByName(commandName); } @@ -129,7 +135,7 @@ namespace IW4MAdmin.Application.Misc { foreach (var command in GenerateScriptCommands(commands, scriptCommandFactory)) { - manager.GetLogger(0).WriteDebug($"Adding plugin registered command \"{command.Name}\""); + _logger.LogDebug("Adding plugin registered command {commandName}", command.Name); manager.AddAdditionalCommand(command); _registeredCommandNames.Add(command.Name); } @@ -167,12 +173,20 @@ namespace IW4MAdmin.Application.Misc catch (JavaScriptException ex) { - throw new PluginException($"An error occured while initializing script plugin: {ex.Error} (Line: {ex.Location.Start.Line}, Character: {ex.Location.Start.Column})") { PluginFile = _fileName }; + _logger.LogError(ex, + "Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} initialization {@locationInfo}", + nameof(OnLoadAsync), _fileName, ex.Location); + + throw new PluginException("An error occured while initializing script plugin"); } - - catch + + catch (Exception ex) { - throw; + _logger.LogError(ex, + "Encountered unexpected error while running {methodName} for script plugin {plugin} with event type {eventType}", + nameof(OnLoadAsync), _fileName); + + throw new PluginException("An unexpected error occured while initializing script plugin"); } finally @@ -197,10 +211,29 @@ namespace IW4MAdmin.Application.Misc _scriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(S)); _scriptEngine.Execute("plugin.onEventAsync(_gameEvent, _server)").GetCompletionValue(); } - - catch + + catch (JavaScriptException ex) { - throw; + using (LogContext.PushProperty("Server", S.ToString())) + { + _logger.LogError(ex, + "Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} with event type {eventType} {@locationInfo}", + nameof(OnEventAsync), _fileName, E.Type, ex.Location); + } + + throw new PluginException($"An error occured while executing action for script plugin"); + } + + catch (Exception e) + { + using (LogContext.PushProperty("Server", S.ToString())) + { + _logger.LogError(e, + "Encountered unexpected error while running {methodName} for script plugin {plugin} with event type {eventType}", + nameof(OnEventAsync), _fileName, E.Type); + } + + throw new PluginException($"An error occured while executing action for script plugin"); } finally @@ -215,7 +248,7 @@ namespace IW4MAdmin.Application.Misc public Task OnLoadAsync(IManager manager) { - manager.GetLogger(0).WriteDebug($"OnLoad executing for {Name}"); + _logger.LogDebug("OnLoad executing for {name}", Name); _scriptEngine.SetValue("_manager", manager); return Task.FromResult(_scriptEngine.Execute("plugin.onLoadAsync(_manager)").GetCompletionValue()); } diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 8dbadbb3..c320800c 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -11,6 +11,9 @@ using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.RCon { @@ -27,7 +30,7 @@ namespace IW4MAdmin.Application.RCon private readonly ILogger _log; private readonly Encoding _gameEncoding; - public RConConnection(string ipAddress, int port, string password, ILogger log, Encoding gameEncoding) + public RConConnection(string ipAddress, int port, string password, ILogger log, Encoding gameEncoding) { Endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port); _gameEncoding = gameEncoding; @@ -49,10 +52,7 @@ namespace IW4MAdmin.Application.RCon var connectionState = ActiveQueries[this.Endpoint]; - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Waiting for semaphore to be released [{this.Endpoint}]"); - } + _log.LogDebug("Waiting for semaphore to be released [{endpoint}]", Endpoint); // enter the semaphore so only one query is sent at a time per server. await connectionState.OnComplete.WaitAsync(); @@ -66,11 +66,8 @@ namespace IW4MAdmin.Application.RCon connectionState.LastQuery = DateTime.Now; - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Semaphore has been released [{Endpoint}]"); - _log.WriteDebug($"Query [{Endpoint},{type},{parameters}]"); - } + _log.LogDebug("Semaphore has been released [{endpoint}]", Endpoint); + _log.LogDebug("Query {@queryInfo}", new { endpoint=Endpoint.ToString(), type, parameters }); byte[] payload = null; bool waitForResponse = config.WaitForResponse; @@ -115,10 +112,16 @@ namespace IW4MAdmin.Application.RCon // this happens when someone tries to send something that can't be converted into a 7 bit character set // e.g: emoji -> windows-1252 - catch (OverflowException) + catch (OverflowException ex) { connectionState.OnComplete.Release(1); - throw new NetworkException($"Invalid character encountered when converting encodings - {parameters}"); + using (LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogError(ex, "Could not convert RCon data payload to desired encoding {encoding} {params}", + _gameEncoding.EncodingName, parameters); + } + + throw new RConException($"Invalid character encountered when converting encodings"); } byte[][] response = null; @@ -137,16 +140,17 @@ namespace IW4MAdmin.Application.RCon connectionState.ConnectionAttempts++; connectionState.BytesReadPerSegment.Clear(); bool exceptionCaught = false; -#if DEBUG == true - _log.WriteDebug($"Sending {payload.Length} bytes to [{this.Endpoint}] ({connectionState.ConnectionAttempts}/{StaticHelpers.AllowedConnectionFails})"); -#endif + + _log.LogDebug("Sending {payloadLength} bytes to [{endpoint}] ({connectionAttempts}/{allowedConnectionFailures})", + payload.Length, Endpoint, connectionState.ConnectionAttempts, StaticHelpers.AllowedConnectionFails); + try { response = await SendPayloadAsync(payload, waitForResponse); if ((response.Length == 0 || response[0].Length == 0) && waitForResponse) { - throw new NetworkException("Expected response but got 0 bytes back"); + throw new RConException("Expected response but got 0 bytes back"); } connectionState.ConnectionAttempts = 0; @@ -162,7 +166,14 @@ namespace IW4MAdmin.Application.RCon goto retrySend; } - throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMUNICATION"].FormatExt(Endpoint)); + using (LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogWarning( + "Made {connectionAttempts} attempts to send RCon data to server, but received no response", + connectionState.ConnectionAttempts); + } + connectionState.ConnectionAttempts = 0; + throw new NetworkException("Reached maximum retry attempts to send RCon data to server"); } finally @@ -177,7 +188,7 @@ namespace IW4MAdmin.Application.RCon if (response.Length == 0) { - _log.WriteWarning($"Received empty response for request [{type}, {parameters}, {Endpoint}]"); + _log.LogDebug("Received empty response for RCon request {@query}", new { endpoint=Endpoint.ToString(), type, parameters }); return new string[0]; } @@ -187,12 +198,12 @@ namespace IW4MAdmin.Application.RCon // note: not all games respond if the pasword is wrong or not set if (responseString.Contains("Invalid password") || responseString.Contains("rconpassword")) { - throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]); + throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]); } if (responseString.Contains("rcon_password")) { - throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]); + throw new RConException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]); } if (responseString.Contains(config.ServerNotRunningResponse)) @@ -205,7 +216,13 @@ namespace IW4MAdmin.Application.RCon if (headerSplit.Length != 2) { - throw new NetworkException("Unexpected response header from server"); + using (LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogWarning("Invalid response header from server. Expected {expected}, but got {response}", + config.CommandPrefixes.RConResponse, headerSplit.FirstOrDefault()); + } + + throw new RConException("Unexpected response header from server"); } string[] splitResponse = headerSplit.Last().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); @@ -293,12 +310,17 @@ namespace IW4MAdmin.Application.RCon if (sendDataPending) { - // the send has not been completed asyncronously + // the send has not been completed asynchronously // this really shouldn't ever happen because it's UDP if (!await Task.Run(() => connectionState.OnSentData.Wait(StaticHelpers.SocketTimeout(1)))) { + using(LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogWarning("Socket timed out while sending RCon data on attempt {attempt}", + connectionState.ConnectionAttempts); + } rconSocket.Close(); - throw new NetworkException("Timed out sending data", rconSocket); + throw new NetworkException("Timed out sending RCon data", rconSocket); } } @@ -314,14 +336,22 @@ namespace IW4MAdmin.Application.RCon if (receiveDataPending) { - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Waiting to asynchrously receive data on attempt #{connectionState.ConnectionAttempts}"); - } + _log.LogDebug("Waiting to asynchronously receive data on attempt #{connectionAttempts}", connectionState.ConnectionAttempts); if (!await Task.Run(() => connectionState.OnReceivedData.Wait(StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts)))) { + if (connectionState.ConnectionAttempts > 1) // this reduces some spam for unstable connections + { + using (LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogWarning( + "Socket timed out while waiting for RCon response on attempt {attempt} with timeout delay of {timeout}", + connectionState.ConnectionAttempts, + StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts)); + } + } + rconSocket.Close(); - throw new NetworkException("Timed out waiting for response", rconSocket); + throw new NetworkException("Timed out receiving RCon response", rconSocket); } } @@ -350,10 +380,7 @@ namespace IW4MAdmin.Application.RCon private void OnDataReceived(object sender, SocketAsyncEventArgs e) { - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Read {e.BytesTransferred} bytes from {e.RemoteEndPoint}"); - } + _log.LogDebug("Read {bytesTransferred} bytes from {endpoint}", e.BytesTransferred, e.RemoteEndPoint); // this occurs when we close the socket if (e.BytesTransferred == 0) @@ -376,10 +403,7 @@ namespace IW4MAdmin.Application.RCon if (!sock.ReceiveAsync(state.ReceiveEventArgs)) { - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Read {state.ReceiveEventArgs.BytesTransferred} synchronous bytes from {e.RemoteEndPoint}"); - } + _log.LogDebug("Read {bytesTransferred} synchronous bytes from {endpoint}", state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint); // we need to increment this here because the callback isn't executed if there's no pending IO state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred); ActiveQueries[this.Endpoint].OnReceivedData.Set(); @@ -401,10 +425,7 @@ namespace IW4MAdmin.Application.RCon private void OnDataSent(object sender, SocketAsyncEventArgs e) { - if (Utilities.IsDevelopment) - { - _log.WriteDebug($"Sent {e.Buffer?.Length} bytes to {e.ConnectSocket?.RemoteEndPoint?.ToString()}"); - } + _log.LogDebug("Sent {byteCount} bytes to {endpoint}", e.Buffer?.Length, e.ConnectSocket?.RemoteEndPoint); ActiveQueries[this.Endpoint].OnSentData.Set(); } } diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index d797111c..6b8b63a8 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -8,14 +8,19 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Application.RconParsers { public class BaseRConParser : IRConParser { - public BaseRConParser(IParserRegexFactory parserRegexFactory) + private readonly ILogger _logger; + + public BaseRConParser(ILogger logger, IParserRegexFactory parserRegexFactory) { + _logger = logger; Configuration = new DynamicRConParserConfiguration(parserRegexFactory) { CommandPrefixes = new CommandPrefix() @@ -133,12 +138,7 @@ namespace IW4MAdmin.Application.RconParsers public virtual async Task<(List, string, string)> GetStatusAsync(IRConConnection connection) { string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS); -#if DEBUG - foreach (var line in response) - { - Console.WriteLine(line); - } -#endif + _logger.LogDebug("Status Response {@response}", (object)response); return (ClientsFromStatus(response), MapFromStatus(response), GameTypeFromStatus(response)); } diff --git a/Application/RconParsers/DynamicRConParser.cs b/Application/RconParsers/DynamicRConParser.cs index 380062f1..f642a5b9 100644 --- a/Application/RconParsers/DynamicRConParser.cs +++ b/Application/RconParsers/DynamicRConParser.cs @@ -1,4 +1,5 @@ -using SharedLibraryCore.Interfaces; +using Microsoft.Extensions.Logging; +using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.RconParsers { @@ -8,7 +9,7 @@ namespace IW4MAdmin.Application.RconParsers /// sealed internal class DynamicRConParser : BaseRConParser { - public DynamicRConParser(IParserRegexFactory parserRegexFactory) : base(parserRegexFactory) + public DynamicRConParser(ILogger logger, IParserRegexFactory parserRegexFactory) : base(logger, parserRegexFactory) { } } diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj index 2a894b5c..fc817db3 100644 --- a/Plugins/AutomessageFeed/AutomessageFeed.csproj +++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj index 8c371e52..2c925e28 100644 --- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj +++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/LiveRadar/LiveRadar.csproj b/Plugins/LiveRadar/LiveRadar.csproj index efd9d1d9..7f066573 100644 --- a/Plugins/LiveRadar/LiveRadar.csproj +++ b/Plugins/LiveRadar/LiveRadar.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/LiveRadar/Plugin.cs b/Plugins/LiveRadar/Plugin.cs index fbbb3930..c787a805 100644 --- a/Plugins/LiveRadar/Plugin.cs +++ b/Plugins/LiveRadar/Plugin.cs @@ -1,11 +1,12 @@ using LiveRadar.Configuration; using SharedLibraryCore; -using SharedLibraryCore.Configuration; -using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using SharedLibraryCore.Interfaces; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace LiveRadar { @@ -21,11 +22,13 @@ namespace LiveRadar private readonly Dictionary _botGuidLookups; private bool addedPage; private readonly object lockObject = new object(); + private readonly ILogger _logger; - public Plugin(IConfigurationHandlerFactory configurationHandlerFactory) + public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory) { _configurationHandler = configurationHandlerFactory.GetConfigurationHandler("LiveRadarConfiguration"); _botGuidLookups = new Dictionary(); + _logger = logger; } public Task OnEventAsync(GameEvent E, Server S) @@ -80,8 +83,7 @@ namespace LiveRadar catch (Exception e) { - S.Logger.WriteWarning($"Could not parse live radar output: {e.Data}"); - S.Logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogError(e, "Could not parse live radar output: {data}", e.Data); } } diff --git a/Plugins/Login/Login.csproj b/Plugins/Login/Login.csproj index c43bfe7d..49933244 100644 --- a/Plugins/Login/Login.csproj +++ b/Plugins/Login/Login.csproj @@ -23,7 +23,7 @@ - + diff --git a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj index 3b98cd45..1a8aa316 100644 --- a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj +++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/ScriptPlugins/ParserIW6x.js b/Plugins/ScriptPlugins/ParserIW6x.js index facfedab..a9133446 100644 --- a/Plugins/ScriptPlugins/ParserIW6x.js +++ b/Plugins/ScriptPlugins/ParserIW6x.js @@ -21,7 +21,7 @@ var plugin = { rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick {0} "{1}"'; rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n(?:latched: \\"(.+)?\\"\\n)? *(.+)$'; - rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$'; + rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$'; rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *'; rconParser.Configuration.WaitForResponse = false; rconParser.Configuration.Status.AddMapping(102, 4); diff --git a/Plugins/ScriptPlugins/SampleScriptPluginCommand.js b/Plugins/ScriptPlugins/SampleScriptPluginCommand.js index b02f9238..63929aa3 100644 --- a/Plugins/ScriptPlugins/SampleScriptPluginCommand.js +++ b/Plugins/ScriptPlugins/SampleScriptPluginCommand.js @@ -27,6 +27,7 @@ let commands = [{ // we want to print out a pong message for the number of times they requested for (var i = 0; i < times; i++) { + gameEvent.Origin = undefined; gameEvent.Origin.Tell(`^${i}pong #${i + 1}^7`); // don't want to wait if it's the last pong diff --git a/Plugins/Stats/Cheat/Detection.cs b/Plugins/Stats/Cheat/Detection.cs index bf689db6..f5357939 100644 --- a/Plugins/Stats/Cheat/Detection.cs +++ b/Plugins/Stats/Cheat/Detection.cs @@ -1,13 +1,13 @@ using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Plugins.Stats.Cheat { @@ -223,11 +223,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat if (weightedSessionAverage > Thresholds.MaxOffset(totalSessionHits) && totalSessionHits >= (Thresholds.MediumSampleMinKills * 2)) { - Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***"); - Log.WriteDebug($"Session Average = {weightedSessionAverage}"); - Log.WriteDebug($"HitCount = {HitCount}"); - Log.WriteDebug($"ID = {hit.AttackerId}"); - results.Add(new DetectionPenaltyResult() { ClientPenalty = EFPenalty.PenaltyType.Ban, @@ -237,18 +232,14 @@ namespace IW4MAdmin.Plugins.Stats.Cheat Location = hitLoc.Location }); } - -#if DEBUG - Log.WriteDebug($"PredictVsReal={realAgainstPredict}"); -#endif + + Log.LogDebug("PredictVsReal={realAgainstPredict}", realAgainstPredict); } #endregion #region STRAIN double currentStrain = Strain.GetStrain(hit.Distance / 0.0254, hit.ViewAngles, Math.Max(50, LastOffset == 0 ? 50 : (hit.TimeOffset - LastOffset))); -#if DEBUG == true - Log.WriteDebug($"Current Strain: {currentStrain}"); -#endif + Log.LogDebug("Current Strain: {currentStrain}", currentStrain); LastOffset = hit.TimeOffset; if (currentStrain > ClientStats.MaxStrain) diff --git a/Plugins/Stats/Cheat/Strain.cs b/Plugins/Stats/Cheat/Strain.cs index 3f4fc01a..7fe4b1d5 100644 --- a/Plugins/Stats/Cheat/Strain.cs +++ b/Plugins/Stats/Cheat/Strain.cs @@ -27,12 +27,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat double[] distance = Utilities.AngleStuff(newAngle, LastAngle); LastDistance = distance[0] + distance[1]; -#if DEBUG == true - Console.WriteLine($"Angle Between = {LastDistance}"); - Console.WriteLine($"Distance From Target = {killDistance}"); - Console.WriteLine($"Time Offset = {deltaTime}"); - Console.WriteLine($"Decay Factor = {decayFactor} "); -#endif // this happens on first kill if ((distance[0] == 0 && distance[1] == 0) || deltaTime == 0 || diff --git a/Plugins/Stats/Helpers/MigrationHelper.cs b/Plugins/Stats/Helpers/MigrationHelper.cs new file mode 100644 index 00000000..e63638df --- /dev/null +++ b/Plugins/Stats/Helpers/MigrationHelper.cs @@ -0,0 +1,7 @@ +namespace Stats.Helpers +{ + public class MigrationHelper + { + + } +} \ No newline at end of file diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index ff33e991..e6a4d933 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -4,7 +4,6 @@ using IW4MAdmin.Plugins.Stats.Models; using IW4MAdmin.Plugins.Stats.Web.Dtos; using Microsoft.EntityFrameworkCore; using SharedLibraryCore; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; @@ -15,7 +14,9 @@ using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using static IW4MAdmin.Plugins.Stats.Cheat.Detection; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Plugins.Stats.Helpers { @@ -30,10 +31,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers public static string CLIENT_STATS_KEY = "ClientStats"; public static string CLIENT_DETECTIONS_KEY = "ClientDetections"; - public StatManager(IManager mgr, IDatabaseContextFactory contextFactory, IConfigurationHandler configHandler) + public StatManager(ILogger logger, IManager mgr, IDatabaseContextFactory contextFactory, IConfigurationHandler configHandler) { _servers = new ConcurrentDictionary(); - _log = mgr.GetLogger(0); + _log = logger; _contextFactory = contextFactory; _configHandler = configHandler; } @@ -265,8 +266,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception e) { - _log.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]} - {e.Message}"); - _log.WriteDebug(e.GetExceptionInfo()); + _log.LogError(e, "{message}", Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]); } } @@ -283,7 +283,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers if (!_servers.ContainsKey(serverId)) { - _log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found"); + _log.LogError("[Stats::AddPlayer] Server with id {serverId} could not be found", serverId); return null; } @@ -360,7 +360,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers clientStats.LastScore = pl.Score; pl.SetAdditionalProperty(CLIENT_DETECTIONS_KEY, new Detection(_log, clientStats)); - pl.CurrentServer.Logger.WriteInfo($"Added {pl} to stats"); + _log.LogDebug("Added {client} to stats", pl.ToString()); } return clientStats; @@ -368,8 +368,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception ex) { - _log.WriteWarning("Could not add client to stats"); - _log.WriteDebug(ex.GetExceptionInfo()); + _log.LogError(ex, "Could not add client to stats {@client}", pl); } return null; @@ -382,11 +381,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// public async Task RemovePlayer(EFClient pl) { - pl.CurrentServer.Logger.WriteInfo($"Removing {pl} from stats"); + _log.LogDebug("Removing {client} from stats", pl.ToString()); if (pl.CurrentServer == null) { - pl.CurrentServer.Logger.WriteWarning($"Disconnecting client {pl} is not on a server, state is {pl.State}"); + _log.LogWarning("Disconnecting client {@client} is not on a server", pl); return; } @@ -407,7 +406,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers else { - pl.CurrentServer.Logger.WriteWarning($"Disconnecting client {pl} has not been added to stats, state is {pl.State}"); + _log.LogWarning("Disconnecting client {@client} has not been added to stats", pl); } } @@ -452,10 +451,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } } - catch (FormatException) + catch (FormatException ex) { - _log.WriteError("Could not parse vector data from hit"); - _log.WriteDebug($"Kill - {killOrigin} Death - {deathOrigin} ViewAngle - {viewAngles} Snapshot - {string.Join(",", snapshotAngles.Select(_a => _a.ToString()))}"); + _log.LogWarning(ex, "Could not parse vector data from hit"); return; } @@ -527,8 +525,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception e) { - _log.WriteError("Could not store client kills"); - _log.WriteDebug(e.GetExceptionInfo()); + _log.LogError(e, "Could not store client kills"); } finally @@ -583,9 +580,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (TaskCanceledException) { } catch (Exception ex) { - _log.WriteError("Could not save hit or AC info"); - _log.WriteDebug(ex.GetExceptionInfo()); - _log.WriteDebug($"Attacker: {attacker} Victim: {victim}, ServerId {serverId}"); + _log.LogError(ex, "Could not save hit or anti-cheat info {@attacker} {@victim} {server}", attacker, victim, serverId); } finally @@ -714,9 +709,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers var attackerStats = attacker.GetAdditionalProperty(CLIENT_STATS_KEY); var victimStats = victim.GetAdditionalProperty(CLIENT_STATS_KEY); -#if DEBUG - _log.WriteDebug("Processing standard kill"); -#endif // update the total stats _servers[serverId].ServerStatistics.TotalKills += 1; @@ -754,14 +746,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers // fixme: why? if (double.IsNaN(victimStats.SPM) || double.IsNaN(victimStats.Skill)) { - _log.WriteDebug($"[StatManager::AddStandardKill] victim SPM/SKILL {victimStats.SPM} {victimStats.Skill}"); + _log.LogWarning("victim SPM/SKILL {@victimStats}", victimStats); victimStats.SPM = 0.0; victimStats.Skill = 0.0; } if (double.IsNaN(attackerStats.SPM) || double.IsNaN(attackerStats.Skill)) { - _log.WriteDebug($"[StatManager::AddStandardKill] attacker SPM/SKILL {victimStats.SPM} {victimStats.Skill}"); + _log.LogWarning("attacker SPM/SKILL {@attackerStats}", attackerStats); attackerStats.SPM = 0.0; attackerStats.Skill = 0.0; } @@ -781,8 +773,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception e) { - _log.WriteWarning($"Could not update stat history for {attacker}"); - _log.WriteDebug(e.GetExceptionInfo()); + _log.LogWarning(e, "Could not update stat history for {attacker}", attacker.ToString()); } finally @@ -1099,8 +1090,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers if (clientStats.SPM < 0) { - _log.WriteWarning("[StatManager:UpdateStats] clientStats SPM < 0"); - _log.WriteDebug($"{scoreDifference}-{clientStats.RoundScore} - {clientStats.LastScore} - {clientStats.SessionScore}"); + _log.LogWarning("clientStats SPM < 0 {scoreDifference} {@clientStats}", scoreDifference, clientStats); clientStats.SPM = 0; } @@ -1110,8 +1100,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers // fixme: how does this happen? if (double.IsNaN(clientStats.SPM) || double.IsNaN(clientStats.Skill)) { - _log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN"); - _log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}"); + _log.LogWarning("clientStats SPM/Skill NaN {@killInfo}", new {killSPM, KDRWeight, totalPlayTime, SPMAgainstPlayWeight, clientStats, scoreDifference}); clientStats.SPM = 0; clientStats.Skill = 0; } @@ -1133,7 +1122,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers if (serverStats == null) { - _log.WriteDebug($"Initializing server stats for {serverId}"); + _log.LogDebug("Initializing server stats for {serverId}", serverId); // server stats have never been generated before serverStats = new EFServerStatistics() { @@ -1225,8 +1214,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception e) { - _log.WriteError("There was a probably syncing server stats"); - _log.WriteDebug(e.GetExceptionInfo()); + _log.LogError(e, "There was a problem syncing server stats"); } finally diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 995eacf8..3cccb07f 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; namespace IW4MAdmin.Plugins.Stats { @@ -28,23 +29,24 @@ namespace IW4MAdmin.Plugins.Stats public static StatManager Manager { get; private set; } public static IManager ServerManager; public static IConfigurationHandler Config { get; private set; } -#if DEBUG - int scriptDamageCount; - int scriptKillCount; -#endif + private readonly IDatabaseContextFactory _databaseContextFactory; private readonly ITranslationLookup _translationLookup; private readonly IMetaService _metaService; private readonly IResourceQueryHelper _chatQueryHelper; + private readonly ILogger _managerLogger; + private readonly ILogger _logger; - public Plugin(IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory databaseContextFactory, - ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper chatQueryHelper) + public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory databaseContextFactory, + ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper chatQueryHelper, ILogger managerLogger) { Config = configurationHandlerFactory.GetConfigurationHandler("StatsPluginSettings"); _databaseContextFactory = databaseContextFactory; _translationLookup = translationLookup; _metaService = metaService; _chatQueryHelper = chatQueryHelper; + _managerLogger = managerLogger; + _logger = logger; } public async Task OnEventAsync(GameEvent E, Server S) @@ -102,23 +104,13 @@ namespace IW4MAdmin.Plugins.Stats { E.Origin = E.Target; } - -#if DEBUG - scriptKillCount++; - S.Logger.WriteInfo($"Start ScriptKill {scriptKillCount}"); -#endif - await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); - -#if DEBUG - S.Logger.WriteInfo($"End ScriptKill {scriptKillCount}"); -#endif } else { - S.Logger.WriteDebug("Skipping script kill as it is ignored or data in customcallbacks is outdated/missing"); + _logger.LogDebug("Skipping script kill as it is ignored or data in customcallbacks is outdated/missing"); } break; case GameEvent.EventType.Kill: @@ -155,22 +147,13 @@ namespace IW4MAdmin.Plugins.Stats E.Origin = E.Target; } -#if DEBUG - scriptDamageCount++; - S.Logger.WriteInfo($"Start ScriptDamage {scriptDamageCount}"); -#endif - await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); - -#if DEBUG - S.Logger.WriteInfo($"End ScriptDamage {scriptDamageCount}"); -#endif } else { - S.Logger.WriteDebug("Skipping script damage as it is ignored or data in customcallbacks is outdated/missing"); + _logger.LogDebug("Skipping script damage as it is ignored or data in customcallbacks is outdated/missing"); } break; } @@ -457,7 +440,7 @@ namespace IW4MAdmin.Plugins.Stats manager.GetMessageTokens().Add(new MessageToken("MOSTKILLS", mostKills)); ServerManager = manager; - Manager = new StatManager(manager, _databaseContextFactory, Config); + Manager = new StatManager(_managerLogger, manager, _databaseContextFactory, Config); } public Task OnTickAsync(Server S) diff --git a/Plugins/Stats/Stats.csproj b/Plugins/Stats/Stats.csproj index 879a9535..1c379fca 100644 --- a/Plugins/Stats/Stats.csproj +++ b/Plugins/Stats/Stats.csproj @@ -13,13 +13,15 @@ 2018 Debug;Release;Prerelease 8.0 + false - + + diff --git a/Plugins/Web/StatsWeb/API/StatsController.cs b/Plugins/Web/StatsWeb/API/StatsController.cs index 48391861..9b2e72cf 100644 --- a/Plugins/Web/StatsWeb/API/StatsController.cs +++ b/Plugins/Web/StatsWeb/API/StatsController.cs @@ -1,11 +1,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using SharedLibraryCore; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using Stats.Dtos; using System; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace StatsWeb.API { @@ -16,7 +17,7 @@ namespace StatsWeb.API private readonly ILogger _logger; private readonly IResourceQueryHelper _statsQueryHelper; - public StatsController(ILogger logger, IResourceQueryHelper statsQueryHelper) + public StatsController(ILogger logger, IResourceQueryHelper statsQueryHelper) { _statsQueryHelper = statsQueryHelper; _logger = logger; @@ -56,8 +57,7 @@ namespace StatsWeb.API catch (Exception e) { - _logger.WriteWarning($"Could not get client stats for client id {clientId}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Could not get client stats for client id {clientId}", clientId); return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse { diff --git a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs index cb5bed5e..7af3cfcc 100644 --- a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs +++ b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs @@ -10,6 +10,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace StatsWeb { @@ -23,7 +25,7 @@ namespace StatsWeb private readonly ApplicationConfiguration _appConfig; private List serverCache; - public ChatResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig) + public ChatResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig) { _contextFactory = contextFactory; _logger = logger; diff --git a/Plugins/Web/StatsWeb/Controllers/StatsController.cs b/Plugins/Web/StatsWeb/Controllers/StatsController.cs index 77a0a0e8..1fa81696 100644 --- a/Plugins/Web/StatsWeb/Controllers/StatsController.cs +++ b/Plugins/Web/StatsWeb/Controllers/StatsController.cs @@ -12,6 +12,8 @@ using StatsWeb.Extensions; using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers { @@ -22,7 +24,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers private readonly IResourceQueryHelper _chatResourceQueryHelper; private readonly ITranslationLookup _translationLookup; - public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, + public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, ITranslationLookup translationLookup) : base(manager) { _logger = logger; @@ -108,15 +110,13 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers catch (ArgumentException e) { - _logger.WriteWarning($"Could not parse chat message search query - {query}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Could not parse chat message search query {query}", query); ViewBag.Error = e; } catch (FormatException e) { - _logger.WriteWarning($"Could not parse chat message search query filter format - {query}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Could not parse chat message search query filter format {query}", query); ViewBag.Error = e; } @@ -136,15 +136,13 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers catch (ArgumentException e) { - _logger.WriteWarning($"Could not parse chat message search query - {query}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Could not parse chat message search query {query}", query); throw; } catch (FormatException e) { - _logger.WriteWarning($"Could not parse chat message search query filter format - {query}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Could not parse chat message search query filter format {query}", query); throw; } diff --git a/Plugins/Web/StatsWeb/StatsWeb.csproj b/Plugins/Web/StatsWeb/StatsWeb.csproj index b7ce2d2d..75017f63 100644 --- a/Plugins/Web/StatsWeb/StatsWeb.csproj +++ b/Plugins/Web/StatsWeb/StatsWeb.csproj @@ -14,7 +14,7 @@ Always - + @@ -28,7 +28,7 @@ Never - + diff --git a/Plugins/Welcome/Welcome.csproj b/Plugins/Welcome/Welcome.csproj index 02dc83ee..ebdc6a2e 100644 --- a/Plugins/Welcome/Welcome.csproj +++ b/Plugins/Welcome/Welcome.csproj @@ -16,7 +16,7 @@ - + diff --git a/SharedLibraryCore/Command.cs b/SharedLibraryCore/Command.cs index 2f0c5e5f..5a8b788d 100644 --- a/SharedLibraryCore/Command.cs +++ b/SharedLibraryCore/Command.cs @@ -6,6 +6,7 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using static SharedLibraryCore.Server; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore { diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 9d47a2cf..7429f16b 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -12,6 +12,8 @@ using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; using static SharedLibraryCore.Database.Models.EFClient; namespace SharedLibraryCore.Commands @@ -646,7 +648,7 @@ namespace SharedLibraryCore.Commands /// public class SetLevelCommand : Command { - public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup, ILogger logger) : base(config, translationLookup) + public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup, ILogger logger) : base(config, translationLookup) { Name = "setlevel"; Description = _translationLookup["COMMANDS_SETLEVEL_DESC"]; @@ -727,13 +729,16 @@ namespace SharedLibraryCore.Commands gameEvent.Owner.Manager.GetActiveClients() .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : targetClient; - logger.WriteInfo($"Beginning set level of client {gameEvent.Origin} to {newPerm}"); + logger.LogDebug("Beginning set level of client {origin} to {newPermission}", gameEvent.Origin.ToString(), newPerm); var result = await targetClient.SetLevel(newPerm, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken); if (result.Failed) { - logger.WriteInfo($"Failed to set level of client {gameEvent.Origin}"); + using (LogContext.PushProperty("Server", gameEvent.Origin.CurrentServer?.ToString())) + { + logger.LogWarning("Failed to set level of client {origin}", gameEvent.Origin.ToString()); + } gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); return; } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index 40586d38..293d4465 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -3,6 +3,8 @@ using SharedLibraryCore.Events; using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; namespace SharedLibraryCore { @@ -254,9 +256,6 @@ namespace SharedLibraryCore public void Complete() { _eventFinishedWaiter.Set(); -#if DEBUG - Owner?.Logger.WriteDebug($"Completed internal for event {Id}"); -#endif } /// @@ -266,11 +265,7 @@ namespace SharedLibraryCore public async Task WaitAsync(TimeSpan timeSpan, CancellationToken token) { bool processed = false; - -#if DEBUG - Owner?.Logger.WriteDebug($"Begin wait for event {Id}"); -#endif - + Utilities.DefaultLogger.LogDebug("Begin wait for event {Id}", Id); try { processed = await Task.Run(() => _eventFinishedWaiter.WaitOne(timeSpan), token); @@ -283,14 +278,12 @@ namespace SharedLibraryCore if (!processed) { - Owner?.Logger.WriteError("Waiting for event to complete timed out"); - Owner?.Logger.WriteDebug($"{Id}, {Type}, {Data}, {Extra}, {FailReason.ToString()}, {Message}, {Origin}, {Target}"); -#if DEBUG - //throw new Exception(); -#endif + using(LogContext.PushProperty("Server", Owner?.ToString())) + { + Utilities.DefaultLogger.LogError("Waiting for event to complete timed out {@eventData}", new { Event = this, Message, Origin = Origin.ToString(), Target = Target.ToString()}); + } } - // this lets us know if the the action timed out FailReason = FailReason == EventFailReason.None && !processed ? EventFailReason.Timeout : FailReason; return this; diff --git a/SharedLibraryCore/Exceptions/RConException.cs b/SharedLibraryCore/Exceptions/RConException.cs new file mode 100644 index 00000000..e5f993e2 --- /dev/null +++ b/SharedLibraryCore/Exceptions/RConException.cs @@ -0,0 +1,11 @@ +using System; + +namespace SharedLibraryCore.Exceptions +{ + public class RConException : Exception + { + public RConException(string message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/ILogger.cs b/SharedLibraryCore/Interfaces/ILogger.cs index 57049b52..5afb04b8 100644 --- a/SharedLibraryCore/Interfaces/ILogger.cs +++ b/SharedLibraryCore/Interfaces/ILogger.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SharedLibraryCore.Interfaces { + [Obsolete] public interface ILogger { void WriteVerbose(string msg); diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs index 95bf4b88..8153e6ce 100644 --- a/SharedLibraryCore/Interfaces/IManager.cs +++ b/SharedLibraryCore/Interfaces/IManager.cs @@ -6,6 +6,7 @@ using SharedLibraryCore.Database.Models; using System.Threading; using System.Collections; using System; +using Microsoft.Extensions.Logging; namespace SharedLibraryCore.Interfaces { @@ -15,6 +16,7 @@ namespace SharedLibraryCore.Interfaces Task Start(); void Stop(); void Restart(); + [Obsolete] ILogger GetLogger(long serverId); IList GetServers(); IList GetCommands(); diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index ee6234d4..2782ed38 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -8,6 +8,8 @@ using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; namespace SharedLibraryCore.Database.Models { @@ -89,6 +91,7 @@ namespace SharedLibraryCore.Database.Models SetAdditionalProperty("_reportCount", 0); ReceivedPenalties = new List(); _processingEvent = new SemaphoreSlim(1, 1); + } ~EFClient() @@ -475,39 +478,42 @@ namespace SharedLibraryCore.Database.Models { var loc = Utilities.CurrentLocalization.LocalizationIndex; - if (string.IsNullOrWhiteSpace(Name) || CleanedName.Replace(" ", "").Length < 3) + using (LogContext.PushProperty("Server", CurrentServer?.ToString())) { - CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short"); - Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer)); - return false; - } + if (string.IsNullOrWhiteSpace(Name) || CleanedName.Replace(" ", "").Length < 3) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} because their name is too short", ToString()); + Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer)); + return false; + } - if (CurrentServer.Manager.GetApplicationSettings().Configuration() - .DisallowedClientNames - ?.Any(_name => Regex.IsMatch(Name, _name)) ?? false) - { - CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is not allowed"); - Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer)); - return false; - } + if (CurrentServer.Manager.GetApplicationSettings().Configuration() + .DisallowedClientNames + ?.Any(_name => Regex.IsMatch(Name, _name)) ?? false) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} because their name is not allowed", ToString()); + Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer)); + return false; + } - if (Name.Where(c => char.IsControl(c)).Count() > 0) - { - CurrentServer.Logger.WriteDebug($"Kicking {this} because their name contains control characters"); - Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer)); - return false; - } + if (Name.Where(c => char.IsControl(c)).Count() > 0) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} because their name contains control characters", ToString()); + Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer)); + return false; + } - // reserved slots stuff - // todo: bots don't seem to honor party_maxplayers/sv_maxclients - if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber && - !this.IsPrivileged() && - CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients && - CurrentServer.MaxClients != 0) - { - CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved"); - Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer)); - return false; + // reserved slots stuff + // todo: bots don't seem to honor party_maxplayers/sv_maxclients + if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber && + !this.IsPrivileged() && + CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients && + CurrentServer.MaxClients != 0) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} their spot is reserved", ToString()); + Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer)); + return false; + } } return true; @@ -515,126 +521,151 @@ namespace SharedLibraryCore.Database.Models public async Task OnDisconnect() { - TotalConnectionTime += ConnectionLength; - LastConnection = DateTime.UtcNow; - - try + using (LogContext.PushProperty("Server", CurrentServer?.ToString())) { - await CurrentServer.Manager.GetClientService().Update(this); - } + TotalConnectionTime += ConnectionLength; + LastConnection = DateTime.UtcNow; - catch (Exception e) - { - CurrentServer.Logger.WriteWarning($"Could not update disconnected player {this}"); - CurrentServer.Logger.WriteDebug(e.GetExceptionInfo()); - } + Utilities.DefaultLogger.LogInformation("Client {client} is leaving the game", ToString()); - finally - { - State = ClientState.Unknown; + try + { + await CurrentServer.Manager.GetClientService().Update(this); + } + + catch (Exception e) + { + Utilities.DefaultLogger.LogError(e, "Could not update disconnected client {client}", + ToString()); + } + + finally + { + State = ClientState.Unknown; + } } } public async Task OnJoin(int? ipAddress) { - CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}"); - - if (ipAddress != null) + using (LogContext.PushProperty("Server", CurrentServer?.ToString())) { - IPAddress = ipAddress; - await CurrentServer.Manager.GetClientService().UpdateAlias(this); - CurrentServer.Logger.WriteDebug($"Updated alias for {this}"); - await CurrentServer.Manager.GetClientService().Update(this); - CurrentServer.Logger.WriteDebug($"Updated client for {this}"); + Utilities.DefaultLogger.LogInformation("Client {client} is joining the game from {source}", ToString(), ipAddress.HasValue ? "Status" : "Log"); - bool canConnect = await CanConnect(ipAddress); - - if (!canConnect) + if (ipAddress != null) { - CurrentServer.Logger.WriteDebug($"Client {this} is not allowed to join the server"); + IPAddress = ipAddress; + Utilities.DefaultLogger.LogInformation("Received ip from client {client}", ToString()); + await CurrentServer.Manager.GetClientService().UpdateAlias(this); + await CurrentServer.Manager.GetClientService().Update(this); + + bool canConnect = await CanConnect(ipAddress); + + if (!canConnect) + { + Utilities.DefaultLogger.LogInformation("Client {client} is not allowed to join the server", + ToString()); + } + + else + { + Utilities.DefaultLogger.LogDebug("Creating join event for {client}", ToString()); + var e = new GameEvent() + { + Type = GameEvent.EventType.Join, + Origin = this, + Target = this, + Owner = CurrentServer, + }; + + CurrentServer.Manager.AddEvent(e); + } } else { - CurrentServer.Logger.WriteDebug($"Creating join event for {this}"); - var e = new GameEvent() - { - Type = GameEvent.EventType.Join, - Origin = this, - Target = this, - Owner = CurrentServer, - }; - - CurrentServer.Manager.AddEvent(e); + Utilities.DefaultLogger.LogInformation("Waiting to receive ip from client {client}", ToString()); } - } - else - { - CurrentServer.Logger.WriteDebug($"Client {this} does not have an IP yet"); + Utilities.DefaultLogger.LogDebug("OnJoin finished for {client}", ToString()); } - - CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}"); } public async Task CanConnect(int? ipAddress) { - var loc = Utilities.CurrentLocalization.LocalizationIndex; - var autoKickClient = Utilities.IW4MAdminClient(CurrentServer); - - bool isAbleToConnectSimple = IsAbleToConnectSimple(); - - if (!isAbleToConnectSimple) + using (LogContext.PushProperty("Server", CurrentServer?.ToString())) { - return false; - } + var loc = Utilities.CurrentLocalization.LocalizationIndex; + var autoKickClient = Utilities.IW4MAdminClient(CurrentServer); - // we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID) - var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress); - var banPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Ban); - var tempbanPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan); - var flagPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag); + bool isAbleToConnectSimple = IsAbleToConnectSimple(); - // we want to kick them if any account is banned - if (banPenalty != null) - { - if (Level == Permission.Banned) + if (!isAbleToConnectSimple) { - CurrentServer.Logger.WriteDebug($"Kicking {this} because they are banned"); - Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); return false; } - else + // we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID) + var activePenalties = await CurrentServer.Manager.GetPenaltyService() + .GetActivePenaltiesAsync(AliasLinkId, ipAddress); + var banPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Ban); + var tempbanPenalty = + activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan); + var flagPenalty = + activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag); + + // we want to kick them if any account is banned + if (banPenalty != null) { - CurrentServer.Logger.WriteDebug($"Client {this} is banned, but using a new GUID, we we're updating their level and kicking them"); - await SetLevel(Permission.Banned, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, CurrentServer.Manager.CancellationToken); - Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); + if (Level == Permission.Banned) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} because they are banned", ToString()); + Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); + return false; + } + + else + { + Utilities.DefaultLogger.LogInformation( + "Client {client} is banned, but using a new GUID, we we're updating their level and kicking them", + ToString()); + await SetLevel(Permission.Banned, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, + CurrentServer.Manager.CancellationToken); + Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); + return false; + } + } + + // we want to kick them if any account is tempbanned + if (tempbanPenalty != null) + { + Utilities.DefaultLogger.LogInformation("Kicking {client} because their GUID is temporarily banned", + ToString()); + Kick( + $"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", + autoKickClient); return false; } - } - // we want to kick them if any account is tempbanned - if (tempbanPenalty != null) - { - CurrentServer.Logger.WriteDebug($"Kicking {this} because their GUID is temporarily banned"); - Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient); - return false; - } + // if we found a flag, we need to make sure all the accounts are flagged + if (flagPenalty != null && Level != Permission.Flagged) + { + Utilities.DefaultLogger.LogInformation( + "Flagged client {client} joining with new GUID, so we are changing their level to flagged", + ToString()); + await SetLevel(Permission.Flagged, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, + CurrentServer.Manager.CancellationToken); + } - // if we found a flag, we need to make sure all the accounts are flagged - if (flagPenalty != null && Level != Permission.Flagged) - { - CurrentServer.Logger.WriteDebug($"Flagged client {this} joining with new GUID, so we are changing their level to flagged"); - await SetLevel(Permission.Flagged, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, CurrentServer.Manager.CancellationToken); - } - - // remove their auto flag - if (Level == Permission.Flagged && !activePenalties.Any(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag)) - { - // remove their auto flag status after a week - CurrentServer.Logger.WriteInfo($"Unflagging {this} because the auto flag time has expired"); - Unflag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTOFLAG_UNFLAG"], autoKickClient); + // remove their auto flag + if (Level == Permission.Flagged && + !activePenalties.Any(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag)) + { + // remove their auto flag status after a week + Utilities.DefaultLogger.LogInformation("Unflagging {client} because the auto flag time has expired", + ToString()); + Unflag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTOFLAG_UNFLAG"], autoKickClient); + } } return true; diff --git a/SharedLibraryCore/RCon/StaticHelpers.cs b/SharedLibraryCore/RCon/StaticHelpers.cs index 68625a5a..1fc58b62 100644 --- a/SharedLibraryCore/RCon/StaticHelpers.cs +++ b/SharedLibraryCore/RCon/StaticHelpers.cs @@ -56,7 +56,8 @@ namespace SharedLibraryCore.RCon 1 => TimeSpan.FromMilliseconds(550), 2 => TimeSpan.FromMilliseconds(1000), 3 => TimeSpan.FromMilliseconds(2000), - _ => TimeSpan.FromMilliseconds(5000), + 4 => TimeSpan.FromMilliseconds(5000), + _ => TimeSpan.FromMilliseconds(10000), }; } /// @@ -66,6 +67,6 @@ namespace SharedLibraryCore.RCon /// /// how many failed connection attempts before aborting connection /// - public static readonly int AllowedConnectionFails = 4; + public static readonly int AllowedConnectionFails = 5; } } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 2428ce30..63c7ae4a 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -3,12 +3,14 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; - +using Microsoft.Extensions.Logging; +using Serilog.Context; using SharedLibraryCore.Helpers; using SharedLibraryCore.Dtos; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Database.Models; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore { @@ -28,14 +30,15 @@ namespace SharedLibraryCore T7 = 8 } - public Server(ServerConfiguration config, IManager mgr, IRConConnectionFactory rconConnectionFactory, IGameLogReaderFactory gameLogReaderFactory) + public Server(ILogger logger, SharedLibraryCore.Interfaces.ILogger deprecatedLogger, + ServerConfiguration config, IManager mgr, IRConConnectionFactory rconConnectionFactory, + IGameLogReaderFactory gameLogReaderFactory) { Password = config.Password; IP = config.IPAddress; Port = config.Port; Manager = mgr; - Logger = Manager.GetLogger(this.EndPoint); - Logger.WriteInfo(this.ToString()); + Logger = deprecatedLogger; ServerConfig = config; RemoteConnection = rconConnectionFactory.CreateConnection(IP, Port, Password); EventProcessing = new SemaphoreSlim(1, 1); @@ -47,6 +50,7 @@ namespace SharedLibraryCore CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName; CustomSayName = Manager.GetApplicationSettings().Configuration().CustomSayName; this.gameLogReaderFactory = gameLogReaderFactory; + ServerLogger = logger; InitializeTokens(); InitializeAutoMessages(); } @@ -123,9 +127,7 @@ namespace SharedLibraryCore public GameEvent Broadcast(string message, EFClient sender = null) { string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Say ?? "", $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}"); -#if DEBUG == true - Logger.WriteVerbose(message.StripColors()); -#endif + ServerLogger.LogDebug("All->" + message.StripColors()); var e = new GameEvent() { @@ -146,18 +148,27 @@ namespace SharedLibraryCore /// EFClient to send message to protected async Task Tell(string message, EFClient target) { -#if !DEBUG - string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, target.ClientNumber, $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}"); - if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console) - await this.ExecuteCommandAsync(formattedMessage); -#else - Logger.WriteVerbose($"{target.ClientNumber}->{message.StripColors()}"); - await Task.CompletedTask; -#endif + if (!Utilities.IsDevelopment) + { + var formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, + target.ClientNumber, + $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}"); + if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console) + await this.ExecuteCommandAsync(formattedMessage); + } + else + { + ServerLogger.LogDebug("Tell[{clientNumber}]->{message}", target.ClientNumber, message.StripColors()); + } + if (target.Level == EFClient.Permission.Console) { Console.ForegroundColor = ConsoleColor.Green; + using (LogContext.PushProperty("Server", ToString())) + { + ServerLogger.LogInformation("Command output received: {message}", message); + } Console.WriteLine(message.StripColors()); Console.ForegroundColor = ConsoleColor.Gray; } @@ -280,7 +291,8 @@ namespace SharedLibraryCore // Objects public IManager Manager { get; protected set; } - public ILogger Logger { get; private set; } + [Obsolete] + public SharedLibraryCore.Interfaces.ILogger Logger { get; private set; } public ServerConfiguration ServerConfig { get; private set; } public List Maps { get; protected set; } = new List(); public List Reports { get; set; } @@ -319,6 +331,7 @@ namespace SharedLibraryCore public string IP { get; protected set; } public string Version { get; protected set; } public bool IsInitialized { get; set; } + protected readonly ILogger ServerLogger; public int Port { get; private set; } protected string FSGame; diff --git a/SharedLibraryCore/Services/ChangeHistoryService.cs b/SharedLibraryCore/Services/ChangeHistoryService.cs index 7b3ceefb..ad49608b 100644 --- a/SharedLibraryCore/Services/ChangeHistoryService.cs +++ b/SharedLibraryCore/Services/ChangeHistoryService.cs @@ -5,11 +5,20 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore.Services { public class ChangeHistoryService : IEntityService { + private readonly ILogger _logger; + + public ChangeHistoryService(ILogger logger) + { + _logger = logger; + } + public Task Create(EFChangeHistory entity) { throw new NotImplementedException(); @@ -79,8 +88,7 @@ namespace SharedLibraryCore.Services catch (Exception ex) { - e.Owner.Logger.WriteWarning(ex.Message); - e.Owner.Logger.WriteDebug(ex.GetExceptionInfo()); + _logger.LogError(ex, "Could not persist change @{change}", change); } finally diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index 094e09bd..61deb4fe 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -8,22 +8,28 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Serilog.Context; using static SharedLibraryCore.Database.Models.EFClient; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore.Services { public class ClientService : IEntityService, IResourceQueryHelper { private readonly IDatabaseContextFactory _contextFactory; + private readonly ILogger _logger; - public ClientService(IDatabaseContextFactory databaseContextFactory) + public ClientService(ILogger logger, IDatabaseContextFactory databaseContextFactory) { _contextFactory = databaseContextFactory; + _logger = logger; } public async Task Create(EFClient entity) { using (var context = new DatabaseContext()) + using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { int? linkId = null; int? aliasId = null; @@ -40,13 +46,13 @@ namespace SharedLibraryCore.Services { linkId = existingAliases.OrderBy(_alias => _alias.LinkId).First().LinkId; - entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing link {linkId}"); + _logger.LogDebug("[create] client with new GUID {entity} has existing link {linkId}", entity.ToString(), linkId); var existingExactAlias = existingAliases.FirstOrDefault(_alias => _alias.Name == entity.Name); if (existingExactAlias != null) { - entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing alias {existingExactAlias.AliasId}"); + _logger.LogDebug("[create] client with new GUID {entity} has existing alias {aliasId}", entity.ToString(), existingExactAlias.AliasId); aliasId = existingExactAlias.AliasId; } } @@ -60,13 +66,13 @@ namespace SharedLibraryCore.Services NetworkId = entity.NetworkId }; - entity.CurrentServer.Logger.WriteDebug($"[create] adding {entity} to context"); + _logger.LogDebug("[create] adding {entity} to context", entity.ToString()); context.Clients.Add(client); // they're just using a new GUID if (aliasId.HasValue) { - entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s alias id and linkid to ({aliasId.Value}, {linkId.Value})"); + _logger.LogDebug("[create] setting {entity}'s alias id and linkid to ({aliasId}, {linkId})", entity.ToString(), aliasId, linkId); client.CurrentAliasId = aliasId.Value; client.AliasLinkId = linkId.Value; } @@ -74,7 +80,7 @@ namespace SharedLibraryCore.Services // link was found but they don't have an exact alias else if (!aliasId.HasValue && linkId.HasValue) { - entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s linkid to {linkId.Value}, but creating new alias"); + _logger.LogDebug("[create] setting {entity}'s linkid to {linkId}, but creating new alias", entity.ToString(), linkId); client.AliasLinkId = linkId.Value; client.CurrentAlias = new EFAlias() { @@ -89,7 +95,7 @@ namespace SharedLibraryCore.Services // brand new players (supposedly) else { - entity.CurrentServer.Logger.WriteDebug($"[create] creating new Link and Alias for {entity}"); + _logger.LogDebug("[create] creating new Link and Alias for {entity}", entity.ToString()); var link = new EFAliasLink(); var alias = new EFAlias() { @@ -114,129 +120,139 @@ namespace SharedLibraryCore.Services private async Task UpdateAlias(string originalName, int? ip, EFClient entity, DatabaseContext context) { - string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH); - - // entity is the tracked db context item - // get all aliases by IP address and LinkId - var iqAliases = context.Aliases - .Include(a => a.Link) - // we only want alias that have the same IP address or share a link - .Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId)); - - var aliases = await iqAliases.ToListAsync(); - var currentIPs = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct(); - var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress)).ToListAsync(); - aliases.AddRange(floatingIPAliases); - - // see if they have a matching IP + Name but new NetworkId - var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault(a => a.Name == name && a.IPAddress == ip); - bool hasExactAliasMatch = existingExactAlias != null; - - // if existing alias matches link them - var newAliasLink = existingExactAlias?.Link; - // if no exact matches find the first IP or LinkId that matches - newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link; - // if no matches are found, use our current one ( it will become permanent ) - newAliasLink = newAliasLink ?? entity.AliasLink; - - bool hasExistingAlias = aliases.Count > 0; - bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId; - - await context.SaveChangesAsync(); - int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count(); - // this happens when the link we found is different than the one we create before adding an IP - if (isAliasLinkUpdated || distinctLinkCount > 1) + using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { - entity.CurrentServer.Logger.WriteDebug($"[updatealias] found a link for {entity} so we are updating link from {entity.AliasLink.AliasLinkId} to {newAliasLink.AliasLinkId}"); + string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH); - var completeAliasLinkIds = aliases.Select(_item => _item.LinkId) - .Append(entity.AliasLinkId) - .Distinct() - .ToList(); + // entity is the tracked db context item + // get all aliases by IP address and LinkId + var iqAliases = context.Aliases + .Include(a => a.Link) + // we only want alias that have the same IP address or share a link + .Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId)); - entity.CurrentServer.Logger.WriteDebug($"[updatealias] updating aliasLinks {string.Join(',', completeAliasLinkIds)} for IP {ip} to {newAliasLink.AliasLinkId}"); + var aliases = await iqAliases.ToListAsync(); + var currentIPs = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct(); + var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress)) + .ToListAsync(); + aliases.AddRange(floatingIPAliases); - // update all the clients that have the old alias link - await context.Clients - .Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId)) - .ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId); + // see if they have a matching IP + Name but new NetworkId + var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId) + .FirstOrDefault(a => a.Name == name && a.IPAddress == ip); + bool hasExactAliasMatch = existingExactAlias != null; - // we also need to update all the penalties or they get deleted - // scenario - // link1 joins with ip1 - // link2 joins with ip2, - // link2 receives penalty - // link2 joins with ip1 - // pre existing link for link2 detected - // link2 is deleted - // link2 penalties are orphaned - await context.Penalties - .Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId)) - .ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId); + // if existing alias matches link them + var newAliasLink = existingExactAlias?.Link; + // if no exact matches find the first IP or LinkId that matches + newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link; + // if no matches are found, use our current one ( it will become permanent ) + newAliasLink = newAliasLink ?? entity.AliasLink; - entity.AliasLink = newAliasLink; - entity.AliasLinkId = newAliasLink.AliasLinkId; - - // update all previous aliases - await context.Aliases - .Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId)) - .ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId); + bool hasExistingAlias = aliases.Count > 0; + bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId; await context.SaveChangesAsync(); - // we want to delete the now inactive alias - if (newAliasLink.AliasLinkId != entity.AliasLinkId) + int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count(); + // this happens when the link we found is different than the one we create before adding an IP + if (isAliasLinkUpdated || distinctLinkCount > 1) { - context.AliasLinks.Remove(entity.AliasLink); - await context.SaveChangesAsync(); - } - } + _logger.LogDebug( + "[updatealias] found a link for {entity} so we are updating link from {oldAliasLinkId} to {newAliasLinkId}", + entity.ToString(), entity.AliasLink.AliasLinkId, newAliasLink.AliasLinkId); - // the existing alias matches ip and name, so we can just ignore the temporary one - if (hasExactAliasMatch) - { - entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} has exact alias match"); + var completeAliasLinkIds = aliases.Select(_item => _item.LinkId) + .Append(entity.AliasLinkId) + .Distinct() + .ToList(); - var oldAlias = entity.CurrentAlias; - entity.CurrentAliasId = existingExactAlias.AliasId; - entity.CurrentAlias = existingExactAlias; - await context.SaveChangesAsync(); + _logger.LogDebug("[updatealias] updating aliasLinks {links} for IP {ip} to {linkId}", + string.Join(',', completeAliasLinkIds), ip, newAliasLink.AliasLinkId); - // the alias is the same so we can just remove it - if (oldAlias.AliasId != existingExactAlias.AliasId && oldAlias.AliasId > 0) - { + // update all the clients that have the old alias link await context.Clients - .Where(_client => _client.CurrentAliasId == oldAlias.AliasId) - .ForEachAsync(_client => _client.CurrentAliasId = existingExactAlias.AliasId); + .Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId)) + .ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId); + + // we also need to update all the penalties or they get deleted + // scenario + // link1 joins with ip1 + // link2 joins with ip2, + // link2 receives penalty + // link2 joins with ip1 + // pre existing link for link2 detected + // link2 is deleted + // link2 penalties are orphaned + await context.Penalties + .Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId)) + .ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId); + + entity.AliasLink = newAliasLink; + entity.AliasLinkId = newAliasLink.AliasLinkId; + + // update all previous aliases + await context.Aliases + .Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId)) + .ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId); await context.SaveChangesAsync(); - - if (context.Entry(oldAlias).State != EntityState.Deleted) + // we want to delete the now inactive alias + if (newAliasLink.AliasLinkId != entity.AliasLinkId) { - entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} has exact alias match, so we're going to try to remove aliasId {oldAlias.AliasId} with linkId {oldAlias.AliasId}"); - context.Aliases.Remove(oldAlias); + context.AliasLinks.Remove(entity.AliasLink); await context.SaveChangesAsync(); } } - } - // theres no exact match, but they've played before with the GUID or IP - else - { - entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} is using a new alias"); - - var newAlias = new EFAlias() + // the existing alias matches ip and name, so we can just ignore the temporary one + if (hasExactAliasMatch) { - DateAdded = DateTime.UtcNow, - IPAddress = ip, - LinkId = newAliasLink.AliasLinkId, - Name = name, - SearchableName = name.StripColors().ToLower(), - Active = true, - }; + _logger.LogDebug("[updatealias] {entity} has exact alias match", entity.ToString()); - entity.CurrentAlias = newAlias; - entity.CurrentAliasId = 0; - await context.SaveChangesAsync(); + var oldAlias = entity.CurrentAlias; + entity.CurrentAliasId = existingExactAlias.AliasId; + entity.CurrentAlias = existingExactAlias; + await context.SaveChangesAsync(); + + // the alias is the same so we can just remove it + if (oldAlias.AliasId != existingExactAlias.AliasId && oldAlias.AliasId > 0) + { + await context.Clients + .Where(_client => _client.CurrentAliasId == oldAlias.AliasId) + .ForEachAsync(_client => _client.CurrentAliasId = existingExactAlias.AliasId); + + await context.SaveChangesAsync(); + + if (context.Entry(oldAlias).State != EntityState.Deleted) + { + _logger.LogDebug( + "[updatealias] {entity} has exact alias match, so we're going to try to remove aliasId {aliasId} with linkId {linkId}", + entity.ToString(), oldAlias.AliasId, oldAlias.LinkId); + context.Aliases.Remove(oldAlias); + await context.SaveChangesAsync(); + } + } + } + + // theres no exact match, but they've played before with the GUID or IP + else + { + _logger.LogDebug("[updatealias] {entity} is using a new alias", entity.ToString()); + + var newAlias = new EFAlias() + { + DateAdded = DateTime.UtcNow, + IPAddress = ip, + LinkId = newAliasLink.AliasLinkId, + Name = name, + SearchableName = name.StripColors().ToLower(), + Active = true, + }; + + entity.CurrentAlias = newAlias; + entity.CurrentAliasId = 0; + await context.SaveChangesAsync(); + } } } @@ -261,29 +277,29 @@ namespace SharedLibraryCore.Services entity.Level = newPermission; await ctx.SaveChangesAsync(); -#if DEBUG == true - temporalClient.CurrentServer.Logger.WriteDebug($"Updated {temporalClient.ClientId} to {newPermission}"); -#endif - - var linkedPermissionSet = new[] { Permission.Banned, Permission.Flagged }; - // if their permission level has been changed to level that needs to be updated on all accounts - if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission)) + using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { - //get all clients that have the same linkId - var iqMatchingClients = ctx.Clients - .Where(_client => _client.AliasLinkId == entity.AliasLinkId); + _logger.LogInformation("Updated {clientId} to {newPermission}", temporalClient.ClientId, newPermission); - // this updates the level for all the clients with the same LinkId - // only if their new level is flagged or banned - await iqMatchingClients.ForEachAsync(_client => + var linkedPermissionSet = new[] {Permission.Banned, Permission.Flagged}; + // if their permission level has been changed to level that needs to be updated on all accounts + if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission)) { - _client.Level = newPermission; -#if DEBUG == true - temporalClient.CurrentServer.Logger.WriteDebug($"Updated linked {_client.ClientId} to {newPermission}"); -#endif - }); + //get all clients that have the same linkId + var iqMatchingClients = ctx.Clients + .Where(_client => _client.AliasLinkId == entity.AliasLinkId); - await ctx.SaveChangesAsync(); + // this updates the level for all the clients with the same LinkId + // only if their new level is flagged or banned + await iqMatchingClients.ForEachAsync(_client => + { + _client.Level = newPermission; + _logger.LogInformation("Updated linked {clientId} to {newPermission}", _client.ClientId, + newPermission); + }); + + await ctx.SaveChangesAsync(); + } } } @@ -432,7 +448,7 @@ namespace SharedLibraryCore.Services { if (temporalClient.ClientId < 1) { - temporalClient.CurrentServer?.Logger.WriteDebug($"[update] {temporalClient} needs to be updated but they do not have a valid client id, ignoring.."); + _logger.LogDebug("[update] {client} needs to be updated but they do not have a valid client id, ignoring..", temporalClient.ToString()); // note: we never do anything with the result of this so we can safely return null return null; } diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 901741fb..42186029 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -3,8 +3,6 @@ Library netcoreapp3.1 - - RaidMax.IW4MAdmin.SharedLibraryCore 2.4.10 RaidMax @@ -21,8 +19,9 @@ true MIT Shared Library for IW4MAdmin - 2.4.10.0 - 2.4.10.0 + 2020.11.11.1 + 2020.11.11.1 + 2020.11.11.1 @@ -54,6 +53,7 @@ + diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 827589c1..de364089 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -17,14 +17,18 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Database.Models.EFClient; using static SharedLibraryCore.Database.Models.EFPenalty; using static SharedLibraryCore.Server; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore { public static class Utilities { + // note: this is only to be used by classes not created by dependency injection + public static ILogger DefaultLogger { get; set; } #if DEBUG == true public static string OperatingDirectory => $"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}{Path.DirectorySeparatorChar}"; #else @@ -881,8 +885,7 @@ namespace SharedLibraryCore catch (Exception e) { - logger.WriteWarning($"Could not create penalty of type {penalty.Type.ToString()}"); - logger.WriteDebug(e.GetExceptionInfo()); + logger.LogError(e, $"Could not create penalty of type {penalty.Type.ToString()}"); } return false; diff --git a/Tests/ApplicationTests/BaseEventParserTests.cs b/Tests/ApplicationTests/BaseEventParserTests.cs index 37f8f06e..242878f9 100644 --- a/Tests/ApplicationTests/BaseEventParserTests.cs +++ b/Tests/ApplicationTests/BaseEventParserTests.cs @@ -9,6 +9,7 @@ using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.GameEvent; namespace ApplicationTests @@ -18,7 +19,6 @@ namespace ApplicationTests { private EventLogTest eventLogData; private IServiceProvider serviceProvider; - private ILogger fakeLogger; private ApplicationConfiguration appConfig; [SetUp] @@ -27,13 +27,12 @@ namespace ApplicationTests eventLogData = JsonConvert.DeserializeObject(System.IO.File.ReadAllText("Files/GameEvents.json")); appConfig = ConfigurationGenerators.CreateApplicationConfiguration(); - fakeLogger = A.Fake(); serviceProvider = new ServiceCollection() + .AddSingleton(A.Fake()) .AddSingleton() .AddTransient() .AddSingleton() .AddSingleton(appConfig) - .AddSingleton(fakeLogger) .BuildServiceProvider(); } @@ -86,18 +85,6 @@ namespace ApplicationTests }); } - [Test] - public void TestCustomEventParsingLogsWarningOnException() - { - var eventParser = serviceProvider.GetService(); - - eventParser.RegisterCustomEvent("test", "test", (a, b, c) => throw new Exception()); - eventParser.GenerateGameEvent("12:12 test"); - - A.CallTo(() => fakeLogger.WriteWarning(A.Ignored)) - .MustHaveHappenedOnceExactly(); - } - [Test] public void Test_CustomCommandPrefix_Parses() { diff --git a/Tests/ApplicationTests/BaseRConParserTests.cs b/Tests/ApplicationTests/BaseRConParserTests.cs index 781fe1c1..dc4068e3 100644 --- a/Tests/ApplicationTests/BaseRConParserTests.cs +++ b/Tests/ApplicationTests/BaseRConParserTests.cs @@ -1,5 +1,6 @@ using FakeItEasy; using IW4MAdmin.Application.RconParsers; +using Microsoft.Extensions.Logging; using NUnit.Framework; using SharedLibraryCore.Interfaces; @@ -8,10 +9,12 @@ namespace ApplicationTests [TestFixture] public class BaseRConParserTests { + private readonly ILogger _fakeLogger = A.Fake>(); + [Test] public void SetDvarAsync_FormatStringType() { - var parser = new BaseRConParser(A.Fake()); + var parser = new BaseRConParser(_fakeLogger, A.Fake()); var connection = A.Fake(); parser.SetDvarAsync(connection, "test", "test").Wait(); @@ -23,7 +26,7 @@ namespace ApplicationTests [Test] public void SetDvarAsync_FormatEmptyStringTypeIncludesQuotes() { - var parser = new BaseRConParser(A.Fake()); + var parser = new BaseRConParser(_fakeLogger, A.Fake()); var connection = A.Fake(); parser.SetDvarAsync(connection, "test", "").Wait(); @@ -35,7 +38,7 @@ namespace ApplicationTests [Test] public void SetDvarAsync_FormatsNonString() { - var parser = new BaseRConParser(A.Fake()); + var parser = new BaseRConParser(_fakeLogger, A.Fake()); var connection = A.Fake(); parser.SetDvarAsync(connection, "test", 123).Wait(); diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index fc73a2cc..aa6ff8c2 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -22,7 +22,6 @@ namespace ApplicationTests [TestFixture] public class CommandTests { - ILogger logger; private IServiceProvider serviceProvider; private ITranslationLookup transLookup; private CommandConfiguration cmdConfig; @@ -34,8 +33,6 @@ namespace ApplicationTests [SetUp] public void Setup() { - logger = A.Fake(); - serviceProvider = new ServiceCollection() .BuildBase(new EventHandlerMock(true)) .AddSingleton(A.Fake()) diff --git a/Tests/ApplicationTests/DependencyInjectionExtensions.cs b/Tests/ApplicationTests/DependencyInjectionExtensions.cs index 954c7a4c..61352967 100644 --- a/Tests/ApplicationTests/DependencyInjectionExtensions.cs +++ b/Tests/ApplicationTests/DependencyInjectionExtensions.cs @@ -4,10 +4,10 @@ using FakeItEasy; using IW4MAdmin; using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; using SharedLibraryCore.Interfaces; -using SharedLibraryCore.Services; using System; +using Microsoft.Extensions.Logging; +using SharedLibraryCore; namespace ApplicationTests { @@ -34,10 +34,9 @@ namespace ApplicationTests A.CallTo(() => transLookup[A.Ignored]) .Returns("test"); - A.CallTo(() => manager.GetLogger(A.Ignored)) - .Returns(logger); - - serviceCollection.AddSingleton(logger) + serviceCollection + .AddLogging() + .AddSingleton(A.Fake()) .AddSingleton(manager) .AddSingleton() .AddSingleton(A.Fake()) @@ -53,8 +52,13 @@ namespace ApplicationTests .AddSingleton(ConfigurationGenerators.CreateCommandConfiguration()) .AddSingleton, ApplicationConfigurationHandlerMock>(); - serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService(), ConfigurationGenerators.CreateServerConfiguration(), - _sp.GetRequiredService(), _sp.GetRequiredService(), _sp.GetRequiredService(), _sp.GetRequiredService()) + serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService(), + ConfigurationGenerators.CreateServerConfiguration(), + _sp.GetRequiredService(), + _sp.GetRequiredService(), + _sp.GetRequiredService(), + _sp.GetRequiredService(), + _sp.GetRequiredService>()) { RconParser = _sp.GetRequiredService() }); diff --git a/Tests/ApplicationTests/IW4MServerTests.cs b/Tests/ApplicationTests/IW4MServerTests.cs index 02d645b6..99c269a5 100644 --- a/Tests/ApplicationTests/IW4MServerTests.cs +++ b/Tests/ApplicationTests/IW4MServerTests.cs @@ -11,6 +11,7 @@ using SharedLibraryCore.Database.Models; using System.Threading.Tasks; using ApplicationTests.Mocks; using System.Linq; +using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Exceptions; using SharedLibraryCore.Configuration; @@ -529,9 +530,6 @@ namespace ApplicationTests { await server.ProcessUpdatesAsync(new System.Threading.CancellationToken()); } - - A.CallTo(() => fakeLogger.WriteError(A.Ignored)) - .MustNotHaveHappened(); } [Test] @@ -555,9 +553,6 @@ namespace ApplicationTests await server.ExecuteEvent(e); } - A.CallTo(() => fakeLogger.WriteError(A.Ignored)) - .MustHaveHappenedOnceExactly(); - Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ConnectionLost)); Assert.AreEqual("err", (mockEventHandler.Events[0].Extra as NetworkException).Message); } diff --git a/Tests/ApplicationTests/PluginTests.cs b/Tests/ApplicationTests/PluginTests.cs index 893c8e22..475501bc 100644 --- a/Tests/ApplicationTests/PluginTests.cs +++ b/Tests/ApplicationTests/PluginTests.cs @@ -11,11 +11,9 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Services; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; namespace ApplicationTests { @@ -53,7 +51,7 @@ namespace ApplicationTests [Test] public async Task Test_GenericGuidClientIsKicked() { - var plugin = new ScriptPlugin(Path.Join(PLUGIN_DIR, "SharedGUIDKick.js"), PLUGIN_DIR); + var plugin = new ScriptPlugin(serviceProvider.GetRequiredService(), Path.Join(PLUGIN_DIR, "SharedGUIDKick.js"), PLUGIN_DIR); var server = serviceProvider.GetRequiredService(); server.GameName = Server.Game.IW4; var client = ClientGenerators.CreateBasicClient(server, hasIp: false, clientState: EFClient.ClientState.Connecting); diff --git a/Tests/ApplicationTests/ServerTests.cs b/Tests/ApplicationTests/ServerTests.cs index df792d8b..1cffc1f0 100644 --- a/Tests/ApplicationTests/ServerTests.cs +++ b/Tests/ApplicationTests/ServerTests.cs @@ -7,25 +7,19 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; using System.Diagnostics; +using Microsoft.Extensions.Logging; +using SharedLibraryCore; namespace ApplicationTests { [TestFixture] public class ServerTests { - ILogger logger; [SetUp] public void Setup() { - logger = A.Fake(); - void testLog(string msg) => Console.WriteLine(msg); - - A.CallTo(() => logger.WriteError(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteWarning(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteInfo(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteDebug(A.Ignored)).Invokes((string msg) => testLog(msg)); } [Test] @@ -34,7 +28,8 @@ namespace ApplicationTests var mgr = A.Fake(); var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, - A.Fake(), A.Fake(), A.Fake(), A.Fake()); + A.Fake(), A.Fake(), + A.Fake(), A.Fake(), A.Fake>()); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; @@ -56,11 +51,11 @@ namespace ApplicationTests public void LogFileReplay() { var mgr = A.Fake(); - A.CallTo(() => mgr.GetLogger(A.Ignored)).Returns(logger); var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, - A.Fake(), A.Fake(), A.Fake(), A.Fake()); + A.Fake(), A.Fake(), A.Fake(), A.Fake(), + A.Fake>()); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; @@ -70,7 +65,6 @@ namespace ApplicationTests foreach (string line in log) { var e = parser.GenerateGameEvent(line); - server.Logger.WriteInfo($"{e.GameTime}"); if (e.Origin != null) { e.Origin.CurrentServer = server; diff --git a/Tests/ApplicationTests/StatsTests.cs b/Tests/ApplicationTests/StatsTests.cs index e8fa46b3..9f647dc8 100644 --- a/Tests/ApplicationTests/StatsTests.cs +++ b/Tests/ApplicationTests/StatsTests.cs @@ -6,7 +6,6 @@ using FakeItEasy; using IW4MAdmin.Application.EventParsers; using System.Linq; using IW4MAdmin.Plugins.Stats.Models; -using IW4MAdmin.Application.Helpers; using IW4MAdmin.Plugins.Stats.Config; using System.Collections.Generic; using SharedLibraryCore.Database.Models; @@ -14,9 +13,12 @@ using Microsoft.Extensions.DependencyInjection; using IW4MAdmin.Plugins.Stats.Helpers; using ApplicationTests.Fixtures; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using SharedLibraryCore; using Stats.Helpers; using Stats.Dtos; using SharedLibraryCore.Configuration; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { @@ -41,13 +43,6 @@ namespace ApplicationTests .BuildServiceProvider(); contextFactory = serviceProvider.GetRequiredService(); - - void testLog(string msg) => Console.WriteLine(msg); - - A.CallTo(() => logger.WriteError(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteWarning(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteInfo(A.Ignored)).Invokes((string msg) => testLog(msg)); - A.CallTo(() => logger.WriteDebug(A.Ignored)).Invokes((string msg) => testLog(msg)); } [Test] @@ -66,13 +61,11 @@ namespace ApplicationTests A.CallTo(() => handlerFactory.GetConfigurationHandler(A.Ignored)) .Returns(config); - A.CallTo(() => mgr.GetLogger(A.Ignored)) - .Returns(logger); - var server = new IW4MServer(mgr, new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, A.Fake(), - A.Fake(), A.Fake(), A.Fake()); + A.Fake(), + A.Fake(), A.Fake(), A.Fake>()); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; diff --git a/WebfrontCore/Controllers/API/ClientController.cs b/WebfrontCore/Controllers/API/ClientController.cs index 51fe3485..9f149635 100644 --- a/WebfrontCore/Controllers/API/ClientController.cs +++ b/WebfrontCore/Controllers/API/ClientController.cs @@ -1,12 +1,13 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using SharedLibraryCore; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using WebfrontCore.Controllers.API.Dtos; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace WebfrontCore.Controllers.API { @@ -20,7 +21,7 @@ namespace WebfrontCore.Controllers.API private readonly IResourceQueryHelper _clientQueryHelper; private readonly ILogger _logger; - public ClientController(ILogger logger, IResourceQueryHelper clientQueryHelper) + public ClientController(ILogger logger, IResourceQueryHelper clientQueryHelper) { _logger = logger; _clientQueryHelper = clientQueryHelper; @@ -53,8 +54,7 @@ namespace WebfrontCore.Controllers.API catch (Exception e) { - _logger.WriteWarning($"Failed to retrieve clients with query - {request.ToDebugString()}"); - _logger.WriteDebug(e.GetExceptionInfo()); + _logger.LogWarning(e, "Failed to retrieve clients with query - {@request}", request); return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse() { diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index 7b3d75c2..a7e79261 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -171,7 +171,7 @@ namespace WebfrontCore.Controllers var meta = await ProfileMetaListViewComponent.GetClientMeta(_metaService, metaFilterType, Client.Level, request); - if (meta.Count() == 0) + if (!meta.Any()) { return Ok(); } diff --git a/WebfrontCore/Controllers/HomeController.cs b/WebfrontCore/Controllers/HomeController.cs index 77aa71ec..fbc03f6d 100644 --- a/WebfrontCore/Controllers/HomeController.cs +++ b/WebfrontCore/Controllers/HomeController.cs @@ -3,19 +3,22 @@ using Microsoft.AspNetCore.Mvc; using SharedLibraryCore; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace WebfrontCore.Controllers { public class HomeController : BaseController { private readonly ITranslationLookup _translationLookup; + private readonly ILogger _logger; - public HomeController(IManager manager, ITranslationLookup translationLookup) : base(manager) + public HomeController(ILogger logger, IManager manager, ITranslationLookup translationLookup) : base(manager) { + _logger = logger; _translationLookup = translationLookup; } @@ -43,10 +46,7 @@ namespace WebfrontCore.Controllers public IActionResult Error() { var exceptionFeature = HttpContext.Features.Get(); - Manager.GetLogger(0).WriteError($"[Webfront] {exceptionFeature.Error.Message}"); - Manager.GetLogger(0).WriteDebug(exceptionFeature.Path); - Manager.GetLogger(0).WriteDebug(exceptionFeature.Error.StackTrace); - + _logger.LogError("[Webfront] {path} {message} {@exception}", exceptionFeature.Path, exceptionFeature.Error.Message, exceptionFeature.Error); ViewBag.Description = Localization["WEBFRONT_ERROR_DESC"]; ViewBag.Title = Localization["WEBFRONT_ERROR_TITLE"]; return View(exceptionFeature.Error); diff --git a/WebfrontCore/Middleware/IPWhitelist.cs b/WebfrontCore/Middleware/IPWhitelist.cs index 85d8c163..e6cebe32 100644 --- a/WebfrontCore/Middleware/IPWhitelist.cs +++ b/WebfrontCore/Middleware/IPWhitelist.cs @@ -1,9 +1,8 @@ using Microsoft.AspNetCore.Http; -using SharedLibraryCore.Interfaces; -using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace WebfrontCore.Middleware { @@ -22,7 +21,7 @@ namespace WebfrontCore.Middleware /// /// /// list of textual ip addresses - public IPWhitelist(RequestDelegate nextRequest, ILogger logger, string[] whitelistedIps) + public IPWhitelist(RequestDelegate nextRequest, ILogger logger, string[] whitelistedIps) { _whitelistedIps = whitelistedIps.Select(_ip => System.Net.IPAddress.Parse(_ip).GetAddressBytes()).ToArray(); _nextRequest = nextRequest; @@ -31,21 +30,21 @@ namespace WebfrontCore.Middleware public async Task Invoke(HttpContext context) { - bool isAlllowed = true; + var isAllowed = true; if (_whitelistedIps.Length > 0) { - isAlllowed = _whitelistedIps.Any(_ip => _ip.SequenceEqual(context.Connection.RemoteIpAddress.GetAddressBytes())); + isAllowed = _whitelistedIps.Any(_ip => _ip.SequenceEqual(context.Connection.RemoteIpAddress.GetAddressBytes())); } - if (isAlllowed) + if (isAllowed) { await _nextRequest.Invoke(context); } else { - _logger.WriteInfo($"Blocking HTTP request from {context.Connection.RemoteIpAddress.ToString()}"); + _logger.LogDebug("Blocking HTTP request from {ipAddress}", context.Connection.RemoteIpAddress); context.Abort(); } } diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index 6db504e2..9d640d81 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -79,11 +79,11 @@ namespace WebfrontCore }); #if DEBUG - mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); + /*mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); services.Configure(_options => { _options.ViewLocationFormats.Add(@"/Views/Plugins/{1}/{0}" + RazorViewEngine.ViewExtension); - }); + });*/ #endif foreach (var asm in pluginAssemblies()) @@ -103,13 +103,6 @@ namespace WebfrontCore options.LoginPath = "/"; }); -#if DEBUG - services.AddLogging(_builder => - { - _builder.AddDebug(); - }); -#endif - services.AddSingleton(Program.Manager); services.AddSingleton, ChatResourceQueryHelper>(); services.AddTransient, FindClientRequestValidator>(); @@ -121,7 +114,6 @@ namespace WebfrontCore services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); - services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService>()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); @@ -152,7 +144,7 @@ namespace WebfrontCore if (Program.Manager.GetApplicationSettings().Configuration().EnableWebfrontConnectionWhitelist) { - app.UseMiddleware(manager.GetLogger(0), manager.GetApplicationSettings().Configuration().WebfrontConnectionWhitelist); + app.UseMiddleware(Program.ApplicationServiceProvider.GetService>(), manager.GetApplicationSettings().Configuration().WebfrontConnectionWhitelist); } app.UseStaticFiles(); diff --git a/WebfrontCore/Views/Client/Find/Index.cshtml b/WebfrontCore/Views/Client/Find/Index.cshtml index 45387ec5..81d95162 100644 --- a/WebfrontCore/Views/Client/Find/Index.cshtml +++ b/WebfrontCore/Views/Client/Find/Index.cshtml @@ -1,4 +1,4 @@ -@model List +@model IList @{ var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; } diff --git a/WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml b/WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml index 63f6c2ac..ed1dde7d 100644 --- a/WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml +++ b/WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml @@ -1,7 +1,7 @@ @{ Layout = null; } -@model List +@model IList @{ foreach (var penalty in Model) diff --git a/WebfrontCore/Views/Shared/ResponseStatusCode.cshtml b/WebfrontCore/Views/Shared/ResponseStatusCode.cshtml index 384a4360..0a79e164 100644 --- a/WebfrontCore/Views/Shared/ResponseStatusCode.cshtml +++ b/WebfrontCore/Views/Shared/ResponseStatusCode.cshtml @@ -1,4 +1,4 @@ -@model int +@model int? @{ ViewData["Title"] = "Error"; } @@ -6,7 +6,7 @@

@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_ERROR_GENERIC_TITLE"]

@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_ERROR_GENERIC_DESC"]

- @if (Model == 404) + @if (Model.HasValue && Model.Value == 404) { @SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_ERROR_NOTFOUND"] } diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index b3e416e1..db0af4d2 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -81,7 +81,13 @@ - + + + + + + + From 5d9c8f5369d728ec66e806f0f1919bffd5abbe4c Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 11 Nov 2020 18:53:23 -0600 Subject: [PATCH 006/143] fix introduced issue with map/map_rotate commands --- Application/Application.csproj | 4 +--- Application/IW4MServer.cs | 2 +- Application/RCon/RConConnection.cs | 18 +++++++++++++----- Application/RconParsers/BaseRConParser.cs | 11 +++++++++++ .../ScriptPlugins/SampleScriptPluginCommand.js | 1 - .../Interfaces/IRConConnection.cs | 6 +++--- SharedLibraryCore/Interfaces/IRConParser.cs | 10 +++++++++- Tests/ApplicationTests/IW4MServerTests.cs | 1 + WebfrontCore/WebfrontCore.csproj | 8 +------- 9 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Application/Application.csproj b/Application/Application.csproj index 8665b750..39f2879d 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -5,7 +5,7 @@ netcoreapp3.1 false RaidMax.IW4MAdmin.Application - 2.3.2.0 + 2020.0.0.0 RaidMax Forever None IW4MAdmin @@ -21,8 +21,6 @@ IW4MAdmin.Application false - 2020.0.0.0 - 2020.0.0.0 diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 26e0fecb..75a1331f 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -952,7 +952,7 @@ namespace IW4MAdmin RconParser = RconParser ?? Manager.AdditionalRConParsers[0]; EventParser = EventParser ?? Manager.AdditionalEventParsers[0]; - RemoteConnection.SetConfiguration(RconParser.Configuration); + RemoteConnection.SetConfiguration(RconParser); var version = await this.GetMappedDvarValueOrDefaultAsync("version"); Version = version.Value; diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index c320800c..2c81bab5 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -26,6 +26,7 @@ namespace IW4MAdmin.Application.RCon public IPEndPoint Endpoint { get; private set; } public string RConPassword { get; private set; } + private IRConParser parser; private IRConParserConfiguration config; private readonly ILogger _log; private readonly Encoding _gameEncoding; @@ -38,9 +39,10 @@ namespace IW4MAdmin.Application.RCon _log = log; } - public void SetConfiguration(IRConParserConfiguration config) + public void SetConfiguration(IRConParser parser) { - this.config = config; + this.parser = parser; + config = parser.Configuration; } public async Task SendQueryAsync(StaticHelpers.QueryType type, string parameters = "") @@ -146,7 +148,8 @@ namespace IW4MAdmin.Application.RCon try { - response = await SendPayloadAsync(payload, waitForResponse); + + response = await SendPayloadAsync(payload, waitForResponse, parser.OverrideTimeoutForCommand(parameters)); if ((response.Length == 0 || response[0].Length == 0) && waitForResponse) { @@ -286,7 +289,7 @@ namespace IW4MAdmin.Application.RCon } } - private async Task SendPayloadAsync(byte[] payload, bool waitForResponse) + private async Task SendPayloadAsync(byte[] payload, bool waitForResponse, TimeSpan overrideTimeout) { var connectionState = ActiveQueries[this.Endpoint]; var rconSocket = (Socket)connectionState.SendEventArgs.UserToken; @@ -337,7 +340,12 @@ namespace IW4MAdmin.Application.RCon if (receiveDataPending) { _log.LogDebug("Waiting to asynchronously receive data on attempt #{connectionAttempts}", connectionState.ConnectionAttempts); - if (!await Task.Run(() => connectionState.OnReceivedData.Wait(StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts)))) + if (!await Task.Run(() => connectionState.OnReceivedData.Wait( + new[] + { + StaticHelpers.SocketTimeout(connectionState.ConnectionAttempts), + overrideTimeout + }.Max()))) { if (connectionState.ConnectionAttempts > 1) // this reduces some spam for unstable connections { diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index 6b8b63a8..ab0aebd7 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -278,5 +278,16 @@ namespace IW4MAdmin.Application.RconParsers public T GetDefaultDvarValue(string dvarName) => Configuration.DefaultDvarValues.ContainsKey(dvarName) ? (T)Convert.ChangeType(Configuration.DefaultDvarValues[dvarName], typeof(T)) : default; + + public TimeSpan OverrideTimeoutForCommand(string command) + { + if (command.Contains("map_rotate", StringComparison.InvariantCultureIgnoreCase) || + command.StartsWith("map ", StringComparison.InvariantCultureIgnoreCase)) + { + return TimeSpan.FromSeconds(30); + } + + return TimeSpan.Zero; + } } } diff --git a/Plugins/ScriptPlugins/SampleScriptPluginCommand.js b/Plugins/ScriptPlugins/SampleScriptPluginCommand.js index 63929aa3..b02f9238 100644 --- a/Plugins/ScriptPlugins/SampleScriptPluginCommand.js +++ b/Plugins/ScriptPlugins/SampleScriptPluginCommand.js @@ -27,7 +27,6 @@ let commands = [{ // we want to print out a pong message for the number of times they requested for (var i = 0; i < times; i++) { - gameEvent.Origin = undefined; gameEvent.Origin.Tell(`^${i}pong #${i + 1}^7`); // don't want to wait if it's the last pong diff --git a/SharedLibraryCore/Interfaces/IRConConnection.cs b/SharedLibraryCore/Interfaces/IRConConnection.cs index ec716c3d..2d4a715b 100644 --- a/SharedLibraryCore/Interfaces/IRConConnection.cs +++ b/SharedLibraryCore/Interfaces/IRConConnection.cs @@ -17,9 +17,9 @@ namespace SharedLibraryCore.Interfaces Task SendQueryAsync(StaticHelpers.QueryType type, string parameters = ""); /// - /// sets the rcon parser configuration + /// sets the rcon parser /// - /// parser config - void SetConfiguration(IRConParserConfiguration config); + /// parser + void SetConfiguration(IRConParser config); } } diff --git a/SharedLibraryCore/Interfaces/IRConParser.cs b/SharedLibraryCore/Interfaces/IRConParser.cs index d560a377..8a03ed01 100644 --- a/SharedLibraryCore/Interfaces/IRConParser.cs +++ b/SharedLibraryCore/Interfaces/IRConParser.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using SharedLibraryCore.Database.Models; using static SharedLibraryCore.Server; @@ -82,5 +83,12 @@ namespace SharedLibraryCore.Interfaces /// dvar key name /// T GetDefaultDvarValue(string dvarName); + + /// + /// determines the amount of time to wait for the command to respond + /// + /// name of command being executed + /// + TimeSpan OverrideTimeoutForCommand(string command); } } diff --git a/Tests/ApplicationTests/IW4MServerTests.cs b/Tests/ApplicationTests/IW4MServerTests.cs index 99c269a5..8cdda09a 100644 --- a/Tests/ApplicationTests/IW4MServerTests.cs +++ b/Tests/ApplicationTests/IW4MServerTests.cs @@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Exceptions; using SharedLibraryCore.Configuration; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index db0af4d2..b3e416e1 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -81,13 +81,7 @@ - - - - - - - + From e997b94b3b7434b9110322069ef5b89817ef5665 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 12 Nov 2020 19:46:17 -0600 Subject: [PATCH 007/143] update unit tests --- Application/IO/GameLogEventDetection.cs | 2 +- .../ApplicationTests/BaseEventParserTests.cs | 2 +- Tests/ApplicationTests/ClientTests.cs | 1 + Tests/ApplicationTests/CommandTests.cs | 5 ++++ .../DependencyInjectionExtensions.cs | 18 +++--------- Tests/ApplicationTests/IOTests.cs | 14 ++++++---- Tests/ApplicationTests/IW4MServerTests.cs | 10 ++++--- Tests/ApplicationTests/PluginTests.cs | 2 +- Tests/ApplicationTests/ServerTests.cs | 28 ++++++------------- Tests/ApplicationTests/StatsTests.cs | 28 ++++++++++--------- 10 files changed, 52 insertions(+), 58 deletions(-) diff --git a/Application/IO/GameLogEventDetection.cs b/Application/IO/GameLogEventDetection.cs index 9a9a1f0b..955a95c5 100644 --- a/Application/IO/GameLogEventDetection.cs +++ b/Application/IO/GameLogEventDetection.cs @@ -17,7 +17,7 @@ namespace IW4MAdmin.Application.IO private readonly bool _ignoreBots; private readonly ILogger _logger; - public GameLogEventDetection(ILogger logger, Server server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory) + public GameLogEventDetection(ILogger logger, IW4MServer server, Uri[] gameLogUris, IGameLogReaderFactory gameLogReaderFactory) { _reader = gameLogReaderFactory.CreateGameLogReader(gameLogUris, server.EventParser); _server = server; diff --git a/Tests/ApplicationTests/BaseEventParserTests.cs b/Tests/ApplicationTests/BaseEventParserTests.cs index 242878f9..40cd4374 100644 --- a/Tests/ApplicationTests/BaseEventParserTests.cs +++ b/Tests/ApplicationTests/BaseEventParserTests.cs @@ -9,8 +9,8 @@ using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; -using Microsoft.Extensions.Logging; using static SharedLibraryCore.GameEvent; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { diff --git a/Tests/ApplicationTests/ClientTests.cs b/Tests/ApplicationTests/ClientTests.cs index 4a294968..788972cb 100644 --- a/Tests/ApplicationTests/ClientTests.cs +++ b/Tests/ApplicationTests/ClientTests.cs @@ -8,6 +8,7 @@ using SharedLibraryCore.Database.Models; using System; using System.Collections.Generic; using System.Text; +using SharedLibraryCore.Configuration; namespace ApplicationTests { diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index aa6ff8c2..8de324be 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -16,6 +16,7 @@ using SharedLibraryCore.Services; using static SharedLibraryCore.Database.Models.EFClient; using FluentAssertions; using FluentAssertions.Extensions; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { @@ -50,6 +51,10 @@ namespace ApplicationTests appConfig = serviceProvider.GetRequiredService(); appConfig.MapChangeDelaySeconds = 1; cmdConfig = serviceProvider.GetRequiredService(); + serviceProvider.GetService().RconParser = + serviceProvider.GetService(); + + Utilities.DefaultLogger = serviceProvider.GetRequiredService(); A.CallTo(() => manager.GetClientService()) .Returns(clientService); diff --git a/Tests/ApplicationTests/DependencyInjectionExtensions.cs b/Tests/ApplicationTests/DependencyInjectionExtensions.cs index 61352967..f2496260 100644 --- a/Tests/ApplicationTests/DependencyInjectionExtensions.cs +++ b/Tests/ApplicationTests/DependencyInjectionExtensions.cs @@ -6,8 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; -using Microsoft.Extensions.Logging; -using SharedLibraryCore; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { @@ -28,7 +27,6 @@ namespace ApplicationTests } var manager = A.Fake(); - var logger = A.Fake(); var transLookup = A.Fake(); A.CallTo(() => transLookup[A.Ignored]) @@ -37,8 +35,11 @@ namespace ApplicationTests serviceCollection .AddLogging() .AddSingleton(A.Fake()) + .AddSingleton(A.Fake()) + .AddSingleton(new ServerConfiguration { IPAddress = "127.0.0.1", Port = 28960 }) .AddSingleton(manager) .AddSingleton() + .AddSingleton() .AddSingleton(A.Fake()) .AddSingleton(A.Fake()) .AddSingleton(transLookup) @@ -52,17 +53,6 @@ namespace ApplicationTests .AddSingleton(ConfigurationGenerators.CreateCommandConfiguration()) .AddSingleton, ApplicationConfigurationHandlerMock>(); - serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService(), - ConfigurationGenerators.CreateServerConfiguration(), - _sp.GetRequiredService(), - _sp.GetRequiredService(), - _sp.GetRequiredService(), - _sp.GetRequiredService(), - _sp.GetRequiredService>()) - { - RconParser = _sp.GetRequiredService() - }); - return serviceCollection; } diff --git a/Tests/ApplicationTests/IOTests.cs b/Tests/ApplicationTests/IOTests.cs index 9c09767a..d137e986 100644 --- a/Tests/ApplicationTests/IOTests.cs +++ b/Tests/ApplicationTests/IOTests.cs @@ -1,12 +1,11 @@ using FakeItEasy; -using IW4MAdmin; using IW4MAdmin.Application.IO; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; -using SharedLibraryCore; using SharedLibraryCore.Interfaces; using System; using System.Threading.Tasks; +using SharedLibraryCore; namespace ApplicationTests { @@ -19,19 +18,24 @@ namespace ApplicationTests [SetUp] public void Setup() { - serviceProvider = new ServiceCollection().BuildBase().BuildServiceProvider(); + serviceProvider = new ServiceCollection() + .BuildBase() + .AddSingleton(new Uri[] { new Uri("C:\\test.log")}) + .AddSingleton(A.Fake()) + .AddSingleton() + .BuildServiceProvider(); } [Test] public async Task GameLogEventDetection_WorksAfterFileSizeReset() { var reader = A.Fake(); - var factory = A.Fake(); + var factory = serviceProvider.GetRequiredService(); A.CallTo(() => factory.CreateGameLogReader(A.Ignored, A.Ignored)) .Returns(reader); - var detect = new GameLogEventDetection(serviceProvider.GetService(), new Uri[] { new Uri("C:\\test.log") }, factory); + var detect = serviceProvider.GetRequiredService(); A.CallTo(() => reader.Length) .Returns(100) diff --git a/Tests/ApplicationTests/IW4MServerTests.cs b/Tests/ApplicationTests/IW4MServerTests.cs index 8cdda09a..e1a1b1dd 100644 --- a/Tests/ApplicationTests/IW4MServerTests.cs +++ b/Tests/ApplicationTests/IW4MServerTests.cs @@ -41,6 +41,8 @@ namespace ApplicationTests fakeRConParser = serviceProvider.GetRequiredService(); mockEventHandler = serviceProvider.GetRequiredService(); appConfig = serviceProvider.GetRequiredService(); + serviceProvider.GetService().RconParser = + serviceProvider.GetService(); var rconConnectionFactory = serviceProvider.GetRequiredService(); @@ -215,7 +217,7 @@ namespace ApplicationTests await server.Ban("test reason", target, origin); - A.CallTo(() => fakeRConParser.ExecuteCommandAsync(fakeRConConnection, "kick")) + A.CallTo(() => server.RconParser.ExecuteCommandAsync(A.Ignored, "kick")) .MustHaveHappenedOnceExactly(); } @@ -290,7 +292,7 @@ namespace ApplicationTests await server.TempBan("test reason", TimeSpan.Zero, target, origin); - A.CallTo(() => fakeRConParser.ExecuteCommandAsync(fakeRConConnection, "kick")) + A.CallTo(() => server.RconParser.ExecuteCommandAsync(A.Ignored, "kick")) .MustHaveHappenedOnceExactly(); } @@ -312,7 +314,7 @@ namespace ApplicationTests await server.TempBan("test reason", TimeSpan.Zero, target, origin); - A.CallTo(() => fakeRConParser.ExecuteCommandAsync(fakeRConConnection, "kick")) + A.CallTo(() => server.RconParser.ExecuteCommandAsync(A.Ignored, "kick")) .MustHaveHappenedOnceExactly(); } #endregion @@ -348,7 +350,7 @@ namespace ApplicationTests await server.Kick("test reason", target, origin); - A.CallTo(() => fakeRConParser.ExecuteCommandAsync(fakeRConConnection, "kick")) + A.CallTo(() => server.RconParser.ExecuteCommandAsync(A.Ignored, "kick")) .MustHaveHappenedOnceExactly(); } diff --git a/Tests/ApplicationTests/PluginTests.cs b/Tests/ApplicationTests/PluginTests.cs index 475501bc..a05bd750 100644 --- a/Tests/ApplicationTests/PluginTests.cs +++ b/Tests/ApplicationTests/PluginTests.cs @@ -13,7 +13,7 @@ using SharedLibraryCore.Services; using System; using System.IO; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { diff --git a/Tests/ApplicationTests/ServerTests.cs b/Tests/ApplicationTests/ServerTests.cs index 1cffc1f0..ea3833fb 100644 --- a/Tests/ApplicationTests/ServerTests.cs +++ b/Tests/ApplicationTests/ServerTests.cs @@ -1,36 +1,32 @@ using FakeItEasy; using IW4MAdmin; -using IW4MAdmin.Application; using IW4MAdmin.Application.EventParsers; using NUnit.Framework; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; -using System.Diagnostics; -using Microsoft.Extensions.Logging; -using SharedLibraryCore; +using Microsoft.Extensions.DependencyInjection; +using ILogger = Microsoft.Extensions.Logging.ILogger; namespace ApplicationTests { [TestFixture] public class ServerTests { - + private IServiceProvider _serviceProvider; + [SetUp] public void Setup() { - + _serviceProvider = new ServiceCollection() + .BuildBase() + .BuildServiceProvider(); } [Test] public void GameTimeFalseQuitTest() { - var mgr = A.Fake(); - var server = new IW4MServer(mgr, - new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, - A.Fake(), A.Fake(), - A.Fake(), A.Fake(), A.Fake>()); - + var server = _serviceProvider.GetRequiredService(); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; @@ -50,13 +46,7 @@ namespace ApplicationTests [Test] public void LogFileReplay() { - var mgr = A.Fake(); - - var server = new IW4MServer(mgr, - new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, - A.Fake(), A.Fake(), A.Fake(), A.Fake(), - A.Fake>()); - + var server = _serviceProvider.GetRequiredService(); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; diff --git a/Tests/ApplicationTests/StatsTests.cs b/Tests/ApplicationTests/StatsTests.cs index 9f647dc8..7ac2b1dd 100644 --- a/Tests/ApplicationTests/StatsTests.cs +++ b/Tests/ApplicationTests/StatsTests.cs @@ -13,8 +13,6 @@ using Microsoft.Extensions.DependencyInjection; using IW4MAdmin.Plugins.Stats.Helpers; using ApplicationTests.Fixtures; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using SharedLibraryCore; using Stats.Helpers; using Stats.Dtos; using SharedLibraryCore.Configuration; @@ -37,8 +35,11 @@ namespace ApplicationTests handlerFactory = A.Fake(); serviceProvider = new ServiceCollection() - .AddSingleton() .BuildBase() + .AddSingleton(A.Fake>()) + .AddSingleton() + .AddSingleton(new ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }) + .AddSingleton() .AddSingleton() .BuildServiceProvider(); @@ -61,11 +62,7 @@ namespace ApplicationTests A.CallTo(() => handlerFactory.GetConfigurationHandler(A.Ignored)) .Returns(config); - var server = new IW4MServer(mgr, - new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 }, - A.Fake(), - A.Fake(), - A.Fake(), A.Fake(), A.Fake>()); + var server = serviceProvider.GetRequiredService(); var parser = new BaseEventParser(A.Fake(), A.Fake(), A.Fake()); parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer; @@ -128,8 +125,8 @@ namespace ApplicationTests public async Task Test_ConcurrentCallsToUpdateStatHistoryDoesNotCauseException() { var server = serviceProvider.GetRequiredService(); - var configHandler = A.Fake>(); - var mgr = new StatManager(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService(), configHandler); + var configHandler = serviceProvider.GetRequiredService>(); + var mgr = serviceProvider.GetRequiredService(); var target = ClientGenerators.CreateDatabaseClient(); target.CurrentServer = server; @@ -141,10 +138,11 @@ namespace ApplicationTests var dbFactory = serviceProvider.GetRequiredService(); var db = dbFactory.CreateContext(true); - db.Set().Add(new EFServer() + var efServer = new EFServer() { EndPoint = server.EndPoint.ToString() - }); + }; + db.Set().Add(efServer); db.Clients.Add(target); db.SaveChanges(); @@ -154,6 +152,10 @@ namespace ApplicationTests var stats = target.GetAdditionalProperty("ClientStats"); await mgr.UpdateStatHistory(target, stats); + + db.Clients.Remove(target); + db.Set().Remove(efServer); + await db.SaveChangesAsync(); } #region QUERY_HELPER @@ -161,7 +163,7 @@ namespace ApplicationTests public async Task Test_StatsQueryHelper_Get() { var queryHelper = serviceProvider.GetRequiredService(); - using var context = contextFactory.CreateContext(); + await using var context = contextFactory.CreateContext(); var server = new EFServer() { ServerId = 1 }; var stats = new EFClientStatistics() From 6619ce714a0f49971503b5904bee64aac33bcbc2 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 12 Nov 2020 20:39:56 -0600 Subject: [PATCH 008/143] modify iw6x parser to default game log vars temporarily, small amount of code cleanup to git rid of warnings --- Application/RCon/RConConnection.cs | 12 +++++++++++- Plugins/ScriptPlugins/ParserIW6x.js | 4 +++- .../Web/StatsWeb/Controllers/StatsController.cs | 9 +++++---- .../Stats/Components/TopPlayers/_List.cshtml | 16 ++++++++++++++++ .../StatsWeb/Views/Stats/_MessageContext.cshtml | 2 +- .../ViewComponents/PenaltyListViewComponent.cs | 2 +- .../PenaltyInfoList.cshtml} | 0 7 files changed, 37 insertions(+), 8 deletions(-) rename WebfrontCore/Views/{Shared/Components/PenaltyList/_List.cshtml => Penalty/PenaltyInfoList.cshtml} (100%) diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 2c81bab5..6586cdef 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -128,7 +128,17 @@ namespace IW4MAdmin.Application.RCon byte[][] response = null; - retrySend: + retrySend: + if (connectionState.ConnectionAttempts > 1) + { + using (LogContext.PushProperty("Server", Endpoint.ToString())) + { + _log.LogInformation( + "Retrying RCon message ({connectionAttempts}/{allowedConnectionFailures} attempts) with parameters {payload}", + connectionState.ConnectionAttempts, + StaticHelpers.AllowedConnectionFails, parameters); + } + } using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { DontFragment = true, diff --git a/Plugins/ScriptPlugins/ParserIW6x.js b/Plugins/ScriptPlugins/ParserIW6x.js index a9133446..5f8ce15f 100644 --- a/Plugins/ScriptPlugins/ParserIW6x.js +++ b/Plugins/ScriptPlugins/ParserIW6x.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'Xerxes, RaidMax', - version: 0.1, + version: 0.2, name: 'IW6x Parser', isParser: true, @@ -27,6 +27,8 @@ var plugin = { rconParser.Configuration.Status.AddMapping(102, 4); rconParser.Configuration.Status.AddMapping(103, 5); rconParser.Configuration.Status.AddMapping(104, 6); + rconParser.Configuration.DefaultDvarValues.Add('g_log', 'games_mp.log'); // todo: remove this once proper log support is implemented + rconParser.Configuration.DefaultDvarValues.Add('g_logsync', '1'); // todo: remove this once proper log support is implemented rconParser.Version = 'IW6 MP 3.15 build 2 Sat Sep 14 2013 03:58:30PM win64'; rconParser.GameName = 4; // IW6 diff --git a/Plugins/Web/StatsWeb/Controllers/StatsController.cs b/Plugins/Web/StatsWeb/Controllers/StatsController.cs index 1fa81696..1fc704a5 100644 --- a/Plugins/Web/StatsWeb/Controllers/StatsController.cs +++ b/Plugins/Web/StatsWeb/Controllers/StatsController.cs @@ -10,6 +10,7 @@ using SharedLibraryCore.Interfaces; using Stats.Dtos; using StatsWeb.Extensions; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -88,7 +89,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers SentAfter = whenLower }); - return View("_MessageContext", messages.Results); + return View("_MessageContext", messages.Results.ToList()); } [HttpGet("Message/Find")] @@ -187,13 +188,13 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers // we want to show anything related to the automated offense else { - return View("_MessageContext", new[] + return View("_MessageContext", new List { - new ChatInfo() + new MessageResponse() { ClientId = penalty.OffenderId, Message = penalty.AutomatedOffense, - Time = penalty.When + When = penalty.When } }); } diff --git a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml b/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml index ebb5bb3f..b747b6fc 100644 --- a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml +++ b/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml @@ -6,21 +6,37 @@ string rankIcon(double elo) { if (elo >= getDeviation(-0.75) && elo < getDeviation(1.25)) + { return "0_no-place/menu_div_no_place.png"; + } if (elo >= getDeviation(0.125) && elo < getDeviation(0.625)) + { return "1_iron/menu_div_iron_sub03.png"; + } if (elo >= getDeviation(0.625) && elo < getDeviation(1.0)) + { return "2_bronze/menu_div_bronze_sub03.png"; + } if (elo >= getDeviation(1.0) && elo < getDeviation(1.25)) + { return "3_silver/menu_div_silver_sub03.png"; + } if (elo >= getDeviation(1.25) && elo < getDeviation(1.5)) + { return "4_gold/menu_div_gold_sub03.png"; + } if (elo >= getDeviation(1.5) && elo < getDeviation(1.75)) + { return "5_platinum/menu_div_platinum_sub03.png"; + } if (elo >= getDeviation(1.75) && elo < getDeviation(2.0)) + { return "6_semipro/menu_div_semipro_sub03.png"; + } if (elo >= getDeviation(2.0)) + { return "7_pro/menu_div_pro_sub03.png"; + } return "0_no-place/menu_div_no_place.png"; } diff --git a/Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml b/Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml index 602d21b5..c9adc191 100644 --- a/Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml +++ b/Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml @@ -1,5 +1,5 @@ @using SharedLibraryCore.Dtos.Meta.Responses -@model IEnumerable +@model IList @{ Layout = null; } diff --git a/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs b/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs index 93074857..ccb1ceae 100644 --- a/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs +++ b/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs @@ -14,7 +14,7 @@ namespace WebfrontCore.ViewComponents var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(PENALTY_COUNT, offset, showOnly, ignoreAutomated); penalties = User.Identity.IsAuthenticated ? penalties : penalties.Where(p => !p.Sensitive).ToList(); - return View("_List", penalties); + return View("~/Views/Penalty/PenaltyInfoList.cshtml", penalties); } } } diff --git a/WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml b/WebfrontCore/Views/Penalty/PenaltyInfoList.cshtml similarity index 100% rename from WebfrontCore/Views/Shared/Components/PenaltyList/_List.cshtml rename to WebfrontCore/Views/Penalty/PenaltyInfoList.cshtml From 664eb325877858c1be34aa2ed29121871491f8eb Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 14 Nov 2020 10:53:01 -0600 Subject: [PATCH 009/143] fix small logging issue with loading plugins add minigun turret to list of ignored ac weapons --- Application/Misc/ScriptPlugin.cs | 2 +- Plugins/Stats/Config/AnticheatConfiguration.cs | 2 +- Plugins/Stats/Helpers/StatManager.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Application/Misc/ScriptPlugin.cs b/Application/Misc/ScriptPlugin.cs index 4075cac3..20568a7c 100644 --- a/Application/Misc/ScriptPlugin.cs +++ b/Application/Misc/ScriptPlugin.cs @@ -183,7 +183,7 @@ namespace IW4MAdmin.Application.Misc catch (Exception ex) { _logger.LogError(ex, - "Encountered unexpected error while running {methodName} for script plugin {plugin} with event type {eventType}", + "Encountered unexpected error while running {methodName} for script plugin {plugin}", nameof(OnLoadAsync), _fileName); throw new PluginException("An unexpected error occured while initializing script plugin"); diff --git a/Plugins/Stats/Config/AnticheatConfiguration.cs b/Plugins/Stats/Config/AnticheatConfiguration.cs index a85e2922..f0a9de6f 100644 --- a/Plugins/Stats/Config/AnticheatConfiguration.cs +++ b/Plugins/Stats/Config/AnticheatConfiguration.cs @@ -15,7 +15,7 @@ namespace Stats.Config Game.IW4, new Dictionary { { DetectionType.Chest, new[] { "m21.+" } }, - { DetectionType.Recoil, new[] { "ranger.*_mp", "model1887.*_mp", ".+shotgun.*_mp" } }, + { DetectionType.Recoil, new[] { "ranger.*_mp", "model1887.*_mp", ".+shotgun.*_mp", "turret_minigun_mp" } }, { DetectionType.Button, new[] { ".*akimbo.*" } } } } diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index e6a4d933..92d8ee5e 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -385,7 +385,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers if (pl.CurrentServer == null) { - _log.LogWarning("Disconnecting client {@client} is not on a server", pl); + _log.LogWarning("Disconnecting client {client} is not on a server", pl.ToString()); return; } @@ -406,7 +406,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers else { - _log.LogWarning("Disconnecting client {@client} has not been added to stats", pl); + _log.LogWarning("Disconnecting client {client} has not been added to stats", pl.ToString()); } } From a574fb0d4b4e69cd08681482c9365f24a7405433 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 14 Nov 2020 18:24:51 -0600 Subject: [PATCH 010/143] update index for ratings/prune old entries small stat tweaks to add players on first kill/damage event (instead of on connect which causes issues with slow writes) --- Application/ApplicationManager.cs | 2 + Application/Migration/DatabaseHousekeeping.cs | 20 + Application/RconParsers/BaseRConParser.cs | 8 +- Plugins/Stats/Helpers/StatManager.cs | 9 +- Plugins/Stats/Models/ModelConfiguration.cs | 5 +- Plugins/Stats/Plugin.cs | 9 +- README.md | 2 +- ...1114232340_UpdateEFRatingIndex.Designer.cs | 927 ++++++++++++++++++ .../20201114232340_UpdateEFRatingIndex.cs | 22 + .../DatabaseContextModelSnapshot.cs | 2 + 10 files changed, 999 insertions(+), 7 deletions(-) create mode 100644 Application/Migration/DatabaseHousekeeping.cs create mode 100644 SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 5324bc05..257d648a 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -21,6 +21,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using IW4MAdmin.Application.Migration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog.Context; @@ -404,6 +405,7 @@ namespace IW4MAdmin.Application GetApplicationSettings().Configuration()?.DatabaseProvider)) { await new ContextSeed(db).Seed(); + DatabaseHousekeeping.RemoveOldRatings(db); } #endregion diff --git a/Application/Migration/DatabaseHousekeeping.cs b/Application/Migration/DatabaseHousekeeping.cs new file mode 100644 index 00000000..b42b7f60 --- /dev/null +++ b/Application/Migration/DatabaseHousekeeping.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using IW4MAdmin.Plugins.Stats.Models; +using SharedLibraryCore.Database; + +namespace IW4MAdmin.Application.Migration +{ + public static class DatabaseHousekeeping + { + private static DateTime _cutoffDate = DateTime.UtcNow.AddMonths(-6); + + public static void RemoveOldRatings(DatabaseContext context) + { + var dbSet = context.Set(); + var itemsToDelete = dbSet.Where(rating => rating.When <= _cutoffDate); + dbSet.RemoveRange(itemsToDelete); + context.SaveChanges(); + } + } +} \ No newline at end of file diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index ab0aebd7..55ca9794 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -138,7 +138,7 @@ namespace IW4MAdmin.Application.RconParsers public virtual async Task<(List, string, string)> GetStatusAsync(IRConConnection connection) { string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS); - _logger.LogDebug("Status Response {@response}", (object)response); + _logger.LogDebug("Status Response {response}", string.Join(Environment.NewLine, response)); return (ClientsFromStatus(response), MapFromStatus(response), GameTypeFromStatus(response)); } @@ -205,6 +205,12 @@ namespace IW4MAdmin.Application.RconParsers if (match.Success) { + if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI") + { + _logger.LogDebug("Ignoring detected client {client} because they are zombie state", string.Join(",", match.Values)); + continue; + } + int clientNumber = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConClientNumber]]); int score = int.Parse(match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConScore]]); diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 92d8ee5e..0a2a9c03 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -277,6 +277,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// EFClientStatistic of specified player public async Task AddPlayer(EFClient pl) { + var existingStats = pl.GetAdditionalProperty(CLIENT_STATS_KEY); + + if (existingStats != null) + { + return existingStats; + } + try { long serverId = GetIdForServer(pl.CurrentServer); @@ -368,7 +375,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception ex) { - _log.LogError(ex, "Could not add client to stats {@client}", pl); + _log.LogError(ex, "Could not add client to stats {@client}", pl.ToString()); } return null; diff --git a/Plugins/Stats/Models/ModelConfiguration.cs b/Plugins/Stats/Models/ModelConfiguration.cs index a84d9087..f87e5fc3 100644 --- a/Plugins/Stats/Models/ModelConfiguration.cs +++ b/Plugins/Stats/Models/ModelConfiguration.cs @@ -22,7 +22,10 @@ namespace Stats.Models builder.Entity() .HasIndex(p => new { p.Performance, p.Ranking, p.When }); - + + builder.Entity() + .HasIndex(p => new { p.When, p.ServerId, p.Performance, p.ActivityAmount }); + builder.Entity() .HasIndex(p => p.TimeSent); diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 3cccb07f..22545df9 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -58,9 +58,6 @@ namespace IW4MAdmin.Plugins.Stats break; case GameEvent.EventType.Stop: break; - case GameEvent.EventType.PreConnect: - await Manager.AddPlayer(E.Origin); - break; case GameEvent.EventType.Disconnect: await Manager.RemovePlayer(E.Origin); break; @@ -104,6 +101,8 @@ namespace IW4MAdmin.Plugins.Stats { E.Origin = E.Target; } + await Manager.AddPlayer(E.Origin); + await Manager.AddPlayer(E.Target); await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } @@ -122,6 +121,8 @@ namespace IW4MAdmin.Plugins.Stats E.Origin = E.Target; } + await Manager.AddPlayer(E.Origin); + await Manager.AddPlayer(E.Target); await Manager.AddStandardKill(E.Origin, E.Target); } break; @@ -147,6 +148,8 @@ namespace IW4MAdmin.Plugins.Stats E.Origin = E.Target; } + await Manager.AddPlayer(E.Origin); + await Manager.AddPlayer(E.Target); await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } diff --git a/README.md b/README.md index 71554cb2..3559015a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/J3J821KUJ) ## About -**IW4MAdmin** is an administration tool for [IW4x](https://iw4x.org/), [Pluto T6](https://forum.plutonium.pw/category/6/plutonium-t6), [Pluto IW5](https://forum.plutonium.pw/category/14/plutonium-iw5), [CoD4x](https://cod4x.me/), [TeknoMW3](https://github.com/Musta1337/TeknoMW3), and most Call of Duty® dedicated servers. It allows complete control of your server; from changing maps, to banning players, **IW4MAdmin** monitors and records activity on your server(s). With plugin support, extending its functionality is a breeze. +**IW4MAdmin** is an administration tool for [IW4x](https://iw4x.org/), [IW6x](https://xlabs.dev), [Pluto T6](https://forum.plutonium.pw/category/6/plutonium-t6), [Pluto IW5](https://forum.plutonium.pw/category/14/plutonium-iw5), [CoD4x](https://cod4x.me/), [TeknoMW3](https://github.com/Musta1337/TeknoMW3), and most Call of Duty® dedicated servers. It allows complete control of your server; from changing maps, to banning players, **IW4MAdmin** monitors and records activity on your server(s). With plugin support, extending its functionality is a breeze. ### Download Latest binary builds are always available at: - [GitHub](https://github.com/RaidMax/IW4M-Admin/releases) diff --git a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs new file mode 100644 index 00000000..404a0487 --- /dev/null +++ b/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -0,0 +1,927 @@ +// +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("20201114232340_UpdateEFRatingIndex")] + partial class UpdateEFRatingIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs b/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs new file mode 100644 index 00000000..b0503fa5 --- /dev/null +++ b/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations +{ + public partial class UpdateEFRatingIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating", + columns: new[] { "When", "ServerId", "Performance", "ActivityAmount" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs index 66dc63c1..4a6d3f7f 100644 --- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs @@ -388,6 +388,8 @@ namespace SharedLibraryCore.Migrations b.HasIndex("Performance", "Ranking", "When"); + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + b.ToTable("EFRating"); }); From 941d9cea73fa521dc72238887daba0dd58f4627d Mon Sep 17 00:00:00 2001 From: RaidMax Date: Tue, 17 Nov 2020 18:24:54 -0600 Subject: [PATCH 011/143] more consistent/enhanced game penalty messages per issue #171 --- .../Factories/GameServerInstanceFactory.cs | 3 +- Application/IW4MServer.cs | 39 ++++--- Application/Main.cs | 1 + .../Misc/ClientNoticeMessageFormatter.cs | 101 ++++++++++++++++++ .../DynamicRConParserConfiguration.cs | 2 + .../Configuration/ApplicationConfiguration.cs | 2 + .../IClientNoticeMessageFormatter.cs | 16 +++ SharedLibraryCore/Interfaces/IGameServer.cs | 18 ++++ .../Interfaces/IRConParserConfiguration.cs | 4 + SharedLibraryCore/PartialEntities/EFClient.cs | 31 +++--- SharedLibraryCore/Server.cs | 7 +- 11 files changed, 192 insertions(+), 32 deletions(-) create mode 100644 Application/Misc/ClientNoticeMessageFormatter.cs create mode 100644 SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs create mode 100644 SharedLibraryCore/Interfaces/IGameServer.cs diff --git a/Application/Factories/GameServerInstanceFactory.cs b/Application/Factories/GameServerInstanceFactory.cs index 9e91d54b..8cadbc73 100644 --- a/Application/Factories/GameServerInstanceFactory.cs +++ b/Application/Factories/GameServerInstanceFactory.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; @@ -36,7 +37,7 @@ namespace IW4MAdmin.Application.Factories /// public Server CreateServer(ServerConfiguration config, IManager manager) { - return new IW4MServer(config, _translationLookup, _metaService, _serviceProvider); + return new IW4MServer(config, _translationLookup, _metaService, _serviceProvider, _serviceProvider.GetRequiredService()); } } } diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 75a1331f..7357d0e2 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -32,13 +32,15 @@ namespace IW4MAdmin private int lastGameTime = 0; public int Id { get; private set; } - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _serviceProvider; + private readonly IClientNoticeMessageFormatter _messageFormatter; public IW4MServer( ServerConfiguration serverConfiguration, ITranslationLookup lookup, IMetaService metaService, - IServiceProvider serviceProvider) : base(serviceProvider.GetRequiredService>(), + IServiceProvider serviceProvider, + IClientNoticeMessageFormatter messageFormatter) : base(serviceProvider.GetRequiredService>(), serviceProvider.GetRequiredService(), serverConfiguration, serviceProvider.GetRequiredService(), @@ -48,6 +50,7 @@ namespace IW4MAdmin _translationLookup = lookup; _metaService = metaService; _serviceProvider = serviceProvider; + _messageFormatter = messageFormatter; } public override async Task OnClientConnected(EFClient clientFromLog) @@ -454,7 +457,6 @@ namespace IW4MAdmin else if (E.Type == GameEvent.EventType.TempBan) { await TempBan(E.Data, (TimeSpan) E.Extra, E.Target, E.ImpersonationOrigin ?? E.Origin); - ; } else if (E.Type == GameEvent.EventType.Ban) @@ -470,7 +472,7 @@ namespace IW4MAdmin else if (E.Type == GameEvent.EventType.Kick) { - await Kick(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin); + await Kick(E.Data, E.Target, E.ImpersonationOrigin ?? E.Origin, E.Extra as EFPenalty); } else if (E.Type == GameEvent.EventType.Warn) @@ -1015,6 +1017,12 @@ namespace IW4MAdmin { Website = loc["SERVER_WEBSITE_GENERIC"]; } + + // todo: remove this once _website is weaned off + if (string.IsNullOrEmpty(Manager.GetApplicationSettings().Configuration().ContactUri)) + { + Manager.GetApplicationSettings().Configuration().ContactUri = Website; + } InitializeMaps(); @@ -1190,7 +1198,7 @@ namespace IW4MAdmin } } - public override async Task Kick(string Reason, EFClient targetClient, EFClient originClient) + public override async Task Kick(string reason, EFClient targetClient, EFClient originClient, EFPenalty previousPenalty) { targetClient = targetClient.ClientNumber < 0 ? Manager.GetActiveClients() @@ -1202,7 +1210,7 @@ namespace IW4MAdmin Type = EFPenalty.PenaltyType.Kick, Expires = DateTime.UtcNow, Offender = targetClient, - Offense = Reason, + Offense = reason, Punisher = originClient, Link = targetClient.AliasLink }; @@ -1221,8 +1229,11 @@ namespace IW4MAdmin Manager.AddEvent(e); - // todo: move to translation sheet - string formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"{loc["SERVER_KICK_TEXT"]} - ^5{Reason}^7"); + var formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, + targetClient.ClientNumber, + _messageFormatter.BuildFormattedMessage(RconParser.Configuration, + newPenalty, + previousPenalty)); await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); } } @@ -1250,14 +1261,15 @@ namespace IW4MAdmin if (targetClient.IsIngame) { - // todo: move to translation sheet - string formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"^7{loc["SERVER_TB_TEXT"]}- ^5{Reason}"); + var formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, + targetClient.ClientNumber, + _messageFormatter.BuildFormattedMessage(RconParser.Configuration, newPenalty)); ServerLogger.LogDebug("Executing tempban kick command for {targetClient}", targetClient.ToString()); await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); } } - override public async Task Ban(string reason, EFClient targetClient, EFClient originClient, bool isEvade = false) + public override async Task Ban(string reason, EFClient targetClient, EFClient originClient, bool isEvade = false) { // ensure player gets kicked if command not performed on them in the same server targetClient = targetClient.ClientNumber < 0 ? @@ -1283,8 +1295,9 @@ namespace IW4MAdmin if (targetClient.IsIngame) { ServerLogger.LogDebug("Attempting to kicking newly banned client {targetClient}", targetClient.ToString()); - // todo: move to translation sheet - string formattedString = string.Format(RconParser.Configuration.CommandPrefixes.Kick, targetClient.ClientNumber, $"{loc["SERVER_BAN_TEXT"]} - ^5{reason} ^7{loc["SERVER_BAN_APPEAL"].FormatExt(Website)}^7"); + var formattedString = string.Format(RconParser.Configuration.CommandPrefixes.Kick, + targetClient.ClientNumber, + _messageFormatter.BuildFormattedMessage(RconParser.Configuration, newPenalty)); await targetClient.CurrentServer.ExecuteCommandAsync(formattedString); } } diff --git a/Application/Main.cs b/Application/Main.cs index 4d922277..6b7ecab8 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -350,6 +350,7 @@ namespace IW4MAdmin.Application .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton(translationLookup); if (args.Contains("serialevents")) diff --git a/Application/Misc/ClientNoticeMessageFormatter.cs b/Application/Misc/ClientNoticeMessageFormatter.cs new file mode 100644 index 00000000..e0d9302c --- /dev/null +++ b/Application/Misc/ClientNoticeMessageFormatter.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SharedLibraryCore; +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; + +namespace IW4MAdmin.Application.Misc +{ + /// + /// implementation of IClientNoticeMessageFormatter + /// + public class ClientNoticeMessageFormatter : IClientNoticeMessageFormatter + { + private readonly ITranslationLookup _transLookup; + private readonly ApplicationConfiguration _appConfig; + + public ClientNoticeMessageFormatter(ITranslationLookup transLookup, ApplicationConfiguration appConfig) + { + _transLookup = transLookup; + _appConfig = appConfig; + } + + public string BuildFormattedMessage(IRConParserConfiguration config, EFPenalty currentPenalty, EFPenalty originalPenalty = null) + { + var penalty = originalPenalty ?? currentPenalty; + var builder = new StringBuilder(); + // build the top level header + var header = _transLookup[$"SERVER_{penalty.Type.ToString().ToUpper()}_TEXT"]; + builder.Append(header); + builder.Append(Environment.NewLine); + // build the reason + var reason = _transLookup["GAME_MESSAGE_PENALTY_REASON"].FormatExt(penalty.Offense); + foreach (var splitReason in SplitOverMaxLength(reason, config.NoticeMaxCharactersPerLine)) + { + builder.Append(splitReason); + builder.Append(Environment.NewLine); + } + + if (penalty.Type == EFPenalty.PenaltyType.TempBan) + { + // build the time remaining if temporary + var timeRemainingValue = penalty.Expires.HasValue + ? (penalty.Expires - DateTime.UtcNow).Value.HumanizeForCurrentCulture() + : "--"; + var timeRemaining = _transLookup["GAME_MESSAGE_PENALTY_TIME_REMAINING"].FormatExt(timeRemainingValue); + + foreach (var splitReason in SplitOverMaxLength(timeRemaining, config.NoticeMaxCharactersPerLine)) + { + builder.Append(splitReason); + builder.Append(Environment.NewLine); + } + } + + if (penalty.Type == EFPenalty.PenaltyType.Ban) + { + // provide a place to appeal the ban (should always be specified but including a placeholder just incase) + builder.Append(_transLookup["GAME_MESSAGE_PENALTY_APPEAL"].FormatExt(_appConfig.ContactUri ?? "--")); + } + + // final format looks something like: + /* + * You are permanently banned + * Reason - toxic behavior + * Visit example.com to appeal + */ + + return builder.ToString(); + } + + private static IEnumerable SplitOverMaxLength(string source, int maxCharactersPerLine) + { + if (source.Length <= maxCharactersPerLine) + { + return new[] {source}; + } + + var segments = new List(); + var currentLocation = 0; + while (currentLocation < source.Length) + { + var nextLocation = currentLocation + maxCharactersPerLine; + // there's probably a more efficient way to do this but this is readable + segments.Add(string.Concat( + source + .Skip(currentLocation) + .Take(Math.Min(maxCharactersPerLine, source.Length - currentLocation)))); + currentLocation = nextLocation; + } + + if (currentLocation < source.Length) + { + segments.Add(source.Substring(currentLocation, source.Length - currentLocation)); + } + + return segments; + } + } +} \ No newline at end of file diff --git a/Application/RconParsers/DynamicRConParserConfiguration.cs b/Application/RconParsers/DynamicRConParserConfiguration.cs index 61295f92..c5758909 100644 --- a/Application/RconParsers/DynamicRConParserConfiguration.cs +++ b/Application/RconParsers/DynamicRConParserConfiguration.cs @@ -22,6 +22,8 @@ namespace IW4MAdmin.Application.RconParsers public NumberStyles GuidNumberStyle { get; set; } = NumberStyles.HexNumber; public IDictionary OverrideDvarNameMapping { get; set; } = new Dictionary(); public IDictionary DefaultDvarValues { get; set; } = new Dictionary(); + public int NoticeMaximumLines { get; set; } = 8; + public int NoticeMaxCharactersPerLine { get; set; } = 50; public DynamicRConParserConfiguration(IParserRegexFactory parserRegexFactory) { diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 4764366f..134eb677 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -47,6 +47,8 @@ namespace SharedLibraryCore.Configuration public string SocialLinkAddress { get; set; } [LocalizedDisplayName("SETUP_SOCIAL_TITLE")] public string SocialLinkTitle { get; set; } + [LocalizedDisplayName("SETUP_CONTACT_URI")] + public string ContactUri { get; set; } [LocalizedDisplayName("SETUP_USE_CUSTOMENCODING")] [ConfigurationLinked("CustomParserEncoding")] diff --git a/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs b/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs new file mode 100644 index 00000000..503daf89 --- /dev/null +++ b/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs @@ -0,0 +1,16 @@ +using SharedLibraryCore.Database.Models; + +namespace SharedLibraryCore.Interfaces +{ + public interface IClientNoticeMessageFormatter + { + /// + /// builds a game formatted notice message + /// + /// current penalty the message is for + /// previous penalty the current penalty relates to + /// RCon parser config + /// + string BuildFormattedMessage(IRConParserConfiguration config, EFPenalty currentPenalty, EFPenalty originalPenalty = null); + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/IGameServer.cs b/SharedLibraryCore/Interfaces/IGameServer.cs new file mode 100644 index 00000000..614b0b46 --- /dev/null +++ b/SharedLibraryCore/Interfaces/IGameServer.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using SharedLibraryCore.Database.Models; + +namespace SharedLibraryCore.Interfaces +{ + public interface IGameServer + { + /// + /// kicks target on behalf of origin for given reason + /// + /// reason client is being kicked + /// client to kick + /// source of kick action + /// previous penalty the kick is occuring for (if applicable) + /// + public Task Kick(string reason, EFClient target, EFClient origin, EFPenalty previousPenalty = null); + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs index aee38e28..819aa956 100644 --- a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs +++ b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs @@ -62,5 +62,9 @@ namespace SharedLibraryCore.Interfaces /// specifies the default dvar values for games that don't support certain dvars ///
IDictionary DefaultDvarValues { get; set; } + + int NoticeMaximumLines { get; set; } + + int NoticeMaxCharactersPerLine { get; set; } } } diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index 2782ed38..df2bc1cb 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -320,7 +320,15 @@ namespace SharedLibraryCore.Database.Models /// /// reason to kick for /// client performing the kick - public GameEvent Kick(string kickReason, EFClient sender) + public GameEvent Kick(string kickReason, EFClient sender) => Kick(kickReason, sender, null); + + /// + /// kick a client for the given reason + /// + /// reason to kick for + /// client performing the kick + /// original client penalty + public GameEvent Kick(string kickReason, EFClient sender, EFPenalty originalPenalty) { var e = new GameEvent() { @@ -329,6 +337,7 @@ namespace SharedLibraryCore.Database.Models Target = this, Origin = sender, Data = kickReason, + Extra = originalPenalty, Owner = sender.CurrentServer }; @@ -597,7 +606,6 @@ namespace SharedLibraryCore.Database.Models { var loc = Utilities.CurrentLocalization.LocalizationIndex; var autoKickClient = Utilities.IW4MAdminClient(CurrentServer); - bool isAbleToConnectSimple = IsAbleToConnectSimple(); if (!isAbleToConnectSimple) @@ -617,23 +625,18 @@ namespace SharedLibraryCore.Database.Models // we want to kick them if any account is banned if (banPenalty != null) { - if (Level == Permission.Banned) - { - Utilities.DefaultLogger.LogInformation("Kicking {client} because they are banned", ToString()); - Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); - return false; - } - - else + if (Level != Permission.Banned) { Utilities.DefaultLogger.LogInformation( "Client {client} is banned, but using a new GUID, we we're updating their level and kicking them", ToString()); await SetLevel(Permission.Banned, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, CurrentServer.Manager.CancellationToken); - Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient); - return false; } + + Utilities.DefaultLogger.LogInformation("Kicking {client} because they are banned", ToString()); + Kick(loc["WEBFRONT_PENALTY_LIST_BANNED_REASON"], autoKickClient, banPenalty); + return false; } // we want to kick them if any account is tempbanned @@ -641,9 +644,7 @@ namespace SharedLibraryCore.Database.Models { Utilities.DefaultLogger.LogInformation("Kicking {client} because their GUID is temporarily banned", ToString()); - Kick( - $"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", - autoKickClient); + Kick(loc["WEBFRONT_PENALTY_LIST_TEMPBANNED_REASON"], autoKickClient, tempbanPenalty); return false; } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 63c7ae4a..d129d289 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -14,7 +14,7 @@ using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore { - public abstract class Server + public abstract class Server : IGameServer { public enum Game { @@ -205,9 +205,10 @@ namespace SharedLibraryCore /// /// Kick a player from the server /// - /// Reason for kicking + /// Reason for kicking /// EFClient to kick - abstract public Task Kick(String Reason, EFClient Target, EFClient Origin); + public Task Kick(String reason, EFClient Target, EFClient Origin) => Kick(reason, Target, Origin, null); + public abstract Task Kick(string reason, EFClient target, EFClient origin, EFPenalty originalPenalty); /// /// Temporarily ban a player ( default 1 hour ) from the server From 103d2726c22ad7148f85927752f5cc19e635eccf Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 18 Nov 2020 09:08:24 -0600 Subject: [PATCH 012/143] persist say command messages with webfront denotation to chat log per issue #159 --- .../AutomessageFeed/AutomessageFeed.csproj | 2 +- .../IW4ScriptCommands.csproj | 2 +- Plugins/LiveRadar/LiveRadar.csproj | 2 +- Plugins/Login/Login.csproj | 2 +- .../ProfanityDeterment.csproj | 2 +- Plugins/Stats/Helpers/StatManager.cs | 21 +- Plugins/Stats/Models/EFClientMessage.cs | 1 + Plugins/Stats/Plugin.cs | 27 +- Plugins/Stats/Stats.csproj | 2 +- .../Web/StatsWeb/ChatResourceQueryHelper.cs | 3 +- Plugins/Web/StatsWeb/StatsWeb.csproj | 2 +- Plugins/Welcome/Welcome.csproj | 2 +- .../Dtos/Meta/Responses/MessageResponse.cs | 5 + ...dSentIngameFlagToClientMessage.Designer.cs | 930 ++++++++++++++++++ ...023106_AddSentIngameFlagToClientMessage.cs | 23 + .../DatabaseContextModelSnapshot.cs | 3 + SharedLibraryCore/SharedLibraryCore.csproj | 6 +- .../Profile/Meta/_MessageResponse.cshtml | 7 +- WebfrontCore/WebfrontCore.csproj | 10 + 19 files changed, 1009 insertions(+), 43 deletions(-) create mode 100644 SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs create mode 100644 SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj index fc817db3..91e3147a 100644 --- a/Plugins/AutomessageFeed/AutomessageFeed.csproj +++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj index 2c925e28..e5bca04c 100644 --- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj +++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/LiveRadar/LiveRadar.csproj b/Plugins/LiveRadar/LiveRadar.csproj index 7f066573..03819637 100644 --- a/Plugins/LiveRadar/LiveRadar.csproj +++ b/Plugins/LiveRadar/LiveRadar.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/Login/Login.csproj b/Plugins/Login/Login.csproj index 49933244..d76e4353 100644 --- a/Plugins/Login/Login.csproj +++ b/Plugins/Login/Login.csproj @@ -23,7 +23,7 @@ - + diff --git a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj index 1a8aa316..8cbfdc5a 100644 --- a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj +++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 0a2a9c03..ef6f27df 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -1171,7 +1171,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers stats.EloRating = 200; } - public async Task AddMessageAsync(int clientId, long serverId, string message) + public async Task AddMessageAsync(int clientId, long serverId, bool sentIngame, string message) { // the web users can have no account if (clientId < 1) @@ -1179,18 +1179,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers return; } - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) + await using var ctx = _contextFactory.CreateContext(enableTracking: false); + ctx.Set().Add(new EFClientMessage() { - ctx.Set().Add(new EFClientMessage() - { - ClientId = clientId, - Message = message, - ServerId = serverId, - TimeSent = DateTime.UtcNow - }); + ClientId = clientId, + Message = message, + ServerId = serverId, + TimeSent = DateTime.UtcNow, + SentIngame = sentIngame + }); - await ctx.SaveChangesAsync(); - } + await ctx.SaveChangesAsync(); } public async Task Sync(Server sv) diff --git a/Plugins/Stats/Models/EFClientMessage.cs b/Plugins/Stats/Models/EFClientMessage.cs index 4a4106c1..49c2a931 100644 --- a/Plugins/Stats/Models/EFClientMessage.cs +++ b/Plugins/Stats/Models/EFClientMessage.cs @@ -17,5 +17,6 @@ namespace IW4MAdmin.Plugins.Stats.Models public virtual EFClient Client { get; set; } public string Message { get; set; } public DateTime TimeSent { get; set; } + public bool SentIngame { get; set; } } } diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 22545df9..74983b06 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using SharedLibraryCore.Commands; namespace IW4MAdmin.Plugins.Stats { @@ -56,8 +57,6 @@ namespace IW4MAdmin.Plugins.Stats case GameEvent.EventType.Start: Manager.AddServer(S); break; - case GameEvent.EventType.Stop: - break; case GameEvent.EventType.Disconnect: await Manager.RemovePlayer(E.Origin); break; @@ -65,7 +64,7 @@ namespace IW4MAdmin.Plugins.Stats if (!string.IsNullOrEmpty(E.Data) && E.Origin.ClientId > 1) { - await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), E.Data); + await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), true, E.Data); } break; case GameEvent.EventType.MapChange: @@ -76,21 +75,13 @@ namespace IW4MAdmin.Plugins.Stats case GameEvent.EventType.MapEnd: await Manager.Sync(S); break; - case GameEvent.EventType.JoinTeam: - break; - case GameEvent.EventType.Broadcast: - break; - case GameEvent.EventType.Tell: - break; - case GameEvent.EventType.Kick: - break; - case GameEvent.EventType.Ban: - break; - case GameEvent.EventType.Unknown: - break; - case GameEvent.EventType.Report: - break; - case GameEvent.EventType.Flag: + case GameEvent.EventType.Command: + var shouldPersist = !string.IsNullOrEmpty(E.Data) && + E.Extra is SayCommand; + if (shouldPersist) + { + await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), false, E.Data); + } break; case GameEvent.EventType.ScriptKill: string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; diff --git a/Plugins/Stats/Stats.csproj b/Plugins/Stats/Stats.csproj index 1c379fca..2e2304f1 100644 --- a/Plugins/Stats/Stats.csproj +++ b/Plugins/Stats/Stats.csproj @@ -17,7 +17,7 @@ - + diff --git a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs index 7af3cfcc..34586ded 100644 --- a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs +++ b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs @@ -81,7 +81,8 @@ namespace StatsWeb When = _message.TimeSent, Message = _message.Message, ServerName = query.IsProfileMeta ? "" : _message.Server.HostName, - GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value + GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value, + SentIngame = _message.SentIngame }); if (query.Direction == SharedLibraryCore.Dtos.SortDirection.Descending) diff --git a/Plugins/Web/StatsWeb/StatsWeb.csproj b/Plugins/Web/StatsWeb/StatsWeb.csproj index 75017f63..19bd0453 100644 --- a/Plugins/Web/StatsWeb/StatsWeb.csproj +++ b/Plugins/Web/StatsWeb/StatsWeb.csproj @@ -14,7 +14,7 @@ Always - + diff --git a/Plugins/Welcome/Welcome.csproj b/Plugins/Welcome/Welcome.csproj index ebdc6a2e..44436dc5 100644 --- a/Plugins/Welcome/Welcome.csproj +++ b/Plugins/Welcome/Welcome.csproj @@ -16,7 +16,7 @@ - + diff --git a/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs b/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs index 8ca3693c..17f90e70 100644 --- a/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs +++ b/SharedLibraryCore/Dtos/Meta/Responses/MessageResponse.cs @@ -27,6 +27,11 @@ namespace SharedLibraryCore.Dtos.Meta.Responses /// indicates if the chat message is a quick message phrase /// public bool IsQuickMessage { get; set; } + + /// + /// indicates if the message was sent ingame + /// + public bool SentIngame { get; set; } public string HiddenMessage => string.Concat(Enumerable.Repeat('●', Message.Length)); } diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs new file mode 100644 index 00000000..07205a94 --- /dev/null +++ b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -0,0 +1,930 @@ +// +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("20201118023106_AddSentIngameFlagToClientMessage")] + partial class AddSentIngameFlagToClientMessage + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs new file mode 100644 index 00000000..42ccaf6e --- /dev/null +++ b/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations +{ + public partial class AddSentIngameFlagToClientMessage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SentIngame", + table: "EFClientMessages", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SentIngame", + table: "EFClientMessages"); + } + } +} diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs index 4a6d3f7f..e4371a05 100644 --- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs @@ -222,6 +222,9 @@ namespace SharedLibraryCore.Migrations b.Property("Message") .HasColumnType("TEXT"); + b.Property("SentIngame") + .HasColumnType("INTEGER"); + b.Property("ServerId") .HasColumnType("INTEGER"); diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 42186029..d70dcf2f 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -4,7 +4,7 @@ Library netcoreapp3.1 RaidMax.IW4MAdmin.SharedLibraryCore - 2.4.10 + 2020.11.18.1 RaidMax Forever None Debug;Release;Prerelease @@ -19,9 +19,7 @@ true MIT Shared Library for IW4MAdmin - 2020.11.11.1 - 2020.11.11.1 - 2020.11.11.1 + 2020.11.18.1 diff --git a/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml b/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml index b5d2f9c1..0302d75c 100644 --- a/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml +++ b/WebfrontCore/Views/Client/Profile/Meta/_MessageResponse.cshtml @@ -3,7 +3,12 @@ - + + @if (!Model.SentIngame) + { + [@ViewBag.Localization["WEBFRONT_PROFILE_MESSAGE_EXTERNAL"]] + } + @if (Model.IsHidden && !ViewBag.Authorized) { diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index b3e416e1..fb51fa63 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -40,6 +40,7 @@ + @@ -51,6 +52,7 @@ + @@ -93,6 +95,14 @@ + + + + + + + + From 09f37d79418a0912568528d2e0cd00e8b1d0f73f Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 18 Nov 2020 16:28:14 -0600 Subject: [PATCH 013/143] clean up some logic related to tracking stats on player join --- Plugins/Stats/Helpers/StatManager.cs | 33 +++++++++++++++++++++------- Plugins/Stats/Plugin.cs | 26 +++++++++++++++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index ef6f27df..497b9da6 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -30,6 +30,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers private static List serverModels; public static string CLIENT_STATS_KEY = "ClientStats"; public static string CLIENT_DETECTIONS_KEY = "ClientDetections"; + private readonly SemaphoreSlim _addPlayerWaiter = new SemaphoreSlim(1, 1); public StatManager(ILogger logger, IManager mgr, IDatabaseContextFactory contextFactory, IConfigurationHandler configHandler) { @@ -39,6 +40,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers _configHandler = configHandler; } + ~StatManager() + { + _addPlayerWaiter.Dispose(); + } + private void SetupServerIds() { using (var ctx = _contextFactory.CreateContext(enableTracking: false)) @@ -283,9 +289,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { return existingStats; } - + try { + await _addPlayerWaiter.WaitAsync(); long serverId = GetIdForServer(pl.CurrentServer); if (!_servers.ContainsKey(serverId)) @@ -318,12 +325,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers Skill = 0.0, SPM = 0.0, EloRating = 200.0, - HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType().Select(hl => new EFHitLocationCount() - { - Active = true, - HitCount = 0, - Location = hl - }).ToList() + HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType() + .Select(hl => new EFHitLocationCount() + { + Active = true, + HitCount = 0, + Location = hl + }).ToList() }; // insert if they've not been added @@ -336,7 +344,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers // migration for previous existing stats if (clientStats.HitLocations.Count == 0) { - clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType() + clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)) + .OfType() .Select(hl => new EFHitLocationCount() { Active = true, @@ -378,6 +387,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers _log.LogError(ex, "Could not add client to stats {@client}", pl.ToString()); } + finally + { + if (_addPlayerWaiter.CurrentCount == 0) + { + _addPlayerWaiter.Release(1); + } + } + return null; } diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 74983b06..4fdf4e04 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -92,8 +92,8 @@ namespace IW4MAdmin.Plugins.Stats { E.Origin = E.Target; } - await Manager.AddPlayer(E.Origin); - await Manager.AddPlayer(E.Target); + + await EnsureClientsAdded(E.Origin, E.Target); await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } @@ -112,8 +112,7 @@ namespace IW4MAdmin.Plugins.Stats E.Origin = E.Target; } - await Manager.AddPlayer(E.Origin); - await Manager.AddPlayer(E.Target); + await EnsureClientsAdded(E.Origin, E.Target); await Manager.AddStandardKill(E.Origin, E.Target); } break; @@ -139,8 +138,7 @@ namespace IW4MAdmin.Plugins.Stats E.Origin = E.Target; } - await Manager.AddPlayer(E.Origin); - await Manager.AddPlayer(E.Target); + await EnsureClientsAdded(E.Origin, E.Target); await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } @@ -475,5 +473,21 @@ namespace IW4MAdmin.Plugins.Stats /// /// private bool ShouldOverrideAnticheatSetting(Server s) => Config.Configuration().AnticheatConfiguration.Enable && s.GameName == Server.Game.IW5; + + /// + /// Makes sure both clients are added + /// + /// + /// + /// + private async Task EnsureClientsAdded(EFClient origin, EFClient target) + { + await Manager.AddPlayer(origin); + + if (!origin.Equals(target)) + { + await Manager.AddPlayer(target); + } + } } } From d58b24b5b25be7f8a33c0d3a7452ecf010eddc4f Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 18 Nov 2020 18:48:24 -0600 Subject: [PATCH 014/143] add shortcut for rules in penalty reasons for issue #159 --- Application/IW4MServer.cs | 1 + SharedLibraryCore/Commands/NativeCommands.cs | 65 ++++--- SharedLibraryCore/Utilities.cs | 27 +++ Tests/ApplicationTests/CommandTests.cs | 170 ++++++++++++++++++ .../DependencyInjectionExtensions.cs | 1 + 5 files changed, 238 insertions(+), 26 deletions(-) diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 7357d0e2..922e8415 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -197,6 +197,7 @@ namespace IW4MAdmin catch (Exception e) { + ServerLogger.LogError(e, "Unexpected exception occurred processing event"); if (E.Origin != null && E.Type == GameEvent.EventType.Command) { E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 7429f16b..f3c8afa0 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -101,7 +101,8 @@ namespace SharedLibraryCore.Commands /// public class WarnCommand : Command { - public WarnCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly ApplicationConfiguration _appConfig; + public WarnCommand(ApplicationConfiguration appConfig, CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { Name = "warn"; Description = _translationLookup["COMMANDS_WARN_DESC"]; @@ -121,13 +122,15 @@ namespace SharedLibraryCore.Commands Required = true } }; + _appConfig = appConfig; } - public override Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent gameEvent) { - if (E.Target.Warn(E.Data, E.Origin).Failed) + var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner); + if (gameEvent.Target.Warn(reason, gameEvent.Origin).Failed) { - E.Origin.Tell(_translationLookup["COMMANDS_WARN_FAIL"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_WARN_FAIL"].FormatExt(gameEvent.Target.Name)); } return Task.CompletedTask; @@ -172,7 +175,9 @@ namespace SharedLibraryCore.Commands /// public class KickCommand : Command { - public KickCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly ApplicationConfiguration _appConfig; + + public KickCommand(ApplicationConfiguration appConfig, CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { Name = "kick"; Description = _translationLookup["COMMANDS_KICK_DESC"]; @@ -192,20 +197,22 @@ namespace SharedLibraryCore.Commands Required = true } }; + _appConfig = appConfig; } - public override async Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent gameEvent) { - switch ((await E.Target.Kick(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) + var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner); + switch ((await gameEvent.Target.Kick(reason, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(_translationLookup["COMMANDS_KICK_SUCCESS"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_KICK_SUCCESS"].FormatExt(gameEvent.Target.Name)); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); + gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(_translationLookup["COMMANDS_KICK_FAIL"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_KICK_FAIL"].FormatExt(gameEvent.Target.Name)); break; } } @@ -282,7 +289,9 @@ namespace SharedLibraryCore.Commands /// public class TempBanCommand : Command { - public TempBanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly ApplicationConfiguration _appConfig; + + public TempBanCommand(ApplicationConfiguration appConfig, CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { Name = "tempban"; Description = _translationLookup["COMMANDS_TEMPBAN_DESC"]; @@ -307,35 +316,36 @@ namespace SharedLibraryCore.Commands Required = true } }; + _appConfig = appConfig; } private static readonly string TempBanRegex = @"([0-9]+\w+)\ (.+)"; - public override async Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent gameEvent) { - var match = Regex.Match(E.Data, TempBanRegex); + var match = Regex.Match(gameEvent.Data, TempBanRegex); if (match.Success) { - string tempbanReason = match.Groups[2].ToString(); + var tempbanReason = match.Groups[2].ToString().FindRuleForReason(_appConfig, gameEvent.Owner); var length = match.Groups[1].ToString().ParseTimespan(); - if (length > E.Owner.Manager.GetApplicationSettings().Configuration().MaximumTempBanTime) + if (length > gameEvent.Owner.Manager.GetApplicationSettings().Configuration().MaximumTempBanTime) { - E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL_TOOLONG"]); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL_TOOLONG"]); } else { - switch ((await E.Target.TempBan(tempbanReason, length, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) + switch ((await gameEvent.Target.TempBan(tempbanReason, length, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.HumanizeForCurrentCulture())); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(gameEvent.Target, length.HumanizeForCurrentCulture())); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); + gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL"].FormatExt(gameEvent.Target.Name)); break; } } @@ -348,7 +358,8 @@ namespace SharedLibraryCore.Commands /// public class BanCommand : Command { - public BanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly ApplicationConfiguration _appConfig; + public BanCommand(ApplicationConfiguration appConfig, CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { Name = "ban"; Description = _translationLookup["COMMANDS_BAN_DESC"]; @@ -368,20 +379,22 @@ namespace SharedLibraryCore.Commands Required = true } }; + _appConfig = appConfig; } - public override async Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent gameEvent) { - switch ((await E.Target.Ban(E.Data, E.Origin, false).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) + var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner); + switch ((await gameEvent.Target.Ban(reason, gameEvent.Origin, false).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(_translationLookup["COMMANDS_BAN_SUCCESS"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_BAN_SUCCESS"].FormatExt(gameEvent.Target.Name)); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); + gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(_translationLookup["COMMANDS_BAN_FAIL"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_BAN_FAIL"].FormatExt(gameEvent.Target.Name)); break; } } diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index de364089..af3777b4 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -18,6 +18,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using SharedLibraryCore.Configuration; using static SharedLibraryCore.Database.Models.EFClient; using static SharedLibraryCore.Database.Models.EFPenalty; using static SharedLibraryCore.Server; @@ -997,5 +998,31 @@ namespace SharedLibraryCore { return CurrentLocalization.LocalizationIndex[$"META_TYPE_{metaType.ToString().ToUpper()}_NAME"]; } + + public static string FindRuleForReason(this string reason, ApplicationConfiguration appConfig, Server server) + { + var regex = Regex.Match(reason, @"(rule|serverrule)(\d+)", RegexOptions.IgnoreCase); + if (!regex.Success) + { + return reason; + } + + var serverConfig = appConfig.Servers? + .FirstOrDefault(configServer => + configServer.IPAddress == server.IP && configServer.Port == server.Port); + + var index = int.Parse(regex.Groups[2].ToString()) - 1; + + return regex.Groups[1].ToString().ToLower() switch + { + "rule" => appConfig.GlobalRules?.Length > 0 && appConfig.GlobalRules.Length >= index + ? appConfig.GlobalRules[index] : + reason, + "serverrule" => serverConfig?.Rules?.Length > 0 && serverConfig.Rules?.Length >= index + ? serverConfig.Rules[index] : + reason, + _ => reason + }; + } } } diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index 8de324be..cc3ed8cf 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -41,6 +41,10 @@ namespace ApplicationTests .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() .BuildServiceProvider() .SetupTestHooks(); @@ -628,5 +632,171 @@ namespace ApplicationTests .MustHaveHappened(); } #endregion + + #region REASON_FROM_RULE + [Test] + public async Task Test_Warn_WithGlobalRule() + { + var expectedReason = "testglobalrule"; + appConfig.GlobalRules = new[] {expectedReason}; + var command = serviceProvider.GetRequiredService(); + var server = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "rule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Warn)); + } + + [Test] + public async Task Test_Warn_WithServerRule() + { + var server = serviceProvider.GetRequiredService(); + var expectedReason = "testserverrule"; + appConfig.Servers = new [] { new ServerConfiguration() + { + IPAddress = server.IP, + Port = server.Port, + Rules = new []{ expectedReason } + }}; + var command = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "serverrule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Warn)); + } + + [Test] + public async Task Test_Kick_WithGlobalRule() + { + var expectedReason = "testglobalrule"; + appConfig.GlobalRules = new[] {expectedReason}; + var command = serviceProvider.GetRequiredService(); + var server = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "rule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Kick)); + } + + [Test] + public async Task Test_Kick_WithServerRule() + { + var server = serviceProvider.GetRequiredService(); + var expectedReason = "testserverrule"; + appConfig.Servers = new [] { new ServerConfiguration() + { + IPAddress = server.IP, + Port = server.Port, + Rules = new []{ expectedReason } + }}; + var command = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "serverrule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Kick)); + } + + [Test] + public async Task Test_TempBan_WithGlobalRule() + { + var expectedReason = "testglobalrule"; + appConfig.GlobalRules = new[] {expectedReason}; + var command = serviceProvider.GetRequiredService(); + var server = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "1h rule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.TempBan)); + } + + [Test] + public async Task Test_TempBan_WithServerRule() + { + var server = serviceProvider.GetRequiredService(); + var expectedReason = "testserverrule"; + appConfig.Servers = new [] { new ServerConfiguration() + { + IPAddress = server.IP, + Port = server.Port, + Rules = new []{ expectedReason } + }}; + var command = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "1h serverrule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.TempBan)); + } + + [Test] + public async Task Test_Ban_WithGlobalRule() + { + var expectedReason = "testglobalrule"; + appConfig.GlobalRules = new[] {expectedReason}; + var command = serviceProvider.GetRequiredService(); + var server = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "rule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Ban)); + } + + [Test] + public async Task Test_Ban_WithServerRule() + { + var server = serviceProvider.GetRequiredService(); + var expectedReason = "testserverrule"; + appConfig.Servers = new [] { new ServerConfiguration() + { + IPAddress = server.IP, + Port = server.Port, + Rules = new []{ expectedReason } + }}; + var command = serviceProvider.GetRequiredService(); + var gameEvent = EventGenerators.GenerateEvent(GameEvent.EventType.Command, "serverrule1", server); + gameEvent.Origin.CurrentServer = server; + gameEvent.Target = gameEvent.Origin; + + await command.ExecuteAsync(gameEvent); + + Assert.NotNull(mockEventHandler.Events + .FirstOrDefault(e => e.Data == expectedReason && + e.Type == GameEvent.EventType.Ban)); + } + #endregion } } diff --git a/Tests/ApplicationTests/DependencyInjectionExtensions.cs b/Tests/ApplicationTests/DependencyInjectionExtensions.cs index f2496260..8085ed4c 100644 --- a/Tests/ApplicationTests/DependencyInjectionExtensions.cs +++ b/Tests/ApplicationTests/DependencyInjectionExtensions.cs @@ -48,6 +48,7 @@ namespace ApplicationTests .AddSingleton() .AddSingleton(A.Fake()) .AddSingleton(A.Fake()) + .AddSingleton(A.Fake()) .AddSingleton(eventHandler) .AddSingleton(ConfigurationGenerators.CreateApplicationConfiguration()) .AddSingleton(ConfigurationGenerators.CreateCommandConfiguration()) From 8ef2959f636a1f5a2aa6e72ec96d1d21f2287946 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 19 Nov 2020 20:48:25 -0600 Subject: [PATCH 015/143] make notice line separator configurable for different parsers (updated tekno's as it doesn't support \n) --- Application/Localization/Configure.cs | 4 +++ .../Misc/ClientNoticeMessageFormatter.cs | 35 ++++++++++++++----- .../DynamicRConParserConfiguration.cs | 4 ++- Plugins/ScriptPlugins/ParserTeknoMW3.js | 3 +- .../Interfaces/IRConParserConfiguration.cs | 11 ++++++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Application/Localization/Configure.cs b/Application/Localization/Configure.cs index 8d759fd5..b2155e97 100644 --- a/Application/Localization/Configure.cs +++ b/Application/Localization/Configure.cs @@ -63,6 +63,10 @@ namespace IW4MAdmin.Application.Localization { var localizationContents = File.ReadAllText(filePath, Encoding.UTF8); var eachLocalizationFile = Newtonsoft.Json.JsonConvert.DeserializeObject(localizationContents); + if (eachLocalizationFile == null) + { + continue; + } foreach (var item in eachLocalizationFile.LocalizationIndex.Set) { diff --git a/Application/Misc/ClientNoticeMessageFormatter.cs b/Application/Misc/ClientNoticeMessageFormatter.cs index e0d9302c..d4885c6d 100644 --- a/Application/Misc/ClientNoticeMessageFormatter.cs +++ b/Application/Misc/ClientNoticeMessageFormatter.cs @@ -25,18 +25,29 @@ namespace IW4MAdmin.Application.Misc public string BuildFormattedMessage(IRConParserConfiguration config, EFPenalty currentPenalty, EFPenalty originalPenalty = null) { + var isNewLineSeparator = config.NoticeLineSeparator == Environment.NewLine; var penalty = originalPenalty ?? currentPenalty; var builder = new StringBuilder(); // build the top level header var header = _transLookup[$"SERVER_{penalty.Type.ToString().ToUpper()}_TEXT"]; builder.Append(header); - builder.Append(Environment.NewLine); + builder.Append(config.NoticeLineSeparator); // build the reason var reason = _transLookup["GAME_MESSAGE_PENALTY_REASON"].FormatExt(penalty.Offense); - foreach (var splitReason in SplitOverMaxLength(reason, config.NoticeMaxCharactersPerLine)) + + if (isNewLineSeparator) { - builder.Append(splitReason); - builder.Append(Environment.NewLine); + foreach (var splitReason in SplitOverMaxLength(reason, config.NoticeMaxCharactersPerLine)) + { + builder.Append(splitReason); + builder.Append(config.NoticeLineSeparator); + } + } + + else + { + builder.Append(reason); + builder.Append(config.NoticeLineSeparator); } if (penalty.Type == EFPenalty.PenaltyType.TempBan) @@ -46,11 +57,19 @@ namespace IW4MAdmin.Application.Misc ? (penalty.Expires - DateTime.UtcNow).Value.HumanizeForCurrentCulture() : "--"; var timeRemaining = _transLookup["GAME_MESSAGE_PENALTY_TIME_REMAINING"].FormatExt(timeRemainingValue); - - foreach (var splitReason in SplitOverMaxLength(timeRemaining, config.NoticeMaxCharactersPerLine)) + + if (isNewLineSeparator) { - builder.Append(splitReason); - builder.Append(Environment.NewLine); + foreach (var splitReason in SplitOverMaxLength(timeRemaining, config.NoticeMaxCharactersPerLine)) + { + builder.Append(splitReason); + builder.Append(config.NoticeLineSeparator); + } + } + + else + { + builder.Append(timeRemaining); } } diff --git a/Application/RconParsers/DynamicRConParserConfiguration.cs b/Application/RconParsers/DynamicRConParserConfiguration.cs index c5758909..05b5de61 100644 --- a/Application/RconParsers/DynamicRConParserConfiguration.cs +++ b/Application/RconParsers/DynamicRConParserConfiguration.cs @@ -1,4 +1,5 @@ -using SharedLibraryCore.Interfaces; +using System; +using SharedLibraryCore.Interfaces; using SharedLibraryCore.RCon; using System.Collections.Generic; using System.Globalization; @@ -24,6 +25,7 @@ namespace IW4MAdmin.Application.RconParsers public IDictionary DefaultDvarValues { get; set; } = new Dictionary(); public int NoticeMaximumLines { get; set; } = 8; public int NoticeMaxCharactersPerLine { get; set; } = 50; + public string NoticeLineSeparator { get; set; } = Environment.NewLine; public DynamicRConParserConfiguration(IParserRegexFactory parserRegexFactory) { diff --git a/Plugins/ScriptPlugins/ParserTeknoMW3.js b/Plugins/ScriptPlugins/ParserTeknoMW3.js index 951181d1..0cdd2971 100644 --- a/Plugins/ScriptPlugins/ParserTeknoMW3.js +++ b/Plugins/ScriptPlugins/ParserTeknoMW3.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.7, + version: 0.8, name: 'Tekno MW3 Parser', isParser: true, @@ -27,6 +27,7 @@ var plugin = { rconParser.Configuration.CommandPrefixes.TempBan = 'tempbanclient {0} "{1}"'; rconParser.Configuration.Dvar.AddMapping(107, 1); // RCon DvarValue rconParser.Configuration.Dvar.Pattern = '^(.*)$'; + rconParser.Configuration.NoticeLineSeparator = '. '; rconParser.Configuration.DefaultDvarValues.Add('sv_running', '1'); rconParser.Configuration.OverrideDvarNameMapping.Add('_website', 'sv_clanWebsite'); diff --git a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs index 819aa956..d53c8f92 100644 --- a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs +++ b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs @@ -63,8 +63,19 @@ namespace SharedLibraryCore.Interfaces /// IDictionary DefaultDvarValues { get; set; } + /// + /// specifies how many lines can be used for ingame notice + /// int NoticeMaximumLines { get; set; } + /// + /// specifies how many characters can be displayed per notice line + /// int NoticeMaxCharactersPerLine { get; set; } + + /// + /// specifies the characters used to split a line + /// + string NoticeLineSeparator { get; set; } } } From 36a02b3d7b1b724f65c67b2402945e9a8d2ef2aa Mon Sep 17 00:00:00 2001 From: RaidMax Date: Fri, 27 Nov 2020 21:52:52 -0600 Subject: [PATCH 016/143] update for database provider specific migrations fix issues with live radar --- .gitignore | 3 +- Application/ApplicationManager.cs | 25 +- Application/Extensions/StartupExtensions.cs | 57 +- .../Factories/DatabaseContextFactory.cs | 31 +- Application/IW4MServer.cs | 2 +- Application/Main.cs | 30 +- Application/Migration/DatabaseHousekeeping.cs | 12 +- Application/Misc/ScriptPlugin.cs | 23 +- Plugins/LiveRadar/Plugin.cs | 5 +- Plugins/Stats/Commands/MostPlayedCommand.cs | 54 +- Plugins/Stats/Commands/ResetStats.cs | 40 +- Plugins/Stats/Commands/TopStats.cs | 59 +- Plugins/Stats/Commands/ViewStats.cs | 18 +- Plugins/Stats/Helpers/StatManager.cs | 6 +- Plugins/Stats/Models/ModelConfiguration.cs | 8 +- Plugins/Stats/Plugin.cs | 20 +- .../StatsWeb/Controllers/StatsController.cs | 84 +- Plugins/Welcome/Plugin.cs | 8 +- Plugins/Welcome/Welcome.csproj | 2 +- SharedLibraryCore/Commands/NativeCommands.cs | 24 +- SharedLibraryCore/Database/ContextSeed.cs | 27 +- SharedLibraryCore/Database/DatabaseContext.cs | 102 +- .../MigrationContext/MySqlDatabaseContext.cs | 31 + .../PostgresqlDatabaseContext.cs | 33 + .../MigrationContext/SqliteDatabaseContext.cs | 31 + SharedLibraryCore/Interfaces/IManager.cs | 1 - .../20180409183408_InitialCreate.Designer.cs | 5 +- .../20180409183408_InitialCreate.cs | 2 +- .../20180502195450_Update.Designer.cs | 5 +- .../{ => MySql}/20180502195450_Update.cs | 2 +- .../20180516023249_AddEloField.Designer.cs | 5 +- .../{ => MySql}/20180516023249_AddEloField.cs | 2 +- .../20180517223349_AddRollingKDR.Designer.cs | 5 +- .../20180517223349_AddRollingKDR.cs | 2 +- ...tomatedOffenseAndRatingHistory.Designer.cs | 6 +- ...903_AddAutomatedOffenseAndRatingHistory.cs | 2 +- ...180601172317_AddActivityAmount.Designer.cs | 6 +- .../20180601172317_AddActivityAmount.cs | 2 +- .../20180602041758_AddClientMeta.Designer.cs | 6 +- .../20180602041758_AddClientMeta.cs | 2 +- ...0180605191706_AddEFACSnapshots.Designer.cs | 6 +- .../20180605191706_AddEFACSnapshots.cs | 2 +- ...20180614014303_IndexForEFAlias.Designer.cs | 6 +- .../20180614014303_IndexForEFAlias.cs | 2 +- ...902035612_AddFractionAndIsKill.Designer.cs | 6 +- .../20180902035612_AddFractionAndIsKill.cs | 2 +- ...154622_AddVisibilityPercentage.Designer.cs | 6 +- .../20180904154622_AddVisibilityPercentage.cs | 2 +- .../20180907020706_AddVision.Designer.cs | 6 +- .../{ => MySql}/20180907020706_AddVision.cs | 2 +- ...20180908004053_AddWhenToRating.Designer.cs | 6 +- .../20180908004053_AddWhenToRating.cs | 2 +- ...0180910221749_AddRatingIndexes.Designer.cs | 6 +- .../20180910221749_AddRatingIndexes.cs | 2 +- ...0911184224_AddEFAliasNameIndex.Designer.cs | 6 +- .../20180911184224_AddEFAliasNameIndex.cs | 2 +- ...0823_AddEFAliasNameMaxLength24.Designer.cs | 6 +- ...0180911190823_AddEFAliasNameMaxLength24.cs | 2 +- ...sCurrentValueToEFChangeHistory.Designer.cs | 6 +- ...ddPreviousCurrentValueToEFChangeHistory.cs | 2 +- ...3111_AddIndexToMessageTimeSent.Designer.cs | 6 +- ...0180915163111_AddIndexToMessageTimeSent.cs | 2 +- ...0180922231310_RemoveACSnapShot.Designer.cs | 6 +- .../20180922231310_RemoveACSnapShot.cs | 2 +- ...20180922231600_ReaddACSnapshot.Designer.cs | 6 +- .../20180922231600_ReaddACSnapshot.cs | 2 +- ..._MakePenaltyExpirationNullable.Designer.cs | 6 +- ...014171848_MakePenaltyExpirationNullable.cs | 2 +- ...125193243_MakeClientIPNullable.Designer.cs | 6 +- .../20181125193243_MakeClientIPNullable.cs | 2 +- ...ntToEFServerUpdateServerIdType.Designer.cs | 6 +- ...AddEndpointToEFServerUpdateServerIdType.cs | 2 +- ...1216214513_AddEvadePenaltyFlag.Designer.cs | 6 +- .../20181216214513_AddEvadePenaltyFlag.cs | 2 +- ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 6 +- ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 2 +- ...23142128_AddGameNameToEFServer.Designer.cs | 6 +- .../20190423142128_AddGameNameToEFServer.cs | 2 +- ...90615145212_AddAvgRecoilOffset.Designer.cs | 6 +- .../20190615145212_AddAvgRecoilOffset.cs | 2 +- ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 6 +- ...0190615214055_AddRecoilOffsetToSnapshot.cs | 2 +- ...90725000309_AlterEFRatingIndex.Designer.cs | 6 +- .../20190725000309_AlterEFRatingIndex.cs | 2 +- ...2174908_AddSearchNameToEFAlias.Designer.cs | 6 +- .../20190802174908_AddSearchNameToEFAlias.cs | 2 +- ...AvgSnapValueToClientStatistics.Designer.cs | 6 +- ...31210503_AvgSnapValueToClientStatistics.cs | 2 +- ...SnapHitCountToClientStatistics.Designer.cs | 6 +- ...80209_AddSnapHitCountToClientStatistics.cs | 2 +- ...unctionTableForSnapshotVector3.Designer.cs | 6 +- ...3620_UseJunctionTableForSnapshotVector3.cs | 2 +- ..._AddCurrentSnapValueToSnapshot.Designer.cs | 6 +- ...914011524_AddCurrentSnapValueToSnapshot.cs | 2 +- ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 6 +- ...0914012015_AddSessionSnapHitsToSnapshot.cs | 2 +- ...eClientHitLocationCountColumns.Designer.cs | 6 +- ...550_RenameClientHitLocationCountColumns.cs | 2 +- ...rceUniqueIndexForEFAliasIPName.Designer.cs | 6 +- ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 2 +- ...iveCoallationForAliasNameMySQL.Designer.cs | 6 +- ...aseSensitiveCoallationForAliasNameMySQL.cs | 2 +- ...140947_AddMissingActiveColumns.Designer.cs | 6 +- .../20191230140947_AddMissingActiveColumns.cs | 2 +- ...personationIdToEFChangeHistory.Designer.cs | 6 +- ...137_AddImpersonationIdToEFChangeHistory.cs | 2 +- ...21203304_AddHostnameToEFServer.Designer.cs | 6 +- .../20200521203304_AddHostnameToEFServer.cs | 2 +- ...9_AddIsPasswordProtectedColumn.Designer.cs | 6 +- ...0819224119_AddIsPasswordProtectedColumn.cs | 2 +- ...1114232340_UpdateEFRatingIndex.Designer.cs | 6 +- .../20201114232340_UpdateEFRatingIndex.cs | 2 +- ...dSentIngameFlagToClientMessage.Designer.cs | 6 +- ...023106_AddSentIngameFlagToClientMessage.cs | 2 +- ...024731_UpdateMigrationsToMySql.Designer.cs | 931 +++++++ .../20201124024731_UpdateMigrationsToMySql.cs | 2342 +++++++++++++++++ .../MySqlDatabaseContextModelSnapshot.cs | 929 +++++++ .../20180409183408_InitialCreate.Designer.cs | 431 +++ .../20180409183408_InitialCreate.cs | 483 ++++ .../20180502195450_Update.Designer.cs | 434 +++ .../Postgresql/20180502195450_Update.cs | 35 + .../20180516023249_AddEloField.Designer.cs | 436 +++ .../Postgresql/20180516023249_AddEloField.cs | 25 + .../20180517223349_AddRollingKDR.Designer.cs | 438 +++ .../20180517223349_AddRollingKDR.cs | 25 + ...tomatedOffenseAndRatingHistory.Designer.cs | 501 ++++ ...903_AddAutomatedOffenseAndRatingHistory.cs | 101 + ...180601172317_AddActivityAmount.Designer.cs | 503 ++++ .../20180601172317_AddActivityAmount.cs | 25 + .../20180602041758_AddClientMeta.Designer.cs | 539 ++++ .../20180602041758_AddClientMeta.cs | 52 + ...0180605191706_AddEFACSnapshots.Designer.cs | 638 +++++ .../20180605191706_AddEFACSnapshots.cs | 144 + ...20180614014303_IndexForEFAlias.Designer.cs | 638 +++++ .../20180614014303_IndexForEFAlias.cs | 24 + ...902035612_AddFractionAndIsKill.Designer.cs | 665 +++++ .../20180902035612_AddFractionAndIsKill.cs | 63 + ...154622_AddVisibilityPercentage.Designer.cs | 665 +++++ .../20180904154622_AddVisibilityPercentage.cs | 23 + .../20180907020706_AddVision.Designer.cs | 669 +++++ .../Postgresql/20180907020706_AddVision.cs | 23 + ...20180908004053_AddWhenToRating.Designer.cs | 669 +++++ .../20180908004053_AddWhenToRating.cs | 25 + ...0180910221749_AddRatingIndexes.Designer.cs | 677 +++++ .../20180910221749_AddRatingIndexes.cs | 40 + ...0911184224_AddEFAliasNameIndex.Designer.cs | 679 +++++ .../20180911184224_AddEFAliasNameIndex.cs | 22 + ...0823_AddEFAliasNameMaxLength24.Designer.cs | 680 +++++ ...0180911190823_AddEFAliasNameMaxLength24.cs | 25 + ...sCurrentValueToEFChangeHistory.Designer.cs | 684 +++++ ...ddPreviousCurrentValueToEFChangeHistory.cs | 32 + ...3111_AddIndexToMessageTimeSent.Designer.cs | 686 +++++ ...0180915163111_AddIndexToMessageTimeSent.cs | 22 + ...0180922231310_RemoveACSnapShot.Designer.cs | 587 +++++ .../20180922231310_RemoveACSnapShot.cs | 139 + ...20180922231600_ReaddACSnapshot.Designer.cs | 689 +++++ .../20180922231600_ReaddACSnapshot.cs | 145 + ..._MakePenaltyExpirationNullable.Designer.cs | 690 +++++ ...014171848_MakePenaltyExpirationNullable.cs | 105 + ...125193243_MakeClientIPNullable.Designer.cs | 690 +++++ .../20181125193243_MakeClientIPNullable.cs | 85 + ...ntToEFServerUpdateServerIdType.Designer.cs | 692 +++++ ...AddEndpointToEFServerUpdateServerIdType.cs | 22 + ...1216214513_AddEvadePenaltyFlag.Designer.cs | 694 +++++ .../20181216214513_AddEvadePenaltyFlag.cs | 183 ++ ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 696 +++++ ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 30 + ...23142128_AddGameNameToEFServer.Designer.cs | 699 +++++ .../20190423142128_AddGameNameToEFServer.cs | 22 + ...90615145212_AddAvgRecoilOffset.Designer.cs | 701 +++++ .../20190615145212_AddAvgRecoilOffset.cs | 20 + ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 703 +++++ ...0190615214055_AddRecoilOffsetToSnapshot.cs | 23 + ...90725000309_AlterEFRatingIndex.Designer.cs | 699 +++++ .../20190725000309_AlterEFRatingIndex.cs | 49 + ...2174908_AddSearchNameToEFAlias.Designer.cs | 704 +++++ .../20190802174908_AddSearchNameToEFAlias.cs | 32 + ...AvgSnapValueToClientStatistics.Designer.cs | 706 +++++ ...31210503_AvgSnapValueToClientStatistics.cs | 23 + ...SnapHitCountToClientStatistics.Designer.cs | 708 +++++ ...80209_AddSnapHitCountToClientStatistics.cs | 23 + ...unctionTableForSnapshotVector3.Designer.cs | 728 +++++ ...3620_UseJunctionTableForSnapshotVector3.cs | 89 + ..._AddCurrentSnapValueToSnapshot.Designer.cs | 730 +++++ ...914011524_AddCurrentSnapValueToSnapshot.cs | 23 + ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 732 ++++++ ...0914012015_AddSessionSnapHitsToSnapshot.cs | 23 + ...eClientHitLocationCountColumns.Designer.cs | 910 +++++++ ...550_RenameClientHitLocationCountColumns.cs | 151 ++ ...rceUniqueIndexForEFAliasIPName.Designer.cs | 909 +++++++ ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 188 ++ ...iveCoallationForAliasNameMySQL.Designer.cs | 916 +++++++ ...aseSensitiveCoallationForAliasNameMySQL.cs | 24 + ...140947_AddMissingActiveColumns.Designer.cs | 916 +++++++ .../20191230140947_AddMissingActiveColumns.cs | 27 + ...personationIdToEFChangeHistory.Designer.cs | 919 +++++++ ...137_AddImpersonationIdToEFChangeHistory.cs | 22 + ...21203304_AddHostnameToEFServer.Designer.cs | 922 +++++++ .../20200521203304_AddHostnameToEFServer.cs | 22 + ...9_AddIsPasswordProtectedColumn.Designer.cs | 925 +++++++ ...0819224119_AddIsPasswordProtectedColumn.cs | 35 + ...1114232340_UpdateEFRatingIndex.Designer.cs | 927 +++++++ .../20201114232340_UpdateEFRatingIndex.cs | 22 + ...dSentIngameFlagToClientMessage.Designer.cs | 930 +++++++ ...023106_AddSentIngameFlagToClientMessage.cs | 23 + ..._UpdateMigrationsForPostgresql.Designer.cs | 948 +++++++ ...125160058_UpdateMigrationsForPostgresql.cs | 2341 ++++++++++++++++ .../PostgresqlDatabaseContextModelSnapshot.cs | 946 +++++++ .../20180409183408_InitialCreate.Designer.cs | 431 +++ .../Sqlite/20180409183408_InitialCreate.cs | 483 ++++ .../Sqlite/20180502195450_Update.Designer.cs | 434 +++ .../Sqlite/20180502195450_Update.cs | 35 + .../20180516023249_AddEloField.Designer.cs | 436 +++ .../Sqlite/20180516023249_AddEloField.cs | 25 + .../20180517223349_AddRollingKDR.Designer.cs | 438 +++ .../Sqlite/20180517223349_AddRollingKDR.cs | 25 + ...tomatedOffenseAndRatingHistory.Designer.cs | 501 ++++ ...903_AddAutomatedOffenseAndRatingHistory.cs | 101 + ...180601172317_AddActivityAmount.Designer.cs | 503 ++++ .../20180601172317_AddActivityAmount.cs | 25 + .../20180602041758_AddClientMeta.Designer.cs | 539 ++++ .../Sqlite/20180602041758_AddClientMeta.cs | 52 + ...0180605191706_AddEFACSnapshots.Designer.cs | 638 +++++ .../Sqlite/20180605191706_AddEFACSnapshots.cs | 144 + ...20180614014303_IndexForEFAlias.Designer.cs | 638 +++++ .../Sqlite/20180614014303_IndexForEFAlias.cs | 24 + ...902035612_AddFractionAndIsKill.Designer.cs | 665 +++++ .../20180902035612_AddFractionAndIsKill.cs | 63 + ...154622_AddVisibilityPercentage.Designer.cs | 665 +++++ .../20180904154622_AddVisibilityPercentage.cs | 23 + .../20180907020706_AddVision.Designer.cs | 669 +++++ .../Sqlite/20180907020706_AddVision.cs | 23 + ...20180908004053_AddWhenToRating.Designer.cs | 669 +++++ .../Sqlite/20180908004053_AddWhenToRating.cs | 25 + ...0180910221749_AddRatingIndexes.Designer.cs | 677 +++++ .../Sqlite/20180910221749_AddRatingIndexes.cs | 40 + ...0911184224_AddEFAliasNameIndex.Designer.cs | 679 +++++ .../20180911184224_AddEFAliasNameIndex.cs | 22 + ...0823_AddEFAliasNameMaxLength24.Designer.cs | 680 +++++ ...0180911190823_AddEFAliasNameMaxLength24.cs | 25 + ...sCurrentValueToEFChangeHistory.Designer.cs | 684 +++++ ...ddPreviousCurrentValueToEFChangeHistory.cs | 32 + ...3111_AddIndexToMessageTimeSent.Designer.cs | 686 +++++ ...0180915163111_AddIndexToMessageTimeSent.cs | 22 + ...0180922231310_RemoveACSnapShot.Designer.cs | 587 +++++ .../Sqlite/20180922231310_RemoveACSnapShot.cs | 139 + ...20180922231600_ReaddACSnapshot.Designer.cs | 689 +++++ .../Sqlite/20180922231600_ReaddACSnapshot.cs | 145 + ..._MakePenaltyExpirationNullable.Designer.cs | 690 +++++ ...014171848_MakePenaltyExpirationNullable.cs | 105 + ...125193243_MakeClientIPNullable.Designer.cs | 690 +++++ .../20181125193243_MakeClientIPNullable.cs | 85 + ...ntToEFServerUpdateServerIdType.Designer.cs | 692 +++++ ...AddEndpointToEFServerUpdateServerIdType.cs | 22 + ...1216214513_AddEvadePenaltyFlag.Designer.cs | 694 +++++ .../20181216214513_AddEvadePenaltyFlag.cs | 183 ++ ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 696 +++++ ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 30 + ...23142128_AddGameNameToEFServer.Designer.cs | 699 +++++ .../20190423142128_AddGameNameToEFServer.cs | 22 + ...90615145212_AddAvgRecoilOffset.Designer.cs | 701 +++++ .../20190615145212_AddAvgRecoilOffset.cs | 20 + ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 703 +++++ ...0190615214055_AddRecoilOffsetToSnapshot.cs | 23 + ...90725000309_AlterEFRatingIndex.Designer.cs | 699 +++++ .../20190725000309_AlterEFRatingIndex.cs | 49 + ...2174908_AddSearchNameToEFAlias.Designer.cs | 704 +++++ .../20190802174908_AddSearchNameToEFAlias.cs | 32 + ...AvgSnapValueToClientStatistics.Designer.cs | 706 +++++ ...31210503_AvgSnapValueToClientStatistics.cs | 23 + ...SnapHitCountToClientStatistics.Designer.cs | 708 +++++ ...80209_AddSnapHitCountToClientStatistics.cs | 23 + ...unctionTableForSnapshotVector3.Designer.cs | 728 +++++ ...3620_UseJunctionTableForSnapshotVector3.cs | 89 + ..._AddCurrentSnapValueToSnapshot.Designer.cs | 730 +++++ ...914011524_AddCurrentSnapValueToSnapshot.cs | 23 + ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 732 ++++++ ...0914012015_AddSessionSnapHitsToSnapshot.cs | 23 + ...eClientHitLocationCountColumns.Designer.cs | 910 +++++++ ...550_RenameClientHitLocationCountColumns.cs | 151 ++ ...rceUniqueIndexForEFAliasIPName.Designer.cs | 909 +++++++ ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 188 ++ ...iveCoallationForAliasNameMySQL.Designer.cs | 916 +++++++ ...aseSensitiveCoallationForAliasNameMySQL.cs | 24 + ...140947_AddMissingActiveColumns.Designer.cs | 916 +++++++ .../20191230140947_AddMissingActiveColumns.cs | 27 + ...personationIdToEFChangeHistory.Designer.cs | 919 +++++++ ...137_AddImpersonationIdToEFChangeHistory.cs | 22 + ...21203304_AddHostnameToEFServer.Designer.cs | 922 +++++++ .../20200521203304_AddHostnameToEFServer.cs | 22 + ...9_AddIsPasswordProtectedColumn.Designer.cs | 925 +++++++ ...0819224119_AddIsPasswordProtectedColumn.cs | 35 + ...1114232340_UpdateEFRatingIndex.Designer.cs | 927 +++++++ .../20201114232340_UpdateEFRatingIndex.cs | 22 + ...dSentIngameFlagToClientMessage.Designer.cs | 930 +++++++ ...023106_AddSentIngameFlagToClientMessage.cs | 23 + .../SqliteDatabaseContextModelSnapshot.cs} | 8 +- SharedLibraryCore/Services/AliasService.cs | 65 - .../Services/ChangeHistoryService.cs | 71 +- SharedLibraryCore/Services/ClientService.cs | 601 ++--- SharedLibraryCore/Services/PenaltyService.cs | 197 +- .../SharedLibraryCore - Backup.csproj | 66 + SharedLibraryCore/SharedLibraryCore.csproj | 2 +- SharedLibraryCore/Utilities.cs | 2 + .../Mocks/DatabaseContextFactoryMock.cs | 24 +- WebfrontCore/Controllers/PenaltyController.cs | 50 +- WebfrontCore/Program.cs | 10 +- WebfrontCore/Startup.cs | 16 +- WebfrontCore/WebfrontCore.csproj | 2 +- 309 files changed, 76554 insertions(+), 1067 deletions(-) create mode 100644 SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs create mode 100644 SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs create mode 100644 SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs rename SharedLibraryCore/Migrations/{ => MySql}/20180409183408_InitialCreate.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180409183408_InitialCreate.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180502195450_Update.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180502195450_Update.cs (95%) rename SharedLibraryCore/Migrations/{ => MySql}/20180516023249_AddEloField.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180516023249_AddEloField.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180517223349_AddRollingKDR.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180517223349_AddRollingKDR.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180531212903_AddAutomatedOffenseAndRatingHistory.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20180601172317_AddActivityAmount.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180601172317_AddActivityAmount.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180602041758_AddClientMeta.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180602041758_AddClientMeta.cs (97%) rename SharedLibraryCore/Migrations/{ => MySql}/20180605191706_AddEFACSnapshots.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180605191706_AddEFACSnapshots.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180614014303_IndexForEFAlias.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180614014303_IndexForEFAlias.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180902035612_AddFractionAndIsKill.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180902035612_AddFractionAndIsKill.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20180904154622_AddVisibilityPercentage.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180904154622_AddVisibilityPercentage.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180907020706_AddVision.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180907020706_AddVision.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180908004053_AddWhenToRating.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180908004053_AddWhenToRating.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180910221749_AddRatingIndexes.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180910221749_AddRatingIndexes.cs (96%) rename SharedLibraryCore/Migrations/{ => MySql}/20180911184224_AddEFAliasNameIndex.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180911184224_AddEFAliasNameIndex.cs (92%) rename SharedLibraryCore/Migrations/{ => MySql}/20180911190823_AddEFAliasNameMaxLength24.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180911190823_AddEFAliasNameMaxLength24.cs (94%) rename SharedLibraryCore/Migrations/{ => MySql}/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs (95%) rename SharedLibraryCore/Migrations/{ => MySql}/20180915163111_AddIndexToMessageTimeSent.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180915163111_AddIndexToMessageTimeSent.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20180922231310_RemoveACSnapShot.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180922231310_RemoveACSnapShot.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180922231600_ReaddACSnapshot.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20180922231600_ReaddACSnapshot.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20181014171848_MakePenaltyExpirationNullable.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20181014171848_MakePenaltyExpirationNullable.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20181125193243_MakeClientIPNullable.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20181125193243_MakeClientIPNullable.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs (92%) rename SharedLibraryCore/Migrations/{ => MySql}/20181216214513_AddEvadePenaltyFlag.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20181216214513_AddEvadePenaltyFlag.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs (94%) rename SharedLibraryCore/Migrations/{ => MySql}/20190423142128_AddGameNameToEFServer.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190423142128_AddGameNameToEFServer.cs (92%) rename SharedLibraryCore/Migrations/{ => MySql}/20190615145212_AddAvgRecoilOffset.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190615145212_AddAvgRecoilOffset.cs (91%) rename SharedLibraryCore/Migrations/{ => MySql}/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190615214055_AddRecoilOffsetToSnapshot.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20190725000309_AlterEFRatingIndex.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190725000309_AlterEFRatingIndex.cs (97%) rename SharedLibraryCore/Migrations/{ => MySql}/20190802174908_AddSearchNameToEFAlias.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190802174908_AddSearchNameToEFAlias.cs (95%) rename SharedLibraryCore/Migrations/{ => MySql}/20190831210503_AvgSnapValueToClientStatistics.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190831210503_AvgSnapValueToClientStatistics.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190901180209_AddSnapHitCountToClientStatistics.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190901223620_UseJunctionTableForSnapshotVector3.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190914011524_AddCurrentSnapValueToSnapshot.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20190914012015_AddSessionSnapHitsToSnapshot.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20191004172550_RenameClientHitLocationCountColumns.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20191004172550_RenameClientHitLocationCountColumns.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs (98%) rename SharedLibraryCore/Migrations/{ => MySql}/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs (94%) rename SharedLibraryCore/Migrations/{ => MySql}/20191230140947_AddMissingActiveColumns.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20191230140947_AddMissingActiveColumns.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20200423225137_AddImpersonationIdToEFChangeHistory.cs (93%) rename SharedLibraryCore/Migrations/{ => MySql}/20200521203304_AddHostnameToEFServer.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20200521203304_AddHostnameToEFServer.cs (92%) rename SharedLibraryCore/Migrations/{ => MySql}/20200819224119_AddIsPasswordProtectedColumn.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20200819224119_AddIsPasswordProtectedColumn.cs (95%) rename SharedLibraryCore/Migrations/{ => MySql}/20201114232340_UpdateEFRatingIndex.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20201114232340_UpdateEFRatingIndex.cs (94%) rename SharedLibraryCore/Migrations/{ => MySql}/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs (99%) rename SharedLibraryCore/Migrations/{ => MySql}/20201118023106_AddSentIngameFlagToClientMessage.cs (93%) create mode 100644 SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs create mode 100644 SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs create mode 100644 SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs rename SharedLibraryCore/Migrations/{DatabaseContextModelSnapshot.cs => Sqlite/SqliteDatabaseContextModelSnapshot.cs} (99%) delete mode 100644 SharedLibraryCore/Services/AliasService.cs create mode 100644 SharedLibraryCore/SharedLibraryCore - Backup.csproj diff --git a/.gitignore b/.gitignore index f7743056..18cd25a6 100644 --- a/.gitignore +++ b/.gitignore @@ -244,4 +244,5 @@ launchSettings.json /Tests/ApplicationTests/Files/GameEvents.json /Tests/ApplicationTests/Files/replay.json /GameLogServer/game_log_server_env -.idea/* \ No newline at end of file +.idea/* +*.db \ No newline at end of file diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 257d648a..19d65af2 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -53,7 +53,6 @@ namespace IW4MAdmin.Application private readonly ILogger _logger; private readonly List MessageTokens; private readonly ClientService ClientSvc; - readonly AliasService AliasSvc; readonly PenaltyService PenaltySvc; public IConfigurationHandler ConfigHandler; readonly IPageList PageList; @@ -80,14 +79,13 @@ namespace IW4MAdmin.Application IEnumerable plugins, IParserRegexFactory parserRegexFactory, IEnumerable customParserEvents, IEventHandler eventHandler, IScriptCommandFactory scriptCommandFactory, IDatabaseContextFactory contextFactory, IMetaService metaService, IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver, ClientService clientService, IServiceProvider serviceProvider, - ChangeHistoryService changeHistoryService, ApplicationConfiguration appConfig) + ChangeHistoryService changeHistoryService, ApplicationConfiguration appConfig, PenaltyService penaltyService) { MiddlewareActionHandler = actionHandler; _servers = new ConcurrentBag(); MessageTokens = new List(); ClientSvc = clientService; - AliasSvc = new AliasService(); - PenaltySvc = new PenaltyService(); + PenaltySvc = penaltyService; ConfigHandler = appConfigHandler; StartTime = DateTime.UtcNow; PageList = new PageList(); @@ -401,16 +399,16 @@ namespace IW4MAdmin.Application #endregion #region DATABASE - using (var db = new DatabaseContext(GetApplicationSettings().Configuration()?.ConnectionString, - GetApplicationSettings().Configuration()?.DatabaseProvider)) - { - await new ContextSeed(db).Seed(); - DatabaseHousekeeping.RemoveOldRatings(db); - } + _logger.LogInformation("Beginning database migration sync"); + Console.WriteLine(_translationLookup["MANAGER_MIGRATION_START"]); + await ContextSeed.Seed(_serviceProvider.GetRequiredService(), _tokenSource.Token); + await DatabaseHousekeeping.RemoveOldRatings(_serviceProvider.GetRequiredService(), _tokenSource.Token); + _logger.LogInformation("Finished database migration sync"); + Console.WriteLine(_translationLookup["MANAGER_MIGRATION_END"]); #endregion #region COMMANDS - if (ClientSvc.GetOwners().Result.Count > 0) + if (await ClientSvc.HasOwnerAsync(_tokenSource.Token)) { _commands.RemoveAll(_cmd => _cmd.GetType() == typeof(OwnerCommand)); } @@ -565,11 +563,6 @@ namespace IW4MAdmin.Application return ClientSvc; } - public AliasService GetAliasService() - { - return AliasSvc; - } - public PenaltyService GetPenaltyService() { return PenaltySvc; diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index 614cd2fe..1994983c 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -1,9 +1,16 @@ -using System.IO; +using System; +using System.IO; +using System.Runtime.InteropServices; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Serilog; +using Serilog.Events; using SharedLibraryCore; using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; namespace IW4MAdmin.Application.Extensions { @@ -21,13 +28,16 @@ namespace IW4MAdmin.Application.Extensions .Build(); var loggerConfig = new LoggerConfiguration() - .ReadFrom.Configuration(configuration); + .ReadFrom.Configuration(configuration) + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning); if (Utilities.IsDevelopment) { loggerConfig = loggerConfig.WriteTo.Console( - outputTemplate:"[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") + outputTemplate: + "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Debug(); } @@ -37,5 +47,46 @@ namespace IW4MAdmin.Application.Extensions services.AddLogging(builder => builder.AddSerilog(_defaultLogger, dispose: true)); return services; } + + public static IServiceCollection AddDatabaseContext(this IServiceCollection services, + ApplicationConfiguration appConfig) + { + if (string.IsNullOrEmpty(appConfig.ConnectionString) || appConfig.DatabaseProvider == "sqlite") + { + var currentPath = Utilities.OperatingDirectory; + currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? $"{Path.DirectorySeparatorChar}{currentPath}" + : currentPath; + + var connectionStringBuilder = new SqliteConnectionStringBuilder + {DataSource = Path.Join(currentPath, "Database", "Database.db")}; + var connectionString = connectionStringBuilder.ToString(); + + services.AddDbContext(options => + options.UseSqlite(connectionString), ServiceLifetime.Transient); + return services; + } + + switch (appConfig.DatabaseProvider) + { + case "mysql": + var appendTimeout = !appConfig.ConnectionString.Contains("default command timeout", + StringComparison.InvariantCultureIgnoreCase); + services.AddDbContext(options => + options.UseMySql( + appConfig.ConnectionString + (appendTimeout ? "default command timeout=0" : ""), + mysqlOptions => mysqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); + break; + case "postgresql": + appendTimeout = !appConfig.ConnectionString.Contains("Command Timeout", + StringComparison.InvariantCultureIgnoreCase); + services.AddDbContext(options => + options.UseNpgsql(appConfig.ConnectionString + (appendTimeout ? "Command Timeout=0" : ""), + postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); + break; + } + + return services; + } } } \ No newline at end of file diff --git a/Application/Factories/DatabaseContextFactory.cs b/Application/Factories/DatabaseContextFactory.cs index 631b7b5a..871652a9 100644 --- a/Application/Factories/DatabaseContextFactory.cs +++ b/Application/Factories/DatabaseContextFactory.cs @@ -1,4 +1,7 @@ -using SharedLibraryCore.Database; +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using SharedLibraryCore.Database; using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Factories @@ -8,6 +11,13 @@ namespace IW4MAdmin.Application.Factories /// public class DatabaseContextFactory : IDatabaseContextFactory { + private readonly IServiceProvider _serviceProvider; + + public DatabaseContextFactory(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + /// /// creates a new database context /// @@ -15,7 +25,24 @@ namespace IW4MAdmin.Application.Factories /// public DatabaseContext CreateContext(bool? enableTracking = true) { - return enableTracking.HasValue ? new DatabaseContext(disableTracking: !enableTracking.Value) : new DatabaseContext(); + var context = _serviceProvider.GetRequiredService(); + + enableTracking ??= true; + + if (enableTracking.Value) + { + context.ChangeTracker.AutoDetectChangesEnabled = true; + context.ChangeTracker.LazyLoadingEnabled = true; + context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll; + } + else + { + context.ChangeTracker.AutoDetectChangesEnabled = false; + context.ChangeTracker.LazyLoadingEnabled = false; + context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + } + + return context; } } } diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 922e8415..6b9b1224 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -334,7 +334,7 @@ namespace IW4MAdmin // possible a connect/reconnect game event before we get to process it here // it appears that new games decide to switch client slots between maps (even if the clients aren't disconnecting) // bots can have duplicate names which causes conflicting GUIDs - else if (existingClient != null && existingClient.ClientNumber != E.Origin.ClientNumber && + if (existingClient != null && existingClient.ClientNumber != E.Origin.ClientNumber && !E.Origin.IsBot) { ServerLogger.LogWarning( diff --git a/Application/Main.cs b/Application/Main.cs index 6b7ecab8..e011618b 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -81,6 +81,7 @@ namespace IW4MAdmin.Application ITranslationLookup translationLookup = null; var logger = BuildDefaultLogger(new ApplicationConfiguration()); Utilities.DefaultLogger = logger; + IServiceCollection services = null; logger.LogInformation("Begin IW4MAdmin startup. Version is {version} {@args}", Version, args); try @@ -89,7 +90,7 @@ namespace IW4MAdmin.Application ConfigurationMigration.MoveConfigFolder10518(null); ConfigurationMigration.CheckDirectories(); logger.LogDebug("Configuring services..."); - var services = ConfigureServices(args); + services = ConfigureServices(args); serviceProvider = services.BuildServiceProvider(); var versionChecker = serviceProvider.GetRequiredService(); ServerManager = (ApplicationManager)serviceProvider.GetRequiredService(); @@ -137,7 +138,7 @@ namespace IW4MAdmin.Application try { - ApplicationTask = RunApplicationTasksAsync(logger); + ApplicationTask = RunApplicationTasksAsync(logger, services); await ApplicationTask; } @@ -160,10 +161,10 @@ namespace IW4MAdmin.Application /// runs the core application tasks /// /// - private static async Task RunApplicationTasksAsync(ILogger logger) + private static async Task RunApplicationTasksAsync(ILogger logger, IServiceCollection services) { var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront ? - WebfrontCore.Program.Init(ServerManager, serviceProvider, ServerManager.CancellationToken) : + WebfrontCore.Program.Init(ServerManager, serviceProvider, services, ServerManager.CancellationToken) : Task.CompletedTask; // we want to run this one on a manual thread instead of letting the thread pool handle it, @@ -322,9 +323,13 @@ namespace IW4MAdmin.Application .AddBaseLogger(appConfig) .AddSingleton(_serviceProvider => serviceCollection) .AddSingleton((IConfigurationHandler) appConfigHandler) - .AddSingleton(new BaseConfigurationHandler("CommandConfiguration") as IConfigurationHandler) + .AddSingleton( + new BaseConfigurationHandler("CommandConfiguration") as + IConfigurationHandler) .AddSingleton(appConfig) - .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService>().Configuration() ?? new CommandConfiguration()) + .AddSingleton(_serviceProvider => + _serviceProvider.GetRequiredService>() + .Configuration() ?? new CommandConfiguration()) .AddSingleton() .AddSingleton() .AddSingleton() @@ -338,12 +343,16 @@ namespace IW4MAdmin.Application .AddSingleton, ClientService>() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton, ReceivedPenaltyResourceQueryHelper>() - .AddSingleton, AdministeredPenaltyResourceQueryHelper>() - .AddSingleton, UpdatedAliasResourceQueryHelper>() + .AddSingleton, + ReceivedPenaltyResourceQueryHelper>() + .AddSingleton, + AdministeredPenaltyResourceQueryHelper>() + .AddSingleton, + UpdatedAliasResourceQueryHelper>() .AddSingleton, ChatResourceQueryHelper>() .AddTransient() .AddSingleton() @@ -351,7 +360,8 @@ namespace IW4MAdmin.Application .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton(translationLookup); + .AddSingleton(translationLookup) + .AddDatabaseContext(appConfig); if (args.Contains("serialevents")) { diff --git a/Application/Migration/DatabaseHousekeeping.cs b/Application/Migration/DatabaseHousekeeping.cs index b42b7f60..eec18006 100644 --- a/Application/Migration/DatabaseHousekeeping.cs +++ b/Application/Migration/DatabaseHousekeeping.cs @@ -1,20 +1,24 @@ using System; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using IW4MAdmin.Plugins.Stats.Models; using SharedLibraryCore.Database; +using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Migration { public static class DatabaseHousekeeping { - private static DateTime _cutoffDate = DateTime.UtcNow.AddMonths(-6); + private static readonly DateTime CutoffDate = DateTime.UtcNow.AddMonths(-6); - public static void RemoveOldRatings(DatabaseContext context) + public static async Task RemoveOldRatings(IDatabaseContextFactory contextFactory, CancellationToken token) { + await using var context = contextFactory.CreateContext(); var dbSet = context.Set(); - var itemsToDelete = dbSet.Where(rating => rating.When <= _cutoffDate); + var itemsToDelete = dbSet.Where(rating => rating.When <= CutoffDate); dbSet.RemoveRange(itemsToDelete); - context.SaveChanges(); + await context.SaveChangesAsync(token); } } } \ No newline at end of file diff --git a/Application/Misc/ScriptPlugin.cs b/Application/Misc/ScriptPlugin.cs index 20568a7c..2a50fac7 100644 --- a/Application/Misc/ScriptPlugin.cs +++ b/Application/Misc/ScriptPlugin.cs @@ -118,7 +118,28 @@ namespace IW4MAdmin.Application.Misc }) .CatchClrExceptions()); - _scriptEngine.Execute(script); + try + { + _scriptEngine.Execute(script); + } + catch (JavaScriptException ex) + { + + _logger.LogError(ex, + "Encountered JavaScript runtime error while executing {methodName} for script plugin {plugin} at {@locationInfo}", + nameof(Initialize), _fileName, ex.Location); + throw new PluginException($"A JavaScript parsing error occured while initializing script plugin"); + } + + catch (Exception e) + { + + _logger.LogError(e, + "Encountered unexpected error while running {methodName} for script plugin {plugin}", + nameof(Initialize), _fileName); + throw new PluginException($"An unexpected error occured while initialization script plugin"); + } + _scriptEngine.SetValue("_localization", Utilities.CurrentLocalization); _scriptEngine.SetValue("_serviceResolver", serviceResolver); dynamic pluginObject = _scriptEngine.GetValue("plugin").ToObject(); diff --git a/Plugins/LiveRadar/Plugin.cs b/Plugins/LiveRadar/Plugin.cs index c787a805..245129af 100644 --- a/Plugins/LiveRadar/Plugin.cs +++ b/Plugins/LiveRadar/Plugin.cs @@ -2,6 +2,7 @@ using SharedLibraryCore; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -68,7 +69,9 @@ namespace LiveRadar lock (lockObject) { - generatedBotGuid = _botGuidLookups.ContainsKey(botKey) ? _botGuidLookups[botKey] : 0; + generatedBotGuid = _botGuidLookups.ContainsKey(botKey) + ? _botGuidLookups[botKey] + : (E.Extra.ToString() ?? "0").ConvertGuidToLong(NumberStyles.HexNumber); } var radarUpdate = RadarEvent.Parse(E.Data, generatedBotGuid); diff --git a/Plugins/Stats/Commands/MostPlayedCommand.cs b/Plugins/Stats/Commands/MostPlayedCommand.cs index fc8b124a..9ad77736 100644 --- a/Plugins/Stats/Commands/MostPlayedCommand.cs +++ b/Plugins/Stats/Commands/MostPlayedCommand.cs @@ -16,7 +16,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands { class MostPlayedCommand : Command { - public static async Task> GetMostPlayed(Server s, ITranslationLookup translationLookup) + public static async Task> GetMostPlayed(Server s, ITranslationLookup translationLookup, IDatabaseContextFactory contextFactory) { long serverId = StatManager.GetIdForServer(s); @@ -25,42 +25,39 @@ namespace IW4MAdmin.Plugins.Stats.Commands $"^5--{translationLookup["PLUGINS_STATS_COMMANDS_MOSTPLAYED_TEXT"]}--" }; - using (var db = new DatabaseContext(true)) - { - db.ChangeTracker.AutoDetectChangesEnabled = false; - db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + await using var context = contextFactory.CreateContext(false); + var thirtyDaysAgo = DateTime.UtcNow.AddMonths(-1); - var thirtyDaysAgo = DateTime.UtcNow.AddMonths(-1); + var iqStats = (from stats in context.Set() + join client in context.Clients + on stats.ClientId equals client.ClientId + join alias in context.Aliases + on client.CurrentAliasId equals alias.AliasId + where stats.ServerId == serverId + where client.Level != EFClient.Permission.Banned + where client.LastConnection >= thirtyDaysAgo + orderby stats.TimePlayed descending + select new + { + alias.Name, + client.TotalConnectionTime, + stats.Kills + }) + .Take(5); - var iqStats = (from stats in db.Set() - join client in db.Clients - on stats.ClientId equals client.ClientId - join alias in db.Aliases - on client.CurrentAliasId equals alias.AliasId - where stats.ServerId == serverId - where client.Level != EFClient.Permission.Banned - where client.LastConnection >= thirtyDaysAgo - orderby stats.TimePlayed descending - select new - { - alias.Name, - client.TotalConnectionTime, - stats.Kills - }) - .Take(5); + var iqList = await iqStats.ToListAsync(); - var iqList = await iqStats.ToListAsync(); - - mostPlayed.AddRange(iqList.Select(stats => translationLookup["COMMANDS_MOST_PLAYED_FORMAT"].FormatExt(stats.Name, stats.Kills, (DateTime.UtcNow - DateTime.UtcNow.AddSeconds(-stats.TotalConnectionTime)).HumanizeForCurrentCulture()))); - } + mostPlayed.AddRange(iqList.Select(stats => translationLookup["COMMANDS_MOST_PLAYED_FORMAT"].FormatExt(stats.Name, stats.Kills, (DateTime.UtcNow - DateTime.UtcNow.AddSeconds(-stats.TotalConnectionTime)).HumanizeForCurrentCulture()))); return mostPlayed; } private readonly CommandConfiguration _config; + private readonly IDatabaseContextFactory _contextFactory; - public MostPlayedCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + public MostPlayedCommand(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "mostplayed"; Description = translationLookup["PLUGINS_STATS_COMMANDS_MOSTPLAYED_DESC"]; @@ -69,11 +66,12 @@ namespace IW4MAdmin.Plugins.Stats.Commands RequiresTarget = false; _config = config; + _contextFactory = contextFactory; } public override async Task ExecuteAsync(GameEvent E) { - var topStats = await GetMostPlayed(E.Owner, _translationLookup); + var topStats = await GetMostPlayed(E.Owner, _translationLookup, _contextFactory); if (!E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { foreach (var stat in topStats) diff --git a/Plugins/Stats/Commands/ResetStats.cs b/Plugins/Stats/Commands/ResetStats.cs index 20fd8031..ef4637c1 100644 --- a/Plugins/Stats/Commands/ResetStats.cs +++ b/Plugins/Stats/Commands/ResetStats.cs @@ -12,14 +12,17 @@ namespace IW4MAdmin.Plugins.Stats.Commands { public class ResetStats : Command { - public ResetStats(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly IDatabaseContextFactory _contextFactory; + + public ResetStats(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "resetstats"; Description = translationLookup["PLUGINS_STATS_COMMANDS_RESET_DESC"]; Alias = "rs"; Permission = EFClient.Permission.User; RequiresTarget = false; - //AllowImpersonation = true; + AllowImpersonation = true; } public override async Task ExecuteAsync(GameEvent E) @@ -30,27 +33,24 @@ namespace IW4MAdmin.Plugins.Stats.Commands long serverId = Helpers.StatManager.GetIdForServer(E.Owner); EFClientStatistics clientStats; - using (var ctx = new DatabaseContext(disableTracking: true)) - { - clientStats = await ctx.Set() - .Where(s => s.ClientId == E.Origin.ClientId) - .Where(s => s.ServerId == serverId) - .FirstAsync(); + await using var context = _contextFactory.CreateContext(); + clientStats = await context.Set() + .Where(s => s.ClientId == E.Origin.ClientId) + .Where(s => s.ServerId == serverId) + .FirstAsync(); - clientStats.Deaths = 0; - clientStats.Kills = 0; - clientStats.SPM = 0.0; - clientStats.Skill = 0.0; - clientStats.TimePlayed = 0; - // todo: make this more dynamic - clientStats.EloRating = 200.0; + clientStats.Deaths = 0; + clientStats.Kills = 0; + clientStats.SPM = 0.0; + clientStats.Skill = 0.0; + clientStats.TimePlayed = 0; + // todo: make this more dynamic + clientStats.EloRating = 200.0; - // reset the cached version - Plugin.Manager.ResetStats(E.Origin); + // reset the cached version + Plugin.Manager.ResetStats(E.Origin); - // fixme: this doesn't work properly when another context exists - await ctx.SaveChangesAsync(); - } + await context.SaveChangesAsync(); E.Origin.Tell(_translationLookup["PLUGINS_STATS_COMMANDS_RESET_SUCCESS"]); } diff --git a/Plugins/Stats/Commands/TopStats.cs b/Plugins/Stats/Commands/TopStats.cs index a81e1522..19b33f99 100644 --- a/Plugins/Stats/Commands/TopStats.cs +++ b/Plugins/Stats/Commands/TopStats.cs @@ -16,7 +16,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands { class TopStats : Command { - public static async Task> GetTopStats(Server s, ITranslationLookup translationLookup) + public static async Task> GetTopStats(Server s, ITranslationLookup translationLookup, IDatabaseContextFactory contextFactory) { long serverId = StatManager.GetIdForServer(s); var topStatsText = new List() @@ -24,36 +24,34 @@ namespace IW4MAdmin.Plugins.Stats.Commands $"^5--{translationLookup["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--" }; - using (var db = new DatabaseContext(true)) - { - var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15); - int minPlayTime = Plugin.Config.Configuration().TopPlayersMinPlayTime; + await using var context = contextFactory.CreateContext(false); + var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15); + int minPlayTime = Plugin.Config.Configuration().TopPlayersMinPlayTime; - var iqStats = (from stats in db.Set() - join client in db.Clients - on stats.ClientId equals client.ClientId - join alias in db.Aliases - on client.CurrentAliasId equals alias.AliasId - where stats.ServerId == serverId - where stats.TimePlayed >= minPlayTime - where client.Level != EFClient.Permission.Banned - where client.LastConnection >= fifteenDaysAgo - orderby (stats.EloRating + stats.Skill) / 2.0d descending - select new - { - stats.KDR, - stats.Performance, - alias.Name - }) - .Take(5); + var iqStats = (from stats in context.Set() + join client in context.Clients + on stats.ClientId equals client.ClientId + join alias in context.Aliases + on client.CurrentAliasId equals alias.AliasId + where stats.ServerId == serverId + where stats.TimePlayed >= minPlayTime + where client.Level != EFClient.Permission.Banned + where client.LastConnection >= fifteenDaysAgo + orderby (stats.EloRating + stats.Skill) / 2.0d descending + select new + { + stats.KDR, + stats.Performance, + alias.Name + }) + .Take(5); - var statsList = (await iqStats.ToListAsync()) - .Select(stats => $"^3{stats.Name}^7 - ^5{stats.KDR} ^7{translationLookup["PLUGINS_STATS_TEXT_KDR"]} | ^5{stats.Performance} ^7{translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"]}"); + var statsList = (await iqStats.ToListAsync()) + .Select(stats => $"^3{stats.Name}^7 - ^5{stats.KDR} ^7{translationLookup["PLUGINS_STATS_TEXT_KDR"]} | ^5{stats.Performance} ^7{translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"]}"); - topStatsText.AddRange(statsList); - } + topStatsText.AddRange(statsList); - // no one qualified + // no one qualified if (topStatsText.Count == 1) { topStatsText = new List() @@ -66,8 +64,10 @@ namespace IW4MAdmin.Plugins.Stats.Commands } private readonly CommandConfiguration _config; + private readonly IDatabaseContextFactory _contextFactory; - public TopStats(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + public TopStats(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "topstats"; Description = translationLookup["PLUGINS_STATS_COMMANDS_TOP_DESC"]; @@ -76,11 +76,12 @@ namespace IW4MAdmin.Plugins.Stats.Commands RequiresTarget = false; _config = config; + _contextFactory = contextFactory; } public override async Task ExecuteAsync(GameEvent E) { - var topStats = await GetTopStats(E.Owner, _translationLookup); + var topStats = await GetTopStats(E.Owner, _translationLookup, _contextFactory); if (!E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { foreach (var stat in topStats) diff --git a/Plugins/Stats/Commands/ViewStats.cs b/Plugins/Stats/Commands/ViewStats.cs index 188e153b..676c1b37 100644 --- a/Plugins/Stats/Commands/ViewStats.cs +++ b/Plugins/Stats/Commands/ViewStats.cs @@ -14,7 +14,10 @@ namespace IW4MAdmin.Plugins.Stats.Commands { public class ViewStatsCommand : Command { - public ViewStatsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly IDatabaseContextFactory _contextFactory; + + public ViewStatsCommand(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "stats"; @@ -32,6 +35,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands }; _config = config; + _contextFactory = contextFactory; } private readonly CommandConfiguration _config; @@ -66,10 +70,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands else { - using (var ctx = new DatabaseContext(true)) - { - pStats = (await ctx.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId)); - } + await using var context = _contextFactory.CreateContext(false); + pStats = (await context.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId)); } statLine = $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; } @@ -86,10 +88,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands else { - using (var ctx = new DatabaseContext(true)) - { - pStats = (await ctx.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)); - } + await using var context = _contextFactory.CreateContext(false); + pStats = (await context.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)); } statLine = $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; } diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 497b9da6..678fa7de 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -47,10 +47,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers private void SetupServerIds() { - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) - { - serverModels = ctx.Set().ToList(); - } + using var ctx = _contextFactory.CreateContext(enableTracking: false); + serverModels = ctx.Set().ToList(); } public Expression> GetRankingFunc(long? serverId = null) diff --git a/Plugins/Stats/Models/ModelConfiguration.cs b/Plugins/Stats/Models/ModelConfiguration.cs index f87e5fc3..b2427afc 100644 --- a/Plugins/Stats/Models/ModelConfiguration.cs +++ b/Plugins/Stats/Models/ModelConfiguration.cs @@ -25,10 +25,12 @@ namespace Stats.Models builder.Entity() .HasIndex(p => new { p.When, p.ServerId, p.Performance, p.ActivityAmount }); - - builder.Entity() - .HasIndex(p => p.TimeSent); + builder.Entity(message => + { + message.HasIndex(p => p.TimeSent); + }); + // force pluralization builder.Entity().ToTable("EFClientKills"); builder.Entity().ToTable("EFClientMessages"); diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 4fdf4e04..19e83b72 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -391,32 +391,28 @@ namespace IW4MAdmin.Plugins.Stats async Task totalKills(Server server) { - using (var ctx = new DatabaseContext(disableTracking: true)) - { - long kills = await ctx.Set().Where(s => s.Active).SumAsync(s => s.TotalKills); - return kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); - } + await using var context = _databaseContextFactory.CreateContext(false); + long kills = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalKills); + return kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } async Task totalPlayTime(Server server) { - using (var ctx = new DatabaseContext(disableTracking: true)) - { - long playTime = await ctx.Set().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); - return (playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); - } + await using var context = _databaseContextFactory.CreateContext(false); + long playTime = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); + return (playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } async Task topStats(Server s) { // todo: this needs to needs to be updated when we DI the lookup - return string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s, Utilities.CurrentLocalization.LocalizationIndex)); + return string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s, Utilities.CurrentLocalization.LocalizationIndex, _databaseContextFactory)); } async Task mostPlayed(Server s) { // todo: this needs to needs to be updated when we DI the lookup - return string.Join(Environment.NewLine, await Commands.MostPlayedCommand.GetMostPlayed(s, Utilities.CurrentLocalization.LocalizationIndex)); + return string.Join(Environment.NewLine, await Commands.MostPlayedCommand.GetMostPlayed(s, Utilities.CurrentLocalization.LocalizationIndex, _databaseContextFactory)); } async Task mostKills(Server gameServer) diff --git a/Plugins/Web/StatsWeb/Controllers/StatsController.cs b/Plugins/Web/StatsWeb/Controllers/StatsController.cs index 1fc704a5..a6dee0d7 100644 --- a/Plugins/Web/StatsWeb/Controllers/StatsController.cs +++ b/Plugins/Web/StatsWeb/Controllers/StatsController.cs @@ -24,14 +24,17 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers private readonly IManager _manager; private readonly IResourceQueryHelper _chatResourceQueryHelper; private readonly ITranslationLookup _translationLookup; + private readonly IDatabaseContextFactory _contextFactory; - public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, - ITranslationLookup translationLookup) : base(manager) + public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(manager) { _logger = logger; _manager = manager; _chatResourceQueryHelper = resourceQueryHelper; _translationLookup = translationLookup; + _contextFactory = contextFactory; } [HttpGet] @@ -155,49 +158,48 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers [Authorize] public async Task GetAutomatedPenaltyInfoAsync(int penaltyId) { - using (var ctx = new SharedLibraryCore.Database.DatabaseContext(true)) + await using var context = _contextFactory.CreateContext(false); + + var penalty = await context.Penalties + .Select(_penalty => new { _penalty.OffenderId, _penalty.PenaltyId, _penalty.When, _penalty.AutomatedOffense }) + .FirstOrDefaultAsync(_penalty => _penalty.PenaltyId == penaltyId); + + if (penalty == null) { - var penalty = await ctx.Penalties - .Select(_penalty => new { _penalty.OffenderId, _penalty.PenaltyId, _penalty.When, _penalty.AutomatedOffense }) - .FirstOrDefaultAsync(_penalty => _penalty.PenaltyId == penaltyId); + return NotFound(); + } - if (penalty == null) + // todo: this can be optimized + var iqSnapshotInfo = context.Set() + .Where(s => s.ClientId == penalty.OffenderId) + .Include(s => s.LastStrainAngle) + .Include(s => s.HitOrigin) + .Include(s => s.HitDestination) + .Include(s => s.CurrentViewAngle) + .Include(s => s.PredictedViewAngles) + .ThenInclude(_angles => _angles.Vector) + .OrderBy(s => s.When) + .ThenBy(s => s.Hits); + + var penaltyInfo = await iqSnapshotInfo.ToListAsync(); + + if (penaltyInfo.Count > 0) + { + return View("_PenaltyInfo", penaltyInfo); + } + + // we want to show anything related to the automated offense + else + { + return View("_MessageContext", new List { - return NotFound(); - } - - // todo: this can be optimized - var iqSnapshotInfo = ctx.Set() - .Where(s => s.ClientId == penalty.OffenderId) - .Include(s => s.LastStrainAngle) - .Include(s => s.HitOrigin) - .Include(s => s.HitDestination) - .Include(s => s.CurrentViewAngle) - .Include(s => s.PredictedViewAngles) - .ThenInclude(_angles => _angles.Vector) - .OrderBy(s => s.When) - .ThenBy(s => s.Hits); - - var penaltyInfo = await iqSnapshotInfo.ToListAsync(); - - if (penaltyInfo.Count > 0) - { - return View("_PenaltyInfo", penaltyInfo); - } - - // we want to show anything related to the automated offense - else - { - return View("_MessageContext", new List + new MessageResponse() { - new MessageResponse() - { - ClientId = penalty.OffenderId, - Message = penalty.AutomatedOffense, - When = penalty.When - } - }); - } + ClientId = penalty.OffenderId, + Message = penalty.AutomatedOffense, + When = penalty.When + } + }); } } } diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index b0f57764..00716d9c 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -65,10 +65,12 @@ namespace IW4MAdmin.Plugins.Welcome public string Name => "Welcome Plugin"; private readonly IConfigurationHandler _configHandler; + private readonly IDatabaseContextFactory _contextFactory; - public Plugin(IConfigurationHandlerFactory configurationHandlerFactory) + public Plugin(IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory contextFactory) { _configHandler = configurationHandlerFactory.GetConfigurationHandler("WelcomePluginSettings"); + _contextFactory = contextFactory; } public async Task OnLoadAsync(IManager manager) @@ -98,9 +100,9 @@ namespace IW4MAdmin.Plugins.Welcome { string penaltyReason; - using (var ctx = new DatabaseContext(disableTracking: true)) + await using var context = _contextFactory.CreateContext(false); { - penaltyReason = await ctx.Penalties + penaltyReason = await context.Penalties .Where(p => p.OffenderId == newPlayer.ClientId && p.Type == EFPenalty.PenaltyType.Flag) .OrderByDescending(p => p.When) .Select(p => p.AutomatedOffense ?? p.Offense) diff --git a/Plugins/Welcome/Welcome.csproj b/Plugins/Welcome/Welcome.csproj index 44436dc5..2c64865e 100644 --- a/Plugins/Welcome/Welcome.csproj +++ b/Plugins/Welcome/Welcome.csproj @@ -12,7 +12,7 @@ Welcome plugin for IW4MAdmin welcomes clients to the server 2018 Debug;Release;Prerelease - 7.1 + Latest diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index f3c8afa0..e4d0fa02 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -1434,7 +1434,10 @@ namespace SharedLibraryCore.Commands /// public class PruneAdminsCommand : Command { - public PruneAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + private readonly IDatabaseContextFactory _contextFactory; + + public PruneAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "prune"; Description = _translationLookup["COMMANDS_PRUNE_DESC"]; @@ -1476,16 +1479,15 @@ namespace SharedLibraryCore.Commands List inactiveUsers = null; // todo: make an event for this // update user roles - using (var context = new DatabaseContext()) - { - var lastActive = DateTime.UtcNow.AddDays(-inactiveDays); - inactiveUsers = await context.Clients - .Where(c => c.Level > Permission.Flagged && c.Level <= Permission.Moderator) - .Where(c => c.LastConnection < lastActive) - .ToListAsync(); - inactiveUsers.ForEach(c => c.SetLevel(Permission.User, E.Origin)); - await context.SaveChangesAsync(); - } + await using var context = _contextFactory.CreateContext(); + var lastActive = DateTime.UtcNow.AddDays(-inactiveDays); + inactiveUsers = await context.Clients + .Where(c => c.Level > Permission.Flagged && c.Level <= Permission.Moderator) + .Where(c => c.LastConnection < lastActive) + .ToListAsync(); + inactiveUsers.ForEach(c => c.SetLevel(Permission.User, E.Origin)); + await context.SaveChangesAsync(); + E.Origin.Tell(_translationLookup["COMMANDS_PRUNE_SUCCESS"].FormatExt(inactiveUsers.Count)); } } diff --git a/SharedLibraryCore/Database/ContextSeed.cs b/SharedLibraryCore/Database/ContextSeed.cs index 028eae8c..fac72d75 100644 --- a/SharedLibraryCore/Database/ContextSeed.cs +++ b/SharedLibraryCore/Database/ContextSeed.cs @@ -2,31 +2,30 @@ using SharedLibraryCore.Database.Models; using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; +using SharedLibraryCore.Interfaces; using static SharedLibraryCore.Database.Models.EFClient; namespace SharedLibraryCore.Database { - public class ContextSeed + public static class ContextSeed { - private DatabaseContext context; - - public ContextSeed(DatabaseContext ctx) + public static async Task Seed(IDatabaseContextFactory contextFactory, CancellationToken token) { - context = ctx; - } + var context = contextFactory.CreateContext(); + var strategy = context.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => + { + await context.Database.MigrateAsync(token); + }); - public async Task Seed() - { - context.Database.Migrate(); - - if (context.AliasLinks.Count() == 0) + if (!await context.AliasLinks.AnyAsync(token)) { var link = new EFAliasLink(); context.Clients.Add(new EFClient() { - ClientId = 1, Active = false, Connections = 0, FirstConnection = DateTime.UtcNow, @@ -44,8 +43,8 @@ namespace SharedLibraryCore.Database }, }); - await context.SaveChangesAsync(); + await context.SaveChangesAsync(token); } } } -} +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs index f6b11ab0..354919df 100644 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ b/SharedLibraryCore/Database/DatabaseContext.cs @@ -15,7 +15,7 @@ using System.Threading.Tasks; namespace SharedLibraryCore.Database { - public class DatabaseContext : DbContext + public abstract class DatabaseContext : DbContext { public DbSet Clients { get; set; } public DbSet Aliases { get; set; } @@ -24,88 +24,6 @@ namespace SharedLibraryCore.Database public DbSet EFMeta { get; set; } public DbSet EFChangeHistory { get; set; } - static string _ConnectionString; - static string _provider; - private static readonly ILoggerFactory _loggerFactory = LoggerFactory.Create(builder => - { - builder.AddConsole() - .AddDebug() - .AddFilter((category, level) => true); - }); - - public DatabaseContext(DbContextOptions opt) : base(opt) - { - } - - public DatabaseContext() - { - } - - public override void Dispose() - { - } - - public DatabaseContext(bool disableTracking) : this() - { - if (disableTracking) - { - this.ChangeTracker.AutoDetectChangesEnabled = false; - this.ChangeTracker.LazyLoadingEnabled = false; - this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - } - - else - { - this.ChangeTracker.AutoDetectChangesEnabled = true; - this.ChangeTracker.LazyLoadingEnabled = true; - this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll; - } - } - - public DatabaseContext(string connStr, string provider) : this() - { - _ConnectionString = connStr; - _provider = provider; - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - //optionsBuilder.UseLoggerFactory(_loggerFactory) - // .EnableSensitiveDataLogging(); - - if (string.IsNullOrEmpty(_ConnectionString)) - { - string currentPath = Utilities.OperatingDirectory; - // allows the application to find the database file - currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? - $"{Path.DirectorySeparatorChar}{currentPath}" : - currentPath; - - var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = Path.Join(currentPath, "Database", "Database.db") }; - var connectionString = connectionStringBuilder.ToString(); - var connection = new SqliteConnection(connectionString); - - if (!optionsBuilder.IsConfigured) - { - optionsBuilder.UseSqlite(connection); - } - } - - else - { - switch (_provider) - { - default: - case "mysql": - optionsBuilder.UseMySql(_ConnectionString, _options => _options.EnableRetryOnFailure()); - break; - case "postgresql": - optionsBuilder.UseNpgsql(_ConnectionString, _options => _options.EnableRetryOnFailure()); - break; - } - } - } - private void SetAuditColumns() { return; @@ -129,6 +47,24 @@ namespace SharedLibraryCore.Database } } + public DatabaseContext() + { + if (!Utilities.IsMigration) + { + throw new InvalidOperationException(); + } + } + + public DatabaseContext(DbContextOptions options) : base(options) + { + + } + + protected DatabaseContext(DbContextOptions options) : base(options) + { + + } + public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) { SetAuditColumns(); diff --git a/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs new file mode 100644 index 00000000..946ac39e --- /dev/null +++ b/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.EntityFrameworkCore; + +namespace SharedLibraryCore.Database.MigrationContext +{ + public class MySqlDatabaseContext : DatabaseContext + { + public MySqlDatabaseContext() + { + if (!Utilities.IsMigration) + { + throw new InvalidOperationException(); + } + } + + public MySqlDatabaseContext(DbContextOptions options) : base(options) + { + + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (Utilities.IsMigration) + { + optionsBuilder.UseMySql("Server=127.0.0.1;Database=IW4MAdmin_Migration;Uid=root;Pwd=password;") + .EnableDetailedErrors(true) + .EnableSensitiveDataLogging(true); + } + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs new file mode 100644 index 00000000..2167c954 --- /dev/null +++ b/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.EntityFrameworkCore; + +namespace SharedLibraryCore.Database.MigrationContext +{ + public class PostgresqlDatabaseContext : DatabaseContext + { + public PostgresqlDatabaseContext() + { + if (!Utilities.IsMigration) + { + throw new InvalidOperationException(); + } + } + + public PostgresqlDatabaseContext(DbContextOptions options) : base(options) + { + + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (Utilities.IsMigration) + { + optionsBuilder.UseNpgsql( + "Host=127.0.0.1;Database=IW4MAdmin_Migration;Username=postgres;Password=password;") + .EnableDetailedErrors(true) + .EnableSensitiveDataLogging(true); + } + } + + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs new file mode 100644 index 00000000..ff30d6d3 --- /dev/null +++ b/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.EntityFrameworkCore; + +namespace SharedLibraryCore.Database.MigrationContext +{ + public class SqliteDatabaseContext : DatabaseContext + { + public SqliteDatabaseContext() + { + if (!Utilities.IsMigration) + { + throw new InvalidOperationException(); + } + } + + public SqliteDatabaseContext(DbContextOptions options) : base(options) + { + + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (Utilities.IsMigration) + { + optionsBuilder.UseSqlite("Data Source=IW4MAdmin_Migration.db") + .EnableDetailedErrors(true) + .EnableSensitiveDataLogging(true); + } + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs index 8153e6ce..6ba8f6c2 100644 --- a/SharedLibraryCore/Interfaces/IManager.cs +++ b/SharedLibraryCore/Interfaces/IManager.cs @@ -24,7 +24,6 @@ namespace SharedLibraryCore.Interfaces IList GetActiveClients(); IConfigurationHandler GetApplicationSettings(); ClientService GetClientService(); - AliasService GetAliasService(); PenaltyService GetPenaltyService(); /// /// enumerates the registered plugin instances diff --git a/SharedLibraryCore/Migrations/20180409183408_InitialCreate.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180409183408_InitialCreate.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs index 84faa86d..686e0fb5 100644 --- a/SharedLibraryCore/Migrations/20180409183408_InitialCreate.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs @@ -6,11 +6,12 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180409183408_InitialCreate")] partial class InitialCreate { diff --git a/SharedLibraryCore/Migrations/20180409183408_InitialCreate.cs b/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180409183408_InitialCreate.cs rename to SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs index cec05467..32e488c7 100644 --- a/SharedLibraryCore/Migrations/20180409183408_InitialCreate.cs +++ b/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class InitialCreate : Migration { diff --git a/SharedLibraryCore/Migrations/20180502195450_Update.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180502195450_Update.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs index ba7b79de..576eeed1 100644 --- a/SharedLibraryCore/Migrations/20180502195450_Update.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs @@ -6,11 +6,12 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180502195450_Update")] partial class Update { diff --git a/SharedLibraryCore/Migrations/20180502195450_Update.cs b/SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs similarity index 95% rename from SharedLibraryCore/Migrations/20180502195450_Update.cs rename to SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs index e446ed36..fc7795f5 100644 --- a/SharedLibraryCore/Migrations/20180502195450_Update.cs +++ b/SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class Update : Migration { diff --git a/SharedLibraryCore/Migrations/20180516023249_AddEloField.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180516023249_AddEloField.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs index edb3d77a..7cda630b 100644 --- a/SharedLibraryCore/Migrations/20180516023249_AddEloField.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs @@ -6,11 +6,12 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180516023249_AddEloField")] partial class AddEloField { diff --git a/SharedLibraryCore/Migrations/20180516023249_AddEloField.cs b/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180516023249_AddEloField.cs rename to SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs index 8f3c3c03..ccf1b51e 100644 --- a/SharedLibraryCore/Migrations/20180516023249_AddEloField.cs +++ b/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEloField : Migration { diff --git a/SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs index 5bfa9a4d..0e6991cf 100644 --- a/SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs @@ -6,11 +6,12 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180517223349_AddRollingKDR")] partial class AddRollingKDR { diff --git a/SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.cs b/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.cs rename to SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs index 8c3a6c81..638a2743 100644 --- a/SharedLibraryCore/Migrations/20180517223349_AddRollingKDR.cs +++ b/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddRollingKDR : Migration { diff --git a/SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs index 1f524b8e..442b7098 100644 --- a/SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -5,12 +5,12 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] partial class AddAutomatedOffenseAndRatingHistory { diff --git a/SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs similarity index 98% rename from SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.cs rename to SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs index 620eacf4..b497989a 100644 --- a/SharedLibraryCore/Migrations/20180531212903_AddAutomatedOffenseAndRatingHistory.cs +++ b/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddAutomatedOffenseAndRatingHistory : Migration { diff --git a/SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs index a985be77..0e4bdd5b 100644 --- a/SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs @@ -5,12 +5,12 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180601172317_AddActivityAmount")] partial class AddActivityAmount { diff --git a/SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.cs b/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.cs rename to SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs index fc82d29a..a8ff56ff 100644 --- a/SharedLibraryCore/Migrations/20180601172317_AddActivityAmount.cs +++ b/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddActivityAmount : Migration { diff --git a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs index 30d97b21..66dc5702 100644 --- a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs @@ -5,12 +5,12 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180602041758_AddClientMeta")] partial class AddClientMeta { diff --git a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs b/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs rename to SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs index 2aa91d5a..9566c210 100644 --- a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs +++ b/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs index 5d1b1e57..7d586f1b 100644 --- a/SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs @@ -5,12 +5,12 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180605191706_AddEFACSnapshots")] partial class AddEFACSnapshots { diff --git a/SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.cs b/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.cs rename to SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs index bcd5c946..e6c7e721 100644 --- a/SharedLibraryCore/Migrations/20180605191706_AddEFACSnapshots.cs +++ b/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEFACSnapshots : Migration { diff --git a/SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs index 1c01efc6..24cee69e 100644 --- a/SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs @@ -5,12 +5,12 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using System; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180614014303_IndexForEFAlias")] partial class IndexForEFAlias { diff --git a/SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.cs b/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.cs rename to SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs index 8b5d732c..4137b988 100644 --- a/SharedLibraryCore/Migrations/20180614014303_IndexForEFAlias.cs +++ b/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class IndexForEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs index 9d0f5ab1..76646c90 100644 --- a/SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180902035612_AddFractionAndIsKill")] partial class AddFractionAndIsKill { diff --git a/SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.cs b/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs similarity index 98% rename from SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.cs rename to SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs index 16505dd4..529a79c4 100644 --- a/SharedLibraryCore/Migrations/20180902035612_AddFractionAndIsKill.cs +++ b/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddFractionAndIsKill : Migration { diff --git a/SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs index d6c51939..b9ec66ff 100644 --- a/SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180904154622_AddVisibilityPercentage")] partial class AddVisibilityPercentage { diff --git a/SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.cs b/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.cs rename to SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs index b30d9120..d4a8132e 100644 --- a/SharedLibraryCore/Migrations/20180904154622_AddVisibilityPercentage.cs +++ b/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddVisibilityPercentage : Migration { diff --git a/SharedLibraryCore/Migrations/20180907020706_AddVision.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180907020706_AddVision.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs index 461dad07..ade98e4e 100644 --- a/SharedLibraryCore/Migrations/20180907020706_AddVision.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180907020706_AddVision")] partial class AddVision { diff --git a/SharedLibraryCore/Migrations/20180907020706_AddVision.cs b/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180907020706_AddVision.cs rename to SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs index 9d2a216c..8085963a 100644 --- a/SharedLibraryCore/Migrations/20180907020706_AddVision.cs +++ b/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddVision : Migration { diff --git a/SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs index f72cd6da..2d700dce 100644 --- a/SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180908004053_AddWhenToRating")] partial class AddWhenToRating { diff --git a/SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.cs b/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.cs rename to SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs index 8f5e6fd4..63e84cc3 100644 --- a/SharedLibraryCore/Migrations/20180908004053_AddWhenToRating.cs +++ b/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddWhenToRating : Migration { diff --git a/SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs index 5dfa35a8..15b4bd6d 100644 --- a/SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180910221749_AddRatingIndexes")] partial class AddRatingIndexes { diff --git a/SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.cs b/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs similarity index 96% rename from SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.cs rename to SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs index 5a4d62f0..fc26e0d7 100644 --- a/SharedLibraryCore/Migrations/20180910221749_AddRatingIndexes.cs +++ b/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddRatingIndexes : Migration { diff --git a/SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs index e2f3504b..e740317a 100644 --- a/SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180911184224_AddEFAliasNameIndex")] partial class AddEFAliasNameIndex { diff --git a/SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.cs b/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs similarity index 92% rename from SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.cs rename to SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs index fa1ab6c7..f810fc9f 100644 --- a/SharedLibraryCore/Migrations/20180911184224_AddEFAliasNameIndex.cs +++ b/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEFAliasNameIndex : Migration { diff --git a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs index 714c1ddf..2c099c6e 100644 --- a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180911190823_AddEFAliasNameMaxLength24")] partial class AddEFAliasNameMaxLength24 { diff --git a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs b/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs similarity index 94% rename from SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs rename to SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs index 362b5131..7e03a909 100644 --- a/SharedLibraryCore/Migrations/20180911190823_AddEFAliasNameMaxLength24.cs +++ b/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEFAliasNameMaxLength24 : Migration { diff --git a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs index c8b715c4..68be3dbe 100644 --- a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] partial class AddPreviousCurrentValueToEFChangeHistory { diff --git a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs similarity index 95% rename from SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs rename to SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs index 6fba7b03..a910959c 100644 --- a/SharedLibraryCore/Migrations/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs +++ b/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddPreviousCurrentValueToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs index d13a69e8..27b20cb9 100644 --- a/SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180915163111_AddIndexToMessageTimeSent")] partial class AddIndexToMessageTimeSent { diff --git a/SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.cs b/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs similarity index 93% rename from SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.cs rename to SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs index 0e74e631..18e39938 100644 --- a/SharedLibraryCore/Migrations/20180915163111_AddIndexToMessageTimeSent.cs +++ b/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddIndexToMessageTimeSent : Migration { diff --git a/SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs index b5ed15ac..f0cc690b 100644 --- a/SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180922231310_RemoveACSnapShot")] partial class RemoveACSnapShot { diff --git a/SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.cs b/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.cs rename to SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs index 1b43c8f1..d1804ad0 100644 --- a/SharedLibraryCore/Migrations/20180922231310_RemoveACSnapShot.cs +++ b/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class RemoveACSnapShot : Migration { diff --git a/SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.Designer.cs b/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs index b4238885..acb00ec6 100644 --- a/SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180922231600_ReaddACSnapshot")] partial class ReaddACSnapshot { diff --git a/SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.cs b/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs similarity index 99% rename from SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.cs rename to SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs index fe7e907f..da730312 100644 --- a/SharedLibraryCore/Migrations/20180922231600_ReaddACSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class ReaddACSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs index 034f5a20..387e3e69 100644 --- a/SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181014171848_MakePenaltyExpirationNullable")] partial class MakePenaltyExpirationNullable { diff --git a/SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.cs b/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.cs rename to SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs index a9ec9b9c..d1ab3570 100644 --- a/SharedLibraryCore/Migrations/20181014171848_MakePenaltyExpirationNullable.cs +++ b/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class MakePenaltyExpirationNullable : Migration { diff --git a/SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.Designer.cs b/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs index 4ca423dd..62ca0ffb 100644 --- a/SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181125193243_MakeClientIPNullable")] partial class MakeClientIPNullable { diff --git a/SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.cs b/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.cs rename to SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs index b5aa5845..8e858b04 100644 --- a/SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.cs +++ b/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class MakeClientIPNullable : Migration { diff --git a/SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs index f4b8aa2e..f6a21ff9 100644 --- a/SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] partial class AddEndpointToEFServerUpdateServerIdType { diff --git a/SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs similarity index 92% rename from SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs rename to SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs index e149e5d7..52d1d831 100644 --- a/SharedLibraryCore/Migrations/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs +++ b/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEndpointToEFServerUpdateServerIdType : Migration { diff --git a/SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.Designer.cs b/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs index 0df2a3c9..2f6186b8 100644 --- a/SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181216214513_AddEvadePenaltyFlag")] partial class AddEvadePenaltyFlag { diff --git a/SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.cs b/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs similarity index 99% rename from SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.cs rename to SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs index 7afa124e..0037aae5 100644 --- a/SharedLibraryCore/Migrations/20181216214513_AddEvadePenaltyFlag.cs +++ b/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddEvadePenaltyFlag : Migration { diff --git a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs index 284f8133..a114d3a9 100644 --- a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] partial class AddIndexToEFMetaKeyAndClientId { diff --git a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs similarity index 94% rename from SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs rename to SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs index b90b489b..3b9621cd 100644 --- a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs +++ b/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddIndexToEFMetaKeyAndClientId : Migration { diff --git a/SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs index 3c9e2308..0ff15914 100644 --- a/SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190423142128_AddGameNameToEFServer")] partial class AddGameNameToEFServer { diff --git a/SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.cs b/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.cs rename to SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs index 28e7155c..45b6a189 100644 --- a/SharedLibraryCore/Migrations/20190423142128_AddGameNameToEFServer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddGameNameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs index 41879a2b..2023a061 100644 --- a/SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190615145212_AddAvgRecoilOffset")] partial class AddAvgRecoilOffset { diff --git a/SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.cs b/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs similarity index 91% rename from SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.cs rename to SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs index 027d4ed8..d74bfd95 100644 --- a/SharedLibraryCore/Migrations/20190615145212_AddAvgRecoilOffset.cs +++ b/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddAvgRecoilOffset : Migration { diff --git a/SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs index f9873604..25f0f3f3 100644 --- a/SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190615214055_AddRecoilOffsetToSnapshot")] partial class AddRecoilOffsetToSnapshot { diff --git a/SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.cs b/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.cs rename to SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs index 59f39a46..481e74bd 100644 --- a/SharedLibraryCore/Migrations/20190615214055_AddRecoilOffsetToSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddRecoilOffsetToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs index 6f960f01..d26ad7cf 100644 --- a/SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190725000309_AlterEFRatingIndex")] partial class AlterEFRatingIndex { diff --git a/SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.cs b/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs similarity index 97% rename from SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.cs rename to SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs index 9022c31b..d198ee2d 100644 --- a/SharedLibraryCore/Migrations/20190725000309_AlterEFRatingIndex.cs +++ b/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AlterEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs index c59a5bf1..2498fc41 100644 --- a/SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190802174908_AddSearchNameToEFAlias")] partial class AddSearchNameToEFAlias { diff --git a/SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.cs b/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs similarity index 95% rename from SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.cs rename to SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs index 639559ed..249713b6 100644 --- a/SharedLibraryCore/Migrations/20190802174908_AddSearchNameToEFAlias.cs +++ b/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddSearchNameToEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs index a100afbb..ca976673 100644 --- a/SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190831210503_AvgSnapValueToClientStatistics")] partial class AvgSnapValueToClientStatistics { diff --git a/SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.cs b/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.cs rename to SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs index e8e40520..ddd0278a 100644 --- a/SharedLibraryCore/Migrations/20190831210503_AvgSnapValueToClientStatistics.cs +++ b/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AvgSnapValueToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs index a9ac29de..46ca9d25 100644 --- a/SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190901180209_AddSnapHitCountToClientStatistics")] partial class AddSnapHitCountToClientStatistics { diff --git a/SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.cs b/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.cs rename to SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs index 017c9230..0b102af3 100644 --- a/SharedLibraryCore/Migrations/20190901180209_AddSnapHitCountToClientStatistics.cs +++ b/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddSnapHitCountToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs index c2e00ad9..a16f5ed5 100644 --- a/SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] partial class UseJunctionTableForSnapshotVector3 { diff --git a/SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.cs b/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs similarity index 98% rename from SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.cs rename to SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs index 9d36fde1..82d20240 100644 --- a/SharedLibraryCore/Migrations/20190901223620_UseJunctionTableForSnapshotVector3.cs +++ b/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class UseJunctionTableForSnapshotVector3 : Migration { diff --git a/SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs index e4bcbe1c..4f4d44ab 100644 --- a/SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] partial class AddCurrentSnapValueToSnapshot { diff --git a/SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.cs b/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.cs rename to SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs index e833a17b..9b225d5d 100644 --- a/SharedLibraryCore/Migrations/20190914011524_AddCurrentSnapValueToSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddCurrentSnapValueToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs index 7c6e207f..97118961 100644 --- a/SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] partial class AddSessionSnapHitsToSnapshot { diff --git a/SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.cs b/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.cs rename to SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs index 0e7048c9..e4b2340b 100644 --- a/SharedLibraryCore/Migrations/20190914012015_AddSessionSnapHitsToSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddSessionSnapHitsToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs index 95944248..91727ea7 100644 --- a/SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191004172550_RenameClientHitLocationCountColumns")] partial class RenameClientHitLocationCountColumns { diff --git a/SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.cs b/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs similarity index 99% rename from SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.cs rename to SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs index f63f2253..4ebe4ccd 100644 --- a/SharedLibraryCore/Migrations/20191004172550_RenameClientHitLocationCountColumns.cs +++ b/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class RenameClientHitLocationCountColumns : Migration { diff --git a/SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs index 67e9bc33..d156f99b 100644 --- a/SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] partial class EnforceUniqueIndexForEFAliasIPName { diff --git a/SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs similarity index 98% rename from SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs rename to SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs index 6a913e2a..bd5c6a82 100644 --- a/SharedLibraryCore/Migrations/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs +++ b/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class EnforceUniqueIndexForEFAliasIPName : Migration { diff --git a/SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs index 57d939fc..59ca1e24 100644 --- a/SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] partial class SetCaseSensitiveCoallationForAliasNameMySQL { diff --git a/SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs similarity index 94% rename from SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs rename to SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs index a72e2756..e91b3f53 100644 --- a/SharedLibraryCore/Migrations/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs +++ b/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration { diff --git a/SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.Designer.cs b/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs index 8086df2f..01a9b9f2 100644 --- a/SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191230140947_AddMissingActiveColumns")] partial class AddMissingActiveColumns { diff --git a/SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.cs b/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs similarity index 93% rename from SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.cs rename to SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs index e2b89e0d..13afb77f 100644 --- a/SharedLibraryCore/Migrations/20191230140947_AddMissingActiveColumns.cs +++ b/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddMissingActiveColumns : Migration { diff --git a/SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs index 9720f13f..b3cf9f08 100644 --- a/SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] partial class AddImpersonationIdToEFChangeHistory { diff --git a/SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs similarity index 93% rename from SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.cs rename to SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs index 9b11124d..b1d337d9 100644 --- a/SharedLibraryCore/Migrations/20200423225137_AddImpersonationIdToEFChangeHistory.cs +++ b/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddImpersonationIdToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs index f741702e..0de748a5 100644 --- a/SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200521203304_AddHostnameToEFServer")] partial class AddHostnameToEFServer { diff --git a/SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.cs b/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.cs rename to SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs index 95d24d17..7f0e8657 100644 --- a/SharedLibraryCore/Migrations/20200521203304_AddHostnameToEFServer.cs +++ b/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddHostnameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs index f54f9cb2..2dbf60c8 100644 --- a/SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200819224119_AddIsPasswordProtectedColumn")] partial class AddIsPasswordProtectedColumn { diff --git a/SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.cs b/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs similarity index 95% rename from SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.cs rename to SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs index 937548ff..410ad8ff 100644 --- a/SharedLibraryCore/Migrations/20200819224119_AddIsPasswordProtectedColumn.cs +++ b/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddIsPasswordProtectedColumn : Migration { diff --git a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs index 404a0487..72108831 100644 --- a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20201114232340_UpdateEFRatingIndex")] partial class UpdateEFRatingIndex { diff --git a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs b/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs similarity index 94% rename from SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs rename to SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs index b0503fa5..510663d0 100644 --- a/SharedLibraryCore/Migrations/20201114232340_UpdateEFRatingIndex.cs +++ b/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class UpdateEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs rename to SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs index 07205a94..d807ea9b 100644 --- a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs +++ b/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { - [DbContext(typeof(DatabaseContext))] + [DbContext(typeof(MySqlDatabaseContext))] [Migration("20201118023106_AddSentIngameFlagToClientMessage")] partial class AddSentIngameFlagToClientMessage { diff --git a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs b/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs similarity index 93% rename from SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs rename to SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs index 42ccaf6e..56a27833 100644 --- a/SharedLibraryCore/Migrations/20201118023106_AddSentIngameFlagToClientMessage.cs +++ b/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.MySql { public partial class AddSentIngameFlagToClientMessage : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs b/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs new file mode 100644 index 00000000..ae78d67b --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs @@ -0,0 +1,931 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20201124024731_UpdateMigrationsToMySql")] + partial class UpdateMigrationsToMySql + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CurrentSessionLength") + .HasColumnType("int"); + + b.Property("CurrentStrain") + .HasColumnType("double"); + + b.Property("CurrentViewAngleId") + .HasColumnType("int"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("Distance") + .HasColumnType("double"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("HitDestinationId") + .HasColumnType("int"); + + b.Property("HitLocation") + .HasColumnType("int"); + + b.Property("HitOriginId") + .HasColumnType("int"); + + b.Property("HitType") + .HasColumnType("int"); + + b.Property("Hits") + .HasColumnType("int"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("LastStrainAngleId") + .HasColumnType("int"); + + b.Property("RecoilOffset") + .HasColumnType("double"); + + b.Property("SessionAngleOffset") + .HasColumnType("double"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double"); + + b.Property("SessionSPM") + .HasColumnType("double"); + + b.Property("SessionScore") + .HasColumnType("int"); + + b.Property("SessionSnapHits") + .HasColumnType("int"); + + b.Property("StrainAngleBetween") + .HasColumnType("double"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + b.Property("AverageSnapValue") + .HasColumnType("double"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("MaxStrain") + .HasColumnType("double"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double"); + + b.Property("SPM") + .HasColumnType("double"); + + b.Property("Skill") + .HasColumnType("double"); + + b.Property("SnapHitCount") + .HasColumnType("int"); + + b.Property("TimePlayed") + .HasColumnType("int"); + + b.Property("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("int"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitOffsetAverage") + .HasColumnType("float"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("MaxAngleDistance") + .HasColumnType("float"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ActivityAmount") + .HasColumnType("int"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("Performance") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("RatingHistoryId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("IPAddress") + .HasColumnType("int"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Comment") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImpersonationEntityId") + .HasColumnType("int"); + + b.Property("OriginEntityId") + .HasColumnType("int"); + + b.Property("PreviousValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TargetEntityId") + .HasColumnType("int"); + + b.Property("TimeChanged") + .HasColumnType("datetime(6)"); + + b.Property("TypeOfChange") + .HasColumnType("int"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Extra") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AutomatedOffense") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Expires") + .HasColumnType("datetime(6)"); + + b.Property("IsEvadedOffense") + .HasColumnType("tinyint(1)"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("OffenderId") + .HasColumnType("int"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PunisherId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs b/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs new file mode 100644 index 00000000..83b7e2a2 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs @@ -0,0 +1,2342 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.MySql +{ + public partial class UpdateMigrationsToMySql : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("set foreign_key_checks=0;"); + + migrationBuilder.AlterColumn( + name: "Z", + table: "Vector3", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Y", + table: "Vector3", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "X", + table: "Vector3", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "Vector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TotalPlayTime", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TotalKills", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "StatisticId", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Port", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IsPasswordProtected", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HostName", + table: "EFServers", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GameName", + table: "EFServers", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndPoint", + table: "EFServers", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFRating", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFRating", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Ranking", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Performance", + table: "EFRating", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Newest", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ActivityAmount", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "RatingId", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Type", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PunisherId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Offense", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "OffenderId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AutomatedOffense", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PenaltyId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Value", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Updated", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "EFMeta", + maxLength: 32, + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "Extra", + table: "EFMeta", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Created", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "MetaId", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Location", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitOffsetAverage", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "HitCount", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsServerId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsClientId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLocationCountId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "VisionAverage", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "TimePlayed", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Skill", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SPM", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "MaxStrain", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TotalConnectionTime", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PasswordSalt", + table: "EFClients", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Password", + table: "EFClients", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NetworkId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Masked", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Level", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "LastConnection", + table: "EFClients", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "FirstConnection", + table: "EFClients", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "CurrentAliasId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Connections", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TimeSent", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SentIngame", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Message", + table: "EFClientMessages", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "MessageId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Weapon", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "ViewAnglesVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "VictimId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Map", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "KillOriginVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "IsKill", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLoc", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Fraction", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "DeathType", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "DeathOriginVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Damage", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AttackerId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "KillId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TypeOfChange", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TimeChanged", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "TargetEntityId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PreviousValue", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OriginEntityId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CurrentValue", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "EFChangeHistory", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ChangeHistoryId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAliasLinks", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFAliasLinks", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "SearchableName", + table: "EFAlias", + maxLength: 24, + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 24, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + maxLength: 24, + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 24); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DateAdded", + table: "EFAlias", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasId", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ACSnapshotVector3Id", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "WeaponId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TimeSinceLastEvent", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "StrainAngleBetween", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SessionScore", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SessionSPM", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionAngleOffset", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "LastStrainAngleId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Hits", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitType", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitOriginId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLocation", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitDestinationId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Distance", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "CurrentViewAngleId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "CurrentStrain", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(double), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "CurrentSessionLength", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsCli~", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + + migrationBuilder.Sql("set foreign_key_checks=1;"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsCli~", + table: "EFHitLocationCounts"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStati~", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStatisticsServerId"); + + migrationBuilder.AlterColumn( + name: "Z", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Y", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "X", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "Vector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TotalPlayTime", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "TotalKills", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "StatisticId", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Port", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IsPasswordProtected", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HostName", + table: "EFServers", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GameName", + table: "EFServers", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndPoint", + table: "EFServers", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFRating", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFRating", + type: "INTEGER", + nullable: true, + oldClrType: typeof(long), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Ranking", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Performance", + table: "EFRating", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Newest", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ActivityAmount", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "RatingId", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFPenalties", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Type", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PunisherId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Offense", + table: "EFPenalties", + type: "TEXT", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "OffenderId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + type: "TEXT", + nullable: true, + oldClrType: typeof(DateTime), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AutomatedOffense", + table: "EFPenalties", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "PenaltyId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Value", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "Updated", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Key", + table: "EFMeta", + type: "TEXT", + maxLength: 32, + nullable: false, + oldClrType: typeof(string), + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "Extra", + table: "EFMeta", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Created", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "MetaId", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Location", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitOffsetAverage", + table: "EFHitLocationCounts", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "HitCount", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsServerId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsClientId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HitLocationCountId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "VisionAverage", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "TimePlayed", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Skill", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SPM", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "MaxStrain", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TotalConnectionTime", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PasswordSalt", + table: "EFClients", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Password", + table: "EFClients", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NetworkId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Masked", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Level", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "LastConnection", + table: "EFClients", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "FirstConnection", + table: "EFClients", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "CurrentAliasId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Connections", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TimeSent", + table: "EFClientMessages", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "SentIngame", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Message", + table: "EFClientMessages", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "MessageId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFClientKills", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Weapon", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "ViewAnglesVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "VictimId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Map", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "KillOriginVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "IsKill", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HitLoc", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Fraction", + table: "EFClientKills", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "DeathType", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "DeathOriginVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Damage", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AttackerId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "KillId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "TypeOfChange", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TimeChanged", + table: "EFChangeHistory", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "TargetEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PreviousValue", + table: "EFChangeHistory", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OriginEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CurrentValue", + table: "EFChangeHistory", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "EFChangeHistory", + type: "TEXT", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ChangeHistoryId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAliasLinks", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFAliasLinks", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "SearchableName", + table: "EFAlias", + type: "TEXT", + maxLength: 24, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 24, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + type: "TEXT", + maxLength: 24, + nullable: false, + oldClrType: typeof(string), + oldMaxLength: 24); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DateAdded", + table: "EFAlias", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "AliasId", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ACSnapshotVector3Id", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFACSnapshot", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "WeaponId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TimeSinceLastEvent", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "StrainAngleBetween", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SessionScore", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SessionSPM", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionAngleOffset", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "LastStrainAngleId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Hits", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitType", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitOriginId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitLocation", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitDestinationId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Distance", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "CurrentViewAngleId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "CurrentStrain", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "CurrentSessionLength", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) + .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs new file mode 100644 index 00000000..49d3de31 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs @@ -0,0 +1,929 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + partial class MySqlDatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CurrentSessionLength") + .HasColumnType("int"); + + b.Property("CurrentStrain") + .HasColumnType("double"); + + b.Property("CurrentViewAngleId") + .HasColumnType("int"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("Distance") + .HasColumnType("double"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("HitDestinationId") + .HasColumnType("int"); + + b.Property("HitLocation") + .HasColumnType("int"); + + b.Property("HitOriginId") + .HasColumnType("int"); + + b.Property("HitType") + .HasColumnType("int"); + + b.Property("Hits") + .HasColumnType("int"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("LastStrainAngleId") + .HasColumnType("int"); + + b.Property("RecoilOffset") + .HasColumnType("double"); + + b.Property("SessionAngleOffset") + .HasColumnType("double"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double"); + + b.Property("SessionSPM") + .HasColumnType("double"); + + b.Property("SessionScore") + .HasColumnType("int"); + + b.Property("SessionSnapHits") + .HasColumnType("int"); + + b.Property("StrainAngleBetween") + .HasColumnType("double"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + b.Property("AverageSnapValue") + .HasColumnType("double"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("MaxStrain") + .HasColumnType("double"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double"); + + b.Property("SPM") + .HasColumnType("double"); + + b.Property("Skill") + .HasColumnType("double"); + + b.Property("SnapHitCount") + .HasColumnType("int"); + + b.Property("TimePlayed") + .HasColumnType("int"); + + b.Property("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("int"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitOffsetAverage") + .HasColumnType("float"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("MaxAngleDistance") + .HasColumnType("float"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ActivityAmount") + .HasColumnType("int"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("Performance") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("RatingHistoryId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("IPAddress") + .HasColumnType("int"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Comment") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImpersonationEntityId") + .HasColumnType("int"); + + b.Property("OriginEntityId") + .HasColumnType("int"); + + b.Property("PreviousValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TargetEntityId") + .HasColumnType("int"); + + b.Property("TimeChanged") + .HasColumnType("datetime(6)"); + + b.Property("TypeOfChange") + .HasColumnType("int"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Extra") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AutomatedOffense") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Expires") + .HasColumnType("datetime(6)"); + + b.Property("IsEvadedOffense") + .HasColumnType("tinyint(1)"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("OffenderId") + .HasColumnType("int"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PunisherId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs new file mode 100644 index 00000000..8bbe0b2e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs @@ -0,0 +1,431 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180409183408_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("Kills"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs b/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs new file mode 100644 index 00000000..acd57084 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs @@ -0,0 +1,483 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFAliasLinks", + columns: table => new + { + AliasLinkId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFAliasLinks", x => x.AliasLinkId); + }); + + migrationBuilder.CreateTable( + name: "EFServers", + columns: table => new + { + ServerId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Port = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFServers", x => x.ServerId); + }); + + migrationBuilder.CreateTable( + name: "Vector3", + columns: table => new + { + Vector3Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + X = table.Column(nullable: false), + Y = table.Column(nullable: false), + Z = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Vector3", x => x.Vector3Id); + }); + + migrationBuilder.CreateTable( + name: "EFAlias", + columns: table => new + { + AliasId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + DateAdded = table.Column(nullable: false), + IPAddress = table.Column(nullable: false), + LinkId = table.Column(nullable: false), + Name = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFAlias", x => x.AliasId); + table.ForeignKey( + name: "FK_EFAlias_EFAliasLinks_LinkId", + column: x => x.LinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFServerStatistics", + columns: table => new + { + StatisticId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + TotalKills = table.Column(nullable: false), + TotalPlayTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFServerStatistics", x => x.StatisticId); + table.ForeignKey( + name: "FK_EFServerStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClients", + columns: table => new + { + ClientId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + AliasLinkId = table.Column(nullable: false), + Connections = table.Column(nullable: false), + CurrentAliasId = table.Column(nullable: false), + FirstConnection = table.Column(nullable: false), + LastConnection = table.Column(nullable: false), + Level = table.Column(nullable: false), + Masked = table.Column(nullable: false), + NetworkId = table.Column(nullable: false), + Password = table.Column(nullable: true), + PasswordSalt = table.Column(nullable: true), + TotalConnectionTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClients", x => x.ClientId); + table.ForeignKey( + name: "FK_EFClients_EFAliasLinks_AliasLinkId", + column: x => x.AliasLinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClients_EFAlias_CurrentAliasId", + column: x => x.CurrentAliasId, + principalTable: "EFAlias", + principalColumn: "AliasId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClientKills", + columns: table => new + { + KillId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true). + Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + AttackerId = table.Column(nullable: false), + Damage = table.Column(nullable: false), + DeathOriginVector3Id = table.Column(nullable: true), + DeathType = table.Column(nullable: false), + HitLoc = table.Column(nullable: false), + KillOriginVector3Id = table.Column(nullable: true), + Map = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + VictimId = table.Column(nullable: false), + ViewAnglesVector3Id = table.Column(nullable: true), + Weapon = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientKills", x => x.KillId); + table.ForeignKey( + name: "FK_EFClientKills_EFClients_AttackerId", + column: x => x.AttackerId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_DeathOriginVector3Id", + column: x => x.DeathOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_KillOriginVector3Id", + column: x => x.KillOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientKills_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_EFClients_VictimId", + column: x => x.VictimId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_ViewAnglesVector3Id", + column: x => x.ViewAnglesVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFClientMessages", + columns: table => new + { + MessageId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + Message = table.Column(nullable: true), + ServerId = table.Column(nullable: false), + TimeSent = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientMessages", x => x.MessageId); + table.ForeignKey( + name: "FK_EFClientMessages_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientMessages_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClientStatistics", + columns: table => new + { + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + Active = table.Column(nullable: false), + Deaths = table.Column(nullable: false), + Kills = table.Column(nullable: false), + SPM = table.Column(nullable: false), + Skill = table.Column(nullable: false), + TimePlayed = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientStatistics", x => new { x.ClientId, x.ServerId }); + table.ForeignKey( + name: "FK_EFClientStatistics_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFPenalties", + columns: table => new + { + PenaltyId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Expires = table.Column(nullable: false), + LinkId = table.Column(nullable: false), + OffenderId = table.Column(nullable: false), + Offense = table.Column(nullable: false), + PunisherId = table.Column(nullable: false), + Type = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFPenalties", x => x.PenaltyId); + table.ForeignKey( + name: "FK_EFPenalties_EFAliasLinks_LinkId", + column: x => x.LinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFPenalties_EFClients_OffenderId", + column: x => x.OffenderId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFPenalties_EFClients_PunisherId", + column: x => x.PunisherId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFHitLocationCounts", + columns: table => new + { + HitLocationCountId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true). + Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn). + Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + EFClientStatistics_ClientId = table.Column(nullable: false), + HitCount = table.Column(nullable: false), + HitOffsetAverage = table.Column(nullable: false), + Location = table.Column(nullable: false), + EFClientStatistics_ServerId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFHitLocationCounts", x => x.HitLocationCountId); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId", + column: x => x.EFClientStatistics_ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId", + column: x => x.EFClientStatistics_ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + columns: x => new { x.EFClientStatistics_ClientId, x.EFClientStatistics_ServerId }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_LinkId", + table: "EFAlias", + column: "LinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_AttackerId", + table: "EFClientKills", + column: "AttackerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_DeathOriginVector3Id", + table: "EFClientKills", + column: "DeathOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_KillOriginVector3Id", + table: "EFClientKills", + column: "KillOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_ServerId", + table: "EFClientKills", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_VictimId", + table: "EFClientKills", + column: "VictimId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_ViewAnglesVector3Id", + table: "EFClientKills", + column: "ViewAnglesVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_ClientId", + table: "EFClientMessages", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_ServerId", + table: "EFClientMessages", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_AliasLinkId", + table: "EFClients", + column: "AliasLinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_CurrentAliasId", + table: "EFClients", + column: "CurrentAliasId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_NetworkId", + table: "EFClients", + column: "NetworkId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ServerId", + table: "EFClientStatistics", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + column: "EFClientStatistics_ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatistics_ClientId", "EFClientStatistics_ServerId" }); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_LinkId", + table: "EFPenalties", + column: "LinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_OffenderId", + table: "EFPenalties", + column: "OffenderId"); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_PunisherId", + table: "EFPenalties", + column: "PunisherId"); + + migrationBuilder.CreateIndex( + name: "IX_EFServerStatistics_ServerId", + table: "EFServerStatistics", + column: "ServerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFClientKills"); + + migrationBuilder.DropTable( + name: "EFClientMessages"); + + migrationBuilder.DropTable( + name: "EFHitLocationCounts"); + + migrationBuilder.DropTable( + name: "EFPenalties"); + + migrationBuilder.DropTable( + name: "EFServerStatistics"); + + migrationBuilder.DropTable( + name: "Vector3"); + + migrationBuilder.DropTable( + name: "EFClientStatistics"); + + migrationBuilder.DropTable( + name: "EFClients"); + + migrationBuilder.DropTable( + name: "EFServers"); + + migrationBuilder.DropTable( + name: "EFAlias"); + + migrationBuilder.DropTable( + name: "EFAliasLinks"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs new file mode 100644 index 00000000..7650eb20 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs @@ -0,0 +1,434 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180502195450_Update")] + partial class Update + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs b/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs new file mode 100644 index 00000000..79b42416 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class Update : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + nullable: false, + defaultValue: 0f); + + migrationBuilder.AddColumn( + name: "MaxStrain", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts"); + + migrationBuilder.DropColumn( + name: "MaxStrain", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs new file mode 100644 index 00000000..f887c6f4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs @@ -0,0 +1,436 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180516023249_AddEloField")] + partial class AddEloField + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs b/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs new file mode 100644 index 00000000..088d71f7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEloField : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EloRating", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EloRating", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs new file mode 100644 index 00000000..96739576 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs @@ -0,0 +1,438 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180517223349_AddRollingKDR")] + partial class AddRollingKDR + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs b/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs new file mode 100644 index 00000000..8b971689 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddRollingKDR : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs new file mode 100644 index 00000000..fcf2a27e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -0,0 +1,501 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] + partial class AddAutomatedOffenseAndRatingHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs new file mode 100644 index 00000000..eeff0d6e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -0,0 +1,101 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddAutomatedOffenseAndRatingHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AutomatedOffense", + table: "EFPenalties", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFClientRatingHistory", + columns: table => new + { + RatingHistoryId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientRatingHistory", x => x.RatingHistoryId); + table.ForeignKey( + name: "FK_EFClientRatingHistory_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFRating", + columns: table => new + { + RatingId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Newest = table.Column(nullable: false), + Performance = table.Column(nullable: false), + Ranking = table.Column(nullable: false), + RatingHistoryId = table.Column(nullable: false), + ServerId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFRating", x => x.RatingId); + table.ForeignKey( + name: "FK_EFRating_EFClientRatingHistory_RatingHistoryId", + column: x => x.RatingHistoryId, + principalTable: "EFClientRatingHistory", + principalColumn: "RatingHistoryId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFRating_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRatingHistory_ClientId", + table: "EFClientRatingHistory", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFRating_RatingHistoryId", + table: "EFRating", + column: "RatingHistoryId"); + + migrationBuilder.CreateIndex( + name: "IX_EFRating_ServerId", + table: "EFRating", + column: "ServerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFRating"); + + migrationBuilder.DropTable( + name: "EFClientRatingHistory"); + + migrationBuilder.DropColumn( + name: "AutomatedOffense", + table: "EFPenalties"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs new file mode 100644 index 00000000..a2baa449 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs @@ -0,0 +1,503 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180601172317_AddActivityAmount")] + partial class AddActivityAmount + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs b/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs new file mode 100644 index 00000000..332f10bb --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddActivityAmount : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ActivityAmount", + table: "EFRating", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ActivityAmount", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs new file mode 100644 index 00000000..7d17e01e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs @@ -0,0 +1,539 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180602041758_AddClientMeta")] + partial class AddClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs b/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs new file mode 100644 index 00000000..31c8e15d --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFMeta", + columns: table => new + { + MetaId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + Created = table.Column(nullable: false), + Extra = table.Column(nullable: true), + Key = table.Column(nullable: false), + Updated = table.Column(nullable: false), + Value = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeta", x => x.MetaId); + table.ForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_ClientId", + table: "EFMeta", + column: "ClientId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs new file mode 100644 index 00000000..dde715ca --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs @@ -0,0 +1,638 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180605191706_AddEFACSnapshots")] + partial class AddEFACSnapshots + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs b/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs new file mode 100644 index 00000000..d989c1e8 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs @@ -0,0 +1,144 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEFACSnapshots : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + Deaths = table.Column(nullable: false), + Distance = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + HitDestinationVector3Id = table.Column(nullable: true), + HitLocation = table.Column(nullable: false), + HitOriginVector3Id = table.Column(nullable: true), + HitType = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + LastStrainAngleVector3Id = table.Column(nullable: true), + SessionAngleOffset = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + WeaponId = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id", + column: x => x.HitDestinationVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id", + column: x => x.HitOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id", + column: x => x.LastStrainAngleVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationVector3Id", + table: "EFACSnapshot", + column: "HitDestinationVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginVector3Id", + table: "EFACSnapshot", + column: "HitOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleVector3Id", + table: "EFACSnapshot", + column: "LastStrainAngleVector3Id"); + + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs new file mode 100644 index 00000000..b55a67c9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs @@ -0,0 +1,638 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180614014303_IndexForEFAlias")] + partial class IndexForEFAlias + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs b/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs new file mode 100644 index 00000000..81ffaf1a --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class IndexForEFAlias : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFAlias_IPAddress", + table: "EFAlias", + column: "IPAddress"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_IPAddress", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs new file mode 100644 index 00000000..454d1a42 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs @@ -0,0 +1,665 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180902035612_AddFractionAndIsKill")] + partial class AddFractionAndIsKill + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs b/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs new file mode 100644 index 00000000..ae30df08 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs @@ -0,0 +1,63 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddFractionAndIsKill : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Fraction", + table: "EFClientKills", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "IsKill", + table: "EFClientKills", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "EFChangeHistory", + columns: table => new + { + ChangeHistoryId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + OriginEntityId = table.Column(nullable: false), + TargetEntityId = table.Column(nullable: false), + TypeOfChange = table.Column(nullable: false), + TimeChanged = table.Column(nullable: false), + Comment = table.Column(maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFChangeHistory", x => x.ChangeHistoryId); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFChangeHistory"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "Fraction", + table: "EFClientKills"); + + migrationBuilder.DropColumn( + name: "IsKill", + table: "EFClientKills"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs new file mode 100644 index 00000000..afba0742 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs @@ -0,0 +1,665 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180904154622_AddVisibilityPercentage")] + partial class AddVisibilityPercentage + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs b/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs new file mode 100644 index 00000000..77b24262 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddVisibilityPercentage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VisibilityPercentage", + table: "EFClientKills"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs new file mode 100644 index 00000000..eb6d0fcb --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs @@ -0,0 +1,669 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180907020706_AddVision")] + partial class AddVision + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs b/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs new file mode 100644 index 00000000..17ce2ea9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddVision : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VisionAverage", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VisionAverage", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs new file mode 100644 index 00000000..9411e8d1 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs @@ -0,0 +1,669 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180908004053_AddWhenToRating")] + partial class AddWhenToRating + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs b/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs new file mode 100644 index 00000000..f6482236 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddWhenToRating : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "When", + table: "EFRating", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "When", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs new file mode 100644 index 00000000..06dfdf36 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs @@ -0,0 +1,677 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180910221749_AddRatingIndexes")] + partial class AddRatingIndexes + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs b/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs new file mode 100644 index 00000000..781d5bba --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddRatingIndexes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + 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"); + } + + protected override void Down(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"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs new file mode 100644 index 00000000..e8acef8c --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -0,0 +1,679 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180911184224_AddEFAliasNameIndex")] + partial class AddEFAliasNameIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs b/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs new file mode 100644 index 00000000..90247335 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEFAliasNameIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFAlias_Name", + table: "EFAlias", + column: "Name"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_Name", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs new file mode 100644 index 00000000..8aabb7cc --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -0,0 +1,680 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180911190823_AddEFAliasNameMaxLength24")] + partial class AddEFAliasNameMaxLength24 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs b/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs new file mode 100644 index 00000000..53ef00b9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEFAliasNameMaxLength24 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + // hack: we can't alter the column on SQLite, but we need max length limit for the Index in MySQL etc + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + maxLength: 24, + nullable: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs new file mode 100644 index 00000000..cb9cc3c0 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -0,0 +1,684 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] + partial class AddPreviousCurrentValueToEFChangeHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs new file mode 100644 index 00000000..c7c7a911 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddPreviousCurrentValueToEFChangeHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CurrentValue", + table: "EFChangeHistory", + nullable: true); + + migrationBuilder.AddColumn( + + name: "PreviousValue", + table: "EFChangeHistory", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CurrentValue", + table: "EFChangeHistory"); + + migrationBuilder.DropColumn( + name: "PreviousValue", + table: "EFChangeHistory"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs new file mode 100644 index 00000000..30151d62 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -0,0 +1,686 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180915163111_AddIndexToMessageTimeSent")] + partial class AddIndexToMessageTimeSent + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs b/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs new file mode 100644 index 00000000..93186b38 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddIndexToMessageTimeSent : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_TimeSent", + table: "EFClientMessages", + column: "TimeSent"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFClientMessages_TimeSent", + table: "EFClientMessages"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs new file mode 100644 index 00000000..d8731227 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs @@ -0,0 +1,587 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180922231310_RemoveACSnapShot")] + partial class RemoveACSnapShot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs b/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs new file mode 100644 index 00000000..b767126f --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs @@ -0,0 +1,139 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class RemoveACSnapShot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + Deaths = table.Column(nullable: false), + Distance = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + HitDestinationVector3Id = table.Column(nullable: true), + HitLocation = table.Column(nullable: false), + HitOriginVector3Id = table.Column(nullable: true), + HitType = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + LastStrainAngleVector3Id = table.Column(nullable: true), + SessionAngleOffset = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + WeaponId = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id", + column: x => x.HitDestinationVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id", + column: x => x.HitOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id", + column: x => x.LastStrainAngleVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationVector3Id", + table: "EFACSnapshot", + column: "HitDestinationVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginVector3Id", + table: "EFACSnapshot", + column: "HitOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleVector3Id", + table: "EFACSnapshot", + column: "LastStrainAngleVector3Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs new file mode 100644 index 00000000..e7917a40 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs @@ -0,0 +1,689 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20180922231600_ReaddACSnapshot")] + partial class ReaddACSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs new file mode 100644 index 00000000..b0938c85 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs @@ -0,0 +1,145 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class ReaddACSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + Active = table.Column(nullable: false), + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ClientId = table.Column(nullable: false), + When = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + Deaths = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + SessionAngleOffset = table.Column(nullable: false), + LastStrainAngleId = table.Column(nullable: false), + HitOriginId = table.Column(nullable: false), + HitDestinationId = table.Column(nullable: false), + Distance = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + WeaponId = table.Column(nullable: false), + HitLocation = table.Column(nullable: false), + HitType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationId", + column: x => x.HitDestinationId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginId", + column: x => x.HitOriginId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleId", + column: x => x.LastStrainAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + }); + + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + } + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationId", + table: "EFACSnapshot", + column: "HitDestinationId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginId", + table: "EFACSnapshot", + column: "HitOriginId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleId", + table: "EFACSnapshot", + column: "LastStrainAngleId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs new file mode 100644 index 00000000..97e85323 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -0,0 +1,690 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20181014171848_MakePenaltyExpirationNullable")] + partial class MakePenaltyExpirationNullable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs b/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs new file mode 100644 index 00000000..6fb055ef --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs @@ -0,0 +1,105 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class MakePenaltyExpirationNullable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + +DROP TABLE EFPenalties; + +CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT +); + +INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1; "); + } + else + { + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(DateTime)); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(DateTime), + oldNullable: true); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs new file mode 100644 index 00000000..9ce5daa4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs @@ -0,0 +1,690 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20181125193243_MakeClientIPNullable")] + partial class MakeClientIPNullable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs b/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs new file mode 100644 index 00000000..9999193f --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs @@ -0,0 +1,85 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class MakeClientIPNullable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFAlias; + +DROP TABLE EFAlias; + +CREATE TABLE EFAlias ( + AliasId INTEGER NOT NULL + CONSTRAINT PK_EFAlias PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + DateAdded TEXT NOT NULL, + IPAddress INTEGER, + LinkId INTEGER NOT NULL, + Name TEXT NOT NULL, + CONSTRAINT FK_EFAlias_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE RESTRICT +); + +INSERT INTO EFAlias ( + AliasId, + Active, + DateAdded, + IPAddress, + LinkId, + Name + ) + SELECT AliasId, + Active, + DateAdded, + IPAddress, + LinkId, + Name + FROM sqlitestudio_temp_table; + +DROP TABLE sqlitestudio_temp_table; + +CREATE INDEX IX_EFAlias_LinkId ON EFAlias ( + ""LinkId"" +); + + CREATE INDEX IX_EFAlias_IPAddress ON EFAlias( + ""IPAddress"" + ); + + CREATE INDEX IX_EFAlias_Name ON EFAlias( + ""Name"" + ); + + PRAGMA foreign_keys = 1; + ", suppressTransaction:true); + } + else + { + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: true, + oldClrType: typeof(int)); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs new file mode 100644 index 00000000..df4a6f0e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -0,0 +1,692 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] + partial class AddEndpointToEFServerUpdateServerIdType + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs new file mode 100644 index 00000000..3f6871f1 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEndpointToEFServerUpdateServerIdType : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EndPoint", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EndPoint", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs new file mode 100644 index 00000000..f006af9e --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -0,0 +1,694 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20181216214513_AddEvadePenaltyFlag")] + partial class AddEvadePenaltyFlag + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs b/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs new file mode 100644 index 00000000..eaf9fbf3 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs @@ -0,0 +1,183 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddEvadePenaltyFlag : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + + DROP TABLE EFPenalties; + + CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + IsEvadedOffense BOOLEAN NOT NULL + DEFAULT (0), + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT + ); + + INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1;", suppressTransaction: false); + } + + else + { + migrationBuilder.AddColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + nullable: false, + defaultValue: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + + DROP TABLE EFPenalties; + + CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT + ); + + INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1;", suppressTransaction: false); + } + + else + { + migrationBuilder.DropColumn( + name: "IsEvadedOffense", + table: "EFPenalties"); + } + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs new file mode 100644 index 00000000..81f02781 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -0,0 +1,696 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] + partial class AddIndexToEFMetaKeyAndClientId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs new file mode 100644 index 00000000..ef8fbff1 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddIndexToEFMetaKeyAndClientId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql("CREATE FULLTEXT INDEX IX_EFMeta_Key ON EFMeta ( `Key` );"); + } + + else + { + migrationBuilder.CreateIndex( + name: "IX_EFMeta_Key", + table: "EFMeta", + column: "Key"); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFMeta_Key", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs new file mode 100644 index 00000000..f57d2e45 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs @@ -0,0 +1,699 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190423142128_AddGameNameToEFServer")] + partial class AddGameNameToEFServer + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs b/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs new file mode 100644 index 00000000..f9bca4c5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddGameNameToEFServer : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GameName", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "GameName", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs new file mode 100644 index 00000000..789c7b13 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -0,0 +1,701 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190615145212_AddAvgRecoilOffset")] + partial class AddAvgRecoilOffset + { + 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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs b/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs new file mode 100644 index 00000000..a884a9fe --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddAvgRecoilOffset : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs new file mode 100644 index 00000000..54190afc --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -0,0 +1,703 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190615214055_AddRecoilOffsetToSnapshot")] + partial class AddRecoilOffsetToSnapshot + { + 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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs new file mode 100644 index 00000000..b7ef1b24 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddRecoilOffsetToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RecoilOffset", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs new file mode 100644 index 00000000..52a49551 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs @@ -0,0 +1,699 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs b/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs new file mode 100644 index 00000000..c85535b7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + 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"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs new file mode 100644 index 00000000..02226b02 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -0,0 +1,704 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190802174908_AddSearchNameToEFAlias")] + partial class AddSearchNameToEFAlias + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs b/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs new file mode 100644 index 00000000..d7311093 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddSearchNameToEFAlias : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SearchableName", + table: "EFAlias", + maxLength: 24, + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_SearchableName", + table: "EFAlias", + column: "SearchableName"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_SearchableName", + table: "EFAlias"); + + migrationBuilder.DropColumn( + name: "SearchableName", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs new file mode 100644 index 00000000..b0c541ff --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -0,0 +1,706 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190831210503_AvgSnapValueToClientStatistics")] + partial class AvgSnapValueToClientStatistics + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs b/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs new file mode 100644 index 00000000..625b3ca1 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AvgSnapValueToClientStatistics : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AverageSnapValue", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs new file mode 100644 index 00000000..c4100f24 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -0,0 +1,708 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190901180209_AddSnapHitCountToClientStatistics")] + partial class AddSnapHitCountToClientStatistics + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs b/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs new file mode 100644 index 00000000..d3ddd2c5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddSnapHitCountToClientStatistics : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SnapHitCount", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs new file mode 100644 index 00000000..631b0a20 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -0,0 +1,728 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] + partial class UseJunctionTableForSnapshotVector3 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs b/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs new file mode 100644 index 00000000..9f23f776 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -0,0 +1,89 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UseJunctionTableForSnapshotVector3 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + + migrationBuilder.CreateTable( + name: "EFACSnapshotVector3", + columns: table => new + { + ACSnapshotVector3Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + SnapshotId = table.Column(nullable: false), + Vector3Id = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshotVector3", x => x.ACSnapshotVector3Id); + table.ForeignKey( + name: "FK_EFACSnapshotVector3_EFACSnapshot_SnapshotId", + column: x => x.SnapshotId, + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshotVector3_Vector3_Vector3Id", + column: x => x.Vector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshotVector3_SnapshotId", + table: "EFACSnapshotVector3", + column: "SnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshotVector3_Vector3Id", + table: "EFACSnapshotVector3", + column: "Vector3Id"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFACSnapshotVector3"); + + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs new file mode 100644 index 00000000..9ffe59a6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -0,0 +1,730 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] + partial class AddCurrentSnapValueToSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("SessionAverageSnapValue"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs new file mode 100644 index 00000000..e0d23b6d --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddCurrentSnapValueToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs new file mode 100644 index 00000000..8bcd882a --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -0,0 +1,732 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] + partial class AddSessionSnapHitsToSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("SessionAverageSnapValue"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("SessionSnapHits"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs new file mode 100644 index 00000000..687fe3ed --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddSessionSnapHitsToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SessionSnapHits", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs new file mode 100644 index 00000000..fe2cc55a --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -0,0 +1,910 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20191004172550_RenameClientHitLocationCountColumns")] + partial class RenameClientHitLocationCountColumns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs b/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs new file mode 100644 index 00000000..ec56f701 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs @@ -0,0 +1,151 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class RenameClientHitLocationCountColumns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFHitLocationCounts; + +DROP TABLE EFHitLocationCounts; + +CREATE TABLE EFHitLocationCounts ( + HitLocationCountId INTEGER NOT NULL + CONSTRAINT PK_EFHitLocationCounts PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + EFClientStatisticsClientId INTEGER NOT NULL, + HitCount INTEGER NOT NULL, + HitOffsetAverage REAL NOT NULL, + Location INTEGER NOT NULL, + EFClientStatisticsServerId INTEGER NOT NULL, + MaxAngleDistance REAL NOT NULL + DEFAULT 0, + CONSTRAINT FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId FOREIGN KEY ( + EFClientStatisticsClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE, + CONSTRAINT FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId FOREIGN KEY ( + EFClientStatisticsServerId + ) + REFERENCES EFServers (ServerId) ON DELETE CASCADE, + CONSTRAINT FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId FOREIGN KEY ( + EFClientStatisticsClientId, + EFClientStatisticsServerId + ) + REFERENCES EFClientStatistics (ClientId, + ServerId) ON DELETE CASCADE +); + +INSERT INTO EFHitLocationCounts ( + HitLocationCountId, + Active, + EFClientStatisticsClientId, + HitCount, + HitOffsetAverage, + Location, + EFClientStatisticsServerId, + MaxAngleDistance + ) + SELECT HitLocationCountId, + Active, + EFClientStatistics_ClientId, + HitCount, + HitOffsetAverage, + Location, + EFClientStatistics_ServerId, + MaxAngleDistance + FROM sqlitestudio_temp_table; + +DROP TABLE sqlitestudio_temp_table; + +CREATE INDEX IX_EFHitLocationCounts_EFClientStatistics_ServerId ON EFHitLocationCounts ( + EFClientStatisticsServerId +); + +CREATE INDEX IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId ON EFHitLocationCounts ( + EFClientStatisticsClientId, + EFClientStatisticsServerId +); + +PRAGMA foreign_keys = 1; +", true); + } + + else if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql("ALTER TABLE `EFHitLocationCounts` CHANGE `EFClientStatistics_ClientId` `EFClientStatisticsClientId` INT(11) NOT NULL;"); + migrationBuilder.Sql("ALTER TABLE `EFHitLocationCounts` CHANGE `EFClientStatistics_ServerId` `EFClientStatisticsServerId` INT(11) NOT NULL;"); + migrationBuilder.Sql("CREATE INDEX `IX_EFClientStatisticsClientId_EFClientStatisticsServerId` ON `EFHitLocationCounts` (`EFClientStatisticsClientId`, `EFClientStatisticsServerId`);"); + } + + else + { + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId", + table: "EFHitLocationCounts"); + + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId", + table: "EFHitLocationCounts"); + + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts"); + + migrationBuilder.RenameColumn( + name: "EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "EFClientStatisticsServerId"); + + migrationBuilder.RenameColumn( + name: "EFClientStatistics_ClientId", + table: "EFHitLocationCounts", + newName: "EFClientStatisticsClientId"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStatisticsServerId"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsServerId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatisticsClientId", + table: "EFHitLocationCounts", + column: "EFClientStatisticsClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + column: "EFClientStatisticsServerId", + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs new file mode 100644 index 00000000..84f64a95 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -0,0 +1,909 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] + partial class EnforceUniqueIndexForEFAliasIPName + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs new file mode 100644 index 00000000..f8d77113 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -0,0 +1,188 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class EnforceUniqueIndexForEFAliasIPName : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"DROP TABLE IF EXISTS DUPLICATE_ALIASES; + CREATE TABLE DUPLICATE_ALIASES AS +SELECT + MIN(AliasId) MIN, + MAX(AliasId) MAX, + LinkId +FROM + EFAlias +WHERE + (IPAddress, NAME) IN( + SELECT DISTINCT + IPAddress, + NAME + FROM + EFAlias + GROUP BY + EFAlias.IPAddress, + NAME + HAVING + COUNT(IPAddress) > 1 AND COUNT(NAME) > 1 +) +GROUP BY + IPAddress +ORDER BY + IPAddress; + + UPDATE + EFClients +SET CurrentAliasId = (SELECT MAX FROM DUPLICATE_ALIASES WHERE CurrentAliasId = MIN) +WHERE + CurrentAliasId IN( + SELECT + MIN + FROM + DUPLICATE_ALIASES +); + DELETE + FROM + EFAlias +WHERE + AliasId IN( + SELECT + MIN + FROM + DUPLICATE_ALIASES +); + + DROP TABLE + DUPLICATE_ALIASES;"); + return; + } + + else if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql(@"CREATE TABLE DUPLICATE_ALIASES +SELECT + MIN(`AliasId`) `MIN`, + MAX(`AliasId`) `MAX`, + `LinkId` +FROM + `EFAlias` +WHERE + (`IPAddress`, `NAME`) IN( + SELECT DISTINCT + `IPAddress`, + `NAME` + FROM + `EFAlias` + GROUP BY + `EFAlias`.`IPAddress`, + `NAME` + HAVING + COUNT(`IPAddress`) > 1 AND COUNT(`NAME`) > 1 +) +GROUP BY + `IPAddress` +ORDER BY + `IPAddress`; +SET + SQL_SAFE_UPDATES = 0; +UPDATE + `EFClients` AS `Client` +JOIN + DUPLICATE_ALIASES `Duplicate` +ON + `Client`.CurrentAliasId = `Duplicate`.`MIN` +SET + `Client`.CurrentAliasId = `Duplicate`.`MAX` +WHERE + `Client`.`CurrentAliasId` IN( + SELECT + `MIN` + FROM + DUPLICATE_ALIASES +); +DELETE +FROM + `EFAlias` +WHERE + `AliasId` IN( + SELECT + `MIN` + FROM + DUPLICATE_ALIASES +); +SET + SQL_SAFE_UPDATES = 1; +DROP TABLE + DUPLICATE_ALIASES;"); + } + + else + { + migrationBuilder.Sql(@"CREATE TEMPORARY TABLE DUPLICATE_ALIASES AS +SELECT + MIN(""AliasId"") ""MIN"", + MAX(""AliasId"") ""MAX"", + MIN(""LinkId"") ""LinkId"" +FROM + ""EFAlias"" +WHERE + (""IPAddress"", ""Name"") IN( + SELECT DISTINCT + ""IPAddress"", + ""Name"" + FROM + ""EFAlias"" + GROUP BY + ""EFAlias"".""IPAddress"", + ""Name"" + HAVING + COUNT(""IPAddress"") > 1 AND COUNT(""Name"") > 1 +) +GROUP BY + ""IPAddress"" +ORDER BY + ""IPAddress""; +UPDATE + ""EFClients"" AS ""Client"" +SET + ""CurrentAliasId"" = ""Duplicate"".""MAX"" +FROM + DUPLICATE_ALIASES ""Duplicate"" +WHERE + ""Client"".""CurrentAliasId"" IN( + SELECT + ""MIN"" + FROM + DUPLICATE_ALIASES +) +AND + ""Client"".""CurrentAliasId"" = ""Duplicate"".""MIN""; +DELETE +FROM + ""EFAlias"" +WHERE + ""AliasId"" IN( + SELECT + ""MIN"" + FROM + DUPLICATE_ALIASES +); +DROP TABLE + DUPLICATE_ALIASES;"); + } + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_Name_IPAddress", + table: "EFAlias", + columns: new[] { "Name", "IPAddress" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs new file mode 100644 index 00000000..525481e7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -0,0 +1,916 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] + partial class SetCaseSensitiveCoallationForAliasNameMySQL + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs new file mode 100644 index 00000000..ae96a8c4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + // this prevents duplicate aliases from being added by changing it to case sensitive collation + migrationBuilder.Sql(@"ALTER TABLE `EFAlias` MODIFY + `Name` VARCHAR(24) + CHARACTER SET utf8 + COLLATE utf8_bin;"); + }; + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs new file mode 100644 index 00000000..c6bf3eee --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs @@ -0,0 +1,916 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20191230140947_AddMissingActiveColumns")] + partial class AddMissingActiveColumns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs b/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs new file mode 100644 index 00000000..c1ce223a --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddMissingActiveColumns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Active", + table: "EFACSnapshotVector3", + nullable: false, + defaultValue: true); + + migrationBuilder.AddColumn( + name: "Active", + table: "Vector3", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs new file mode 100644 index 00000000..5497e0c8 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -0,0 +1,919 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] + partial class AddImpersonationIdToEFChangeHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs new file mode 100644 index 00000000..b2e74946 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddImpersonationIdToEFChangeHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs new file mode 100644 index 00000000..c25872e6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs @@ -0,0 +1,922 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20200521203304_AddHostnameToEFServer")] + partial class AddHostnameToEFServer + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs b/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs new file mode 100644 index 00000000..3fa054c4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddHostnameToEFServer : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "HostName", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "HostName", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs new file mode 100644 index 00000000..ac88256b --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -0,0 +1,925 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20200819224119_AddIsPasswordProtectedColumn")] + partial class AddIsPasswordProtectedColumn + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs b/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs new file mode 100644 index 00000000..0fb89d05 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddIsPasswordProtectedColumn : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Npgsql.EntityFrameworkCore.PostgreSQL") + { + migrationBuilder.AddColumn( + name: "IsPasswordProtected", + type: "bool", + table: "EFServers", + nullable: false, + defaultValue: false); + } + else + { + migrationBuilder.AddColumn( + name: "IsPasswordProtected", + table: "EFServers", + nullable: false, + defaultValue: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsPasswordProtected", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs new file mode 100644 index 00000000..9c968e9a --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -0,0 +1,927 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20201114232340_UpdateEFRatingIndex")] + partial class UpdateEFRatingIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs b/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs new file mode 100644 index 00000000..779a1dc6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateEFRatingIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating", + columns: new[] { "When", "ServerId", "Performance", "ActivityAmount" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs new file mode 100644 index 00000000..1aa80f9b --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -0,0 +1,930 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20201118023106_AddSentIngameFlagToClientMessage")] + partial class AddSentIngameFlagToClientMessage + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs b/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs new file mode 100644 index 00000000..eb652b89 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class AddSentIngameFlagToClientMessage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SentIngame", + table: "EFClientMessages", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SentIngame", + table: "EFClientMessages"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs new file mode 100644 index 00000000..7f27b9c0 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs @@ -0,0 +1,948 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20201125160058_UpdateMigrationsForPostgresql")] + partial class UpdateMigrationsForPostgresql + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn) + .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("HitDestinationId") + .HasColumnType("integer"); + + b.Property("HitLocation") + .HasColumnType("integer"); + + b.Property("HitOriginId") + .HasColumnType("integer"); + + b.Property("HitType") + .HasColumnType("integer"); + + b.Property("Hits") + .HasColumnType("integer"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("LastStrainAngleId") + .HasColumnType("integer"); + + b.Property("RecoilOffset") + .HasColumnType("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitOffsetAverage") + .HasColumnType("real"); + + b.Property("Location") + .HasColumnType("integer"); + + b.Property("MaxAngleDistance") + .HasColumnType("real"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("text"); + + b.Property("ImpersonationEntityId") + .HasColumnType("integer"); + + b.Property("OriginEntityId") + .HasColumnType("integer"); + + b.Property("PreviousValue") + .HasColumnType("text"); + + b.Property("TargetEntityId") + .HasColumnType("integer"); + + b.Property("TimeChanged") + .HasColumnType("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("OffenderId") + .HasColumnType("integer"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("text"); + + b.Property("PunisherId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + + b.Property("X") + .HasColumnType("real"); + + b.Property("Y") + .HasColumnType("real"); + + b.Property("Z") + .HasColumnType("real"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs b/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs new file mode 100644 index 00000000..c44a5008 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs @@ -0,0 +1,2341 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateMigrationsForPostgresql : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStat~"); + + migrationBuilder.AlterColumn( + name: "Z", + table: "Vector3", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Y", + table: "Vector3", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "X", + table: "Vector3", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "Vector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TotalPlayTime", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TotalKills", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "StatisticId", + table: "EFServerStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Port", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IsPasswordProtected", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HostName", + table: "EFServers", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GameName", + table: "EFServers", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndPoint", + table: "EFServers", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServers", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFRating", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFRating", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Ranking", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Performance", + table: "EFRating", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Newest", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ActivityAmount", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "RatingId", + table: "EFRating", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Type", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PunisherId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Offense", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "OffenderId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AutomatedOffense", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PenaltyId", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Value", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Updated", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Key", + table: "EFMeta", + maxLength: 32, + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "Extra", + table: "EFMeta", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Created", + table: "EFMeta", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "MetaId", + table: "EFMeta", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Location", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitOffsetAverage", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "HitCount", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsServerId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsClientId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLocationCountId", + table: "EFHitLocationCounts", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "VisionAverage", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "TimePlayed", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Skill", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SPM", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "MaxStrain", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientStatistics", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TotalConnectionTime", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PasswordSalt", + table: "EFClients", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Password", + table: "EFClients", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NetworkId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Masked", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Level", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "LastConnection", + table: "EFClients", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "FirstConnection", + table: "EFClients", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "CurrentAliasId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Connections", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClients", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFClientRatingHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TimeSent", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.Sql("ALTER TABLE \"EFClientMessages\" ALTER COLUMN \"SentIngame\" DROP DEFAULT;" + + "ALTER TABLE \"EFClientMessages\" ALTER \"SentIngame\" TYPE bool USING CASE WHEN \"SentIngame\"=0 THEN FALSE ELSE TRUE END;" + + "ALTER TABLE \"EFClientMessages\" ALTER COLUMN \"SentIngame\" SET DEFAULT TRUE;"); + + migrationBuilder.AlterColumn( + name: "Message", + table: "EFClientMessages", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "MessageId", + table: "EFClientMessages", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Weapon", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "ViewAnglesVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "VictimId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Map", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "KillOriginVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "IsKill", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLoc", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Fraction", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "DeathType", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "DeathOriginVector3Id", + table: "EFClientKills", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Damage", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AttackerId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "KillId", + table: "EFClientKills", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TypeOfChange", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TimeChanged", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "TargetEntityId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "PreviousValue", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OriginEntityId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CurrentValue", + table: "EFChangeHistory", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "EFChangeHistory", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ChangeHistoryId", + table: "EFChangeHistory", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAliasLinks", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFAliasLinks", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "SearchableName", + table: "EFAlias", + maxLength: 24, + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 24, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + maxLength: 24, + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 24); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DateAdded", + table: "EFAlias", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "AliasId", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.Sql("ALTER TABLE \"EFACSnapshotVector3\" ALTER COLUMN \"Active\" DROP DEFAULT;" + + "ALTER TABLE \"EFACSnapshotVector3\" ALTER \"Active\" TYPE bool USING CASE WHEN \"Active\"=0 THEN FALSE ELSE TRUE END;" + + "ALTER TABLE \"EFACSnapshotVector3\" ALTER COLUMN \"Active\" SET DEFAULT TRUE;"); + + migrationBuilder.AlterColumn( + name: "ACSnapshotVector3Id", + table: "EFACSnapshotVector3", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "WeaponId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "TimeSinceLastEvent", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "StrainAngleBetween", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SessionScore", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SessionSPM", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "SessionAngleOffset", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "LastStrainAngleId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Hits", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitType", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitOriginId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitLocation", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "HitDestinationId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Distance", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "CurrentViewAngleId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "CurrentStrain", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(float), + oldType: "REAL"); + + migrationBuilder.AlterColumn( + name: "CurrentSessionLength", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshot", + nullable: false, + oldClrType: typeof(int), + oldType: "INTEGER") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsCl~", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsCl~", + table: "EFHitLocationCounts"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStat~", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStatisticsServerId"); + + migrationBuilder.AlterColumn( + name: "Z", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Y", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "X", + table: "Vector3", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "Vector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TotalPlayTime", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "TotalKills", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "StatisticId", + table: "EFServerStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Port", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IsPasswordProtected", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HostName", + table: "EFServers", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "GameName", + table: "EFServers", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndPoint", + table: "EFServers", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFServers", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFRating", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFRating", + type: "INTEGER", + nullable: true, + oldClrType: typeof(long), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Ranking", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Performance", + table: "EFRating", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Newest", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ActivityAmount", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "RatingId", + table: "EFRating", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFPenalties", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Type", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PunisherId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Offense", + table: "EFPenalties", + type: "TEXT", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "OffenderId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + type: "TEXT", + nullable: true, + oldClrType: typeof(DateTime), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AutomatedOffense", + table: "EFPenalties", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "PenaltyId", + table: "EFPenalties", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Value", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "Updated", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Key", + table: "EFMeta", + type: "TEXT", + maxLength: 32, + nullable: false, + oldClrType: typeof(string), + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "Extra", + table: "EFMeta", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Created", + table: "EFMeta", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "MetaId", + table: "EFMeta", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "Location", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitOffsetAverage", + table: "EFHitLocationCounts", + type: "REAL", + nullable: false, + oldClrType: typeof(float)); + + migrationBuilder.AlterColumn( + name: "HitCount", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsServerId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "EFClientStatisticsClientId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HitLocationCountId", + table: "EFHitLocationCounts", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "VisionAverage", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "TimePlayed", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Skill", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SPM", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "MaxStrain", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientStatistics", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TotalConnectionTime", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PasswordSalt", + table: "EFClients", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Password", + table: "EFClients", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NetworkId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Masked", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Level", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "LastConnection", + table: "EFClients", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "FirstConnection", + table: "EFClients", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "CurrentAliasId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Connections", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClients", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "RatingHistoryId", + table: "EFClientRatingHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TimeSent", + table: "EFClientMessages", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "SentIngame", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "Message", + table: "EFClientMessages", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "MessageId", + table: "EFClientMessages", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFClientKills", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Weapon", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "ViewAnglesVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "VictimId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ServerId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)); + + migrationBuilder.AlterColumn( + name: "Map", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "KillOriginVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "IsKill", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "HitLoc", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Fraction", + table: "EFClientKills", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "DeathType", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "DeathOriginVector3Id", + table: "EFClientKills", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Damage", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "AttackerId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "KillId", + table: "EFClientKills", + type: "INTEGER", + nullable: false, + oldClrType: typeof(long)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "TypeOfChange", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TimeChanged", + table: "EFChangeHistory", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "TargetEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "PreviousValue", + table: "EFChangeHistory", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OriginEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CurrentValue", + table: "EFChangeHistory", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "EFChangeHistory", + type: "TEXT", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ChangeHistoryId", + table: "EFChangeHistory", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAliasLinks", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "AliasLinkId", + table: "EFAliasLinks", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "SearchableName", + table: "EFAlias", + type: "TEXT", + maxLength: 24, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 24, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + type: "TEXT", + maxLength: 24, + nullable: false, + oldClrType: typeof(string), + oldMaxLength: 24); + + migrationBuilder.AlterColumn( + name: "LinkId", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DateAdded", + table: "EFAlias", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "AliasId", + table: "EFAlias", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "Vector3Id", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "ACSnapshotVector3Id", + table: "EFACSnapshotVector3", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AlterColumn( + name: "When", + table: "EFACSnapshot", + type: "TEXT", + nullable: false, + oldClrType: typeof(DateTime)); + + migrationBuilder.AlterColumn( + name: "WeaponId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "TimeSinceLastEvent", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "StrainAngleBetween", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SessionScore", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "SessionSPM", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "SessionAngleOffset", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "LastStrainAngleId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Kills", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Hits", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitType", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitOriginId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitLocation", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "HitDestinationId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "EloRating", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Distance", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "Deaths", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "CurrentViewAngleId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "CurrentStrain", + table: "EFACSnapshot", + type: "REAL", + nullable: false, + oldClrType: typeof(double)); + + migrationBuilder.AlterColumn( + name: "CurrentSessionLength", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)); + + migrationBuilder.AlterColumn( + name: "Active", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(bool)); + + migrationBuilder.AlterColumn( + name: "SnapshotId", + table: "EFACSnapshot", + type: "INTEGER", + nullable: false, + oldClrType: typeof(int)) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs new file mode 100644 index 00000000..5917c444 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs @@ -0,0 +1,946 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + partial class PostgresqlDatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("HitDestinationId") + .HasColumnType("integer"); + + b.Property("HitLocation") + .HasColumnType("integer"); + + b.Property("HitOriginId") + .HasColumnType("integer"); + + b.Property("HitType") + .HasColumnType("integer"); + + b.Property("Hits") + .HasColumnType("integer"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("LastStrainAngleId") + .HasColumnType("integer"); + + b.Property("RecoilOffset") + .HasColumnType("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitOffsetAverage") + .HasColumnType("real"); + + b.Property("Location") + .HasColumnType("integer"); + + b.Property("MaxAngleDistance") + .HasColumnType("real"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("text"); + + b.Property("ImpersonationEntityId") + .HasColumnType("integer"); + + b.Property("OriginEntityId") + .HasColumnType("integer"); + + b.Property("PreviousValue") + .HasColumnType("text"); + + b.Property("TargetEntityId") + .HasColumnType("integer"); + + b.Property("TimeChanged") + .HasColumnType("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("OffenderId") + .HasColumnType("integer"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("text"); + + b.Property("PunisherId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("X") + .HasColumnType("real"); + + b.Property("Y") + .HasColumnType("real"); + + b.Property("Z") + .HasColumnType("real"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs new file mode 100644 index 00000000..e71e66ac --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs @@ -0,0 +1,431 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180409183408_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("Kills"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs b/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs new file mode 100644 index 00000000..4727c927 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs @@ -0,0 +1,483 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFAliasLinks", + columns: table => new + { + AliasLinkId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFAliasLinks", x => x.AliasLinkId); + }); + + migrationBuilder.CreateTable( + name: "EFServers", + columns: table => new + { + ServerId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Port = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFServers", x => x.ServerId); + }); + + migrationBuilder.CreateTable( + name: "Vector3", + columns: table => new + { + Vector3Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + X = table.Column(nullable: false), + Y = table.Column(nullable: false), + Z = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Vector3", x => x.Vector3Id); + }); + + migrationBuilder.CreateTable( + name: "EFAlias", + columns: table => new + { + AliasId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + DateAdded = table.Column(nullable: false), + IPAddress = table.Column(nullable: false), + LinkId = table.Column(nullable: false), + Name = table.Column(maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFAlias", x => x.AliasId); + table.ForeignKey( + name: "FK_EFAlias_EFAliasLinks_LinkId", + column: x => x.LinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFServerStatistics", + columns: table => new + { + StatisticId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + TotalKills = table.Column(nullable: false), + TotalPlayTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFServerStatistics", x => x.StatisticId); + table.ForeignKey( + name: "FK_EFServerStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClients", + columns: table => new + { + ClientId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + AliasLinkId = table.Column(nullable: false), + Connections = table.Column(nullable: false), + CurrentAliasId = table.Column(nullable: false), + FirstConnection = table.Column(nullable: false), + LastConnection = table.Column(nullable: false), + Level = table.Column(nullable: false), + Masked = table.Column(nullable: false), + NetworkId = table.Column(nullable: false), + Password = table.Column(nullable: true), + PasswordSalt = table.Column(nullable: true), + TotalConnectionTime = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClients", x => x.ClientId); + table.ForeignKey( + name: "FK_EFClients_EFAliasLinks_AliasLinkId", + column: x => x.AliasLinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClients_EFAlias_CurrentAliasId", + column: x => x.CurrentAliasId, + principalTable: "EFAlias", + principalColumn: "AliasId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClientKills", + columns: table => new + { + KillId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true). + Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + AttackerId = table.Column(nullable: false), + Damage = table.Column(nullable: false), + DeathOriginVector3Id = table.Column(nullable: true), + DeathType = table.Column(nullable: false), + HitLoc = table.Column(nullable: false), + KillOriginVector3Id = table.Column(nullable: true), + Map = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + VictimId = table.Column(nullable: false), + ViewAnglesVector3Id = table.Column(nullable: true), + Weapon = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientKills", x => x.KillId); + table.ForeignKey( + name: "FK_EFClientKills_EFClients_AttackerId", + column: x => x.AttackerId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_DeathOriginVector3Id", + column: x => x.DeathOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_KillOriginVector3Id", + column: x => x.KillOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientKills_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_EFClients_VictimId", + column: x => x.VictimId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientKills_Vector3_ViewAnglesVector3Id", + column: x => x.ViewAnglesVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFClientMessages", + columns: table => new + { + MessageId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + Message = table.Column(nullable: true), + ServerId = table.Column(nullable: false), + TimeSent = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientMessages", x => x.MessageId); + table.ForeignKey( + name: "FK_EFClientMessages_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientMessages_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFClientStatistics", + columns: table => new + { + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: false), + Active = table.Column(nullable: false), + Deaths = table.Column(nullable: false), + Kills = table.Column(nullable: false), + SPM = table.Column(nullable: false), + Skill = table.Column(nullable: false), + TimePlayed = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientStatistics", x => new { x.ClientId, x.ServerId }); + table.ForeignKey( + name: "FK_EFClientStatistics_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFPenalties", + columns: table => new + { + PenaltyId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Expires = table.Column(nullable: false), + LinkId = table.Column(nullable: false), + OffenderId = table.Column(nullable: false), + Offense = table.Column(nullable: false), + PunisherId = table.Column(nullable: false), + Type = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFPenalties", x => x.PenaltyId); + table.ForeignKey( + name: "FK_EFPenalties_EFAliasLinks_LinkId", + column: x => x.LinkId, + principalTable: "EFAliasLinks", + principalColumn: "AliasLinkId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFPenalties_EFClients_OffenderId", + column: x => x.OffenderId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFPenalties_EFClients_PunisherId", + column: x => x.PunisherId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFHitLocationCounts", + columns: table => new + { + HitLocationCountId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true). + Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn). + Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + EFClientStatistics_ClientId = table.Column(nullable: false), + HitCount = table.Column(nullable: false), + HitOffsetAverage = table.Column(nullable: false), + Location = table.Column(nullable: false), + EFClientStatistics_ServerId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFHitLocationCounts", x => x.HitLocationCountId); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId", + column: x => x.EFClientStatistics_ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId", + column: x => x.EFClientStatistics_ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + columns: x => new { x.EFClientStatistics_ClientId, x.EFClientStatistics_ServerId }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_LinkId", + table: "EFAlias", + column: "LinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_AttackerId", + table: "EFClientKills", + column: "AttackerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_DeathOriginVector3Id", + table: "EFClientKills", + column: "DeathOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_KillOriginVector3Id", + table: "EFClientKills", + column: "KillOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_ServerId", + table: "EFClientKills", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_VictimId", + table: "EFClientKills", + column: "VictimId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientKills_ViewAnglesVector3Id", + table: "EFClientKills", + column: "ViewAnglesVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_ClientId", + table: "EFClientMessages", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_ServerId", + table: "EFClientMessages", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_AliasLinkId", + table: "EFClients", + column: "AliasLinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_CurrentAliasId", + table: "EFClients", + column: "CurrentAliasId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClients_NetworkId", + table: "EFClients", + column: "NetworkId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ServerId", + table: "EFClientStatistics", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + column: "EFClientStatistics_ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatistics_ClientId", "EFClientStatistics_ServerId" }); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_LinkId", + table: "EFPenalties", + column: "LinkId"); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_OffenderId", + table: "EFPenalties", + column: "OffenderId"); + + migrationBuilder.CreateIndex( + name: "IX_EFPenalties_PunisherId", + table: "EFPenalties", + column: "PunisherId"); + + migrationBuilder.CreateIndex( + name: "IX_EFServerStatistics_ServerId", + table: "EFServerStatistics", + column: "ServerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFClientKills"); + + migrationBuilder.DropTable( + name: "EFClientMessages"); + + migrationBuilder.DropTable( + name: "EFHitLocationCounts"); + + migrationBuilder.DropTable( + name: "EFPenalties"); + + migrationBuilder.DropTable( + name: "EFServerStatistics"); + + migrationBuilder.DropTable( + name: "Vector3"); + + migrationBuilder.DropTable( + name: "EFClientStatistics"); + + migrationBuilder.DropTable( + name: "EFClients"); + + migrationBuilder.DropTable( + name: "EFServers"); + + migrationBuilder.DropTable( + name: "EFAlias"); + + migrationBuilder.DropTable( + name: "EFAliasLinks"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs new file mode 100644 index 00000000..9ca5b7e3 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs @@ -0,0 +1,434 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180502195450_Update")] + partial class Update + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs b/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs new file mode 100644 index 00000000..eebdb16d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class Update : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts", + nullable: false, + defaultValue: 0f); + + migrationBuilder.AddColumn( + name: "MaxStrain", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MaxAngleDistance", + table: "EFHitLocationCounts"); + + migrationBuilder.DropColumn( + name: "MaxStrain", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs new file mode 100644 index 00000000..debb8507 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs @@ -0,0 +1,436 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180516023249_AddEloField")] + partial class AddEloField + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs b/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs new file mode 100644 index 00000000..0b6eb37a --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEloField : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EloRating", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EloRating", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs new file mode 100644 index 00000000..0888266d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs @@ -0,0 +1,438 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180517223349_AddRollingKDR")] + partial class AddRollingKDR + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("ServerId") + .HasColumnName("EFClientStatistics_ServerId"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ClientId", "ServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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.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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs b/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs new file mode 100644 index 00000000..83b39456 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddRollingKDR : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RollingWeightedKDR", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs new file mode 100644 index 00000000..db0edba5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -0,0 +1,501 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] + partial class AddAutomatedOffenseAndRatingHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs new file mode 100644 index 00000000..1b597008 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -0,0 +1,101 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddAutomatedOffenseAndRatingHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AutomatedOffense", + table: "EFPenalties", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFClientRatingHistory", + columns: table => new + { + RatingHistoryId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientRatingHistory", x => x.RatingHistoryId); + table.ForeignKey( + name: "FK_EFClientRatingHistory_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFRating", + columns: table => new + { + RatingId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + Newest = table.Column(nullable: false), + Performance = table.Column(nullable: false), + Ranking = table.Column(nullable: false), + RatingHistoryId = table.Column(nullable: false), + ServerId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFRating", x => x.RatingId); + table.ForeignKey( + name: "FK_EFRating_EFClientRatingHistory_RatingHistoryId", + column: x => x.RatingHistoryId, + principalTable: "EFClientRatingHistory", + principalColumn: "RatingHistoryId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFRating_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRatingHistory_ClientId", + table: "EFClientRatingHistory", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFRating_RatingHistoryId", + table: "EFRating", + column: "RatingHistoryId"); + + migrationBuilder.CreateIndex( + name: "IX_EFRating_ServerId", + table: "EFRating", + column: "ServerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFRating"); + + migrationBuilder.DropTable( + name: "EFClientRatingHistory"); + + migrationBuilder.DropColumn( + name: "AutomatedOffense", + table: "EFPenalties"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs new file mode 100644 index 00000000..52414186 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs @@ -0,0 +1,503 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180601172317_AddActivityAmount")] + partial class AddActivityAmount + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("TotalConnectionTime"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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.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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs b/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs new file mode 100644 index 00000000..61ab0518 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddActivityAmount : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ActivityAmount", + table: "EFRating", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ActivityAmount", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs new file mode 100644 index 00000000..ca057232 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs @@ -0,0 +1,539 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180602041758_AddClientMeta")] + partial class AddClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs b/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs new file mode 100644 index 00000000..5fff4b5c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFMeta", + columns: table => new + { + MetaId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + Created = table.Column(nullable: false), + Extra = table.Column(nullable: true), + Key = table.Column(nullable: false), + Updated = table.Column(nullable: false), + Value = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeta", x => x.MetaId); + table.ForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_ClientId", + table: "EFMeta", + column: "ClientId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs new file mode 100644 index 00000000..9a941e7d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs @@ -0,0 +1,638 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180605191706_AddEFACSnapshots")] + partial class AddEFACSnapshots + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs b/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs new file mode 100644 index 00000000..bdf00e1c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs @@ -0,0 +1,144 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEFACSnapshots : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + Deaths = table.Column(nullable: false), + Distance = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + HitDestinationVector3Id = table.Column(nullable: true), + HitLocation = table.Column(nullable: false), + HitOriginVector3Id = table.Column(nullable: true), + HitType = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + LastStrainAngleVector3Id = table.Column(nullable: true), + SessionAngleOffset = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + WeaponId = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id", + column: x => x.HitDestinationVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id", + column: x => x.HitOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id", + column: x => x.LastStrainAngleVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationVector3Id", + table: "EFACSnapshot", + column: "HitDestinationVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginVector3Id", + table: "EFACSnapshot", + column: "HitOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleVector3Id", + table: "EFACSnapshot", + column: "LastStrainAngleVector3Id"); + + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs new file mode 100644 index 00000000..553c7183 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs @@ -0,0 +1,638 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database.MigrationContext; +using System; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180614014303_IndexForEFAlias")] + partial class IndexForEFAlias + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs b/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs new file mode 100644 index 00000000..de188ae2 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class IndexForEFAlias : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFAlias_IPAddress", + table: "EFAlias", + column: "IPAddress"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_IPAddress", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs new file mode 100644 index 00000000..a79bb713 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs @@ -0,0 +1,665 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180902035612_AddFractionAndIsKill")] + partial class AddFractionAndIsKill + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs b/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs new file mode 100644 index 00000000..be6423b4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs @@ -0,0 +1,63 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddFractionAndIsKill : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Fraction", + table: "EFClientKills", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "IsKill", + table: "EFClientKills", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "EFChangeHistory", + columns: table => new + { + ChangeHistoryId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + OriginEntityId = table.Column(nullable: false), + TargetEntityId = table.Column(nullable: false), + TypeOfChange = table.Column(nullable: false), + TimeChanged = table.Column(nullable: false), + Comment = table.Column(maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFChangeHistory", x => x.ChangeHistoryId); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFChangeHistory"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "Fraction", + table: "EFClientKills"); + + migrationBuilder.DropColumn( + name: "IsKill", + table: "EFClientKills"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs new file mode 100644 index 00000000..c2f06539 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs @@ -0,0 +1,665 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180904154622_AddVisibilityPercentage")] + partial class AddVisibilityPercentage + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs b/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs new file mode 100644 index 00000000..01407acc --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddVisibilityPercentage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VisibilityPercentage", + table: "EFClientKills", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VisibilityPercentage", + table: "EFClientKills"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs new file mode 100644 index 00000000..7b996dc6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs @@ -0,0 +1,669 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180907020706_AddVision")] + partial class AddVision + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs b/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs new file mode 100644 index 00000000..80ac8fe6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddVision : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VisionAverage", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VisionAverage", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs new file mode 100644 index 00000000..fe43268f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs @@ -0,0 +1,669 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180908004053_AddWhenToRating")] + partial class AddWhenToRating + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs b/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs new file mode 100644 index 00000000..1af6caa4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddWhenToRating : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "When", + table: "EFRating", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "When", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs new file mode 100644 index 00000000..9b3b9e99 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs @@ -0,0 +1,677 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180910221749_AddRatingIndexes")] + partial class AddRatingIndexes + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs b/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs new file mode 100644 index 00000000..5f634a08 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddRatingIndexes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + 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"); + } + + protected override void Down(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"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs new file mode 100644 index 00000000..e9feb60e --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -0,0 +1,679 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180911184224_AddEFAliasNameIndex")] + partial class AddEFAliasNameIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired(); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs b/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs new file mode 100644 index 00000000..ab34699e --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEFAliasNameIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFAlias_Name", + table: "EFAlias", + column: "Name"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_Name", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs new file mode 100644 index 00000000..f6275417 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -0,0 +1,680 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180911190823_AddEFAliasNameMaxLength24")] + partial class AddEFAliasNameMaxLength24 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("OriginEntityId"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs b/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs new file mode 100644 index 00000000..6389196c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEFAliasNameMaxLength24 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + // hack: we can't alter the column on SQLite, but we need max length limit for the Index in MySQL etc + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AlterColumn( + name: "Name", + table: "EFAlias", + maxLength: 24, + nullable: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs new file mode 100644 index 00000000..ba6dcaf7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -0,0 +1,684 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] + partial class AddPreviousCurrentValueToEFChangeHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("TimeSent"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs new file mode 100644 index 00000000..195bbda0 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddPreviousCurrentValueToEFChangeHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CurrentValue", + table: "EFChangeHistory", + nullable: true); + + migrationBuilder.AddColumn( + + name: "PreviousValue", + table: "EFChangeHistory", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CurrentValue", + table: "EFChangeHistory"); + + migrationBuilder.DropColumn( + name: "PreviousValue", + table: "EFChangeHistory"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs new file mode 100644 index 00000000..3ec9944c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -0,0 +1,686 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180915163111_AddIndexToMessageTimeSent")] + partial class AddIndexToMessageTimeSent + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.2-rtm-30932"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationVector3Id"); + + b.Property("HitLocation"); + + b.Property("HitOriginVector3Id"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleVector3Id"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("When"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationVector3Id"); + + b.HasIndex("HitOriginVector3Id"); + + b.HasIndex("LastStrainAngleVector3Id"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginVector3Id"); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleVector3Id"); + }); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs b/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs new file mode 100644 index 00000000..9e82c11d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddIndexToMessageTimeSent : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFClientMessages_TimeSent", + table: "EFClientMessages", + column: "TimeSent"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFClientMessages_TimeSent", + table: "EFClientMessages"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs new file mode 100644 index 00000000..1c7aac12 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs @@ -0,0 +1,587 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180922231310_RemoveACSnapShot")] + partial class RemoveACSnapShot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs b/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs new file mode 100644 index 00000000..60d4622a --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs @@ -0,0 +1,139 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class RemoveACSnapShot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + Deaths = table.Column(nullable: false), + Distance = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + HitDestinationVector3Id = table.Column(nullable: true), + HitLocation = table.Column(nullable: false), + HitOriginVector3Id = table.Column(nullable: true), + HitType = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + LastStrainAngleVector3Id = table.Column(nullable: true), + SessionAngleOffset = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + WeaponId = table.Column(nullable: false), + When = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationVector3Id", + column: x => x.HitDestinationVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginVector3Id", + column: x => x.HitOriginVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleVector3Id", + column: x => x.LastStrainAngleVector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationVector3Id", + table: "EFACSnapshot", + column: "HitDestinationVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginVector3Id", + table: "EFACSnapshot", + column: "HitOriginVector3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleVector3Id", + table: "EFACSnapshot", + column: "LastStrainAngleVector3Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs new file mode 100644 index 00000000..3c43b4bf --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs @@ -0,0 +1,689 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20180922231600_ReaddACSnapshot")] + partial class ReaddACSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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"); + + 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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs new file mode 100644 index 00000000..849f683d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs @@ -0,0 +1,145 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class ReaddACSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + migrationBuilder.CreateTable( + name: "EFACSnapshot", + columns: table => new + { + Active = table.Column(nullable: false), + SnapshotId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ClientId = table.Column(nullable: false), + When = table.Column(nullable: false), + CurrentSessionLength = table.Column(nullable: false), + TimeSinceLastEvent = table.Column(nullable: false), + EloRating = table.Column(nullable: false), + SessionScore = table.Column(nullable: false), + SessionSPM = table.Column(nullable: false), + Hits = table.Column(nullable: false), + Kills = table.Column(nullable: false), + Deaths = table.Column(nullable: false), + CurrentStrain = table.Column(nullable: false), + StrainAngleBetween = table.Column(nullable: false), + SessionAngleOffset = table.Column(nullable: false), + LastStrainAngleId = table.Column(nullable: false), + HitOriginId = table.Column(nullable: false), + HitDestinationId = table.Column(nullable: false), + Distance = table.Column(nullable: false), + CurrentViewAngleId = table.Column(nullable: true), + WeaponId = table.Column(nullable: false), + HitLocation = table.Column(nullable: false), + HitType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshot", x => x.SnapshotId); + table.ForeignKey( + name: "FK_EFACSnapshot_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_CurrentViewAngleId", + column: x => x.CurrentViewAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitDestinationId", + column: x => x.HitDestinationId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_HitOriginId", + column: x => x.HitOriginId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshot_Vector3_LastStrainAngleId", + column: x => x.LastStrainAngleId, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + }); + + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + } + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_ClientId", + table: "EFACSnapshot", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_CurrentViewAngleId", + table: "EFACSnapshot", + column: "CurrentViewAngleId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitDestinationId", + table: "EFACSnapshot", + column: "HitDestinationId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_HitOriginId", + table: "EFACSnapshot", + column: "HitOriginId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshot_LastStrainAngleId", + table: "EFACSnapshot", + column: "LastStrainAngleId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropTable( + name: "EFACSnapshot"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs new file mode 100644 index 00000000..62deb8a6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -0,0 +1,690 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20181014171848_MakePenaltyExpirationNullable")] + partial class MakePenaltyExpirationNullable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs b/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs new file mode 100644 index 00000000..7a1815e5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs @@ -0,0 +1,105 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class MakePenaltyExpirationNullable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + +DROP TABLE EFPenalties; + +CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT +); + +INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1; "); + } + else + { + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: true, + oldClrType: typeof(DateTime)); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Expires", + table: "EFPenalties", + nullable: false, + oldClrType: typeof(DateTime), + oldNullable: true); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs new file mode 100644 index 00000000..9ec28f7f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs @@ -0,0 +1,690 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20181125193243_MakeClientIPNullable")] + partial class MakeClientIPNullable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs b/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs new file mode 100644 index 00000000..0d201fe5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs @@ -0,0 +1,85 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class MakeClientIPNullable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFAlias; + +DROP TABLE EFAlias; + +CREATE TABLE EFAlias ( + AliasId INTEGER NOT NULL + CONSTRAINT PK_EFAlias PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + DateAdded TEXT NOT NULL, + IPAddress INTEGER, + LinkId INTEGER NOT NULL, + Name TEXT NOT NULL, + CONSTRAINT FK_EFAlias_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE RESTRICT +); + +INSERT INTO EFAlias ( + AliasId, + Active, + DateAdded, + IPAddress, + LinkId, + Name + ) + SELECT AliasId, + Active, + DateAdded, + IPAddress, + LinkId, + Name + FROM sqlitestudio_temp_table; + +DROP TABLE sqlitestudio_temp_table; + +CREATE INDEX IX_EFAlias_LinkId ON EFAlias ( + ""LinkId"" +); + + CREATE INDEX IX_EFAlias_IPAddress ON EFAlias( + ""IPAddress"" + ); + + CREATE INDEX IX_EFAlias_Name ON EFAlias( + ""Name"" + ); + + PRAGMA foreign_keys = 1; + ", suppressTransaction:true); + } + else + { + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: true, + oldClrType: typeof(int)); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IPAddress", + table: "EFAlias", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs new file mode 100644 index 00000000..8042335f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -0,0 +1,692 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] + partial class AddEndpointToEFServerUpdateServerIdType + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs new file mode 100644 index 00000000..284d5fa3 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEndpointToEFServerUpdateServerIdType : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EndPoint", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EndPoint", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs new file mode 100644 index 00000000..389817fd --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -0,0 +1,694 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20181216214513_AddEvadePenaltyFlag")] + partial class AddEvadePenaltyFlag + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs b/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs new file mode 100644 index 00000000..0d49cc07 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs @@ -0,0 +1,183 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddEvadePenaltyFlag : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + + DROP TABLE EFPenalties; + + CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + IsEvadedOffense BOOLEAN NOT NULL + DEFAULT (0), + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT + ); + + INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1;", suppressTransaction: false); + } + + else + { + migrationBuilder.AddColumn( + name: "IsEvadedOffense", + table: "EFPenalties", + nullable: false, + defaultValue: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFPenalties; + + DROP TABLE EFPenalties; + + CREATE TABLE EFPenalties ( + PenaltyId INTEGER NOT NULL + CONSTRAINT PK_EFPenalties PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + Expires TEXT, + LinkId INTEGER NOT NULL, + OffenderId INTEGER NOT NULL, + Offense TEXT NOT NULL, + PunisherId INTEGER NOT NULL, + Type INTEGER NOT NULL, + [When] TEXT NOT NULL, + AutomatedOffense TEXT, + CONSTRAINT FK_EFPenalties_EFAliasLinks_LinkId FOREIGN KEY ( + LinkId + ) + REFERENCES EFAliasLinks (AliasLinkId) ON DELETE CASCADE, + CONSTRAINT FK_EFPenalties_EFClients_OffenderId FOREIGN KEY ( + OffenderId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT, + CONSTRAINT FK_EFPenalties_EFClients_PunisherId FOREIGN KEY ( + PunisherId + ) + REFERENCES EFClients (ClientId) ON DELETE RESTRICT + ); + + INSERT INTO EFPenalties ( + PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + [When], + AutomatedOffense + ) + SELECT PenaltyId, + Active, + Expires, + LinkId, + OffenderId, + Offense, + PunisherId, + Type, + ""When"", + AutomatedOffense + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFPenalties_LinkId ON EFPenalties( + ""LinkId"" + ); + + CREATE INDEX IX_EFPenalties_OffenderId ON EFPenalties( + ""OffenderId"" + ); + + CREATE INDEX IX_EFPenalties_PunisherId ON EFPenalties( + ""PunisherId"" + ); + + PRAGMA foreign_keys = 1;", suppressTransaction: false); + } + + else + { + migrationBuilder.DropColumn( + name: "IsEvadedOffense", + table: "EFPenalties"); + } + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs new file mode 100644 index 00000000..6f1aa63e --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -0,0 +1,696 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] + partial class AddIndexToEFMetaKeyAndClientId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired(); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs new file mode 100644 index 00000000..10b7fbd9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddIndexToEFMetaKeyAndClientId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql("CREATE FULLTEXT INDEX IX_EFMeta_Key ON EFMeta ( `Key` );"); + } + + else + { + migrationBuilder.CreateIndex( + name: "IX_EFMeta_Key", + table: "EFMeta", + column: "Key"); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFMeta_Key", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs new file mode 100644 index 00000000..2522be0f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs @@ -0,0 +1,699 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190423142128_AddGameNameToEFServer")] + partial class AddGameNameToEFServer + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs b/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs new file mode 100644 index 00000000..ded914a9 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddGameNameToEFServer : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GameName", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "GameName", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs new file mode 100644 index 00000000..04bcc51c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -0,0 +1,701 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190615145212_AddAvgRecoilOffset")] + partial class AddAvgRecoilOffset + { + 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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs b/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs new file mode 100644 index 00000000..ccd978c6 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddAvgRecoilOffset : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs new file mode 100644 index 00000000..51fa8efd --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -0,0 +1,703 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190615214055_AddRecoilOffsetToSnapshot")] + partial class AddRecoilOffsetToSnapshot + { + 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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("When"); + + b.HasKey("RatingId"); + + b.HasIndex("Performance"); + + b.HasIndex("Ranking"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("When"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs new file mode 100644 index 00000000..5256281c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddRecoilOffsetToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RecoilOffset", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RecoilOffset", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs new file mode 100644 index 00000000..1a953f48 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs @@ -0,0 +1,699 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [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("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("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("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs b/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs new file mode 100644 index 00000000..74d61590 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + 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"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs new file mode 100644 index 00000000..576968f2 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -0,0 +1,704 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190802174908_AddSearchNameToEFAlias")] + partial class AddSearchNameToEFAlias + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs b/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs new file mode 100644 index 00000000..c9dc245b --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddSearchNameToEFAlias : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SearchableName", + table: "EFAlias", + maxLength: 24, + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_SearchableName", + table: "EFAlias", + column: "SearchableName"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFAlias_SearchableName", + table: "EFAlias"); + + migrationBuilder.DropColumn( + name: "SearchableName", + table: "EFAlias"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs new file mode 100644 index 00000000..da616783 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -0,0 +1,706 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190831210503_AvgSnapValueToClientStatistics")] + partial class AvgSnapValueToClientStatistics + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs b/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs new file mode 100644 index 00000000..944173d5 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AvgSnapValueToClientStatistics : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AverageSnapValue", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AverageSnapValue", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs new file mode 100644 index 00000000..a199c814 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -0,0 +1,708 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190901180209_AddSnapHitCountToClientStatistics")] + partial class AddSnapHitCountToClientStatistics + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("EFACSnapshotSnapshotId"); + + b.Property("X"); + + b.Property("Y"); + + b.Property("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 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs b/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs new file mode 100644 index 00000000..96c9161d --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddSnapHitCountToClientStatistics : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SnapHitCount", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SnapHitCount", + table: "EFClientStatistics"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs new file mode 100644 index 00000000..4c012301 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -0,0 +1,728 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] + partial class UseJunctionTableForSnapshotVector3 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs b/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs new file mode 100644 index 00000000..b4a816b8 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -0,0 +1,89 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class UseJunctionTableForSnapshotVector3 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.DropForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3"); + + migrationBuilder.DropColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3"); + } + + migrationBuilder.CreateTable( + name: "EFACSnapshotVector3", + columns: table => new + { + ACSnapshotVector3Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + SnapshotId = table.Column(nullable: false), + Vector3Id = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFACSnapshotVector3", x => x.ACSnapshotVector3Id); + table.ForeignKey( + name: "FK_EFACSnapshotVector3_EFACSnapshot_SnapshotId", + column: x => x.SnapshotId, + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFACSnapshotVector3_Vector3_Vector3Id", + column: x => x.Vector3Id, + principalTable: "Vector3", + principalColumn: "Vector3Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshotVector3_SnapshotId", + table: "EFACSnapshotVector3", + column: "SnapshotId"); + + migrationBuilder.CreateIndex( + name: "IX_EFACSnapshotVector3_Vector3Id", + table: "EFACSnapshotVector3", + column: "Vector3Id"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFACSnapshotVector3"); + + migrationBuilder.AddColumn( + name: "EFACSnapshotSnapshotId", + table: "Vector3", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Vector3_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId"); + + migrationBuilder.AddForeignKey( + name: "FK_Vector3_EFACSnapshot_EFACSnapshotSnapshotId", + table: "Vector3", + column: "EFACSnapshotSnapshotId", + principalTable: "EFACSnapshot", + principalColumn: "SnapshotId", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs new file mode 100644 index 00000000..54a1a989 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -0,0 +1,730 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] + partial class AddCurrentSnapValueToSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("SessionAverageSnapValue"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs new file mode 100644 index 00000000..3dc2405b --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddCurrentSnapValueToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SessionAverageSnapValue", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs new file mode 100644 index 00000000..9ddf2969 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -0,0 +1,732 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] + partial class AddSessionSnapHitsToSnapshot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("CurrentSessionLength"); + + b.Property("SessionAverageSnapValue"); + + b.Property("CurrentStrain"); + + b.Property("CurrentViewAngleId"); + + b.Property("Deaths"); + + b.Property("Distance"); + + b.Property("EloRating"); + + b.Property("HitDestinationId"); + + b.Property("HitLocation"); + + b.Property("HitOriginId"); + + b.Property("HitType"); + + b.Property("Hits"); + + b.Property("Kills"); + + b.Property("LastStrainAngleId"); + + b.Property("RecoilOffset"); + + b.Property("SessionAngleOffset"); + + b.Property("SessionSPM"); + + b.Property("SessionScore"); + + b.Property("SessionSnapHits"); + + b.Property("StrainAngleBetween"); + + b.Property("TimeSinceLastEvent"); + + b.Property("WeaponId"); + + b.Property("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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd(); + + b.Property("SnapshotId"); + + b.Property("Vector3Id"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AttackerId"); + + b.Property("Damage"); + + b.Property("DeathOriginVector3Id"); + + b.Property("DeathType"); + + b.Property("Fraction"); + + b.Property("HitLoc"); + + b.Property("IsKill"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + b.Property("VisibilityPercentage"); + + b.Property("Weapon"); + + b.Property("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("MessageId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("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("RatingHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId"); + + b.Property("ServerId"); + + b.Property("Active"); + + b.Property("AverageRecoilOffset"); + + b.Property("AverageSnapValue"); + + b.Property("Deaths"); + + b.Property("EloRating"); + + b.Property("Kills"); + + b.Property("MaxStrain"); + + b.Property("RollingWeightedKDR"); + + b.Property("SPM"); + + b.Property("Skill"); + + b.Property("SnapHitCount"); + + b.Property("TimePlayed"); + + b.Property("VisionAverage"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId") + .HasColumnName("EFClientStatistics_ClientId"); + + b.Property("HitCount"); + + b.Property("HitOffsetAverage"); + + b.Property("Location"); + + b.Property("MaxAngleDistance"); + + b.Property("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("RatingId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ActivityAmount"); + + b.Property("Newest"); + + b.Property("Performance"); + + b.Property("Ranking"); + + b.Property("RatingHistoryId"); + + b.Property("ServerId"); + + b.Property("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("ServerId"); + + b.Property("Active"); + + b.Property("EndPoint"); + + b.Property("GameName"); + + b.Property("Port"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ServerId"); + + b.Property("TotalKills"); + + b.Property("TotalPlayTime"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("DateAdded"); + + b.Property("IPAddress"); + + b.Property("LinkId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24); + + b.Property("SearchableName") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("Comment") + .HasMaxLength(128); + + b.Property("CurrentValue"); + + b.Property("OriginEntityId"); + + b.Property("PreviousValue"); + + b.Property("TargetEntityId"); + + b.Property("TimeChanged"); + + b.Property("TypeOfChange"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AliasLinkId"); + + b.Property("Connections"); + + b.Property("CurrentAliasId"); + + b.Property("FirstConnection"); + + b.Property("LastConnection"); + + b.Property("Level"); + + b.Property("Masked"); + + b.Property("NetworkId"); + + b.Property("Password"); + + b.Property("PasswordSalt"); + + b.Property("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("MetaId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("ClientId"); + + b.Property("Created"); + + b.Property("Extra"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32); + + b.Property("Updated"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + b.Property("IsEvadedOffense"); + + b.Property("LinkId"); + + b.Property("OffenderId"); + + b.Property("Offense") + .IsRequired(); + + b.Property("PunisherId"); + + b.Property("Type"); + + b.Property("When"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd(); + + b.Property("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + 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.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs new file mode 100644 index 00000000..4f233b2f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddSessionSnapHitsToSnapshot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SessionSnapHits", + table: "EFACSnapshot", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SessionSnapHits", + table: "EFACSnapshot"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs new file mode 100644 index 00000000..200be1d0 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -0,0 +1,910 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20191004172550_RenameClientHitLocationCountColumns")] + partial class RenameClientHitLocationCountColumns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs b/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs new file mode 100644 index 00000000..92c6fe9b --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs @@ -0,0 +1,151 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class RenameClientHitLocationCountColumns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + +CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFHitLocationCounts; + +DROP TABLE EFHitLocationCounts; + +CREATE TABLE EFHitLocationCounts ( + HitLocationCountId INTEGER NOT NULL + CONSTRAINT PK_EFHitLocationCounts PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + EFClientStatisticsClientId INTEGER NOT NULL, + HitCount INTEGER NOT NULL, + HitOffsetAverage REAL NOT NULL, + Location INTEGER NOT NULL, + EFClientStatisticsServerId INTEGER NOT NULL, + MaxAngleDistance REAL NOT NULL + DEFAULT 0, + CONSTRAINT FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId FOREIGN KEY ( + EFClientStatisticsClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE, + CONSTRAINT FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId FOREIGN KEY ( + EFClientStatisticsServerId + ) + REFERENCES EFServers (ServerId) ON DELETE CASCADE, + CONSTRAINT FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId FOREIGN KEY ( + EFClientStatisticsClientId, + EFClientStatisticsServerId + ) + REFERENCES EFClientStatistics (ClientId, + ServerId) ON DELETE CASCADE +); + +INSERT INTO EFHitLocationCounts ( + HitLocationCountId, + Active, + EFClientStatisticsClientId, + HitCount, + HitOffsetAverage, + Location, + EFClientStatisticsServerId, + MaxAngleDistance + ) + SELECT HitLocationCountId, + Active, + EFClientStatistics_ClientId, + HitCount, + HitOffsetAverage, + Location, + EFClientStatistics_ServerId, + MaxAngleDistance + FROM sqlitestudio_temp_table; + +DROP TABLE sqlitestudio_temp_table; + +CREATE INDEX IX_EFHitLocationCounts_EFClientStatistics_ServerId ON EFHitLocationCounts ( + EFClientStatisticsServerId +); + +CREATE INDEX IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId ON EFHitLocationCounts ( + EFClientStatisticsClientId, + EFClientStatisticsServerId +); + +PRAGMA foreign_keys = 1; +", true); + } + + else if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql("ALTER TABLE `EFHitLocationCounts` CHANGE `EFClientStatistics_ClientId` `EFClientStatisticsClientId` INT(11) NOT NULL;"); + migrationBuilder.Sql("ALTER TABLE `EFHitLocationCounts` CHANGE `EFClientStatistics_ServerId` `EFClientStatisticsServerId` INT(11) NOT NULL;"); + migrationBuilder.Sql("CREATE INDEX `IX_EFClientStatisticsClientId_EFClientStatisticsServerId` ON `EFHitLocationCounts` (`EFClientStatisticsClientId`, `EFClientStatisticsServerId`);"); + } + + else + { + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatistics_ClientId", + table: "EFHitLocationCounts"); + + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatistics_ServerId", + table: "EFHitLocationCounts"); + + migrationBuilder.DropForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts"); + + migrationBuilder.RenameColumn( + name: "EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "EFClientStatisticsServerId"); + + migrationBuilder.RenameColumn( + name: "EFClientStatistics_ClientId", + table: "EFHitLocationCounts", + newName: "EFClientStatisticsClientId"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ClientId_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsClientId_EFClientStatisticsServerId"); + + migrationBuilder.RenameIndex( + name: "IX_EFHitLocationCounts_EFClientStatistics_ServerId", + table: "EFHitLocationCounts", + newName: "IX_EFHitLocationCounts_EFClientStatisticsServerId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClients_EFClientStatisticsClientId", + table: "EFHitLocationCounts", + column: "EFClientStatisticsClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFServers_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + column: "EFClientStatisticsServerId", + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_EFHitLocationCounts_EFClientStatistics_EFClientStatisticsClientId_EFClientStatisticsServerId", + table: "EFHitLocationCounts", + columns: new[] { "EFClientStatisticsClientId", "EFClientStatisticsServerId" }, + principalTable: "EFClientStatistics", + principalColumns: new[] { "ClientId", "ServerId" }, + onDelete: ReferentialAction.Cascade); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs new file mode 100644 index 00000000..7000be7a --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -0,0 +1,909 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] + partial class EnforceUniqueIndexForEFAliasIPName + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.0.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs new file mode 100644 index 00000000..5e713f81 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -0,0 +1,188 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class EnforceUniqueIndexForEFAliasIPName : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite") + { + migrationBuilder.Sql(@"DROP TABLE IF EXISTS DUPLICATE_ALIASES; + CREATE TABLE DUPLICATE_ALIASES AS +SELECT + MIN(AliasId) MIN, + MAX(AliasId) MAX, + LinkId +FROM + EFAlias +WHERE + (IPAddress, NAME) IN( + SELECT DISTINCT + IPAddress, + NAME + FROM + EFAlias + GROUP BY + EFAlias.IPAddress, + NAME + HAVING + COUNT(IPAddress) > 1 AND COUNT(NAME) > 1 +) +GROUP BY + IPAddress +ORDER BY + IPAddress; + + UPDATE + EFClients +SET CurrentAliasId = (SELECT MAX FROM DUPLICATE_ALIASES WHERE CurrentAliasId = MIN) +WHERE + CurrentAliasId IN( + SELECT + MIN + FROM + DUPLICATE_ALIASES +); + DELETE + FROM + EFAlias +WHERE + AliasId IN( + SELECT + MIN + FROM + DUPLICATE_ALIASES +); + + DROP TABLE + DUPLICATE_ALIASES;"); + return; + } + + else if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + migrationBuilder.Sql(@"CREATE TABLE DUPLICATE_ALIASES +SELECT + MIN(`AliasId`) `MIN`, + MAX(`AliasId`) `MAX`, + `LinkId` +FROM + `EFAlias` +WHERE + (`IPAddress`, `NAME`) IN( + SELECT DISTINCT + `IPAddress`, + `NAME` + FROM + `EFAlias` + GROUP BY + `EFAlias`.`IPAddress`, + `NAME` + HAVING + COUNT(`IPAddress`) > 1 AND COUNT(`NAME`) > 1 +) +GROUP BY + `IPAddress` +ORDER BY + `IPAddress`; +SET + SQL_SAFE_UPDATES = 0; +UPDATE + `EFClients` AS `Client` +JOIN + DUPLICATE_ALIASES `Duplicate` +ON + `Client`.CurrentAliasId = `Duplicate`.`MIN` +SET + `Client`.CurrentAliasId = `Duplicate`.`MAX` +WHERE + `Client`.`CurrentAliasId` IN( + SELECT + `MIN` + FROM + DUPLICATE_ALIASES +); +DELETE +FROM + `EFAlias` +WHERE + `AliasId` IN( + SELECT + `MIN` + FROM + DUPLICATE_ALIASES +); +SET + SQL_SAFE_UPDATES = 1; +DROP TABLE + DUPLICATE_ALIASES;"); + } + + else + { + migrationBuilder.Sql(@"CREATE TEMPORARY TABLE DUPLICATE_ALIASES AS +SELECT + MIN(""AliasId"") ""MIN"", + MAX(""AliasId"") ""MAX"", + MIN(""LinkId"") ""LinkId"" +FROM + ""EFAlias"" +WHERE + (""IPAddress"", ""Name"") IN( + SELECT DISTINCT + ""IPAddress"", + ""Name"" + FROM + ""EFAlias"" + GROUP BY + ""EFAlias"".""IPAddress"", + ""Name"" + HAVING + COUNT(""IPAddress"") > 1 AND COUNT(""Name"") > 1 +) +GROUP BY + ""IPAddress"" +ORDER BY + ""IPAddress""; +UPDATE + ""EFClients"" AS ""Client"" +SET + ""CurrentAliasId"" = ""Duplicate"".""MAX"" +FROM + DUPLICATE_ALIASES ""Duplicate"" +WHERE + ""Client"".""CurrentAliasId"" IN( + SELECT + ""MIN"" + FROM + DUPLICATE_ALIASES +) +AND + ""Client"".""CurrentAliasId"" = ""Duplicate"".""MIN""; +DELETE +FROM + ""EFAlias"" +WHERE + ""AliasId"" IN( + SELECT + ""MIN"" + FROM + DUPLICATE_ALIASES +); +DROP TABLE + DUPLICATE_ALIASES;"); + } + + migrationBuilder.CreateIndex( + name: "IX_EFAlias_Name_IPAddress", + table: "EFAlias", + columns: new[] { "Name", "IPAddress" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs new file mode 100644 index 00000000..840ea878 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -0,0 +1,916 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] + partial class SetCaseSensitiveCoallationForAliasNameMySQL + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs new file mode 100644 index 00000000..38b6b619 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Pomelo.EntityFrameworkCore.MySql") + { + // this prevents duplicate aliases from being added by changing it to case sensitive collation + migrationBuilder.Sql(@"ALTER TABLE `EFAlias` MODIFY + `Name` VARCHAR(24) + CHARACTER SET utf8 + COLLATE utf8_bin;"); + }; + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs new file mode 100644 index 00000000..e412d2c7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs @@ -0,0 +1,916 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20191230140947_AddMissingActiveColumns")] + partial class AddMissingActiveColumns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.0"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs b/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs new file mode 100644 index 00000000..58ee70ea --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddMissingActiveColumns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Active", + table: "EFACSnapshotVector3", + nullable: false, + defaultValue: true); + + migrationBuilder.AddColumn( + name: "Active", + table: "Vector3", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs new file mode 100644 index 00000000..6a74f44c --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -0,0 +1,919 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] + partial class AddImpersonationIdToEFChangeHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs new file mode 100644 index 00000000..cadd981f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddImpersonationIdToEFChangeHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ImpersonationEntityId", + table: "EFChangeHistory"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs new file mode 100644 index 00000000..4bcbd7b7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs @@ -0,0 +1,922 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20200521203304_AddHostnameToEFServer")] + partial class AddHostnameToEFServer + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs b/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs new file mode 100644 index 00000000..79c48c9b --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddHostnameToEFServer : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "HostName", + table: "EFServers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "HostName", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs new file mode 100644 index 00000000..cb82b6fb --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -0,0 +1,925 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20200819224119_AddIsPasswordProtectedColumn")] + partial class AddIsPasswordProtectedColumn + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs b/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs new file mode 100644 index 00000000..506be9b7 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddIsPasswordProtectedColumn : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.ActiveProvider == "Npgsql.EntityFrameworkCore.PostgreSQL") + { + migrationBuilder.AddColumn( + name: "IsPasswordProtected", + type: "bool", + table: "EFServers", + nullable: false, + defaultValue: false); + } + else + { + migrationBuilder.AddColumn( + name: "IsPasswordProtected", + table: "EFServers", + nullable: false, + defaultValue: false); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsPasswordProtected", + table: "EFServers"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs new file mode 100644 index 00000000..1a50b70f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -0,0 +1,927 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20201114232340_UpdateEFRatingIndex")] + partial class UpdateEFRatingIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs b/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs new file mode 100644 index 00000000..2f476b00 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class UpdateEFRatingIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating", + columns: new[] { "When", "ServerId", "Performance", "ActivityAmount" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFRating_When_ServerId_Performance_ActivityAmount", + table: "EFRating"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs new file mode 100644 index 00000000..c43c421f --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -0,0 +1,930 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20201118023106_AddSentIngameFlagToClientMessage")] + partial class AddSentIngameFlagToClientMessage + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs b/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs new file mode 100644 index 00000000..48300e72 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class AddSentIngameFlagToClientMessage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SentIngame", + table: "EFClientMessages", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SentIngame", + table: "EFClientMessages"); + } + } +} diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs similarity index 99% rename from SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs rename to SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index e4371a05..e8455691 100644 --- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -3,12 +3,12 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations +namespace SharedLibraryCore.Migrations.Sqlite { - [DbContext(typeof(DatabaseContext))] - partial class DatabaseContextModelSnapshot : ModelSnapshot + [DbContext(typeof(SqliteDatabaseContext))] + partial class SqliteDatabaseContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { diff --git a/SharedLibraryCore/Services/AliasService.cs b/SharedLibraryCore/Services/AliasService.cs deleted file mode 100644 index 511882c4..00000000 --- a/SharedLibraryCore/Services/AliasService.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Linq.Expressions; - -using SharedLibraryCore.Interfaces; -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Database; -using Microsoft.EntityFrameworkCore; - -namespace SharedLibraryCore.Services -{ - public class AliasService : IEntityService - { - public async Task Create(EFAlias entity) - { - throw await Task.FromResult(new Exception()); - } - - public async Task Delete(EFAlias entity) - { - using (var context = new DatabaseContext()) - { - var alias = context.Aliases - .Single(e => e.AliasId == entity.AliasId); - alias.Active = false; - await context.SaveChangesAsync(); - return entity; - } - } - - public async Task> Find(Func expression) - { - // todo: max better? - return await Task.Run(() => - { - using (var context = new DatabaseContext(true)) - return context.Aliases - .AsNoTracking() - .Include(a => a.Link.Children) - .Where(expression) - .ToList(); - }); - } - - public async Task Get(int entityID) - { - using (var context = new DatabaseContext(true)) - return await context.Aliases - .FirstOrDefaultAsync(e => e.AliasId == entityID); - } - - public Task GetUnique(long entityProperty) - { - throw new NotImplementedException(); - } - - public async Task Update(EFAlias entity) - { - throw await Task.FromResult(new Exception()); - } - } -} diff --git a/SharedLibraryCore/Services/ChangeHistoryService.cs b/SharedLibraryCore/Services/ChangeHistoryService.cs index ad49608b..24e00f8f 100644 --- a/SharedLibraryCore/Services/ChangeHistoryService.cs +++ b/SharedLibraryCore/Services/ChangeHistoryService.cs @@ -10,21 +10,18 @@ using ILogger = Microsoft.Extensions.Logging.ILogger; namespace SharedLibraryCore.Services { - public class ChangeHistoryService : IEntityService + public class ChangeHistoryService { private readonly ILogger _logger; + private readonly IDatabaseContextFactory _contextFactory; - public ChangeHistoryService(ILogger logger) + public ChangeHistoryService(ILogger logger, IDatabaseContextFactory contextFactory) { _logger = logger; - } - - public Task Create(EFChangeHistory entity) - { - throw new NotImplementedException(); + _contextFactory = contextFactory; } - public async Task Add(GameEvent e, DatabaseContext ctx = null) + public async Task Add(GameEvent e) { EFChangeHistory change = null; @@ -74,58 +71,24 @@ namespace SharedLibraryCore.Services break; } - if (change != null) + if (change == null) { - bool existingCtx = ctx != null; - ctx = ctx ?? new DatabaseContext(true); - - ctx.EFChangeHistory.Add(change); - - try - { - await ctx.SaveChangesAsync(); - } - - catch (Exception ex) - { - _logger.LogError(ex, "Could not persist change @{change}", change); - } - - finally - { - if (!existingCtx) - { - ctx.Dispose(); - } - } + return; } - return change; - } + await using var context = _contextFactory.CreateContext(false); - public Task Delete(EFChangeHistory entity) - { - throw new NotImplementedException(); - } + context.EFChangeHistory.Add(change); - public Task> Find(Func expression) - { - throw new NotImplementedException(); - } + try + { + await context.SaveChangesAsync(); + } - public Task Get(int entityID) - { - throw new NotImplementedException(); - } - - public Task GetUnique(long entityProperty) - { - throw new NotImplementedException(); - } - - public Task Update(EFChangeHistory entity) - { - throw new NotImplementedException(); + catch (Exception ex) + { + _logger.LogError(ex, "Could not persist change @{change}", change); + } } } } diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index 61deb4fe..2397e890 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -7,6 +7,7 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Serilog.Context; @@ -28,7 +29,7 @@ namespace SharedLibraryCore.Services public async Task Create(EFClient entity) { - using (var context = new DatabaseContext()) + await using var context = _contextFactory.CreateContext(true); using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { int? linkId = null; @@ -67,7 +68,7 @@ namespace SharedLibraryCore.Services }; _logger.LogDebug("[create] adding {entity} to context", entity.ToString()); - context.Clients.Add(client); + // they're just using a new GUID if (aliasId.HasValue) @@ -106,12 +107,11 @@ namespace SharedLibraryCore.Services Link = link }; - link.Children.Add(alias); - client.AliasLink = link; client.CurrentAlias = alias; } + context.Clients.Add(client); await context.SaveChangesAsync(); return client; @@ -266,40 +266,38 @@ namespace SharedLibraryCore.Services /// public virtual async Task UpdateLevel(Permission newPermission, EFClient temporalClient, EFClient origin) { - using (var ctx = new DatabaseContext()) + await using var ctx = _contextFactory.CreateContext(true); + var entity = await ctx.Clients + .Where(_client => _client.ClientId == temporalClient.ClientId) + .FirstAsync(); + + var oldPermission = entity.Level; + + entity.Level = newPermission; + await ctx.SaveChangesAsync(); + + using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { - var entity = await ctx.Clients - .Where(_client => _client.ClientId == temporalClient.ClientId) - .FirstAsync(); + _logger.LogInformation("Updated {clientId} to {newPermission}", temporalClient.ClientId, newPermission); - var oldPermission = entity.Level; - - entity.Level = newPermission; - await ctx.SaveChangesAsync(); - - using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) + var linkedPermissionSet = new[] {Permission.Banned, Permission.Flagged}; + // if their permission level has been changed to level that needs to be updated on all accounts + if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission)) { - _logger.LogInformation("Updated {clientId} to {newPermission}", temporalClient.ClientId, newPermission); + //get all clients that have the same linkId + var iqMatchingClients = ctx.Clients + .Where(_client => _client.AliasLinkId == entity.AliasLinkId); - var linkedPermissionSet = new[] {Permission.Banned, Permission.Flagged}; - // if their permission level has been changed to level that needs to be updated on all accounts - if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission)) + // this updates the level for all the clients with the same LinkId + // only if their new level is flagged or banned + await iqMatchingClients.ForEachAsync(_client => { - //get all clients that have the same linkId - var iqMatchingClients = ctx.Clients - .Where(_client => _client.AliasLinkId == entity.AliasLinkId); + _client.Level = newPermission; + _logger.LogInformation("Updated linked {clientId} to {newPermission}", _client.ClientId, + newPermission); + }); - // this updates the level for all the clients with the same LinkId - // only if their new level is flagged or banned - await iqMatchingClients.ForEachAsync(_client => - { - _client.Level = newPermission; - _logger.LogInformation("Updated linked {clientId} to {newPermission}", _client.ClientId, - newPermission); - }); - - await ctx.SaveChangesAsync(); - } + await ctx.SaveChangesAsync(); } } @@ -308,15 +306,7 @@ namespace SharedLibraryCore.Services public async Task Delete(EFClient entity) { - using (var context = new DatabaseContext()) - { - var client = context.Clients - .Single(e => e.ClientId == entity.ClientId); - entity.Active = false; - context.Entry(entity).State = EntityState.Modified; - await context.SaveChangesAsync(); - return entity; - } + throw new NotImplementedException(); } public Task> Find(Func e) @@ -327,72 +317,71 @@ namespace SharedLibraryCore.Services public async Task Get(int entityId) { // todo: this needs to be optimized for large linked accounts - using (var context = new DatabaseContext(true)) + await using var context = _contextFactory.CreateContext(false); + + var client = context.Clients + .Select(_client => new EFClient() + { + ClientId = _client.ClientId, + AliasLinkId = _client.AliasLinkId, + Level = _client.Level, + Connections = _client.Connections, + FirstConnection = _client.FirstConnection, + LastConnection = _client.LastConnection, + Masked = _client.Masked, + NetworkId = _client.NetworkId, + CurrentAlias = new EFAlias() + { + Name = _client.CurrentAlias.Name, + IPAddress = _client.CurrentAlias.IPAddress + }, + TotalConnectionTime = _client.TotalConnectionTime + }) + .FirstOrDefault(_client => _client.ClientId == entityId); + + if (client == null) { - var client = context.Clients - .Select(_client => new EFClient() - { - ClientId = _client.ClientId, - AliasLinkId = _client.AliasLinkId, - Level = _client.Level, - Connections = _client.Connections, - FirstConnection = _client.FirstConnection, - LastConnection = _client.LastConnection, - Masked = _client.Masked, - NetworkId = _client.NetworkId, - CurrentAlias = new EFAlias() - { - Name = _client.CurrentAlias.Name, - IPAddress = _client.CurrentAlias.IPAddress - }, - TotalConnectionTime = _client.TotalConnectionTime - }) - .FirstOrDefault(_client => _client.ClientId == entityId); - - if (client == null) - { - return null; - } - - client.AliasLink = new EFAliasLink() - { - AliasLinkId = client.AliasLinkId, - Children = await context.Aliases - .Where(_alias => _alias.LinkId == client.AliasLinkId) - .Select(_alias => new EFAlias() - { - Name = _alias.Name, - IPAddress = _alias.IPAddress - }).ToListAsync() - }; - - var foundClient = new - { - Client = client, - LinkedAccounts = await context.Clients.Where(_client => _client.AliasLinkId == client.AliasLinkId) - .Select(_linkedClient => new - { - _linkedClient.ClientId, - _linkedClient.NetworkId - }) - .ToListAsync() - }; - - if (foundClient == null) - { - return null; - } - - foundClient.Client.LinkedAccounts = new Dictionary(); - // todo: find out the best way to do this - // I'm doing this here because I don't know the best way to have multiple awaits in the query - foreach (var linked in foundClient.LinkedAccounts) - { - foundClient.Client.LinkedAccounts.Add(linked.ClientId, linked.NetworkId); - } - - return foundClient.Client; + return null; } + + client.AliasLink = new EFAliasLink() + { + AliasLinkId = client.AliasLinkId, + Children = await context.Aliases + .Where(_alias => _alias.LinkId == client.AliasLinkId) + .Select(_alias => new EFAlias() + { + Name = _alias.Name, + IPAddress = _alias.IPAddress + }).ToListAsync() + }; + + var foundClient = new + { + Client = client, + LinkedAccounts = await context.Clients.Where(_client => _client.AliasLinkId == client.AliasLinkId) + .Select(_linkedClient => new + { + _linkedClient.ClientId, + _linkedClient.NetworkId + }) + .ToListAsync() + }; + + if (foundClient == null) + { + return null; + } + + foundClient.Client.LinkedAccounts = new Dictionary(); + // todo: find out the best way to do this + // I'm doing this here because I don't know the best way to have multiple awaits in the query + foreach (var linked in foundClient.LinkedAccounts) + { + foundClient.Client.LinkedAccounts.Add(linked.ClientId, linked.NetworkId); + } + + return foundClient.Client; } private static readonly Func> _getUniqueQuery = @@ -418,30 +407,27 @@ namespace SharedLibraryCore.Services public virtual async Task GetUnique(long entityAttribute) { - using (var context = new DatabaseContext(true)) - { - return await _getUniqueQuery(context, entityAttribute); - } + await using var context = _contextFactory.CreateContext(false); + return await _getUniqueQuery(context, entityAttribute); } public async Task UpdateAlias(EFClient temporalClient) { - using (var context = new DatabaseContext()) - { - var entity = context.Clients - .Include(c => c.AliasLink) - .Include(c => c.CurrentAlias) - .First(e => e.ClientId == temporalClient.ClientId); + await using var context = _contextFactory.CreateContext(); - entity.CurrentServer = temporalClient.CurrentServer; + var entity = context.Clients + .Include(c => c.AliasLink) + .Include(c => c.CurrentAlias) + .First(e => e.ClientId == temporalClient.ClientId); - await UpdateAlias(temporalClient.Name, temporalClient.IPAddress, entity, context); + entity.CurrentServer = temporalClient.CurrentServer; - temporalClient.CurrentAlias = entity.CurrentAlias; - temporalClient.CurrentAliasId = entity.CurrentAliasId; - temporalClient.AliasLink = entity.AliasLink; - temporalClient.AliasLinkId = entity.AliasLinkId; - } + await UpdateAlias(temporalClient.Name, temporalClient.IPAddress, entity, context); + + temporalClient.CurrentAlias = entity.CurrentAlias; + temporalClient.CurrentAliasId = entity.CurrentAliasId; + temporalClient.AliasLink = entity.AliasLink; + temporalClient.AliasLinkId = entity.AliasLinkId; } public async Task Update(EFClient temporalClient) @@ -453,54 +439,57 @@ namespace SharedLibraryCore.Services return null; } - using (var context = new DatabaseContext()) + await using var context = _contextFactory.CreateContext(); + + // grab the context version of the entity + var entity = context.Clients + .First(client => client.ClientId == temporalClient.ClientId); + + if (temporalClient.LastConnection > entity.LastConnection) { - // grab the context version of the entity - var entity = context.Clients - .First(client => client.ClientId == temporalClient.ClientId); - - if (temporalClient.LastConnection > entity.LastConnection) - { - entity.LastConnection = temporalClient.LastConnection; - } - - if (temporalClient.Connections > entity.Connections) - { - entity.Connections = temporalClient.Connections; - } - - entity.Masked = temporalClient.Masked; - - if (temporalClient.TotalConnectionTime > entity.TotalConnectionTime) - { - entity.TotalConnectionTime = temporalClient.TotalConnectionTime; - } - - if (temporalClient.Password != null) - { - entity.Password = temporalClient.Password; - } - - if (temporalClient.PasswordSalt != null) - { - entity.PasswordSalt = temporalClient.PasswordSalt; - } - - // update in database - await context.SaveChangesAsync(); - return entity; + entity.LastConnection = temporalClient.LastConnection; } + + if (temporalClient.Connections > entity.Connections) + { + entity.Connections = temporalClient.Connections; + } + + entity.Masked = temporalClient.Masked; + + if (temporalClient.TotalConnectionTime > entity.TotalConnectionTime) + { + entity.TotalConnectionTime = temporalClient.TotalConnectionTime; + } + + if (temporalClient.Password != null) + { + entity.Password = temporalClient.Password; + } + + if (temporalClient.PasswordSalt != null) + { + entity.PasswordSalt = temporalClient.PasswordSalt; + } + + // update in database + await context.SaveChangesAsync(); + return entity; } #region ServiceSpecific public async Task> GetOwners() { - using (var context = new DatabaseContext()) - { - return await context.Clients - .Where(c => c.Level == Permission.Owner) - .ToListAsync(); - } + await using var context = _contextFactory.CreateContext(false); + return await context.Clients + .Where(c => c.Level == Permission.Owner) + .ToListAsync(); + } + + public async Task HasOwnerAsync(CancellationToken token) + { + await using var context = _contextFactory.CreateContext(false); + return await context.Clients.AnyAsync(client => client.Level == Permission.Owner, token); } /// @@ -510,55 +499,50 @@ namespace SharedLibraryCore.Services /// public virtual async Task GetOwnerCount() { - using (var ctx = new DatabaseContext(true)) - { - return await ctx.Clients - .CountAsync(_client => _client.Level == Permission.Owner); - } + await using var context = _contextFactory.CreateContext(false); + return await context.Clients + .CountAsync(_client => _client.Level == Permission.Owner); } public async Task GetClientForLogin(int clientId) { - using (var ctx = new DatabaseContext(true)) - { - return await ctx.Clients - .Select(_client => new EFClient() + await using var context = _contextFactory.CreateContext(false); + return await context.Clients + .Select(_client => new EFClient() + { + NetworkId = _client.NetworkId, + ClientId = _client.ClientId, + CurrentAlias = new EFAlias() { - NetworkId = _client.NetworkId, - ClientId = _client.ClientId, - CurrentAlias = new EFAlias() - { - Name = _client.CurrentAlias.Name - }, - Password = _client.Password, - PasswordSalt = _client.PasswordSalt, - Level = _client.Level - }) - .FirstAsync(_client => _client.ClientId == clientId); - } + Name = _client.CurrentAlias.Name + }, + Password = _client.Password, + PasswordSalt = _client.PasswordSalt, + Level = _client.Level + }) + .FirstAsync(_client => _client.ClientId == clientId); } public async Task> GetPrivilegedClients(bool includeName = true) { - using (var context = new DatabaseContext(disableTracking: true)) - { - var iqClients = from client in context.Clients.AsNoTracking() - where client.Level >= Permission.Trusted - where client.Active - select new EFClient() - { - AliasLinkId = client.AliasLinkId, - CurrentAlias = client.CurrentAlias, - ClientId = client.ClientId, - Level = client.Level, - Password = client.Password, - PasswordSalt = client.PasswordSalt, - NetworkId = client.NetworkId, - LastConnection = client.LastConnection - }; + await using var context = _contextFactory.CreateContext(false); - return await iqClients.ToListAsync(); - } + var iqClients = from client in context.Clients.AsNoTracking() + where client.Level >= Permission.Trusted + where client.Active + select new EFClient() + { + AliasLinkId = client.AliasLinkId, + CurrentAlias = client.CurrentAlias, + ClientId = client.ClientId, + Level = client.Level, + Password = client.Password, + PasswordSalt = client.PasswordSalt, + NetworkId = client.NetworkId, + LastConnection = client.LastConnection + }; + + return await iqClients.ToListAsync(); } public async Task> FindClientsByIdentifier(string identifier) @@ -568,71 +552,67 @@ namespace SharedLibraryCore.Services return new List(); } - using (var context = new DatabaseContext(disableTracking: true)) + await using var context = _contextFactory.CreateContext(false); + long? networkId = null; + try { - long? networkId = null; - try - { - networkId = identifier.ConvertGuidToLong(System.Globalization.NumberStyles.HexNumber); - } - catch { } - - int? ipAddress = identifier.ConvertToIP(); - - IQueryable iqLinkIds = context.Aliases.Where(_alias => _alias.Active); - - // we want to query for the IP ADdress - if (ipAddress != null) - { - iqLinkIds = iqLinkIds.Where(_alias => _alias.IPAddress == ipAddress); - } - - // want to find them by name (wildcard) - else - { - iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like((_alias.SearchableName ?? _alias.Name.ToLower()), $"%{identifier.ToLower()}%")); - } - - var linkIds = await iqLinkIds - .Select(_alias => _alias.LinkId) - .ToListAsync(); - - // get all the clients that match the alias link or the network id - var iqClients = context.Clients - .Where(_client => _client.Active); - - - iqClients = iqClients.Where(_client => networkId == _client.NetworkId || linkIds.Contains(_client.AliasLinkId)); - - // we want to project our results - var iqClientProjection = iqClients.OrderByDescending(_client => _client.LastConnection) - .Select(_client => new PlayerInfo() - { - Name = _client.CurrentAlias.Name, - LevelInt = (int)_client.Level, - LastConnection = _client.LastConnection, - ClientId = _client.ClientId, - }); - - var clients = await iqClientProjection.ToListAsync(); - - // this is so we don't try to evaluate this in the linq to entities query - foreach (var client in clients) - { - client.Level = ((Permission)client.LevelInt).ToLocalizedLevelName(); - } - - return clients; + networkId = identifier.ConvertGuidToLong(System.Globalization.NumberStyles.HexNumber); } + catch { } + + int? ipAddress = identifier.ConvertToIP(); + + IQueryable iqLinkIds = context.Aliases.Where(_alias => _alias.Active); + + // we want to query for the IP ADdress + if (ipAddress != null) + { + iqLinkIds = iqLinkIds.Where(_alias => _alias.IPAddress == ipAddress); + } + + // want to find them by name (wildcard) + else + { + iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like((_alias.SearchableName ?? _alias.Name.ToLower()), $"%{identifier.ToLower()}%")); + } + + var linkIds = await iqLinkIds + .Select(_alias => _alias.LinkId) + .ToListAsync(); + + // get all the clients that match the alias link or the network id + var iqClients = context.Clients + .Where(_client => _client.Active); + + + iqClients = iqClients.Where(_client => networkId == _client.NetworkId || linkIds.Contains(_client.AliasLinkId)); + + // we want to project our results + var iqClientProjection = iqClients.OrderByDescending(_client => _client.LastConnection) + .Select(_client => new PlayerInfo() + { + Name = _client.CurrentAlias.Name, + LevelInt = (int)_client.Level, + LastConnection = _client.LastConnection, + ClientId = _client.ClientId, + }); + + var clients = await iqClientProjection.ToListAsync(); + + // this is so we don't try to evaluate this in the linq to entities query + foreach (var client in clients) + { + client.Level = ((Permission)client.LevelInt).ToLocalizedLevelName(); + } + + return clients; } public async Task GetTotalClientsAsync() { - using (var context = new DatabaseContext(true)) - { - return await context.Clients - .CountAsync(); - } + await using var context = _contextFactory.CreateContext(false); + return await context.Clients + .CountAsync(); } /// @@ -641,13 +621,11 @@ namespace SharedLibraryCore.Services /// public async Task GetRecentClientCount() { - using (var context = new DatabaseContext(true)) - { - var startOfPeriod = DateTime.UtcNow.AddHours(-24); - var iqQuery = context.Clients.Where(_client => _client.LastConnection >= startOfPeriod); + await using var context = _contextFactory.CreateContext(false); + var startOfPeriod = DateTime.UtcNow.AddHours(-24); + var iqQuery = context.Clients.Where(_client => _client.LastConnection >= startOfPeriod); - return await iqQuery.CountAsync(); - } + return await iqQuery.CountAsync(); } /// @@ -658,22 +636,20 @@ namespace SharedLibraryCore.Services { var startOfPeriod = DateTime.UtcNow.AddHours(-24); - using (var context = new DatabaseContext(true)) - { - var iqClients = context.Clients - .Where(_client => _client.CurrentAlias.IPAddress != null) - .Where(_client => _client.FirstConnection >= startOfPeriod) - .OrderByDescending(_client => _client.FirstConnection) - .Select(_client => new PlayerInfo() - { - ClientId = _client.ClientId, - Name = _client.CurrentAlias.Name, - IPAddress = _client.CurrentAlias.IPAddress.ConvertIPtoString(), - LastConnection = _client.FirstConnection - }); + await using var context = _contextFactory.CreateContext(false); + var iqClients = context.Clients + .Where(_client => _client.CurrentAlias.IPAddress != null) + .Where(_client => _client.FirstConnection >= startOfPeriod) + .OrderByDescending(_client => _client.FirstConnection) + .Select(_client => new PlayerInfo() + { + ClientId = _client.ClientId, + Name = _client.CurrentAlias.Name, + IPAddress = _client.CurrentAlias.IPAddress.ConvertIPtoString(), + LastConnection = _client.FirstConnection + }); - return await iqClients.ToListAsync(); - } + return await iqClients.ToListAsync(); } #endregion @@ -684,14 +660,12 @@ namespace SharedLibraryCore.Services /// public async Task GetClientReportCount(int clientId) { - using (var ctx = new DatabaseContext(true)) - { - return await ctx.Penalties - .Where(_penalty => _penalty.Active) - .Where(_penalty => _penalty.OffenderId == clientId) - .Where(_penalty => _penalty.Type == EFPenalty.PenaltyType.Report) - .CountAsync(); - } + await using var context = _contextFactory.CreateContext(false); + return await context.Penalties + .Where(_penalty => _penalty.Active) + .Where(_penalty => _penalty.OffenderId == clientId) + .Where(_penalty => _penalty.Type == EFPenalty.PenaltyType.Report) + .CountAsync(); } /// @@ -701,17 +675,16 @@ namespace SharedLibraryCore.Services /// public async Task IsAutoFlagged(int clientId) { - using (var ctx = new DatabaseContext(true)) - { - var now = DateTime.UtcNow; - return await ctx.Penalties - .Where(_penalty => _penalty.Active) - .Where(_penalty => _penalty.OffenderId == clientId) - .Where(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag) - .Where(_penalty => _penalty.PunisherId == 1) - .Where(_penalty => _penalty.Expires == null || _penalty.Expires > now) - .AnyAsync(); - } + await using var context = _contextFactory.CreateContext(false); + + var now = DateTime.UtcNow; + return await context.Penalties + .Where(_penalty => _penalty.Active) + .Where(_penalty => _penalty.OffenderId == clientId) + .Where(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag) + .Where(_penalty => _penalty.PunisherId == 1) + .Where(_penalty => _penalty.Expires == null || _penalty.Expires > now) + .AnyAsync(); } /// @@ -721,22 +694,20 @@ namespace SharedLibraryCore.Services /// public async Task UnlinkClient(int clientId) { - using (var ctx = new DatabaseContext()) - { - var newLink = new EFAliasLink() { Active = true }; - ctx.AliasLinks.Add(newLink); - await ctx.SaveChangesAsync(); + await using var ctx = _contextFactory.CreateContext(); + var newLink = new EFAliasLink() { Active = true }; + ctx.AliasLinks.Add(newLink); + await ctx.SaveChangesAsync(); - var client = await ctx.Clients.Include(_client => _client.CurrentAlias) - .FirstAsync(_client => _client.ClientId == clientId); - client.AliasLinkId = newLink.AliasLinkId; - client.Level = Permission.User; + var client = await ctx.Clients.Include(_client => _client.CurrentAlias) + .FirstAsync(_client => _client.ClientId == clientId); + client.AliasLinkId = newLink.AliasLinkId; + client.Level = Permission.User; - await ctx.Aliases.Where(_alias => _alias.IPAddress == client.IPAddress) - .ForEachAsync(_alias => _alias.LinkId = newLink.AliasLinkId); + await ctx.Aliases.Where(_alias => _alias.IPAddress == client.IPAddress) + .ForEachAsync(_alias => _alias.LinkId = newLink.AliasLinkId); - await ctx.SaveChangesAsync(); - } + await ctx.SaveChangesAsync(); } /// @@ -747,7 +718,7 @@ namespace SharedLibraryCore.Services public async Task> QueryResource(FindClientRequest query) { var result = new ResourceQueryHelperResult(); - using var context = _contextFactory.CreateContext(enableTracking: false); + await using var context = _contextFactory.CreateContext(enableTracking: false); IQueryable iqClients = null; diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index 1e23fbae..1270699e 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -7,32 +7,38 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using SharedLibraryCore.Interfaces; namespace SharedLibraryCore.Services { public class PenaltyService : Interfaces.IEntityService { + private readonly IDatabaseContextFactory _contextFactory; + + public PenaltyService(IDatabaseContextFactory contextFactory) + { + _contextFactory = contextFactory; + } + public virtual async Task Create(EFPenalty newEntity) { - using (var context = new DatabaseContext()) + await using var context = _contextFactory.CreateContext(); + var penalty = new EFPenalty() { - var penalty = new EFPenalty() - { - Active = true, - OffenderId = newEntity.Offender.ClientId, - PunisherId = newEntity.Punisher.ClientId, - LinkId = newEntity.Link.AliasLinkId, - Type = newEntity.Type, - Expires = newEntity.Expires, - Offense = newEntity.Offense, - When = DateTime.UtcNow, - AutomatedOffense = newEntity.AutomatedOffense ?? newEntity.Punisher.AdministeredPenalties?.FirstOrDefault()?.AutomatedOffense, - IsEvadedOffense = newEntity.IsEvadedOffense - }; + Active = true, + OffenderId = newEntity.Offender.ClientId, + PunisherId = newEntity.Punisher.ClientId, + LinkId = newEntity.Link.AliasLinkId, + Type = newEntity.Type, + Expires = newEntity.Expires, + Offense = newEntity.Offense, + When = DateTime.UtcNow, + AutomatedOffense = newEntity.AutomatedOffense ?? newEntity.Punisher.AdministeredPenalties?.FirstOrDefault()?.AutomatedOffense, + IsEvadedOffense = newEntity.IsEvadedOffense + }; - context.Penalties.Add(penalty); - await context.SaveChangesAsync(); - } + context.Penalties.Add(penalty); + await context.SaveChangesAsync(); return newEntity; } @@ -64,32 +70,30 @@ namespace SharedLibraryCore.Services public async Task> GetRecentPenalties(int count, int offset, EFPenalty.PenaltyType showOnly = EFPenalty.PenaltyType.Any, bool ignoreAutomated = true) { - using (var context = new DatabaseContext(true)) - { - var iqPenalties = context.Penalties - .Where(p => showOnly == EFPenalty.PenaltyType.Any ? p.Type != EFPenalty.PenaltyType.Any : p.Type == showOnly) - .Where(_penalty => ignoreAutomated ? _penalty.PunisherId != 1 : true) - .OrderByDescending(p => p.When) - .Skip(offset) - .Take(count) - .Select(_penalty => new PenaltyInfo() - { - Id = _penalty.PenaltyId, - Offense = _penalty.Offense, - AutomatedOffense = _penalty.AutomatedOffense, - OffenderId = _penalty.OffenderId, - OffenderName = _penalty.Offender.CurrentAlias.Name, - PunisherId = _penalty.PunisherId, - PunisherName = _penalty.Punisher.CurrentAlias.Name, - PunisherLevel = _penalty.Punisher.Level, - PenaltyType = _penalty.Type, - Expires = _penalty.Expires, - TimePunished = _penalty.When, - IsEvade = _penalty.IsEvadedOffense - }); + await using var context = _contextFactory.CreateContext(false); + var iqPenalties = context.Penalties + .Where(p => showOnly == EFPenalty.PenaltyType.Any ? p.Type != EFPenalty.PenaltyType.Any : p.Type == showOnly) + .Where(_penalty => ignoreAutomated ? _penalty.PunisherId != 1 : true) + .OrderByDescending(p => p.When) + .Skip(offset) + .Take(count) + .Select(_penalty => new PenaltyInfo() + { + Id = _penalty.PenaltyId, + Offense = _penalty.Offense, + AutomatedOffense = _penalty.AutomatedOffense, + OffenderId = _penalty.OffenderId, + OffenderName = _penalty.Offender.CurrentAlias.Name, + PunisherId = _penalty.PunisherId, + PunisherName = _penalty.Punisher.CurrentAlias.Name, + PunisherLevel = _penalty.Punisher.Level, + PenaltyType = _penalty.Type, + Expires = _penalty.Expires, + TimePunished = _penalty.When, + IsEvade = _penalty.IsEvadedOffense + }); - return await iqPenalties.ToListAsync(); - } + return await iqPenalties.ToListAsync(); } /// @@ -104,37 +108,35 @@ namespace SharedLibraryCore.Services { var linkedPenaltyType = Utilities.LinkedPenaltyTypes(); - using (var ctx = new DatabaseContext(true)) - { - var linkId = await ctx.Clients.AsNoTracking() - .Where(_penalty => _penalty.ClientId == clientId) - .Select(_penalty => _penalty.AliasLinkId) - .FirstOrDefaultAsync(); + await using var context = _contextFactory.CreateContext(false); + var linkId = await context.Clients.AsNoTracking() + .Where(_penalty => _penalty.ClientId == clientId) + .Select(_penalty => _penalty.AliasLinkId) + .FirstOrDefaultAsync(); - var iqPenalties = ctx.Penalties.AsNoTracking() - .Where(_penalty => _penalty.OffenderId == clientId || _penalty.PunisherId == clientId || (linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId)) - .Where(_penalty => _penalty.When <= startAt) - .OrderByDescending(_penalty => _penalty.When) - .Skip(offset) - .Take(count) - .Select(_penalty => new PenaltyInfo() - { - Id = _penalty.PenaltyId, - Offense = _penalty.Offense, - AutomatedOffense = _penalty.AutomatedOffense, - OffenderId = _penalty.OffenderId, - OffenderName = _penalty.Offender.CurrentAlias.Name, - PunisherId = _penalty.PunisherId, - PunisherName = _penalty.Punisher.CurrentAlias.Name, - PunisherLevel = _penalty.Punisher.Level, - PenaltyType = _penalty.Type, - Expires = _penalty.Expires, - TimePunished = _penalty.When, - IsEvade = _penalty.IsEvadedOffense - }); + var iqPenalties = context.Penalties.AsNoTracking() + .Where(_penalty => _penalty.OffenderId == clientId || _penalty.PunisherId == clientId || (linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId)) + .Where(_penalty => _penalty.When <= startAt) + .OrderByDescending(_penalty => _penalty.When) + .Skip(offset) + .Take(count) + .Select(_penalty => new PenaltyInfo() + { + Id = _penalty.PenaltyId, + Offense = _penalty.Offense, + AutomatedOffense = _penalty.AutomatedOffense, + OffenderId = _penalty.OffenderId, + OffenderName = _penalty.Offender.CurrentAlias.Name, + PunisherId = _penalty.PunisherId, + PunisherName = _penalty.Punisher.CurrentAlias.Name, + PunisherLevel = _penalty.Punisher.Level, + PenaltyType = _penalty.Type, + Expires = _penalty.Expires, + TimePunished = _penalty.When, + IsEvade = _penalty.IsEvadedOffense + }); - return await iqPenalties.Distinct().ToListAsync(); - } + return await iqPenalties.Distinct().ToListAsync(); } public async Task> GetActivePenaltiesAsync(int linkId, int? ip = null, bool includePunisherName = false) @@ -150,42 +152,39 @@ namespace SharedLibraryCore.Services p.Active && (p.Expires == null || p.Expires > now)); - using (var context = new DatabaseContext(true)) - { - var iqLinkPenalties = context.Penalties - .Where(p => p.LinkId == linkId) - .Where(filter); + await using var context = _contextFactory.CreateContext(false); + var iqLinkPenalties = context.Penalties + .Where(p => p.LinkId == linkId) + .Where(filter); - var iqIPPenalties = context.Aliases - .Where(a => a.IPAddress != null && a.IPAddress == ip) - .SelectMany(a => a.Link.ReceivedPenalties) - .Where(filter); + var iqIPPenalties = context.Aliases + .Where(a => a.IPAddress != null && a.IPAddress == ip) + .SelectMany(a => a.Link.ReceivedPenalties) + .Where(filter); - var activePenalties = (await iqLinkPenalties.ToListAsync()) - .Union(await iqIPPenalties.ToListAsync()) - .Distinct(); + var activePenalties = (await iqLinkPenalties.ToListAsync()) + .Union(await iqIPPenalties.ToListAsync()) + .Distinct(); - // this is a bit more performant in memory (ordering) - return activePenalties.OrderByDescending(p => p.When).ToList(); - } + // this is a bit more performant in memory (ordering) + return activePenalties.OrderByDescending(p => p.When).ToList(); } public virtual async Task RemoveActivePenalties(int aliasLinkId) { - using (var context = new DatabaseContext()) - { - var now = DateTime.UtcNow; - await context.Penalties - .Where(p => p.LinkId == aliasLinkId) - .Where(p => p.Expires > now || p.Expires == null) - .ForEachAsync(p => - { - p.Active = false; - p.Expires = now; - }); + await using var context = _contextFactory.CreateContext(); - await context.SaveChangesAsync(); - } + var now = DateTime.UtcNow; + await context.Penalties + .Where(p => p.LinkId == aliasLinkId) + .Where(p => p.Expires > now || p.Expires == null) + .ForEachAsync(p => + { + p.Active = false; + p.Expires = now; + }); + + await context.SaveChangesAsync(); } } } diff --git a/SharedLibraryCore/SharedLibraryCore - Backup.csproj b/SharedLibraryCore/SharedLibraryCore - Backup.csproj new file mode 100644 index 00000000..d70dcf2f --- /dev/null +++ b/SharedLibraryCore/SharedLibraryCore - Backup.csproj @@ -0,0 +1,66 @@ + + + + Library + netcoreapp3.1 + RaidMax.IW4MAdmin.SharedLibraryCore + 2020.11.18.1 + RaidMax + Forever None + Debug;Release;Prerelease + false + 8.0 + IW4MAdmin + https://github.com/RaidMax/IW4M-Admin/ + https://www.raidmax.org/IW4MAdmin/ + 2020 + true + true + true + MIT + Shared Library for IW4MAdmin + 2020.11.18.1 + + + + full + true + + + + + + + + + + + + + + all + runtime; build; native; contentfiles + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index d70dcf2f..4a54280f 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -26,7 +26,7 @@ full true - + diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index af3777b4..ac8a91a6 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -961,6 +961,8 @@ namespace SharedLibraryCore /// public static bool IsDevelopment => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; + public static bool IsMigration => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Migration"; + /// /// replaces any directory separator chars with the platform specific character diff --git a/Tests/ApplicationTests/Mocks/DatabaseContextFactoryMock.cs b/Tests/ApplicationTests/Mocks/DatabaseContextFactoryMock.cs index ee176b36..f453eec9 100644 --- a/Tests/ApplicationTests/Mocks/DatabaseContextFactoryMock.cs +++ b/Tests/ApplicationTests/Mocks/DatabaseContextFactoryMock.cs @@ -2,31 +2,19 @@ using SharedLibraryCore.Database; using SharedLibraryCore.Interfaces; using System; +using SharedLibraryCore.Database.MigrationContext; namespace ApplicationTests.Mocks { class DatabaseContextFactoryMock : IDatabaseContextFactory { - private DatabaseContext ctx; - private readonly IServiceProvider _serviceProvider; - - public DatabaseContextFactoryMock(IServiceProvider sp) - { - _serviceProvider = sp; - } - public DatabaseContext CreateContext(bool? enableTracking) { - if (ctx == null) - { - var contextOptions = new DbContextOptionsBuilder() - .UseInMemoryDatabase(databaseName: "database") - .Options; + var contextOptions = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: "database") + .Options; - ctx = new DatabaseContext(contextOptions); - } - - return ctx; + return new SqliteDatabaseContext(contextOptions); } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/PenaltyController.cs b/WebfrontCore/Controllers/PenaltyController.cs index 04173233..0b40b137 100644 --- a/WebfrontCore/Controllers/PenaltyController.cs +++ b/WebfrontCore/Controllers/PenaltyController.cs @@ -13,9 +13,11 @@ namespace WebfrontCore.Controllers { public class PenaltyController : BaseController { - public PenaltyController(IManager manager) : base(manager) + private readonly IDatabaseContextFactory _contextFactory; + + public PenaltyController(IManager manager, IDatabaseContextFactory contextFactory) : base(manager) { - + _contextFactory = contextFactory; } public IActionResult List(PenaltyType showOnly = PenaltyType.Any, bool hideAutomatedPenalties = true) @@ -47,30 +49,28 @@ namespace WebfrontCore.Controllers { IList penalties; - using (var ctx = new DatabaseContext(disableTracking: true)) - { - var iqPenalties = ctx.Penalties - .AsNoTracking() - .Where(p => p.Type == PenaltyType.Ban && p.Active) - .OrderByDescending(_penalty => _penalty.When) - .Select(p => new PenaltyInfo() - { - Id = p.PenaltyId, - OffenderId = p.OffenderId, - OffenderName = p.Offender.CurrentAlias.Name, - OffenderNetworkId = (ulong)p.Offender.NetworkId, - OffenderIPAddress = Authorized ? p.Offender.CurrentAlias.IPAddress.ConvertIPtoString() : null, - Offense = p.Offense, - PunisherId = p.PunisherId, - PunisherNetworkId = (ulong)p.Punisher.NetworkId, - PunisherName = p.Punisher.CurrentAlias.Name, - PunisherIPAddress = Authorized ? p.Punisher.CurrentAlias.IPAddress.ConvertIPtoString() : null, - TimePunished = p.When, - AutomatedOffense = Authorized ? p.AutomatedOffense : null, - }); + await using var ctx = _contextFactory.CreateContext(false); + var iqPenalties = ctx.Penalties + .AsNoTracking() + .Where(p => p.Type == PenaltyType.Ban && p.Active) + .OrderByDescending(_penalty => _penalty.When) + .Select(p => new PenaltyInfo() + { + Id = p.PenaltyId, + OffenderId = p.OffenderId, + OffenderName = p.Offender.CurrentAlias.Name, + OffenderNetworkId = (ulong)p.Offender.NetworkId, + OffenderIPAddress = Authorized ? p.Offender.CurrentAlias.IPAddress.ConvertIPtoString() : null, + Offense = p.Offense, + PunisherId = p.PunisherId, + PunisherNetworkId = (ulong)p.Punisher.NetworkId, + PunisherName = p.Punisher.CurrentAlias.Name, + PunisherIPAddress = Authorized ? p.Punisher.CurrentAlias.IPAddress.ConvertIPtoString() : null, + TimePunished = p.When, + AutomatedOffense = Authorized ? p.AutomatedOffense : null, + }); - penalties = await iqPenalties.ToListAsync(); - } + penalties = await iqPenalties.ToListAsync(); return Json(penalties); } diff --git a/WebfrontCore/Program.cs b/WebfrontCore/Program.cs index 18a9c256..65365366 100644 --- a/WebfrontCore/Program.cs +++ b/WebfrontCore/Program.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore.Interfaces; using WebfrontCore.Middleware; @@ -12,15 +13,12 @@ namespace WebfrontCore public class Program { public static IManager Manager; + public static IServiceCollection Services; public static IServiceProvider ApplicationServiceProvider; - static void Main() - { - throw new Exception("Webfront core cannot be run as a standalone application"); - } - - public static Task Init(IManager mgr, IServiceProvider existingServiceProvider, CancellationToken cancellationToken) + public static Task Init(IManager mgr, IServiceProvider existingServiceProvider, IServiceCollection services, CancellationToken cancellationToken) { + Services = services; Manager = mgr; ApplicationServiceProvider = existingServiceProvider; var config = Manager.GetApplicationSettings().Configuration(); diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index 9d640d81..f4986473 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -1,4 +1,5 @@ -using FluentValidation; +using System; +using FluentValidation; using FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; @@ -79,11 +80,11 @@ namespace WebfrontCore }); #if DEBUG - /*mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); + mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); services.Configure(_options => { _options.ViewLocationFormats.Add(@"/Views/Plugins/{1}/{0}" + RazorViewEngine.ViewExtension); - });*/ + }); #endif foreach (var asm in pluginAssemblies()) @@ -92,10 +93,7 @@ namespace WebfrontCore } services.AddHttpContextAccessor(); - - services.AddEntityFrameworkSqlite() - .AddDbContext(); - + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { @@ -120,7 +118,7 @@ namespace WebfrontCore } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IManager manager) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider) { app.UseStatusCodePages(_context => { @@ -144,7 +142,7 @@ namespace WebfrontCore if (Program.Manager.GetApplicationSettings().Configuration().EnableWebfrontConnectionWhitelist) { - app.UseMiddleware(Program.ApplicationServiceProvider.GetService>(), manager.GetApplicationSettings().Configuration().WebfrontConnectionWhitelist); + app.UseMiddleware(serviceProvider.GetService>(), serviceProvider.GetRequiredService().WebfrontConnectionWhitelist); } app.UseStaticFiles(); diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index fb51fa63..5cb08065 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -28,7 +28,7 @@ false true true - 7.1 + Latest From b2d282d4120bf76f0c16205906f50722623400d8 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Fri, 27 Nov 2020 22:08:13 -0600 Subject: [PATCH 017/143] include ; for timeout string --- Application/Extensions/StartupExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index 1994983c..6dd69cd7 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -74,14 +74,14 @@ namespace IW4MAdmin.Application.Extensions StringComparison.InvariantCultureIgnoreCase); services.AddDbContext(options => options.UseMySql( - appConfig.ConnectionString + (appendTimeout ? "default command timeout=0" : ""), + appConfig.ConnectionString + (appendTimeout ? ";default command timeout=0" : ""), mysqlOptions => mysqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); break; case "postgresql": appendTimeout = !appConfig.ConnectionString.Contains("Command Timeout", StringComparison.InvariantCultureIgnoreCase); services.AddDbContext(options => - options.UseNpgsql(appConfig.ConnectionString + (appendTimeout ? "Command Timeout=0" : ""), + options.UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); break; } From bd3f0caf60a16f4b908f0391fee3f09edee911a7 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 29 Nov 2020 16:01:52 -0600 Subject: [PATCH 018/143] fix memory leak issue related to AddDbContext not working as expected --- Application/Extensions/StartupExtensions.cs | 37 +- .../Factories/DatabaseContextFactory.cs | 32 +- Application/Main.cs | 2 +- .../AdministeredPenaltyResourceQueryHelper.cs | 2 +- .../ReceivedPenaltyResourceQueryHelper.cs | 2 +- .../Meta/UpdatedAliasResourceQueryHelper.cs | 2 +- Application/Misc/MetaService.cs | 4 +- Plugins/Stats/Commands/MostKillsCommand.cs | 55 +- Plugins/Stats/Helpers/StatManager.cs | 781 +++++++++--------- .../Stats/Helpers/StatsResourceQueryHelper.cs | 2 +- Plugins/Stats/Plugin.cs | 20 +- .../Web/StatsWeb/ChatResourceQueryHelper.cs | 2 +- SharedLibraryCore/Database/ContextSeed.cs | 2 +- .../MigrationContext/MySqlDatabaseContext.cs | 2 +- .../PostgresqlDatabaseContext.cs | 2 +- .../MigrationContext/SqliteDatabaseContext.cs | 2 +- SharedLibraryCore/PartialEntities/EFClient.cs | 3 +- .../AuditInformationRepository.cs | 52 +- 18 files changed, 499 insertions(+), 505 deletions(-) diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index 6dd69cd7..764414da 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -48,10 +48,12 @@ namespace IW4MAdmin.Application.Extensions return services; } - public static IServiceCollection AddDatabaseContext(this IServiceCollection services, + public static IServiceCollection AddDatabaseContextOptions(this IServiceCollection services, ApplicationConfiguration appConfig) { - if (string.IsNullOrEmpty(appConfig.ConnectionString) || appConfig.DatabaseProvider == "sqlite") + var activeProvider = appConfig.DatabaseProvider?.ToLower(); + + if (string.IsNullOrEmpty(appConfig.ConnectionString) || activeProvider == "sqlite") { var currentPath = Utilities.OperatingDirectory; currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) @@ -62,31 +64,34 @@ namespace IW4MAdmin.Application.Extensions {DataSource = Path.Join(currentPath, "Database", "Database.db")}; var connectionString = connectionStringBuilder.ToString(); - services.AddDbContext(options => - options.UseSqlite(connectionString), ServiceLifetime.Transient); + var builder = new DbContextOptionsBuilder() + .UseSqlite(connectionString); + + services.AddSingleton((DbContextOptions) builder.Options); return services; } - switch (appConfig.DatabaseProvider) + switch (activeProvider) { case "mysql": var appendTimeout = !appConfig.ConnectionString.Contains("default command timeout", StringComparison.InvariantCultureIgnoreCase); - services.AddDbContext(options => - options.UseMySql( - appConfig.ConnectionString + (appendTimeout ? ";default command timeout=0" : ""), - mysqlOptions => mysqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); - break; + var mysqlBuilder = new DbContextOptionsBuilder() + .UseMySql(appConfig.ConnectionString + (appendTimeout ? ";default command timeout=0" : ""), + mysqlOptions => mysqlOptions.EnableRetryOnFailure()); + services.AddSingleton((DbContextOptions) mysqlBuilder.Options); + return services; case "postgresql": appendTimeout = !appConfig.ConnectionString.Contains("Command Timeout", StringComparison.InvariantCultureIgnoreCase); - services.AddDbContext(options => - options.UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), - postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()), ServiceLifetime.Transient); - break; + var postgresqlBuilder = new DbContextOptionsBuilder() + .UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), + postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()); + services.AddSingleton((DbContextOptions) postgresqlBuilder.Options); + return services; + default: + throw new ArgumentException($"No context available for {appConfig.DatabaseProvider}"); } - - return services; } } } \ No newline at end of file diff --git a/Application/Factories/DatabaseContextFactory.cs b/Application/Factories/DatabaseContextFactory.cs index 871652a9..87b33f8f 100644 --- a/Application/Factories/DatabaseContextFactory.cs +++ b/Application/Factories/DatabaseContextFactory.cs @@ -1,7 +1,8 @@ using System; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.MigrationContext; using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Factories @@ -11,13 +12,15 @@ namespace IW4MAdmin.Application.Factories /// public class DatabaseContextFactory : IDatabaseContextFactory { - private readonly IServiceProvider _serviceProvider; - - public DatabaseContextFactory(IServiceProvider serviceProvider) + private readonly DbContextOptions _contextOptions; + private readonly string _activeProvider; + + public DatabaseContextFactory(ApplicationConfiguration appConfig, DbContextOptions contextOptions) { - _serviceProvider = serviceProvider; + _contextOptions = contextOptions; + _activeProvider = appConfig.DatabaseProvider?.ToLower(); } - + /// /// creates a new database context /// @@ -25,10 +28,10 @@ namespace IW4MAdmin.Application.Factories /// public DatabaseContext CreateContext(bool? enableTracking = true) { - var context = _serviceProvider.GetRequiredService(); + var context = BuildContext(); enableTracking ??= true; - + if (enableTracking.Value) { context.ChangeTracker.AutoDetectChangesEnabled = true; @@ -44,5 +47,16 @@ namespace IW4MAdmin.Application.Factories return context; } + + private DatabaseContext BuildContext() + { + return _activeProvider switch + { + "sqlite" => new SqliteDatabaseContext(_contextOptions), + "mysql" => new MySqlDatabaseContext(_contextOptions), + "postgresql" => new PostgresqlDatabaseContext(_contextOptions), + _ => throw new ArgumentException($"No context found for {_activeProvider}") + }; + } } -} +} \ No newline at end of file diff --git a/Application/Main.cs b/Application/Main.cs index e011618b..b192ae7c 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -361,7 +361,7 @@ namespace IW4MAdmin.Application .AddSingleton() .AddSingleton() .AddSingleton(translationLookup) - .AddDatabaseContext(appConfig); + .AddDatabaseContextOptions(appConfig); if (args.Contains("serialevents")) { diff --git a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs index 76d9fd76..616e19de 100644 --- a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs +++ b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs @@ -28,7 +28,7 @@ namespace IW4MAdmin.Application.Meta public async Task> QueryResource(ClientPaginationRequest query) { - using var ctx = _contextFactory.CreateContext(enableTracking: false); + await using var ctx = _contextFactory.CreateContext(enableTracking: false); var iqPenalties = ctx.Penalties.AsNoTracking() .Where(_penalty => query.ClientId == _penalty.PunisherId) diff --git a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs index de8b38bf..f63ad068 100644 --- a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs +++ b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs @@ -31,7 +31,7 @@ namespace IW4MAdmin.Application.Meta public async Task> QueryResource(ClientPaginationRequest query) { var linkedPenaltyType = Utilities.LinkedPenaltyTypes(); - using var ctx = _contextFactory.CreateContext(enableTracking: false); + await using var ctx = _contextFactory.CreateContext(enableTracking: false); var linkId = await ctx.Clients.AsNoTracking() .Where(_client => _client.ClientId == query.ClientId) diff --git a/Application/Meta/UpdatedAliasResourceQueryHelper.cs b/Application/Meta/UpdatedAliasResourceQueryHelper.cs index 0adca9f1..4765cbf0 100644 --- a/Application/Meta/UpdatedAliasResourceQueryHelper.cs +++ b/Application/Meta/UpdatedAliasResourceQueryHelper.cs @@ -28,7 +28,7 @@ namespace IW4MAdmin.Application.Meta public async Task> QueryResource(ClientPaginationRequest query) { - using var ctx = _contextFactory.CreateContext(enableTracking: false); + await using var ctx = _contextFactory.CreateContext(enableTracking: false); int linkId = ctx.Clients.First(_client => _client.ClientId == query.ClientId).AliasLinkId; var iqAliasUpdates = ctx.Aliases diff --git a/Application/Misc/MetaService.cs b/Application/Misc/MetaService.cs index 31a62152..fcf0cd48 100644 --- a/Application/Misc/MetaService.cs +++ b/Application/Misc/MetaService.cs @@ -37,7 +37,7 @@ namespace IW4MAdmin.Application.Misc return; } - using var ctx = _contextFactory.CreateContext(); + await using var ctx = _contextFactory.CreateContext(); var existingMeta = await ctx.EFMeta .Where(_meta => _meta.Key == metaKey) @@ -66,7 +66,7 @@ namespace IW4MAdmin.Application.Misc public async Task GetPersistentMeta(string metaKey, EFClient client) { - using var ctx = _contextFactory.CreateContext(enableTracking: false); + await using var ctx = _contextFactory.CreateContext(enableTracking: false); return await ctx.EFMeta .Where(_meta => _meta.Key == metaKey) diff --git a/Plugins/Stats/Commands/MostKillsCommand.cs b/Plugins/Stats/Commands/MostKillsCommand.cs index bb216562..71d081cc 100644 --- a/Plugins/Stats/Commands/MostKillsCommand.cs +++ b/Plugins/Stats/Commands/MostKillsCommand.cs @@ -2,7 +2,6 @@ using System; using System.Linq; using System.Threading.Tasks; - using SharedLibraryCore; using IW4MAdmin.Plugins.Stats.Models; using System.Collections.Generic; @@ -19,7 +18,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands private readonly IDatabaseContextFactory _contextFactory; private readonly CommandConfiguration _config; - public MostKillsCommand(CommandConfiguration config, ITranslationLookup translationLookup, IDatabaseContextFactory contextFactory) : base(config, translationLookup) + public MostKillsCommand(CommandConfiguration config, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory) : base(config, translationLookup) { Name = "mostkills"; Description = translationLookup["PLUGINS_STATS_COMMANDS_MOSTKILLS_DESC"]; @@ -32,7 +32,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands public override async Task ExecuteAsync(GameEvent E) { - var mostKills = await GetMostKills(StatManager.GetIdForServer(E.Owner), Plugin.Config.Configuration(), _contextFactory, _translationLookup); + var mostKills = await GetMostKills(StatManager.GetIdForServer(E.Owner), Plugin.Config.Configuration(), + _contextFactory, _translationLookup); if (!E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { foreach (var stat in mostKills) @@ -50,33 +51,33 @@ namespace IW4MAdmin.Plugins.Stats.Commands } } - public static async Task> GetMostKills(long? serverId, StatsConfiguration config, IDatabaseContextFactory contextFactory, ITranslationLookup translationLookup) + public static async Task> GetMostKills(long? serverId, StatsConfiguration config, + IDatabaseContextFactory contextFactory, ITranslationLookup translationLookup) { - using (var ctx = contextFactory.CreateContext(enableTracking: false)) - { - var dayInPast = DateTime.UtcNow.AddDays(-config.MostKillsMaxInactivityDays); + await using var ctx = contextFactory.CreateContext(enableTracking: false); + var dayInPast = DateTime.UtcNow.AddDays(-config.MostKillsMaxInactivityDays); - var iqStats = (from stats in ctx.Set() - join client in ctx.Clients - on stats.ClientId equals client.ClientId - join alias in ctx.Aliases - on client.CurrentAliasId equals alias.AliasId - where stats.ServerId == serverId - where client.Level != EFClient.Permission.Banned - where client.LastConnection >= dayInPast - orderby stats.Kills descending - select new - { - alias.Name, - stats.Kills - }) - .Take(config.MostKillsClientLimit); + var iqStats = (from stats in ctx.Set() + join client in ctx.Clients + on stats.ClientId equals client.ClientId + join alias in ctx.Aliases + on client.CurrentAliasId equals alias.AliasId + where stats.ServerId == serverId + where client.Level != EFClient.Permission.Banned + where client.LastConnection >= dayInPast + orderby stats.Kills descending + select new + { + alias.Name, + stats.Kills + }) + .Take(config.MostKillsClientLimit); - var iqList = await iqStats.ToListAsync(); + var iqList = await iqStats.ToListAsync(); - return iqList.Select((stats, index) => translationLookup["PLUGINS_STATS_COMMANDS_MOSTKILLS_FORMAT"].FormatExt(index + 1, stats.Name, stats.Kills)) - .Prepend(Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTKILLS_HEADER"]); - } + return iqList.Select((stats, index) => translationLookup["PLUGINS_STATS_COMMANDS_MOSTKILLS_FORMAT"] + .FormatExt(index + 1, stats.Name, stats.Kills)) + .Prepend(Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTKILLS_HEADER"]); } } -} +} \ No newline at end of file diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 678fa7de..52dd6de1 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -68,121 +68,118 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// public async Task GetClientOverallRanking(int clientId) { - using (var context = _contextFactory.CreateContext(enableTracking: false)) + await using var context = _contextFactory.CreateContext(enableTracking: false); + + var clientPerformance = await context.Set() + .Where(r => r.RatingHistory.ClientId == clientId) + .Where(r => r.ServerId == null) + .Where(r => r.Newest) + .Select(r => r.Performance) + .FirstOrDefaultAsync(); + + if (clientPerformance != 0) { - var clientPerformance = await context.Set() - .Where(r => r.RatingHistory.ClientId == clientId) - .Where(r => r.ServerId == null) - .Where(r => r.Newest) - .Select(r => r.Performance) - .FirstOrDefaultAsync(); + var iqClientRanking = context.Set() + .Where(r => r.RatingHistory.ClientId != clientId) + .Where(r => r.Performance > clientPerformance) + .Where(GetRankingFunc()); - if (clientPerformance != 0) - { - var iqClientRanking = context.Set() - .Where(r => r.RatingHistory.ClientId != clientId) - .Where(r => r.Performance > clientPerformance) - .Where(GetRankingFunc()); - - return await iqClientRanking.CountAsync() + 1; - } - - return 0; + return await iqClientRanking.CountAsync() + 1; } + + return 0; } public async Task> GetTopStats(int start, int count, long? serverId = null) { - using (var context = _contextFactory.CreateContext(enableTracking: false)) - { - // setup the query for the clients within the given rating range - var iqClientRatings = (from rating in context.Set() - .Where(GetRankingFunc(serverId)) - select new - { - rating.RatingHistory.ClientId, - rating.RatingHistory.Client.CurrentAlias.Name, - rating.RatingHistory.Client.LastConnection, - rating.Performance, - }) - .OrderByDescending(c => c.Performance) - .Skip(start) - .Take(count); - - // materialized list - var clientRatings = await iqClientRatings.ToListAsync(); - - // get all the unique client ids that are in the top stats - var clientIds = clientRatings - .GroupBy(r => r.ClientId) - .Select(r => r.First().ClientId) - .ToList(); - - var iqRatingInfo = from rating in context.Set() - where clientIds.Contains(rating.RatingHistory.ClientId) - where rating.ServerId == serverId + await using var context = _contextFactory.CreateContext(enableTracking: false); + // setup the query for the clients within the given rating range + var iqClientRatings = (from rating in context.Set() + .Where(GetRankingFunc(serverId)) select new { - rating.Ranking, - rating.Performance, rating.RatingHistory.ClientId, - rating.When - }; + rating.RatingHistory.Client.CurrentAlias.Name, + rating.RatingHistory.Client.LastConnection, + rating.Performance, + }) + .OrderByDescending(c => c.Performance) + .Skip(start) + .Take(count); - var ratingInfo = (await iqRatingInfo.ToListAsync()) - .GroupBy(r => r.ClientId) - .Select(grp => new - { - grp.Key, - Ratings = grp.Select(r => new { r.Performance, r.Ranking, r.When }) - }); + // materialized list + var clientRatings = await iqClientRatings.ToListAsync(); - var iqStatsInfo = (from stat in context.Set() - where clientIds.Contains(stat.ClientId) - where stat.Kills > 0 || stat.Deaths > 0 - where serverId == null ? true : stat.ServerId == serverId - group stat by stat.ClientId into s - select new - { - ClientId = s.Key, - Kills = s.Sum(c => c.Kills), - Deaths = s.Sum(c => c.Deaths), - KDR = s.Sum(c => (c.Kills / (double)(c.Deaths == 0 ? 1 : c.Deaths)) * c.TimePlayed) / s.Sum(c => c.TimePlayed), - TotalTimePlayed = s.Sum(c => c.TimePlayed), - }); - - var topPlayers = await iqStatsInfo.ToListAsync(); - - var clientRatingsDict = clientRatings.ToDictionary(r => r.ClientId); - var finished = topPlayers.Select(s => new TopStatsInfo() - { - ClientId = s.ClientId, - Id = (int?)serverId ?? 0, - Deaths = s.Deaths, - Kills = s.Kills, - KDR = Math.Round(s.KDR, 2), - LastSeen = (DateTime.UtcNow - clientRatingsDict[s.ClientId].LastConnection).HumanizeForCurrentCulture(), - Name = clientRatingsDict[s.ClientId].Name, - Performance = Math.Round(clientRatingsDict[s.ClientId].Performance, 2), - RatingChange = ratingInfo.First(r => r.Key == s.ClientId).Ratings.First().Ranking - ratingInfo.First(r => r.Key == s.ClientId).Ratings.Last().Ranking, - PerformanceHistory = ratingInfo.First(r => r.Key == s.ClientId).Ratings.Count() > 1 ? - ratingInfo.First(r => r.Key == s.ClientId).Ratings.OrderBy(r => r.When).Select(r => r.Performance).ToList() : - new List() { clientRatingsDict[s.ClientId].Performance, clientRatingsDict[s.ClientId].Performance }, - TimePlayed = Math.Round(s.TotalTimePlayed / 3600.0, 1).ToString("#,##0"), - }) - .OrderByDescending(r => r.Performance) + // get all the unique client ids that are in the top stats + var clientIds = clientRatings + .GroupBy(r => r.ClientId) + .Select(r => r.First().ClientId) .ToList(); - // set the ranking numerically - int i = start + 1; - foreach (var stat in finished) - { - stat.Ranking = i; - i++; - } + var iqRatingInfo = from rating in context.Set() + where clientIds.Contains(rating.RatingHistory.ClientId) + where rating.ServerId == serverId + select new + { + rating.Ranking, + rating.Performance, + rating.RatingHistory.ClientId, + rating.When + }; - return finished; + var ratingInfo = (await iqRatingInfo.ToListAsync()) + .GroupBy(r => r.ClientId) + .Select(grp => new + { + grp.Key, + Ratings = grp.Select(r => new { r.Performance, r.Ranking, r.When }) + }); + + var iqStatsInfo = (from stat in context.Set() + where clientIds.Contains(stat.ClientId) + where stat.Kills > 0 || stat.Deaths > 0 + where serverId == null ? true : stat.ServerId == serverId + group stat by stat.ClientId into s + select new + { + ClientId = s.Key, + Kills = s.Sum(c => c.Kills), + Deaths = s.Sum(c => c.Deaths), + KDR = s.Sum(c => (c.Kills / (double)(c.Deaths == 0 ? 1 : c.Deaths)) * c.TimePlayed) / s.Sum(c => c.TimePlayed), + TotalTimePlayed = s.Sum(c => c.TimePlayed), + }); + + var topPlayers = await iqStatsInfo.ToListAsync(); + + var clientRatingsDict = clientRatings.ToDictionary(r => r.ClientId); + var finished = topPlayers.Select(s => new TopStatsInfo() + { + ClientId = s.ClientId, + Id = (int?)serverId ?? 0, + Deaths = s.Deaths, + Kills = s.Kills, + KDR = Math.Round(s.KDR, 2), + LastSeen = (DateTime.UtcNow - clientRatingsDict[s.ClientId].LastConnection).HumanizeForCurrentCulture(), + Name = clientRatingsDict[s.ClientId].Name, + Performance = Math.Round(clientRatingsDict[s.ClientId].Performance, 2), + RatingChange = ratingInfo.First(r => r.Key == s.ClientId).Ratings.First().Ranking - ratingInfo.First(r => r.Key == s.ClientId).Ratings.Last().Ranking, + PerformanceHistory = ratingInfo.First(r => r.Key == s.ClientId).Ratings.Count() > 1 ? + ratingInfo.First(r => r.Key == s.ClientId).Ratings.OrderBy(r => r.When).Select(r => r.Performance).ToList() : + new List() { clientRatingsDict[s.ClientId].Performance, clientRatingsDict[s.ClientId].Performance }, + TimePlayed = Math.Round(s.TotalTimePlayed / 3600.0, 1).ToString("#,##0"), + }) + .OrderByDescending(r => r.Performance) + .ToList(); + + // set the ranking numerically + int i = start + 1; + foreach (var stat in finished) + { + stat.Ranking = i; + i++; } + + return finished; } /// @@ -202,63 +199,61 @@ namespace IW4MAdmin.Plugins.Stats.Helpers long serverId = GetIdForServer(sv); EFServer server; - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) + using var ctx = _contextFactory.CreateContext(enableTracking: false); + var serverSet = ctx.Set(); + // get the server from the database if it exists, otherwise create and insert a new one + server = serverSet.FirstOrDefault(s => s.ServerId == serverId); + + // the server might be using legacy server id + if (server == null) { - var serverSet = ctx.Set(); - // get the server from the database if it exists, otherwise create and insert a new one - server = serverSet.FirstOrDefault(s => s.ServerId == serverId); + server = serverSet.FirstOrDefault(s => s.EndPoint == sv.ToString()); - // the server might be using legacy server id - if (server == null) + if (server != null) { - server = serverSet.FirstOrDefault(s => s.EndPoint == sv.ToString()); - - if (server != null) - { - // this provides a way to identify legacy server entries - server.EndPoint = sv.ToString(); - ctx.Update(server); - ctx.SaveChanges(); - } - } - - // server has never been added before - if (server == null) - { - server = new EFServer() - { - Port = sv.Port, - EndPoint = sv.ToString(), - ServerId = serverId, - GameName = sv.GameName, - HostName = sv.Hostname - }; - - server = serverSet.Add(server).Entity; - // this doesn't need to be async as it's during initialization + // this provides a way to identify legacy server entries + server.EndPoint = sv.ToString(); + ctx.Update(server); ctx.SaveChanges(); } + } - // we want to set the gamename up if it's never been set, or it changed - else if (!server.GameName.HasValue || server.GameName.HasValue && server.GameName.Value != sv.GameName) + // server has never been added before + if (server == null) + { + server = new EFServer() { - server.GameName = sv.GameName; - ctx.Entry(server).Property(_prop => _prop.GameName).IsModified = true; - ctx.SaveChanges(); - } + Port = sv.Port, + EndPoint = sv.ToString(), + ServerId = serverId, + GameName = sv.GameName, + HostName = sv.Hostname + }; - if (server.HostName == null || server.HostName != sv.Hostname) - { - server.HostName = sv.Hostname; - ctx.Entry(server).Property(_prop => _prop.HostName).IsModified = true; - ctx.SaveChanges(); - } - - ctx.Entry(server).Property(_prop => _prop.IsPasswordProtected).IsModified = true; - server.IsPasswordProtected = !string.IsNullOrEmpty(sv.GamePassword); + server = serverSet.Add(server).Entity; + // this doesn't need to be async as it's during initialization ctx.SaveChanges(); } + // we want to set the gamename up if it's never been set, or it changed + else if (!server.GameName.HasValue || server.GameName.HasValue && server.GameName.Value != sv.GameName) + { + server.GameName = sv.GameName; + ctx.Entry(server).Property(_prop => _prop.GameName).IsModified = true; + ctx.SaveChanges(); + } + + if (server.HostName == null || server.HostName != sv.Hostname) + { + server.HostName = sv.Hostname; + ctx.Entry(server).Property(_prop => _prop.HostName).IsModified = true; + ctx.SaveChanges(); + } + + ctx.Entry(server).Property(_prop => _prop.IsPasswordProtected).IsModified = true; + server.IsPasswordProtected = !string.IsNullOrEmpty(sv.GamePassword); + ctx.SaveChanges(); + // check to see if the stats have ever been initialized var serverStats = InitializeServerStats(server.ServerId); @@ -304,79 +299,77 @@ namespace IW4MAdmin.Plugins.Stats.Helpers EFClientStatistics clientStats; - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) + await using var ctx = _contextFactory.CreateContext(enableTracking: false); + var clientStatsSet = ctx.Set(); + clientStats = clientStatsSet + .Include(cl => cl.HitLocations) + .FirstOrDefault(c => c.ClientId == pl.ClientId && c.ServerId == serverId); + + if (clientStats == null) { - var clientStatsSet = ctx.Set(); - clientStats = clientStatsSet - .Include(cl => cl.HitLocations) - .FirstOrDefault(c => c.ClientId == pl.ClientId && c.ServerId == serverId); - - if (clientStats == null) + clientStats = new EFClientStatistics() { - clientStats = new EFClientStatistics() - { - Active = true, - ClientId = pl.ClientId, - Deaths = 0, - Kills = 0, - ServerId = serverId, - Skill = 0.0, - SPM = 0.0, - EloRating = 200.0, - HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType() - .Select(hl => new EFHitLocationCount() - { - Active = true, - HitCount = 0, - Location = hl - }).ToList() - }; - - // insert if they've not been added - clientStats = clientStatsSet.Add(clientStats).Entity; - await ctx.SaveChangesAsync(); - } - - pl.SetAdditionalProperty(CLIENT_STATS_KEY, clientStats); - - // migration for previous existing stats - if (clientStats.HitLocations.Count == 0) - { - clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)) - .OfType() + Active = true, + ClientId = pl.ClientId, + Deaths = 0, + Kills = 0, + ServerId = serverId, + Skill = 0.0, + SPM = 0.0, + EloRating = 200.0, + HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)).OfType() .Select(hl => new EFHitLocationCount() { Active = true, HitCount = 0, Location = hl - }) - .ToList(); + }).ToList() + }; - ctx.Update(clientStats); - await ctx.SaveChangesAsync(); - } - - // for stats before rating - if (clientStats.EloRating == 0.0) - { - clientStats.EloRating = clientStats.Skill; - } - - if (clientStats.RollingWeightedKDR == 0) - { - clientStats.RollingWeightedKDR = clientStats.KDR; - } - - // set these on connecting - clientStats.LastActive = DateTime.UtcNow; - clientStats.LastStatCalculation = DateTime.UtcNow; - clientStats.SessionScore = pl.Score; - clientStats.LastScore = pl.Score; - - pl.SetAdditionalProperty(CLIENT_DETECTIONS_KEY, new Detection(_log, clientStats)); - _log.LogDebug("Added {client} to stats", pl.ToString()); + // insert if they've not been added + clientStats = clientStatsSet.Add(clientStats).Entity; + await ctx.SaveChangesAsync(); } + pl.SetAdditionalProperty(CLIENT_STATS_KEY, clientStats); + + // migration for previous existing stats + if (clientStats.HitLocations.Count == 0) + { + clientStats.HitLocations = Enum.GetValues(typeof(IW4Info.HitLocation)) + .OfType() + .Select(hl => new EFHitLocationCount() + { + Active = true, + HitCount = 0, + Location = hl + }) + .ToList(); + + ctx.Update(clientStats); + await ctx.SaveChangesAsync(); + } + + // for stats before rating + if (clientStats.EloRating == 0.0) + { + clientStats.EloRating = clientStats.Skill; + } + + if (clientStats.RollingWeightedKDR == 0) + { + clientStats.RollingWeightedKDR = clientStats.KDR; + } + + // set these on connecting + clientStats.LastActive = DateTime.UtcNow; + clientStats.LastStatCalculation = DateTime.UtcNow; + clientStats.SessionScore = pl.Score; + clientStats.LastScore = pl.Score; + + pl.SetAdditionalProperty(CLIENT_DETECTIONS_KEY, new Detection(_log, clientStats)); + _log.LogDebug("Added {client} to stats", pl.ToString()); + return clientStats; } @@ -434,11 +427,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers private async Task SaveClientStats(EFClientStatistics clientStats) { - using (var ctx = _contextFactory.CreateContext()) - { - ctx.Update(clientStats); - await ctx.SaveChangesAsync(); - } + await using var ctx = _contextFactory.CreateContext(); + ctx.Update(clientStats); + await ctx.SaveChangesAsync(); } public void AddDamageEvent(string eventLine, int attackerClientId, int victimClientId, long serverId) @@ -628,13 +619,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers public async Task SaveHitCache(long serverId) { - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) - { - var server = _servers[serverId]; - ctx.AddRange(server.HitCache.ToList()); - await ctx.SaveChangesAsync(); - server.HitCache.Clear(); - } + await using var ctx = _contextFactory.CreateContext(enableTracking: false); + var server = _servers[serverId]; + ctx.AddRange(server.HitCache.ToList()); + await ctx.SaveChangesAsync(); + server.HitCache.Clear(); } private bool ShouldUseDetection(Server server, DetectionType detectionType, long clientId) @@ -714,14 +703,12 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { EFACSnapshot change; - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) + await using var ctx = _contextFactory.CreateContext(); + while ((change = clientDetection.Tracker.GetNextChange()) != default(EFACSnapshot)) { - while ((change = clientDetection.Tracker.GetNextChange()) != default(EFACSnapshot)) - { - ctx.Add(change); - } - await ctx.SaveChangesAsync(); + ctx.Add(change); } + await ctx.SaveChangesAsync(); } public async Task AddStandardKill(EFClient attacker, EFClient victim) @@ -826,160 +813,158 @@ namespace IW4MAdmin.Plugins.Stats.Helpers int currentServerTotalPlaytime = clientStats.TimePlayed + currentSessionTime; - using (var ctx = _contextFactory.CreateContext(enableTracking: true)) + await using var ctx = _contextFactory.CreateContext(enableTracking: true); + // select the rating history for client + var iqHistoryLink = from history in ctx.Set() + .Include(h => h.Ratings) + where history.ClientId == client.ClientId + select history; + + // get the client ratings + var clientHistory = await iqHistoryLink + .FirstOrDefaultAsync() ?? new EFClientRatingHistory() + { + Active = true, + ClientId = client.ClientId, + Ratings = new List() + }; + + // it's the first time they've played + if (clientHistory.RatingHistoryId == 0) { - // select the rating history for client - var iqHistoryLink = from history in ctx.Set() - .Include(h => h.Ratings) - where history.ClientId == client.ClientId - select history; - - // get the client ratings - var clientHistory = await iqHistoryLink - .FirstOrDefaultAsync() ?? new EFClientRatingHistory() - { - Active = true, - ClientId = client.ClientId, - Ratings = new List() - }; - - // it's the first time they've played - if (clientHistory.RatingHistoryId == 0) - { - ctx.Add(clientHistory); - } - - #region INDIVIDUAL_SERVER_PERFORMANCE - // get the client ranking for the current server - int individualClientRanking = await ctx.Set() - .Where(GetRankingFunc(clientStats.ServerId)) - // ignore themselves in the query - .Where(c => c.RatingHistory.ClientId != client.ClientId) - .Where(c => c.Performance > clientStats.Performance) - .CountAsync() + 1; - - // limit max history per server to 40 - if (clientHistory.Ratings.Count(r => r.ServerId == clientStats.ServerId) >= 40) - { - // select the oldest one - var ratingToRemove = clientHistory.Ratings - .Where(r => r.ServerId == clientStats.ServerId) - .OrderBy(r => r.When) - .First(); - - ctx.Remove(ratingToRemove); - } - - // set the previous newest to false - var ratingToUnsetNewest = clientHistory.Ratings - .Where(r => r.ServerId == clientStats.ServerId) - .OrderByDescending(r => r.When) - .FirstOrDefault(); - - if (ratingToUnsetNewest != null) - { - if (ratingToUnsetNewest.Newest) - { - ctx.Update(ratingToUnsetNewest); - ctx.Entry(ratingToUnsetNewest).Property(r => r.Newest).IsModified = true; - ratingToUnsetNewest.Newest = false; - } - } - - var newServerRating = new EFRating() - { - Performance = clientStats.Performance, - Ranking = individualClientRanking, - Active = true, - Newest = true, - ServerId = clientStats.ServerId, - RatingHistory = clientHistory, - ActivityAmount = currentServerTotalPlaytime, - }; - - // add new rating for current server - ctx.Add(newServerRating); - - #endregion - #region OVERALL_RATING - // select all performance & time played for current client - var iqClientStats = from stats in ctx.Set() - where stats.ClientId == client.ClientId - where stats.ServerId != clientStats.ServerId - select new - { - stats.Performance, - stats.TimePlayed - }; - - var clientStatsList = await iqClientStats.ToListAsync(); - - // add the current server's so we don't have to pull it from the database - clientStatsList.Add(new - { - clientStats.Performance, - TimePlayed = currentServerTotalPlaytime - }); - - // weight the overall performance based on play time - double performanceAverage = clientStatsList.Sum(p => (p.Performance * p.TimePlayed)) / clientStatsList.Sum(p => p.TimePlayed); - - // shouldn't happen but just in case the sum of time played is 0 - if (double.IsNaN(performanceAverage)) - { - performanceAverage = clientStatsList.Average(p => p.Performance); - } - - int overallClientRanking = await ctx.Set() - .Where(GetRankingFunc()) - .Where(r => r.RatingHistory.ClientId != client.ClientId) - .Where(r => r.Performance > performanceAverage) - .CountAsync() + 1; - - // limit max average history to 40 - if (clientHistory.Ratings.Count(r => r.ServerId == null) >= 40) - { - var ratingToRemove = clientHistory.Ratings - .Where(r => r.ServerId == null) - .OrderBy(r => r.When) - .First(); - - ctx.Remove(ratingToRemove); - } - - // set the previous average newest to false - ratingToUnsetNewest = clientHistory.Ratings - .Where(r => r.ServerId == null) - .OrderByDescending(r => r.When) - .FirstOrDefault(); - - if (ratingToUnsetNewest != null) - { - if (ratingToUnsetNewest.Newest) - { - ctx.Update(ratingToUnsetNewest); - ctx.Entry(ratingToUnsetNewest).Property(r => r.Newest).IsModified = true; - ratingToUnsetNewest.Newest = false; - } - } - - // add new average rating - var averageRating = new EFRating() - { - Active = true, - Newest = true, - Performance = performanceAverage, - Ranking = overallClientRanking, - ServerId = null, - RatingHistory = clientHistory, - ActivityAmount = clientStatsList.Sum(s => s.TimePlayed) - }; - - ctx.Add(averageRating); - #endregion - - await ctx.SaveChangesAsync(); + ctx.Add(clientHistory); } + + #region INDIVIDUAL_SERVER_PERFORMANCE + // get the client ranking for the current server + int individualClientRanking = await ctx.Set() + .Where(GetRankingFunc(clientStats.ServerId)) + // ignore themselves in the query + .Where(c => c.RatingHistory.ClientId != client.ClientId) + .Where(c => c.Performance > clientStats.Performance) + .CountAsync() + 1; + + // limit max history per server to 40 + if (clientHistory.Ratings.Count(r => r.ServerId == clientStats.ServerId) >= 40) + { + // select the oldest one + var ratingToRemove = clientHistory.Ratings + .Where(r => r.ServerId == clientStats.ServerId) + .OrderBy(r => r.When) + .First(); + + ctx.Remove(ratingToRemove); + } + + // set the previous newest to false + var ratingToUnsetNewest = clientHistory.Ratings + .Where(r => r.ServerId == clientStats.ServerId) + .OrderByDescending(r => r.When) + .FirstOrDefault(); + + if (ratingToUnsetNewest != null) + { + if (ratingToUnsetNewest.Newest) + { + ctx.Update(ratingToUnsetNewest); + ctx.Entry(ratingToUnsetNewest).Property(r => r.Newest).IsModified = true; + ratingToUnsetNewest.Newest = false; + } + } + + var newServerRating = new EFRating() + { + Performance = clientStats.Performance, + Ranking = individualClientRanking, + Active = true, + Newest = true, + ServerId = clientStats.ServerId, + RatingHistory = clientHistory, + ActivityAmount = currentServerTotalPlaytime, + }; + + // add new rating for current server + ctx.Add(newServerRating); + + #endregion + #region OVERALL_RATING + // select all performance & time played for current client + var iqClientStats = from stats in ctx.Set() + where stats.ClientId == client.ClientId + where stats.ServerId != clientStats.ServerId + select new + { + stats.Performance, + stats.TimePlayed + }; + + var clientStatsList = await iqClientStats.ToListAsync(); + + // add the current server's so we don't have to pull it from the database + clientStatsList.Add(new + { + clientStats.Performance, + TimePlayed = currentServerTotalPlaytime + }); + + // weight the overall performance based on play time + double performanceAverage = clientStatsList.Sum(p => (p.Performance * p.TimePlayed)) / clientStatsList.Sum(p => p.TimePlayed); + + // shouldn't happen but just in case the sum of time played is 0 + if (double.IsNaN(performanceAverage)) + { + performanceAverage = clientStatsList.Average(p => p.Performance); + } + + int overallClientRanking = await ctx.Set() + .Where(GetRankingFunc()) + .Where(r => r.RatingHistory.ClientId != client.ClientId) + .Where(r => r.Performance > performanceAverage) + .CountAsync() + 1; + + // limit max average history to 40 + if (clientHistory.Ratings.Count(r => r.ServerId == null) >= 40) + { + var ratingToRemove = clientHistory.Ratings + .Where(r => r.ServerId == null) + .OrderBy(r => r.When) + .First(); + + ctx.Remove(ratingToRemove); + } + + // set the previous average newest to false + ratingToUnsetNewest = clientHistory.Ratings + .Where(r => r.ServerId == null) + .OrderByDescending(r => r.When) + .FirstOrDefault(); + + if (ratingToUnsetNewest != null) + { + if (ratingToUnsetNewest.Newest) + { + ctx.Update(ratingToUnsetNewest); + ctx.Entry(ratingToUnsetNewest).Property(r => r.Newest).IsModified = true; + ratingToUnsetNewest.Newest = false; + } + } + + // add new average rating + var averageRating = new EFRating() + { + Active = true, + Newest = true, + Performance = performanceAverage, + Ranking = overallClientRanking, + ServerId = null, + RatingHistory = clientHistory, + ActivityAmount = clientStatsList.Sum(s => s.TimePlayed) + }; + + ctx.Add(averageRating); + #endregion + + await ctx.SaveChangesAsync(); } /// @@ -1137,25 +1122,23 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { EFServerStatistics serverStats; - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) + using var ctx = _contextFactory.CreateContext(enableTracking: false); + var serverStatsSet = ctx.Set(); + serverStats = serverStatsSet.FirstOrDefault(s => s.ServerId == serverId); + + if (serverStats == null) { - var serverStatsSet = ctx.Set(); - serverStats = serverStatsSet.FirstOrDefault(s => s.ServerId == serverId); - - if (serverStats == null) + _log.LogDebug("Initializing server stats for {serverId}", serverId); + // server stats have never been generated before + serverStats = new EFServerStatistics() { - _log.LogDebug("Initializing server stats for {serverId}", serverId); - // server stats have never been generated before - serverStats = new EFServerStatistics() - { - ServerId = serverId, - TotalKills = 0, - TotalPlayTime = 0, - }; + ServerId = serverId, + TotalKills = 0, + TotalPlayTime = 0, + }; - serverStats = serverStatsSet.Add(serverStats).Entity; - ctx.SaveChanges(); - } + serverStats = serverStatsSet.Add(serverStats).Entity; + ctx.SaveChanges(); } return serverStats; @@ -1216,12 +1199,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { await waiter.WaitAsync(); - using (var ctx = _contextFactory.CreateContext()) - { - var serverStatsSet = ctx.Set(); - serverStatsSet.Update(_servers[serverId].ServerStatistics); - await ctx.SaveChangesAsync(); - } + await using var ctx = _contextFactory.CreateContext(); + var serverStatsSet = ctx.Set(); + serverStatsSet.Update(_servers[serverId].ServerStatistics); + await ctx.SaveChangesAsync(); foreach (var stats in sv.GetClientsAsList() .Select(_client => _client.GetAdditionalProperty(CLIENT_STATS_KEY)) diff --git a/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs b/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs index dc76ce29..219f671e 100644 --- a/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs +++ b/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs @@ -26,7 +26,7 @@ namespace Stats.Helpers public async Task> QueryResource(StatsInfoRequest query) { var result = new ResourceQueryHelperResult(); - using var context = _contextFactory.CreateContext(enableTracking: false); + await using var context = _contextFactory.CreateContext(enableTracking: false); // we need to get the ratings separately because there's not explicit FK var ratings = await context.Set() diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 19e83b72..d21e613a 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -173,11 +173,9 @@ namespace IW4MAdmin.Plugins.Stats { IList clientStats; int messageCount = 0; - using (var ctx = _databaseContextFactory.CreateContext(enableTracking: false)) - { - clientStats = await ctx.Set().Where(c => c.ClientId == request.ClientId).ToListAsync(); - messageCount = await ctx.Set().CountAsync(_message => _message.ClientId == request.ClientId); - } + await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false); + clientStats = await ctx.Set().Where(c => c.ClientId == request.ClientId).ToListAsync(); + messageCount = await ctx.Set().CountAsync(_message => _message.ClientId == request.ClientId); int kills = clientStats.Sum(c => c.Kills); int deaths = clientStats.Sum(c => c.Deaths); @@ -252,13 +250,11 @@ namespace IW4MAdmin.Plugins.Stats { IList clientStats; - using (var ctx = _databaseContextFactory.CreateContext(enableTracking: false)) - { - clientStats = await ctx.Set() - .Include(c => c.HitLocations) - .Where(c => c.ClientId == request.ClientId) - .ToListAsync(); - } + await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false); + clientStats = await ctx.Set() + .Include(c => c.HitLocations) + .Where(c => c.ClientId == request.ClientId) + .ToListAsync(); double headRatio = 0; double chestRatio = 0; diff --git a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs index 34586ded..c8b484ba 100644 --- a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs +++ b/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs @@ -41,7 +41,7 @@ namespace StatsWeb } var result = new ResourceQueryHelperResult(); - using var context = _contextFactory.CreateContext(enableTracking: false); + await using var context = _contextFactory.CreateContext(enableTracking: false); if (serverCache == null) { diff --git a/SharedLibraryCore/Database/ContextSeed.cs b/SharedLibraryCore/Database/ContextSeed.cs index fac72d75..770230fb 100644 --- a/SharedLibraryCore/Database/ContextSeed.cs +++ b/SharedLibraryCore/Database/ContextSeed.cs @@ -13,7 +13,7 @@ namespace SharedLibraryCore.Database { public static async Task Seed(IDatabaseContextFactory contextFactory, CancellationToken token) { - var context = contextFactory.CreateContext(); + await using var context = contextFactory.CreateContext(); var strategy = context.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { diff --git a/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs index 946ac39e..88fd9cef 100644 --- a/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs +++ b/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs @@ -13,7 +13,7 @@ namespace SharedLibraryCore.Database.MigrationContext } } - public MySqlDatabaseContext(DbContextOptions options) : base(options) + public MySqlDatabaseContext(DbContextOptions options) : base(options) { } diff --git a/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs index 2167c954..cf6c57b8 100644 --- a/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs +++ b/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs @@ -13,7 +13,7 @@ namespace SharedLibraryCore.Database.MigrationContext } } - public PostgresqlDatabaseContext(DbContextOptions options) : base(options) + public PostgresqlDatabaseContext(DbContextOptions options) : base(options) { } diff --git a/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs b/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs index ff30d6d3..89a8274c 100644 --- a/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs +++ b/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs @@ -13,7 +13,7 @@ namespace SharedLibraryCore.Database.MigrationContext } } - public SqliteDatabaseContext(DbContextOptions options) : base(options) + public SqliteDatabaseContext(DbContextOptions options) : base(options) { } diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index df2bc1cb..957462dd 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -91,12 +91,11 @@ namespace SharedLibraryCore.Database.Models SetAdditionalProperty("_reportCount", 0); ReceivedPenalties = new List(); _processingEvent = new SemaphoreSlim(1, 1); - } ~EFClient() { - _processingEvent.Dispose(); + _processingEvent?.Dispose(); } public override string ToString() diff --git a/SharedLibraryCore/Repositories/AuditInformationRepository.cs b/SharedLibraryCore/Repositories/AuditInformationRepository.cs index fea61c2a..d712ad2f 100644 --- a/SharedLibraryCore/Repositories/AuditInformationRepository.cs +++ b/SharedLibraryCore/Repositories/AuditInformationRepository.cs @@ -22,34 +22,32 @@ namespace SharedLibraryCore.Repositories /// public async Task> ListAuditInformation(PaginationRequest paginationInfo) { - using (var ctx = _contextFactory.CreateContext(enableTracking: false)) - { - var iqItems = (from change in ctx.EFChangeHistory - where change.TypeOfChange != Database.Models.EFChangeHistory.ChangeType.Ban - orderby change.TimeChanged descending - join originClient in ctx.Clients - on (change.ImpersonationEntityId ?? change.OriginEntityId) equals originClient.ClientId - join targetClient in ctx.Clients - on change.TargetEntityId equals targetClient.ClientId - into targetChange - from targetClient in targetChange.DefaultIfEmpty() - select new AuditInfo() - { - Action = change.TypeOfChange.ToString(), - OriginName = originClient.CurrentAlias.Name, - OriginId = originClient.ClientId, - TargetName = targetClient == null ? "" : targetClient.CurrentAlias.Name, - TargetId = targetClient == null ? new int?() : targetClient.ClientId, - When = change.TimeChanged, - Data = change.Comment, - OldValue = change.PreviousValue, - NewValue = change.CurrentValue - }) - .Skip(paginationInfo.Offset) - .Take(paginationInfo.Count); + await using var ctx = _contextFactory.CreateContext(enableTracking: false); + var iqItems = (from change in ctx.EFChangeHistory + where change.TypeOfChange != Database.Models.EFChangeHistory.ChangeType.Ban + orderby change.TimeChanged descending + join originClient in ctx.Clients + on (change.ImpersonationEntityId ?? change.OriginEntityId) equals originClient.ClientId + join targetClient in ctx.Clients + on change.TargetEntityId equals targetClient.ClientId + into targetChange + from targetClient in targetChange.DefaultIfEmpty() + select new AuditInfo() + { + Action = change.TypeOfChange.ToString(), + OriginName = originClient.CurrentAlias.Name, + OriginId = originClient.ClientId, + TargetName = targetClient == null ? "" : targetClient.CurrentAlias.Name, + TargetId = targetClient == null ? new int?() : targetClient.ClientId, + When = change.TimeChanged, + Data = change.Comment, + OldValue = change.PreviousValue, + NewValue = change.CurrentValue + }) + .Skip(paginationInfo.Offset) + .Take(paginationInfo.Count); - return await iqItems.ToListAsync(); - } + return await iqItems.ToListAsync(); } } } From 6648b75255407ea79d56c6b7d487125c3b2e76dd Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 2 Dec 2020 14:29:49 -0600 Subject: [PATCH 019/143] update CoD4x parser tweak handling segmented status response actually support more than 18 clients LOL --- Application/Extensions/StartupExtensions.cs | 20 +++++---- Application/RCon/ConnectionState.cs | 2 +- Application/RCon/RConConnection.cs | 50 +++++++++++---------- Application/RconParsers/BaseRConParser.cs | 3 +- Plugins/ScriptPlugins/ParserCoD4x.js | 3 +- SharedLibraryCore/Server.cs | 2 +- 6 files changed, 44 insertions(+), 36 deletions(-) diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index 764414da..b59a4b0b 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -5,12 +5,13 @@ using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Serilog; using Serilog.Events; using SharedLibraryCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.MigrationContext; +using ILogger = Serilog.ILogger; namespace IW4MAdmin.Application.Extensions { @@ -45,6 +46,8 @@ namespace IW4MAdmin.Application.Extensions } services.AddLogging(builder => builder.AddSerilog(_defaultLogger, dispose: true)); + services.AddSingleton(new LoggerFactory() + .AddSerilog(_defaultLogger, true)); return services; } @@ -76,18 +79,19 @@ namespace IW4MAdmin.Application.Extensions case "mysql": var appendTimeout = !appConfig.ConnectionString.Contains("default command timeout", StringComparison.InvariantCultureIgnoreCase); - var mysqlBuilder = new DbContextOptionsBuilder() + services.AddSingleton(sp => (DbContextOptions) new DbContextOptionsBuilder() .UseMySql(appConfig.ConnectionString + (appendTimeout ? ";default command timeout=0" : ""), - mysqlOptions => mysqlOptions.EnableRetryOnFailure()); - services.AddSingleton((DbContextOptions) mysqlBuilder.Options); + mysqlOptions => mysqlOptions.EnableRetryOnFailure()) + .UseLoggerFactory(sp.GetRequiredService()).Options); return services; case "postgresql": appendTimeout = !appConfig.ConnectionString.Contains("Command Timeout", StringComparison.InvariantCultureIgnoreCase); - var postgresqlBuilder = new DbContextOptionsBuilder() - .UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), - postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()); - services.AddSingleton((DbContextOptions) postgresqlBuilder.Options); + services.AddSingleton(sp => + (DbContextOptions) new DbContextOptionsBuilder() + .UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), + postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()) + .UseLoggerFactory(sp.GetRequiredService()).Options); return services; default: throw new ArgumentException($"No context available for {appConfig.DatabaseProvider}"); diff --git a/Application/RCon/ConnectionState.cs b/Application/RCon/ConnectionState.cs index 00595be2..91307671 100644 --- a/Application/RCon/ConnectionState.cs +++ b/Application/RCon/ConnectionState.cs @@ -18,7 +18,7 @@ namespace IW4MAdmin.Application.RCon } public int ConnectionAttempts { get; set; } - const int BufferSize = 4096; + const int BufferSize = 8192; public readonly byte[] ReceiveBuffer = new byte[BufferSize]; public readonly SemaphoreSlim OnComplete = new SemaphoreSlim(1, 1); public readonly ManualResetEventSlim OnSentData = new ManualResetEventSlim(false); diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 6586cdef..07ea354e 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -407,37 +407,39 @@ namespace IW4MAdmin.Application.RCon return; } - if (sender is Socket sock) + if (!(sender is Socket sock)) { - var state = ActiveQueries[this.Endpoint]; - state.BytesReadPerSegment.Add(e.BytesTransferred); + return; + } + + var state = ActiveQueries[this.Endpoint]; + state.BytesReadPerSegment.Add(e.BytesTransferred); - try + try + { + var totalBytesTransferred = e.BytesTransferred; + // we still have available data so the payload was segmented + while (sock.Available > 0) { - // we still have available data so the payload was segmented - if (sock.Available > 0) + state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available); + + if (sock.ReceiveAsync(state.ReceiveEventArgs)) { - state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, e.BytesTransferred, state.ReceiveBuffer.Length - e.BytesTransferred); - - if (!sock.ReceiveAsync(state.ReceiveEventArgs)) - { - _log.LogDebug("Read {bytesTransferred} synchronous bytes from {endpoint}", state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint); - // we need to increment this here because the callback isn't executed if there's no pending IO - state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred); - ActiveQueries[this.Endpoint].OnReceivedData.Set(); - } - } - - else - { - ActiveQueries[this.Endpoint].OnReceivedData.Set(); + continue; } + + _log.LogDebug("Read {bytesTransferred} synchronous bytes from {endpoint}", state.ReceiveEventArgs.BytesTransferred, e.RemoteEndPoint); + // we need to increment this here because the callback isn't executed if there's no pending IO + state.BytesReadPerSegment.Add(state.ReceiveEventArgs.BytesTransferred); + totalBytesTransferred += state.ReceiveEventArgs.BytesTransferred; } + + ActiveQueries[this.Endpoint].OnReceivedData.Set(); + } - catch (ObjectDisposedException) - { - ActiveQueries[this.Endpoint].OnReceivedData.Set(); - } + catch (ObjectDisposedException) + { + ActiveQueries[this.Endpoint].OnReceivedData.Set(); } } diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index 55ca9794..c77da243 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -205,7 +205,8 @@ namespace IW4MAdmin.Application.RconParsers if (match.Success) { - if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI") + if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI" || + match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "CNCT") { _logger.LogDebug("Ignoring detected client {client} because they are zombie state", string.Join(",", match.Values)); continue; diff --git a/Plugins/ScriptPlugins/ParserCoD4x.js b/Plugins/ScriptPlugins/ParserCoD4x.js index d4fbf074..ada571c6 100644 --- a/Plugins/ScriptPlugins/ParserCoD4x.js +++ b/Plugins/ScriptPlugins/ParserCoD4x.js @@ -15,9 +15,10 @@ var plugin = { eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.StatusHeader.Pattern = 'num +score +ping +playerid +steamid +name +lastmsg +address +qport +rate *'; - rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]{16,32})|bot[0-9]+) ([0-9]+) +(.{0,32}) +([0-9]+) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback) +(-*[0-9]+) +([0-9]+) *$'; + rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]{16,32})|0) +([[0-9]+|0]) +(.{0,32}) +([0-9]+) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|bot) +(-*[0-9]+) +([0-9]+) *$'; rconParser.Configuration.Status.AddMapping(104, 6); // RConName rconParser.Configuration.Status.AddMapping(105, 8); // RConIPAddress + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.Dvar.Pattern = '^"(.+)" is: "(.+)?" default: "(.+)?" info: "(.+)?"$'; rconParser.Configuration.Dvar.AddMapping(109, 2); // DVAR latched value diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index d129d289..84f16916 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -42,7 +42,7 @@ namespace SharedLibraryCore ServerConfig = config; RemoteConnection = rconConnectionFactory.CreateConnection(IP, Port, Password); EventProcessing = new SemaphoreSlim(1, 1); - Clients = new List(new EFClient[18]); + Clients = new List(new EFClient[64]); Reports = new List(); ClientHistory = new Queue(); ChatHistory = new List(); From f03626c3ae3e72aea09bd75ded6d6ba843e96668 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 12 Dec 2020 21:43:27 -0600 Subject: [PATCH 020/143] Another tweak for CoD4x rcon parsing. --- Application/RCon/RConConnection.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 07ea354e..7ce5dc6a 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -10,6 +10,7 @@ using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Serilog.Context; @@ -141,7 +142,7 @@ namespace IW4MAdmin.Application.RCon } using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { - DontFragment = true, + DontFragment = false, Ttl = 100, ExclusiveAddressUse = true, }) @@ -403,6 +404,7 @@ namespace IW4MAdmin.Application.RCon // this occurs when we close the socket if (e.BytesTransferred == 0) { + _log.LogDebug("No bytes were transmitted so the connection was probably closed"); ActiveQueries[this.Endpoint].OnReceivedData.Set(); return; } @@ -415,16 +417,24 @@ namespace IW4MAdmin.Application.RCon var state = ActiveQueries[this.Endpoint]; state.BytesReadPerSegment.Add(e.BytesTransferred); + // I don't even want to know why this works for getting more data from Cod4x + // but I'm leaving it in here as long as it doesn't break anything. + // it's very stupid... + Thread.Sleep(150); + try { var totalBytesTransferred = e.BytesTransferred; + _log.LogDebug("{total} total bytes transferred with {available} bytes remaining", totalBytesTransferred, sock.Available); // we still have available data so the payload was segmented while (sock.Available > 0) { + _log.LogDebug("{available} more bytes to be read", sock.Available); state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available); if (sock.ReceiveAsync(state.ReceiveEventArgs)) { + _log.LogDebug("Remaining bytes are async"); continue; } @@ -439,6 +449,7 @@ namespace IW4MAdmin.Application.RCon catch (ObjectDisposedException) { + _log.LogDebug("Socket was disposed while receiving data"); ActiveQueries[this.Endpoint].OnReceivedData.Set(); } } From 02b910234a0f6ef882863b087c4f7936fe042acd Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 13 Dec 2020 20:33:37 -0600 Subject: [PATCH 021/143] add official T4/WaW support for issue #178 CoD4x parser tweak to parse full guid as decimal --- Application/EventParsers/BaseEventParser.cs | 23 +++++++++++----- Application/IW4MServer.cs | 2 +- IW4MAdmin.sln | 1 + Plugins/ScriptPlugins/ParserCoD4x.js | 3 +++ Plugins/ScriptPlugins/ParserT4.js | 30 +++++++++++++++++++++ SharedLibraryCore/Events/GameEvent.cs | 2 +- SharedLibraryCore/Utilities.cs | 3 ++- 7 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 Plugins/ScriptPlugins/ParserT4.js diff --git a/Application/EventParsers/BaseEventParser.cs b/Application/EventParsers/BaseEventParser.cs index 1d81f308..2bb40fbb 100644 --- a/Application/EventParsers/BaseEventParser.cs +++ b/Application/EventParsers/BaseEventParser.cs @@ -93,16 +93,25 @@ namespace IW4MAdmin.Application.EventParsers public virtual GameEvent GenerateGameEvent(string logLine) { var timeMatch = Configuration.Time.PatternMatcher.Match(logLine); - int gameTime = 0; + var gameTime = 0L; if (timeMatch.Success) { - gameTime = timeMatch - .Values - .Skip(2) - // this converts the timestamp into seconds passed - .Select((_value, index) => int.Parse(_value.ToString()) * (index == 0 ? 60 : 1)) - .Sum(); + if (timeMatch.Values[0].Contains(":")) + { + gameTime = timeMatch + .Values + .Skip(2) + // this converts the timestamp into seconds passed + .Select((_value, index) => long.Parse(_value.ToString()) * (index == 0 ? 60 : 1)) + .Sum(); + + } + else + { + gameTime = long.Parse(timeMatch.Values[0]); + } + // we want to strip the time from the log line logLine = logLine.Substring(timeMatch.Values.First().Length); } diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 6b9b1224..17c9bd80 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -29,7 +29,7 @@ namespace IW4MAdmin private readonly ITranslationLookup _translationLookup; private readonly IMetaService _metaService; private const int REPORT_FLAG_COUNT = 4; - private int lastGameTime = 0; + private long lastGameTime = 0; public int Id { get; private set; } private readonly IServiceProvider _serviceProvider; diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index c2dfee15..1cc50347 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -44,6 +44,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug Plugins\ScriptPlugins\SampleScriptPluginCommand.js = Plugins\ScriptPlugins\SampleScriptPluginCommand.js Plugins\ScriptPlugins\SharedGUIDKick.js = Plugins\ScriptPlugins\SharedGUIDKick.js Plugins\ScriptPlugins\VPNDetection.js = Plugins\ScriptPlugins\VPNDetection.js + Plugins\ScriptPlugins\ParserT4.js = Plugins\ScriptPlugins\ParserT4.js EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{A848FCF1-8527-4AA8-A1AA-50D29695C678}" diff --git a/Plugins/ScriptPlugins/ParserCoD4x.js b/Plugins/ScriptPlugins/ParserCoD4x.js index ada571c6..3a735815 100644 --- a/Plugins/ScriptPlugins/ParserCoD4x.js +++ b/Plugins/ScriptPlugins/ParserCoD4x.js @@ -23,10 +23,13 @@ var plugin = { rconParser.Configuration.Dvar.Pattern = '^"(.+)" is: "(.+)?" default: "(.+)?" info: "(.+)?"$'; rconParser.Configuration.Dvar.AddMapping(109, 2); // DVAR latched value rconParser.Configuration.Dvar.AddMapping(110, 4); // dvar info + rconParser.Configuration.GuidNumberStyle = 7; // Integer + rconParser.Configuration.NoticeLineSeparator = '. '; // CoD4x does not support \n in the client notice rconParser.Version = 'CoD4 X - win_mingw-x86 build 963 Mar 12 2019'; rconParser.GameName = 1; // IW3 eventParser.Configuration.GameDirectory = 'main'; + eventParser.Configuration.GuidNumberStyle = 7; // Integer eventParser.Version = 'CoD4 X - win_mingw-x86 build 963 Mar 12 2019'; eventParser.GameName = 1; // IW3 eventParser.URLProtocolFormat = 'cod4://{{ip}}:{{port}}'; diff --git a/Plugins/ScriptPlugins/ParserT4.js b/Plugins/ScriptPlugins/ParserT4.js new file mode 100644 index 00000000..8186fc38 --- /dev/null +++ b/Plugins/ScriptPlugins/ParserT4.js @@ -0,0 +1,30 @@ +var rconParser; +var eventParser; + +var plugin = { + author: 'RaidMax', + version: 0.1, + name: 'Call of Duty 5: World at War Parser', + isParser: true, + + onEventAsync: function (gameEvent, server) { + }, + + onLoadAsync: function (manager) { + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; + rconParser.Configuration.GuidNumberStyle = 7; // Integer + rconParser.Version = "Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86"; + + eventParser.Configuration.GuidNumberStyle = 7; // Integer + eventParser.GameName = 5; // T4 + eventParser.Version = "Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86"; + }, + + onUnloadAsync: function () { + }, + + onTickAsync: function (server) { + } +}; diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index 293d4465..88db3035 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -235,7 +235,7 @@ namespace SharedLibraryCore /// /// Specifies the game time offset as printed in the log /// - public int? GameTime { get; set; } + public long? GameTime { get; set; } public EFClient Origin; public EFClient Target; public EFClient ImpersonationOrigin { get; set; } diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index ac8a91a6..f956268e 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -366,7 +366,8 @@ namespace SharedLibraryCore /// true if is bot guid, otherwise false public static bool IsBotGuid(this string guid) { - return guid.Contains("bot") || guid == "0"; + // todo: revisit this magic number for cod5 bot guid + return guid.Contains("bot") || guid == "0" || guid == "1075569476"; } /// From 928cbef84584452888773c4312477b204cc5d4f4 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Mon, 14 Dec 2020 21:10:50 -0600 Subject: [PATCH 022/143] resolve bot guid issue with T5 remove unneeded check for CNCT state --- Application/RconParsers/BaseRConParser.cs | 8 +++----- Plugins/ScriptPlugins/ParserT4.js | 4 ++-- SharedLibraryCore/Utilities.cs | 3 +-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index c77da243..45b763c9 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -205,8 +205,7 @@ namespace IW4MAdmin.Application.RconParsers if (match.Success) { - if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI" || - match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "CNCT") + if (match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConPing]] == "ZMBI") { _logger.LogDebug("Ignoring detected client {client} because they are zombie state", string.Join(",", match.Values)); continue; @@ -226,12 +225,13 @@ namespace IW4MAdmin.Application.RconParsers long networkId; string name = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConName]].TrimNewLine(); string networkIdString; + var ip = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConIpAddress]].Split(':')[0].ConvertToIP(); try { networkIdString = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConNetworkId]]; - networkId = networkIdString.IsBotGuid() ? + networkId = networkIdString.IsBotGuid() || (ip == null && ping == 999) ? name.GenerateGuidFromString() : networkIdString.ConvertGuidToLong(Configuration.GuidNumberStyle); } @@ -241,8 +241,6 @@ namespace IW4MAdmin.Application.RconParsers continue; } - int? ip = match.Values[Configuration.Status.GroupMapping[ParserRegex.GroupType.RConIpAddress]].Split(':')[0].ConvertToIP(); - var client = new EFClient() { CurrentAlias = new EFAlias() diff --git a/Plugins/ScriptPlugins/ParserT4.js b/Plugins/ScriptPlugins/ParserT4.js index 8186fc38..e3f68f20 100644 --- a/Plugins/ScriptPlugins/ParserT4.js +++ b/Plugins/ScriptPlugins/ParserT4.js @@ -15,11 +15,11 @@ var plugin = { eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.GuidNumberStyle = 7; // Integer - rconParser.Version = "Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86"; + rconParser.Version = 'Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86'; eventParser.Configuration.GuidNumberStyle = 7; // Integer eventParser.GameName = 5; // T4 - eventParser.Version = "Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86"; + eventParser.Version = 'Call of Duty Multiplayer COD_WaW MP build 1.7.1263 CL(350073) JADAMS2 Thu Oct 29 15:43:55 2009 win-x86'; }, onUnloadAsync: function () { diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index f956268e..ac8a91a6 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -366,8 +366,7 @@ namespace SharedLibraryCore /// true if is bot guid, otherwise false public static bool IsBotGuid(this string guid) { - // todo: revisit this magic number for cod5 bot guid - return guid.Contains("bot") || guid == "0" || guid == "1075569476"; + return guid.Contains("bot") || guid == "0"; } /// From 4afc47807687c5c58ef7db1db93502ab351683ae Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 16 Dec 2020 13:11:30 -0600 Subject: [PATCH 023/143] fix issue with view stats and reset stats failing fix issue with set level returning wrong error message if setting a client to the same level they're currently at update CoD4x parser version update nuget packages --- Application/Application.csproj | 9 ++- Application/Main.cs | 5 +- Plugins/ScriptPlugins/ParserCoD4x.js | 4 +- Plugins/Stats/Commands/ResetStats.cs | 44 +++++++------ Plugins/Stats/Commands/ViewStats.cs | 63 ++++++++++++------- Plugins/Stats/Helpers/StatManager.cs | 7 +++ SharedLibraryCore/Commands/NativeCommands.cs | 18 +++++- SharedLibraryCore/SharedLibraryCore.csproj | 26 ++++---- .../ApplicationTests/ApplicationTests.csproj | 4 +- Tests/ApplicationTests/CommandTests.cs | 25 ++++++++ WebfrontCore/WebfrontCore.csproj | 4 +- 11 files changed, 139 insertions(+), 70 deletions(-) diff --git a/Application/Application.csproj b/Application/Application.csproj index 39f2879d..00b23616 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -25,13 +25,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + @@ -39,7 +39,6 @@ true true Latest - diff --git a/Application/Main.cs b/Application/Main.cs index b192ae7c..3460dfc7 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -68,7 +68,10 @@ namespace IW4MAdmin.Application private static async void OnCancelKey(object sender, ConsoleCancelEventArgs e) { ServerManager?.Stop(); - await ApplicationTask; + if (ApplicationTask != null) + { + await ApplicationTask; + } } /// diff --git a/Plugins/ScriptPlugins/ParserCoD4x.js b/Plugins/ScriptPlugins/ParserCoD4x.js index 3a735815..982acd44 100644 --- a/Plugins/ScriptPlugins/ParserCoD4x.js +++ b/Plugins/ScriptPlugins/ParserCoD4x.js @@ -25,12 +25,12 @@ var plugin = { rconParser.Configuration.Dvar.AddMapping(110, 4); // dvar info rconParser.Configuration.GuidNumberStyle = 7; // Integer rconParser.Configuration.NoticeLineSeparator = '. '; // CoD4x does not support \n in the client notice - rconParser.Version = 'CoD4 X - win_mingw-x86 build 963 Mar 12 2019'; + rconParser.Version = 'CoD4 X - win_mingw-x86 build 1056 Dec 12 2020'; rconParser.GameName = 1; // IW3 eventParser.Configuration.GameDirectory = 'main'; eventParser.Configuration.GuidNumberStyle = 7; // Integer - eventParser.Version = 'CoD4 X - win_mingw-x86 build 963 Mar 12 2019'; + eventParser.Version = 'CoD4 X - win_mingw-x86 build 1056 Dec 12 2020'; eventParser.GameName = 1; // IW3 eventParser.URLProtocolFormat = 'cod4://{{ip}}:{{port}}'; }, diff --git a/Plugins/Stats/Commands/ResetStats.cs b/Plugins/Stats/Commands/ResetStats.cs index ef4637c1..320b319c 100644 --- a/Plugins/Stats/Commands/ResetStats.cs +++ b/Plugins/Stats/Commands/ResetStats.cs @@ -23,40 +23,44 @@ namespace IW4MAdmin.Plugins.Stats.Commands Permission = EFClient.Permission.User; RequiresTarget = false; AllowImpersonation = true; + + _contextFactory = contextFactory; } - public override async Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent gameEvent) { - if (E.Origin.ClientNumber >= 0) + if (gameEvent.Origin.ClientNumber >= 0) { + var serverId = Helpers.StatManager.GetIdForServer(gameEvent.Owner); - long serverId = Helpers.StatManager.GetIdForServer(E.Owner); - - EFClientStatistics clientStats; await using var context = _contextFactory.CreateContext(); - clientStats = await context.Set() - .Where(s => s.ClientId == E.Origin.ClientId) + var clientStats = await context.Set() + .Where(s => s.ClientId == gameEvent.Origin.ClientId) .Where(s => s.ServerId == serverId) - .FirstAsync(); - - clientStats.Deaths = 0; - clientStats.Kills = 0; - clientStats.SPM = 0.0; - clientStats.Skill = 0.0; - clientStats.TimePlayed = 0; - // todo: make this more dynamic - clientStats.EloRating = 200.0; + .FirstOrDefaultAsync(); + + // want to prevent resetting stats before they've gotten any kills + if (clientStats != null) + { + clientStats.Deaths = 0; + clientStats.Kills = 0; + clientStats.SPM = 0.0; + clientStats.Skill = 0.0; + clientStats.TimePlayed = 0; + // todo: make this more dynamic + clientStats.EloRating = 200.0; + await context.SaveChangesAsync(); + } // reset the cached version - Plugin.Manager.ResetStats(E.Origin); + Plugin.Manager.ResetStats(gameEvent.Origin); - await context.SaveChangesAsync(); - E.Origin.Tell(_translationLookup["PLUGINS_STATS_COMMANDS_RESET_SUCCESS"]); + gameEvent.Origin.Tell(_translationLookup["PLUGINS_STATS_COMMANDS_RESET_SUCCESS"]); } else { - E.Origin.Tell(_translationLookup["PLUGINS_STATS_COMMANDS_RESET_FAIL"]); + gameEvent.Origin.Tell(_translationLookup["PLUGINS_STATS_COMMANDS_RESET_FAIL"]); } } } diff --git a/Plugins/Stats/Commands/ViewStats.cs b/Plugins/Stats/Commands/ViewStats.cs index 676c1b37..2ace6997 100644 --- a/Plugins/Stats/Commands/ViewStats.cs +++ b/Plugins/Stats/Commands/ViewStats.cs @@ -15,11 +15,10 @@ namespace IW4MAdmin.Plugins.Stats.Commands public class ViewStatsCommand : Command { private readonly IDatabaseContextFactory _contextFactory; - - public ViewStatsCommand(CommandConfiguration config, ITranslationLookup translationLookup, + + public ViewStatsCommand(CommandConfiguration config, ITranslationLookup translationLookup, IDatabaseContextFactory contextFactory) : base(config, translationLookup) { - Name = "stats"; Description = translationLookup["PLUGINS_STATS_COMMANDS_VIEW_DESC"]; Alias = "xlrstats"; @@ -33,17 +32,14 @@ namespace IW4MAdmin.Plugins.Stats.Commands Required = false } }; - - _config = config; + _contextFactory = contextFactory; } - private readonly CommandConfiguration _config; - public override async Task ExecuteAsync(GameEvent E) { string statLine; - EFClientStatistics pStats; + EFClientStatistics pStats = null; if (E.Data.Length > 0 && E.Target == null) { @@ -55,48 +51,67 @@ namespace IW4MAdmin.Plugins.Stats.Commands } } - long serverId = StatManager.GetIdForServer(E.Owner); - + var serverId = StatManager.GetIdForServer(E.Owner); + // getting stats for a particular client if (E.Target != null) { - int performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Target.ClientId); - string performanceRankingString = performanceRanking == 0 ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; + var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Target.ClientId); + var performanceRankingString = performanceRanking == 0 + ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] + : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; - if (E.Owner.GetClientsAsList().Any(_client => _client.Equals(E.Target))) + // target is currently connected so we want their cached stats if they exist + if (E.Owner.GetClientsAsList().Any(client => client.Equals(E.Target))) { pStats = E.Target.GetAdditionalProperty(StatManager.CLIENT_STATS_KEY); } - else + // target is not connected so we want to look up via database + if (pStats == null) { await using var context = _contextFactory.CreateContext(false); - pStats = (await context.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId)); + pStats = (await context.Set() + .FirstOrDefaultAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId)); } - statLine = $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; + + // if it's still null then they've not gotten a kill or death yet + statLine = pStats == null + ? _translationLookup["PLUGINS_STATS_COMMANDS_NOTAVAILABLE"] + : $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; } + // getting self stats else { - int performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Origin.ClientId); - string performanceRankingString = performanceRanking == 0 ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; + var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Origin.ClientId); + var performanceRankingString = performanceRanking == 0 + ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] + : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; - if (E.Owner.GetClientsAsList().Any(_client => _client.Equals(E.Origin))) + // check if current client is connected to the server + if (E.Owner.GetClientsAsList().Any(client => client.Equals(E.Origin))) { pStats = E.Origin.GetAdditionalProperty(StatManager.CLIENT_STATS_KEY); } - else + // happens if the user has not gotten a kill/death since connecting + if (pStats == null) { await using var context = _contextFactory.CreateContext(false); - pStats = (await context.Set().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)); + pStats = (await context.Set() + .FirstOrDefaultAsync(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)); } - statLine = $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; + + // if it's still null then they've not gotten a kill or death yet + statLine = pStats == null + ? _translationLookup["PLUGINS_STATS_COMMANDS_NOTAVAILABLE"] + : $"^5{pStats.Kills} ^7{_translationLookup["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{_translationLookup["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{_translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}"; } if (E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { - string name = E.Target == null ? E.Origin.Name : E.Target.Name; + var name = E.Target == null ? E.Origin.Name : E.Target.Name; E.Owner.Broadcast(_translationLookup["PLUGINS_STATS_COMMANDS_VIEW_SUCCESS"].FormatExt(name)); E.Owner.Broadcast(statLine); } @@ -112,4 +127,4 @@ namespace IW4MAdmin.Plugins.Stats.Commands } } } -} +} \ No newline at end of file diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 52dd6de1..b9df54b9 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -1161,6 +1161,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers public void ResetStats(EFClient client) { var stats = client.GetAdditionalProperty(CLIENT_STATS_KEY); + + // the cached stats have not been loaded yet + if (stats == null) + { + return; + } + stats.Kills = 0; stats.Deaths = 0; stats.SPM = 0; diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index e4d0fa02..6b8d0dbd 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -725,6 +725,12 @@ namespace SharedLibraryCore.Commands gameEvent.Origin.Tell($"{_translationLookup["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{gameEvent.Target.Name}"); return; } + + else if (gameEvent.Target.Level == Permission.Flagged) + { + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FLAGGED"].FormatExt(gameEvent.Target.Name)); + return; + } // stepped privilege is enabled, but the new level is too high else if (steppedPrivileges && !canPromoteSteppedPriv) @@ -748,9 +754,19 @@ namespace SharedLibraryCore.Commands if (result.Failed) { + // user is the same level + if (result.FailReason == GameEvent.EventFailReason.Invalid) + { + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_INVALID"] + .FormatExt(gameEvent.Target.Name, newPerm.ToString())); + return; + } + using (LogContext.PushProperty("Server", gameEvent.Origin.CurrentServer?.ToString())) { - logger.LogWarning("Failed to set level of client {origin}", gameEvent.Origin.ToString()); + logger.LogWarning("Failed to set level of client {origin} {reason}", + gameEvent.Origin.ToString(), + result.FailReason); } gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); return; diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 4a54280f..55b4e433 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -28,35 +28,35 @@ - + - - - + + + all runtime; build; native; contentfiles - - - - - - + + + + + + - + - + - + diff --git a/Tests/ApplicationTests/ApplicationTests.csproj b/Tests/ApplicationTests/ApplicationTests.csproj index 1c28ad4b..69f4000e 100644 --- a/Tests/ApplicationTests/ApplicationTests.csproj +++ b/Tests/ApplicationTests/ApplicationTests.csproj @@ -6,9 +6,9 @@ - + - + all diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index cc3ed8cf..363cb5ec 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -532,6 +532,31 @@ namespace ApplicationTests Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); } + + [Test] + public async Task Test_SetLevelFail_WhenFlagged() + { + var server = serviceProvider.GetRequiredService(); + var cmd = serviceProvider.GetRequiredService(); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.Flagged; + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Banned", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Flagged, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } #endregion #region PREFIX_PROCESSING diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index 5cb08065..d65527ee 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -68,8 +68,8 @@ - - + + From 5a288dafc1f5a09a3eb5c3ad3eef0350ed40b6d2 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 20 Dec 2020 19:23:14 -0600 Subject: [PATCH 024/143] update shared library core version and plugins --- Plugins/AutomessageFeed/AutomessageFeed.csproj | 2 +- Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj | 2 +- Plugins/LiveRadar/LiveRadar.csproj | 2 +- Plugins/Login/Login.csproj | 2 +- Plugins/ProfanityDeterment/ProfanityDeterment.csproj | 2 +- Plugins/Stats/Stats.csproj | 2 +- Plugins/Web/StatsWeb/StatsWeb.csproj | 2 +- Plugins/Welcome/Welcome.csproj | 2 +- SharedLibraryCore/SharedLibraryCore.csproj | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj index 91e3147a..78bf21a1 100644 --- a/Plugins/AutomessageFeed/AutomessageFeed.csproj +++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj index e5bca04c..24f83fe5 100644 --- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj +++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/LiveRadar/LiveRadar.csproj b/Plugins/LiveRadar/LiveRadar.csproj index 03819637..c767d453 100644 --- a/Plugins/LiveRadar/LiveRadar.csproj +++ b/Plugins/LiveRadar/LiveRadar.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/Login/Login.csproj b/Plugins/Login/Login.csproj index d76e4353..03a890c1 100644 --- a/Plugins/Login/Login.csproj +++ b/Plugins/Login/Login.csproj @@ -23,7 +23,7 @@ - + diff --git a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj index 8cbfdc5a..3c4a7c0e 100644 --- a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj +++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/Stats/Stats.csproj b/Plugins/Stats/Stats.csproj index 2e2304f1..79344a62 100644 --- a/Plugins/Stats/Stats.csproj +++ b/Plugins/Stats/Stats.csproj @@ -17,7 +17,7 @@ - + diff --git a/Plugins/Web/StatsWeb/StatsWeb.csproj b/Plugins/Web/StatsWeb/StatsWeb.csproj index 19bd0453..65b5a055 100644 --- a/Plugins/Web/StatsWeb/StatsWeb.csproj +++ b/Plugins/Web/StatsWeb/StatsWeb.csproj @@ -14,7 +14,7 @@ Always - + diff --git a/Plugins/Welcome/Welcome.csproj b/Plugins/Welcome/Welcome.csproj index 2c64865e..804718cc 100644 --- a/Plugins/Welcome/Welcome.csproj +++ b/Plugins/Welcome/Welcome.csproj @@ -16,7 +16,7 @@ - + diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 55b4e433..35d7baec 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -4,7 +4,7 @@ Library netcoreapp3.1 RaidMax.IW4MAdmin.SharedLibraryCore - 2020.11.18.1 + 2020.12.20.1 RaidMax Forever None Debug;Release;Prerelease @@ -19,7 +19,7 @@ true MIT Shared Library for IW4MAdmin - 2020.11.18.1 + 2020.12.20.1 From 5cb2d05f33d8b1706898d8a55846ac4eec206ff9 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Thu, 31 Dec 2020 18:48:58 -0600 Subject: [PATCH 025/143] add preset rules, configurable time spans, and separate rule shortcut for issue #180 --- .../Configuration/ApplicationConfiguration.cs | 68 ++++++-- SharedLibraryCore/Utilities.cs | 6 + WebfrontCore/Controllers/ActionController.cs | 156 +++++++++++------- 3 files changed, 154 insertions(+), 76 deletions(-) diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 134eb677..999ddcce 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -1,6 +1,7 @@ using SharedLibraryCore.Configuration.Attributes; using SharedLibraryCore.Interfaces; using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace SharedLibraryCore.Configuration @@ -8,63 +9,79 @@ namespace SharedLibraryCore.Configuration public class ApplicationConfiguration : IBaseConfiguration { [LocalizedDisplayName("SETUP_ENABLE_WEBFRONT")] - [ConfigurationLinked("WebfrontBindUrl", "ManualWebfrontUrl", "WebfrontPrimaryColor", "WebfrontSecondaryColor", "WebfrontCustomBranding")] + [ConfigurationLinked("WebfrontBindUrl", "ManualWebfrontUrl", "WebfrontPrimaryColor", "WebfrontSecondaryColor", + "WebfrontCustomBranding")] public bool EnableWebFront { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_BIND_URL")] public string WebfrontBindUrl { get; set; } + [ConfigurationOptional] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_MANUAL_URL")] public string ManualWebfrontUrl { get; set; } + [ConfigurationOptional] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRIMARY_COLOR")] public string WebfrontPrimaryColor { get; set; } + [ConfigurationOptional] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_SECONDARY_COLOR")] public string WebfrontSecondaryColor { get; set; } + [ConfigurationOptional] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_BRANDING")] public string WebfrontCustomBranding { get; set; } [LocalizedDisplayName("SETUP_ENABLE_MULTIOWN")] public bool EnableMultipleOwners { get; set; } + [LocalizedDisplayName("SETUP_ENABLE_STEPPEDPRIV")] public bool EnableSteppedHierarchy { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_USE_LOCAL_TRANSLATIONS")] public bool UseLocalTranslations { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_IGNORE_BOTS")] public bool IgnoreBots { get; set; } [ConfigurationLinked("CustomSayName")] [LocalizedDisplayName("SETUP_ENABLE_CUSTOMSAY")] public bool EnableCustomSayName { get; set; } + [LocalizedDisplayName("SETUP_SAY_NAME")] public string CustomSayName { get; set; } [LocalizedDisplayName("SETUP_DISPLAY_SOCIAL")] [ConfigurationLinked("SocialLinkAddress", "SocialLinkTitle")] public bool EnableSocialLink { get; set; } + [LocalizedDisplayName("SETUP_SOCIAL_LINK")] public string SocialLinkAddress { get; set; } + [LocalizedDisplayName("SETUP_SOCIAL_TITLE")] public string SocialLinkTitle { get; set; } + [LocalizedDisplayName("SETUP_CONTACT_URI")] public string ContactUri { get; set; } [LocalizedDisplayName("SETUP_USE_CUSTOMENCODING")] [ConfigurationLinked("CustomParserEncoding")] public bool EnableCustomParserEncoding { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENCODING")] public string CustomParserEncoding { get; set; } [LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_WHITELIST")] [ConfigurationLinked("WebfrontConnectionWhitelist")] public bool EnableWebfrontConnectionWhitelist { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_WHITELIST_LIST")] public string[] WebfrontConnectionWhitelist { get; set; } = new string[0]; [LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_LOCALE")] [ConfigurationLinked("CustomLocale")] public bool EnableCustomLocale { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_LOCALE")] public string CustomLocale { get; set; } @@ -76,42 +93,63 @@ namespace SharedLibraryCore.Configuration [LocalizedDisplayName("WEBFRONT_CONFIGURATION_DB_PROVIDER")] public string DatabaseProvider { get; set; } = "sqlite"; + [ConfigurationOptional] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_CONNECTION_STRING")] public string ConnectionString { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_RCON_POLLRATE")] public int RConPollRate { get; set; } = 5000; + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_MAX_TB")] public TimeSpan MaximumTempBanTime { get; set; } = new TimeSpan(24 * 30, 0, 0); + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_COLOR_CODES")] public bool EnableColorCodes { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGE_PERIOD")] public int AutoMessagePeriod { get; set; } + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGES")] public string[] AutoMessages { get; set; } = new string[0]; + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_GLOBAL_RULES")] public string[] GlobalRules { get; set; } = new string[0]; + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_DISALLOWED_NAMES")] public string[] DisallowedClientNames { get; set; } = new string[0]; + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_MAP_CHANGE_DELAY")] public int MapChangeDelaySeconds { get; set; } = 5; - [UIHint("ServerConfiguration")] + + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_BAN_DURATIONS")] + public TimeSpan[] BanDurations { get; set; } = { + TimeSpan.FromHours(1), + TimeSpan.FromHours(6), + TimeSpan.FromDays(1), + TimeSpan.FromDays(2), + TimeSpan.FromDays(7), + TimeSpan.FromDays(31) + }; + + [LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRESET_BAN_REASONS")] + public Dictionary PresetPenaltyReasons { get; set; } = new Dictionary + {{"afk", "Away from keyboard"}, {"ci", "Connection interrupted. Reconnect"}}; + [UIHint("ServerConfiguration")] public ServerConfiguration[] Servers { get; set; } + [ConfigurationIgnore] public string Id { get; set; } + [ConfigurationIgnore] public string SubscriptionId { get; set; } + [ConfigurationIgnore] public MapConfiguration[] Maps { get; set; } + [ConfigurationIgnore] public QuickMessageConfiguration[] QuickMessages { get; set; } + [ConfigurationIgnore] - public string Id { get; set; } - [ConfigurationIgnore] - public string SubscriptionId { get; set; } - [ConfigurationIgnore] - public MapConfiguration[] Maps { get; set; } - [ConfigurationIgnore] - public QuickMessageConfiguration[] QuickMessages { get; set; } - [ConfigurationIgnore] - public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) ? WebfrontBindUrl?.Replace("0.0.0.0", "127.0.0.1") : ManualWebfrontUrl; - [ConfigurationIgnore] - public bool IgnoreServerConnectionLost { get; set; } - [ConfigurationIgnore] - public Uri MasterUrl { get; set; } = new Uri("http://api.raidmax.org:5000"); + public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) + ? WebfrontBindUrl?.Replace("0.0.0.0", "127.0.0.1") + : ManualWebfrontUrl; + + [ConfigurationIgnore] public bool IgnoreServerConnectionLost { get; set; } + [ConfigurationIgnore] public Uri MasterUrl { get; set; } = new Uri("http://api.raidmax.org:5000"); public IBaseConfiguration Generate() { diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index ac8a91a6..ab30705e 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -1003,6 +1003,12 @@ namespace SharedLibraryCore public static string FindRuleForReason(this string reason, ApplicationConfiguration appConfig, Server server) { + // allow for penalty presets + if (appConfig.PresetPenaltyReasons?.ContainsKey(reason.ToLower()) ?? false) + { + return appConfig.PresetPenaltyReasons[reason.ToLower()]; + } + var regex = Regex.Match(reason, @"(rule|serverrule)(\d+)", RegexOptions.IgnoreCase); if (!regex.Success) { diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index a6e1caaa..aadd4f31 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; @@ -25,9 +26,10 @@ namespace WebfrontCore.Controllers private readonly string _unflagCommandName; private readonly string _setLevelCommandName; - public ActionController(IManager manager, IEnumerable registeredCommands) : base(manager) + public ActionController(IManager manager, IEnumerable registeredCommands, + ApplicationConfiguration appConfig) : base(manager) { - _appConfig = manager.GetApplicationSettings().Configuration(); + _appConfig = appConfig; foreach (var cmd in registeredCommands) { @@ -73,23 +75,33 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name = "Reason", - Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + Name = "Reason", + Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], }, new InputInfo() { - Name ="Duration", - Label=Localization["WEBFRONT_ACTION_LABEL_DURATION"], - Type="select", - Values = new Dictionary() - { - {"1", $"1 {Localization["GLOBAL_TIME_HOUR"]}" }, - {"2", $"6 {Localization["GLOBAL_TIME_HOURS"]}" }, - {"3", $"1 {Localization["GLOBAL_TIME_DAY"]}" }, - {"4", $"2 {Localization["GLOBAL_TIME_DAYS"]}" }, - {"5", $"1 {Localization["GLOBAL_TIME_WEEK"]}" }, - {"6", $"{Localization["WEBFRONT_ACTION_SELECTION_PERMANENT"]}" }, - } + Name = "PresetReason", + Type = "select", + Label = Localization["WEBFRONT_ACTION_LABEL_PRESET_REASON"], + Values = GetPresetPenaltyReasons() + }, + new InputInfo() + { + Name = "Duration", + Label = Localization["WEBFRONT_ACTION_LABEL_DURATION"], + Type = "select", + Values = _appConfig.BanDurations + .Select((item, index) => new + { + Id = (index + 1).ToString(), + Value = item.HumanizeForCurrentCulture() + } + ) + .Append(new + { + Id = (_appConfig.BanDurations.Length + 1).ToString(), + Value = Localization["WEBFRONT_ACTION_SELECTION_PERMANENT"] + }).ToDictionary(duration => duration.Id, duration => duration.Value), } }, Action = "BanAsync", @@ -99,34 +111,24 @@ namespace WebfrontCore.Controllers return View("_ActionForm", info); } - public async Task BanAsync(int targetId, string Reason, int Duration) + public async Task BanAsync(int targetId, string reason, int duration, string presetReason = null) { - string duration = string.Empty; - - var loc = Utilities.CurrentLocalization.LocalizationIndex; - - switch (Duration) + var fallthroughReason = presetReason ?? reason; + string command; + // permanent + if (duration > _appConfig.BanDurations.Length) { - case 1: - duration = $"1{loc["GLOBAL_TIME_HOURS"][0]}"; - break; - case 2: - duration = $"6{loc["GLOBAL_TIME_HOURS"][0]}"; - break; - case 3: - duration = $"1{loc["GLOBAL_TIME_DAYS"][0]}"; - break; - case 4: - duration = $"2{loc["GLOBAL_TIME_DAYS"][0]}"; - break; - case 5: - duration = $"1{loc["GLOBAL_TIME_WEEKS"][0]}"; - break; + command = $"{_appConfig.CommandPrefix}{_banCommandName} @{targetId} {fallthroughReason}"; + } + // temporary ban + else + { + var durationSpan = _appConfig.BanDurations[duration - 1]; + var durationValue = durationSpan.TotalHours.ToString(CultureInfo.InvariantCulture) + + Localization["GLOBAL_TIME_HOURS"][0]; + command = + $"{_appConfig.CommandPrefix}{_tempbanCommandName} @{targetId} {durationValue} {fallthroughReason}"; } - - string command = Duration == 6 ? - $"{_appConfig.CommandPrefix}{_banCommandName} @{targetId} {Reason}" : - $"{_appConfig.CommandPrefix}{_tempbanCommandName} @{targetId} {duration} {Reason}"; var server = Manager.GetServers().First(); @@ -147,8 +149,8 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name = "Reason", - Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + Name = "Reason", + Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], } }, Action = "UnbanAsync", @@ -197,7 +199,7 @@ namespace WebfrontCore.Controllers public async Task LoginAsync(int clientId, string password) { - return await Task.FromResult(RedirectToAction("LoginAsync", "Account", new { clientId, password })); + return await Task.FromResult(RedirectToAction("LoginAsync", "Account", new {clientId, password})); } public IActionResult EditForm() @@ -210,14 +212,14 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name ="level", - Label=Localization["WEBFRONT_PROFILE_LEVEL"], - Type="select", + Name = "level", + Label = Localization["WEBFRONT_PROFILE_LEVEL"], + Type = "select", Values = Enum.GetValues(typeof(Permission)).OfType() .Where(p => p <= Client.Level) .Where(p => p != Permission.Banned) .Where(p => p != Permission.Flagged) - .ToDictionary(p => p.ToString(), p=> p.ToLocalizedLevelName()) + .ToDictionary(p => p.ToString(), p => p.ToLocalizedLevelName()) }, }, Action = "EditAsync", @@ -255,7 +257,10 @@ namespace WebfrontCore.Controllers public string GenerateLoginTokenAsync() { var state = Manager.TokenAuthenticator.GenerateNextToken(Client.NetworkId); - return string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GENERATETOKEN_SUCCESS"], state.Token, $"{state.RemainingTime} {Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_MINUTES"]}", Client.ClientId); + return string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GENERATETOKEN_SUCCESS"], + state.Token, + $"{state.RemainingTime} {Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_MINUTES"]}", + Client.ClientId); } public IActionResult ChatForm(long id) @@ -321,9 +326,16 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name = "reason", - Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], - } + Name = "reason", + Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + }, + new InputInfo() + { + Name = "PresetReason", + Type = "select", + Label = Localization["WEBFRONT_ACTION_LABEL_PRESET_REASON"], + Values = GetPresetPenaltyReasons() + }, }, Action = "FlagAsync", ShouldRefresh = true @@ -332,14 +344,14 @@ namespace WebfrontCore.Controllers return View("_ActionForm", info); } - public async Task FlagAsync(int targetId, string reason) + public async Task FlagAsync(int targetId, string reason, string presetReason = null) { var server = Manager.GetServers().First(); return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new { serverId = server.EndPoint, - command = $"{_appConfig.CommandPrefix}{_flagCommandName} @{targetId} {reason}" + command = $"{_appConfig.CommandPrefix}{_flagCommandName} @{targetId} {presetReason ?? reason}" })); } @@ -353,8 +365,8 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name = "reason", - Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + Name = "reason", + Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], } }, Action = "UnflagAsync", @@ -385,8 +397,15 @@ namespace WebfrontCore.Controllers { new InputInfo() { - Name = "reason", - Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + Name = "reason", + Label = Localization["WEBFRONT_ACTION_LABEL_REASON"], + }, + new InputInfo() + { + Name = "PresetReason", + Type = "select", + Label = Localization["WEBFRONT_ACTION_LABEL_PRESET_REASON"], + Values = GetPresetPenaltyReasons() }, new InputInfo() { @@ -402,7 +421,7 @@ namespace WebfrontCore.Controllers return View("_ActionForm", info); } - public async Task KickAsync(int targetId, string reason) + public async Task KickAsync(int targetId, string reason, string presetReason = null) { var client = Manager.GetActiveClients().FirstOrDefault(_client => _client.ClientId == targetId); @@ -414,8 +433,23 @@ namespace WebfrontCore.Controllers return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new { serverId = client.CurrentServer.EndPoint, - command = $"{_appConfig.CommandPrefix}{_kickCommandName} {client.ClientNumber} {reason}" + command = $"{_appConfig.CommandPrefix}{_kickCommandName} {client.ClientNumber} {presetReason ?? reason}" })); } + + private Dictionary GetPresetPenaltyReasons() => _appConfig.PresetPenaltyReasons.Values + .Concat(_appConfig.GlobalRules) + .Concat(_appConfig.Servers.SelectMany(server => server.Rules)) + .Distinct() + .Select((value, index) => new + { + Value = value + }) + // this is used for the default empty optional value + .Prepend(new + { + Value = "" + }) + .ToDictionary(item => item.Value, item => item.Value); } -} +} \ No newline at end of file From 843c01061d87c9437874506a12db1ec5ce9e0eaa Mon Sep 17 00:00:00 2001 From: RaidMax Date: Fri, 8 Jan 2021 19:21:23 -0600 Subject: [PATCH 026/143] update 'uptime' output use translations for certain webfront page meta that was neglected update plutonium parsers to not use new line in notices as it is not supported --- Plugins/ScriptPlugins/ParserPIW5.js | 3 ++- Plugins/ScriptPlugins/ParserPT6.js | 3 ++- SharedLibraryCore/Commands/NativeCommands.cs | 4 ++-- SharedLibraryCore/Configuration/ApplicationConfiguration.cs | 2 +- WebfrontCore/Controllers/AccountController.cs | 1 - WebfrontCore/Controllers/ClientController.cs | 4 ++-- WebfrontCore/Controllers/ConsoleController.cs | 4 ++-- WebfrontCore/Controllers/HomeController.cs | 4 ++-- WebfrontCore/Controllers/PenaltyController.cs | 4 ++-- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Plugins/ScriptPlugins/ParserPIW5.js b/Plugins/ScriptPlugins/ParserPIW5.js index 9df8f0d7..1cd9746e 100644 --- a/Plugins/ScriptPlugins/ParserPIW5.js +++ b/Plugins/ScriptPlugins/ParserPIW5.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.5, + version: 0.6, name: 'Plutonium IW5 Parser', isParser: true, @@ -26,6 +26,7 @@ var plugin = { rconParser.Configuration.Dvar.AddMapping(107, 2); rconParser.Configuration.WaitForResponse = true; rconParser.Configuration.CanGenerateLogPath = true; + rconParser.Configuration.NoticeLineSeparator = '. '; rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +lastmsg +address +qport +rate *'; rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(?:[0-1]{1}) +([0-9]{1,4}|[A-Z]{4}) +([a-f|A-F|0-9]{16}) +(.+?) +(?:[0-9]+) +(\\d+\\.\\d+\\.\\d+\\.\\d+\\:-?\\d{1,5}|0+\\.0+:-?\\d{1,5}|loopback) +(?:-?[0-9]+) +(?:[0-9]+) *$'; diff --git a/Plugins/ScriptPlugins/ParserPT6.js b/Plugins/ScriptPlugins/ParserPT6.js index 08026b21..7caa1775 100644 --- a/Plugins/ScriptPlugins/ParserPT6.js +++ b/Plugins/ScriptPlugins/ParserPT6.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax, Xerxes', - version: 0.8, + version: 0.9, name: 'Plutonium T6 Parser', isParser: true, @@ -26,6 +26,7 @@ var plugin = { rconParser.Configuration.Dvar.AddMapping(106, 1); rconParser.Configuration.Dvar.AddMapping(107, 2); rconParser.Configuration.WaitForResponse = false; + rconParser.Configuration.NoticeLineSeparator = '. '; rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +lastmsg +address +qport +rate *'; rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +([0-9]+) +(?:[0-1]{1}) +([0-9]+) +([A-F0-9]+|0) +(.+?) +(?:[0-9]+) +(\\d+\\.\\d+\\.\\d+\\.\\d+\\:-?\\d{1,5}|0+\\.0+:-?\\d{1,5}|loopback) +(?:-?[0-9]+) +(?:[0-9]+) *$'; diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 6b8d0dbd..3926f83b 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -830,9 +830,9 @@ namespace SharedLibraryCore.Commands public override Task ExecuteAsync(GameEvent E) { - TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime; + var uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime; var loc = _translationLookup; - E.Origin.Tell(loc["COMMANDS_UPTIME_TEXT"].FormatExt(uptime.Days, uptime.Hours, uptime.Minutes)); + E.Origin.Tell(loc["COMMANDS_UPTIME_TEXT"].FormatExt(uptime.HumanizeForCurrentCulture(4))); return Task.CompletedTask; } } diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 999ddcce..35290ad8 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -129,7 +129,7 @@ namespace SharedLibraryCore.Configuration TimeSpan.FromDays(1), TimeSpan.FromDays(2), TimeSpan.FromDays(7), - TimeSpan.FromDays(31) + TimeSpan.FromDays(30) }; [LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRESET_BAN_REASONS")] diff --git a/WebfrontCore/Controllers/AccountController.cs b/WebfrontCore/Controllers/AccountController.cs index 798ab98b..6041e9c8 100644 --- a/WebfrontCore/Controllers/AccountController.cs +++ b/WebfrontCore/Controllers/AccountController.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using SharedLibraryCore; using SharedLibraryCore.Interfaces; diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index a7e79261..547d3b7a 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -131,8 +131,8 @@ namespace WebfrontCore.Controllers } ViewBag.Title = Localization["WEBFRONT_CLIENT_PRIVILEGED_TITLE"]; - ViewBag.Description = "List of all privileged clients on IW4MAdmin"; - ViewBag.Keywords = "IW4MAdmin, privileged, admins, clients, administrators"; + ViewBag.Description = Localization["WEBFRONT_DESCRIPTION_PRIVILEGED"]; + ViewBag.Keywords = Localization["WEBFRONT_KEYWORDS_PRIVILEGED"]; return View("Privileged/Index", adminsDict); } diff --git a/WebfrontCore/Controllers/ConsoleController.cs b/WebfrontCore/Controllers/ConsoleController.cs index e3e8f5b9..20365208 100644 --- a/WebfrontCore/Controllers/ConsoleController.cs +++ b/WebfrontCore/Controllers/ConsoleController.cs @@ -26,9 +26,9 @@ namespace WebfrontCore.Controllers ID = s.EndPoint, }); - ViewBag.Description = "Use the IW4MAdmin web console to execute commands"; + ViewBag.Description = Localization["WEFBRONT_DESCRIPTION_CONSOLE"]; ViewBag.Title = Localization["WEBFRONT_CONSOLE_TITLE"]; - ViewBag.Keywords = "IW4MAdmin, console, execute, commands"; + ViewBag.Keywords = Localization["WEBFRONT_KEYWORDS_CONSOLE"]; return View(activeServers); } diff --git a/WebfrontCore/Controllers/HomeController.cs b/WebfrontCore/Controllers/HomeController.cs index fbc03f6d..d6d73bb9 100644 --- a/WebfrontCore/Controllers/HomeController.cs +++ b/WebfrontCore/Controllers/HomeController.cs @@ -24,9 +24,9 @@ namespace WebfrontCore.Controllers public async Task Index(Game? game = null) { - ViewBag.Description = "IW4MAdmin is a complete server administration tool for IW4x."; + ViewBag.Description = Localization["WEBFRONT_DESCRIPTION_HOME"]; ViewBag.Title = Localization["WEBFRONT_HOME_TITLE"]; - ViewBag.Keywords = "IW4MAdmin, server, administration, IW4x, MW2, Modern Warfare 2"; + ViewBag.Keywords = Localization["WEBFRONT_KEWORDS_HOME"]; var servers = Manager.GetServers().Where(_server => !game.HasValue ? true : _server.GameName == game); diff --git a/WebfrontCore/Controllers/PenaltyController.cs b/WebfrontCore/Controllers/PenaltyController.cs index 0b40b137..7620a165 100644 --- a/WebfrontCore/Controllers/PenaltyController.cs +++ b/WebfrontCore/Controllers/PenaltyController.cs @@ -22,9 +22,9 @@ namespace WebfrontCore.Controllers public IActionResult List(PenaltyType showOnly = PenaltyType.Any, bool hideAutomatedPenalties = true) { - ViewBag.Description = "List of all the recent penalties (bans, kicks, warnings) on IW4MAdmin"; + ViewBag.Description = Localization["WEBFRONT_DESCRIPTION_PENALTIES"]; ViewBag.Title = Localization["WEBFRONT_PENALTY_TITLE"]; - ViewBag.Keywords = "IW4MAdmin, penalties, ban, kick, warns"; + ViewBag.Keywords = Localization["WEBFRONT_KEYWORDS_PENALTIES"]; ViewBag.HideAutomatedPenalties = hideAutomatedPenalties; return View(showOnly); From 28373b93254e0b41e3e8527e0d7ea9addd4bee92 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 9 Jan 2021 12:37:20 -0600 Subject: [PATCH 027/143] implement admin "privacy" for issue #185 --- SharedLibraryCore/BaseController.cs | 1 + .../Configuration/ApplicationConfiguration.cs | 2 ++ WebfrontCore/Views/Client/Find/Index.cshtml | 18 ++++++++++-- .../Views/Client/Profile/Index.cshtml | 29 ++++++++++++++----- WebfrontCore/Views/Penalty/_Penalty.cshtml | 14 +++++++-- WebfrontCore/Views/Shared/_Layout.cshtml | 9 +++++- 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/SharedLibraryCore/BaseController.cs b/SharedLibraryCore/BaseController.cs index 63e3a316..d03dfac7 100644 --- a/SharedLibraryCore/BaseController.cs +++ b/SharedLibraryCore/BaseController.cs @@ -134,6 +134,7 @@ namespace SharedLibraryCore ViewBag.Localization = Utilities.CurrentLocalization.LocalizationIndex; ViewBag.CustomBranding = Manager.GetApplicationSettings().Configuration().WebfrontCustomBranding ?? "IW4MAdmin"; ViewBag.EnableColorCodes = Manager.GetApplicationSettings().Configuration().EnableColorCodes; + ViewBag.EnablePrivilegedUserPrivacy = Manager.GetApplicationSettings().Configuration().EnablePrivilegedUserPrivacy; base.OnActionExecuting(context); } diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 35290ad8..f74ee0e6 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -135,6 +135,8 @@ namespace SharedLibraryCore.Configuration [LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRESET_BAN_REASONS")] public Dictionary PresetPenaltyReasons { get; set; } = new Dictionary {{"afk", "Away from keyboard"}, {"ci", "Connection interrupted. Reconnect"}}; + [LocalizedDisplayName(("WEBFRONT_CONFIGURATION_ENABLE_PRIVILEGED_USER_PRIVACY"))] + public bool EnablePrivilegedUserPrivacy { get; set; } [UIHint("ServerConfiguration")] public ServerConfiguration[] Servers { get; set; } diff --git a/WebfrontCore/Views/Client/Find/Index.cshtml b/WebfrontCore/Views/Client/Find/Index.cshtml index 81d95162..edcf8e1d 100644 --- a/WebfrontCore/Views/Client/Find/Index.cshtml +++ b/WebfrontCore/Views/Client/Find/Index.cshtml @@ -20,7 +20,14 @@ -
@client.Level
+ @if (!ViewBag.Authorized && ViewBag.EnablePrivilegedUserPrivacy) + { +
@loc["GLOBAL_PERMISSION_USER"]
+ } + else + { +
@client.Level
+ }
@client.LastConnectionText
} @@ -41,7 +48,14 @@ -
@client.Level
+ @if (!ViewBag.Authorized && ViewBag.EnablePrivilegedUserPrivacy) + { +
@loc["GLOBAL_PERMISSION_USER"]
+ } + else + { +
@client.Level
+ }
@client.LastConnectionText
} diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index 36fdaa26..8d967d06 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -16,7 +16,7 @@
-
+
@if (string.IsNullOrEmpty(gravatarUrl)) { @shortCode @@ -74,9 +74,19 @@ } else { -
- @Model.Level -
+ if (!ViewBag.Authorized && ViewBag.EnablePrivilegedUserPrivacy) + { +
+ @ViewBag.Localization["GLOBAL_PERMISSION_USER"] +
+ } + + else + { +
+ @Model.Level +
+ } }
@if (ViewBag.Authorized) @@ -142,11 +152,14 @@
-
-
- @await Component.InvokeAsync("ProfileMetaList", new { clientId = Model.ClientId, count = 30, offset = 0, startAt = DateTime.UtcNow, metaType = Model.MetaFilterType }) +@if ((!ViewBag.Authorized && !ViewBag.EnablePrivilegedUserPrivacy) || ViewBag.Authorized) +{ +
+
+ @await Component.InvokeAsync("ProfileMetaList", new {clientId = Model.ClientId, count = 30, offset = 0, startAt = DateTime.UtcNow, metaType = Model.MetaFilterType}) +
-
+}
diff --git a/WebfrontCore/Views/Penalty/_Penalty.cshtml b/WebfrontCore/Views/Penalty/_Penalty.cshtml index 689b7fd2..fa9d0e5d 100644 --- a/WebfrontCore/Views/Penalty/_Penalty.cshtml +++ b/WebfrontCore/Views/Penalty/_Penalty.cshtml @@ -31,7 +31,12 @@ @loc["WEBFRONT_PENALTY_TEMPLATE_ADMIN"] - @Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel }) + @Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", + "Client", + new { id = Model.PunisherId }, + new { @class = !ViewBag.Authorized && ViewBag.EnablePrivilegedUserPrivacy + ? "level-color-0" + : "level-color-" + (int)Model.PunisherLevel }) @@ -64,7 +69,12 @@ - @Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel }) + @Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", + "Client", + new { id = Model.PunisherId }, + new { @class = !ViewBag.Authorized && ViewBag.EnablePrivilegedUserPrivacy + ? "level-color-0" + : "level-color-" + (int)Model.PunisherLevel }) @{ diff --git a/WebfrontCore/Views/Shared/_Layout.cshtml b/WebfrontCore/Views/Shared/_Layout.cshtml index abf01e8f..d584e0a2 100644 --- a/WebfrontCore/Views/Shared/_Layout.cshtml +++ b/WebfrontCore/Views/Shared/_Layout.cshtml @@ -35,7 +35,14 @@
/// message content to send to client - public GameEvent Tell(String message) + public GameEvent Tell(string message) { var e = new GameEvent() { @@ -141,8 +141,12 @@ namespace SharedLibraryCore.Database.Models Target = this, Owner = CurrentServer, Type = GameEvent.EventType.Tell, - Data = message + Data = message, + CorrelationId = CurrentServer.Manager.ProcessingEvents.Values + .FirstOrDefault(ev => ev.Type == GameEvent.EventType.Command && (ev.Origin?.ClientId == ClientId || ev.ImpersonationOrigin?.ClientId == ClientId))?.CorrelationId ?? Guid.NewGuid() }; + + e.Output.Add(message.StripColors()); CurrentServer?.Manager.AddEvent(e); return e; diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 84f16916..5449d828 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -172,22 +172,6 @@ namespace SharedLibraryCore Console.WriteLine(message.StripColors()); Console.ForegroundColor = ConsoleColor.Gray; } - - // prevent this from queueing up too many command responses - if (CommandResult.Count > 15) - { - CommandResult.RemoveAt(0); - } - - // it was a remote command so we need to add it to the command result queue - if (target.ClientNumber < 0) - { - CommandResult.Add(new CommandResponseInfo() - { - Response = message.StripColors(), - ClientId = target.ClientId - }); - } } /// @@ -347,8 +331,5 @@ namespace SharedLibraryCore // only here for performance private readonly bool CustomSayEnabled; private readonly string CustomSayName; - - //Remote - public IList CommandResult = new List(); } } diff --git a/WebfrontCore/Controllers/API/ClientController.cs b/WebfrontCore/Controllers/API/ClientController.cs index 9f149635..90bb610b 100644 --- a/WebfrontCore/Controllers/API/ClientController.cs +++ b/WebfrontCore/Controllers/API/ClientController.cs @@ -3,9 +3,15 @@ using Microsoft.AspNetCore.Mvc; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using System; +using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.Extensions.Logging; +using SharedLibraryCore; +using SharedLibraryCore.Services; using WebfrontCore.Controllers.API.Dtos; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -15,29 +21,34 @@ namespace WebfrontCore.Controllers.API /// api controller for client operations /// [ApiController] - [Route("api/client")] - public class ClientController : ControllerBase + [Route("api/[controller]")] + public class ClientController : BaseController { private readonly IResourceQueryHelper _clientQueryHelper; private readonly ILogger _logger; + private readonly ClientService _clientService; - public ClientController(ILogger logger, IResourceQueryHelper clientQueryHelper) + public ClientController(ILogger logger, + IResourceQueryHelper clientQueryHelper, + ClientService clientService, IManager manager) : base(manager) { _logger = logger; _clientQueryHelper = clientQueryHelper; + _clientService = clientService; } [HttpGet("find")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async Task FindAsync([FromQuery]FindClientRequest request) + public async Task FindAsync([FromQuery] FindClientRequest request) { if (!ModelState.IsValid) { return BadRequest(new ErrorResponse() { - Messages = ModelState.Values.SelectMany(_value => _value.Errors.Select(_error => _error.ErrorMessage)).ToArray() + Messages = ModelState.Values + .SelectMany(_value => _value.Errors.Select(_error => _error.ErrorMessage)).ToArray() }); } @@ -58,9 +69,84 @@ namespace WebfrontCore.Controllers.API return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse() { - Messages = new[] { e.Message } + Messages = new[] {e.Message} }); } } + + + [HttpPost("{clientId:int}/login")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task LoginAsync([FromRoute] int clientId, + [FromBody, Required] PasswordRequest request) + { + if (clientId == 0) + { + return Unauthorized(); + } + + HttpContext.Request.Cookies.TryGetValue(".AspNetCore.Cookies", out var cookie); + + if (Authorized) + { + return Ok(); + } + + try + { + var privilegedClient = await _clientService.GetClientForLogin(clientId); + var loginSuccess = false; + + if (!Authorized) + { + loginSuccess = + Manager.TokenAuthenticator.AuthorizeToken(privilegedClient.NetworkId, request.Password) || + (await Task.FromResult(SharedLibraryCore.Helpers.Hashing.Hash(request.Password, + privilegedClient.PasswordSalt)))[0] == privilegedClient.Password; + } + + if (loginSuccess) + { + var claims = new[] + { + new Claim(ClaimTypes.NameIdentifier, privilegedClient.Name), + new Claim(ClaimTypes.Role, privilegedClient.Level.ToString()), + new Claim(ClaimTypes.Sid, privilegedClient.ClientId.ToString()), + new Claim(ClaimTypes.PrimarySid, privilegedClient.NetworkId.ToString("X")) + }; + + var claimsIdentity = new ClaimsIdentity(claims, "login"); + var claimsPrinciple = new ClaimsPrincipal(claimsIdentity); + await SignInAsync(claimsPrinciple); + + return Ok(); + } + } + + catch (Exception) + { + return Unauthorized(); + } + + return Unauthorized(); + } + + [HttpPost("{clientId:int}/logout")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task LogoutAsync() + { + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + + return Ok(); + } + + public class PasswordRequest + { + public string Password { get; set; } + } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/API/Models/CommandRequest.cs b/WebfrontCore/Controllers/API/Models/CommandRequest.cs new file mode 100644 index 00000000..64859a6a --- /dev/null +++ b/WebfrontCore/Controllers/API/Models/CommandRequest.cs @@ -0,0 +1,7 @@ +namespace WebfrontCore.Controllers.API.Models +{ + public class CommandRequest + { + public string Command { get; set; } + } +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/API/Server.cs b/WebfrontCore/Controllers/API/Server.cs new file mode 100644 index 00000000..40903288 --- /dev/null +++ b/WebfrontCore/Controllers/API/Server.cs @@ -0,0 +1,93 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using SharedLibraryCore; +using SharedLibraryCore.Interfaces; +using WebfrontCore.Controllers.API.Models; + +namespace WebfrontCore.Controllers.API +{ + [ApiController] + [Route("api/[controller]")] + public class Server : BaseController + { + + public Server(IManager manager) : base(manager) + { + } + + [HttpGet] + public IActionResult Index() + { + return new JsonResult(Manager.GetServers().Select(server => new + { + Id = server.EndPoint, + server.Hostname, + server.IP, + server.Port + })); + } + + [HttpGet("{id}")] + public IActionResult GetServerById(string id) + { + var foundServer = Manager.GetServers().FirstOrDefault(server => server.EndPoint == long.Parse(id)); + + if (foundServer == null) + { + return new NotFoundResult(); + } + + return new JsonResult(new + { + Id = foundServer.EndPoint, + foundServer.Hostname, + foundServer.IP, + foundServer.Port + }); + } + + [HttpPost("{id}/execute")] + public async Task ExecuteCommandForServer(string id, [FromBody] CommandRequest commandRequest) + { + if (!Authorized) + { + return Unauthorized(); + } + + var foundServer = Manager.GetServers().FirstOrDefault(server => server.EndPoint == long.Parse(id)); + + if (foundServer == null) + { + return new BadRequestObjectResult($"No server with id '{id}' was found"); + } + + if (string.IsNullOrEmpty(commandRequest.Command)) + { + return new BadRequestObjectResult("Command cannot be empty"); + } + + var start = DateTime.Now; + Client.CurrentServer = foundServer; + + var commandEvent = new GameEvent() + { + Type = GameEvent.EventType.Command, + Owner = foundServer, + Origin = Client, + Data = commandRequest.Command, + Extra = commandRequest.Command + }; + + Manager.AddEvent(commandEvent); + var completedEvent = await commandEvent.WaitAsync(Utilities.DefaultCommandTimeout, foundServer.Manager.CancellationToken); + + return new JsonResult(new + { + ExecutionTimeMs = Math.Round((DateTime.Now - start).TotalMilliseconds, 0), + completedEvent.Output + }); + } + } +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/ConsoleController.cs b/WebfrontCore/Controllers/ConsoleController.cs index 20365208..5d2bddad 100644 --- a/WebfrontCore/Controllers/ConsoleController.cs +++ b/WebfrontCore/Controllers/ConsoleController.cs @@ -52,8 +52,10 @@ namespace WebfrontCore.Controllers var remoteEvent = new GameEvent() { Type = GameEvent.EventType.Command, - Data = command.StartsWith(_appconfig.CommandPrefix) || command.StartsWith(_appconfig.BroadcastCommandPrefix) ? - command : $"{_appconfig.CommandPrefix}{command}", + Data = command.StartsWith(_appconfig.CommandPrefix) || + command.StartsWith(_appconfig.BroadcastCommandPrefix) + ? command + : $"{_appconfig.CommandPrefix}{command}", Origin = client, Owner = server, IsRemote = true @@ -65,7 +67,8 @@ namespace WebfrontCore.Controllers try { // wait for the event to process - var completedEvent = await remoteEvent.WaitAsync(Utilities.DefaultCommandTimeout, server.Manager.CancellationToken); + var completedEvent = + await remoteEvent.WaitAsync(Utilities.DefaultCommandTimeout, server.Manager.CancellationToken); if (completedEvent.FailReason == GameEvent.EventFailReason.Timeout) { @@ -81,13 +84,11 @@ namespace WebfrontCore.Controllers else { - response = response = server.CommandResult.Where(c => c.ClientId == client.ClientId).ToArray(); - } - - // remove the added command response - for (int i = 0; i < response?.Length; i++) - { - server.CommandResult.Remove(response[i]); + response = completedEvent.Output.Select(output => new CommandResponseInfo() + { + Response = output, + ClientId = client.ClientId + }).ToArray(); } } @@ -106,4 +107,4 @@ namespace WebfrontCore.Controllers return View("_Response", response); } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index f4986473..1ec1205d 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -115,6 +115,7 @@ namespace WebfrontCore services.AddSingleton(Program.ApplicationServiceProvider.GetService>()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); + services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. From c419d80b577c94c3d0dfb8617a47c0dc34c9837e Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 17 Jan 2021 22:12:18 -0600 Subject: [PATCH 030/143] preemptive checks --- Application/ApplicationManager.cs | 2 +- Application/RCon/RConConnection.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index e16ec046..7ecafa7b 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -196,7 +196,7 @@ namespace IW4MAdmin.Application } // we don't want to remove events that are correlated to command - if (ProcessingEvents.Values.Count(gameEvent => gameEvent.CorrelationId == newEvent.CorrelationId) == 1) + if (ProcessingEvents.Values.ToList()?.Count(gameEvent => gameEvent.CorrelationId == newEvent.CorrelationId) == 1) { ProcessingEvents.Remove(newEvent.Id, out _); } diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 6995373d..8e0e8725 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -435,6 +435,7 @@ namespace IW4MAdmin.Application.RCon if (bufferSpaceAvailable >= 0 ) { _log.LogWarning("Not enough buffer space to store incoming data {bytesNeeded} additional bytes required", bufferSpaceAvailable); + continue; } state.ReceiveEventArgs.SetBuffer(state.ReceiveBuffer, totalBytesTransferred, sock.Available); From 2512b9f25183dc3d0e283253cc5b22c90cdeca54 Mon Sep 17 00:00:00 2001 From: Sparker <60593579+Sparker-99@users.noreply.github.com> Date: Thu, 21 Jan 2021 00:13:44 +0530 Subject: [PATCH 031/143] Added iw6 aliases (#184) --- Application/DefaultSettings.json | 151 ++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json index 811565d1..bac00efb 100644 --- a/Application/DefaultSettings.json +++ b/Application/DefaultSettings.json @@ -1,4 +1,4 @@ -{ +{ "AutoMessagePeriod": 60, "AutoMessages": [ "This server uses ^5IW4M Admin v{{VERSION}} ^7get it at ^5raidmax.org/IW4MAdmin", @@ -884,6 +884,155 @@ "Name": "zm_transit" } ] + }, + { + "Game": "IW6", + "Maps": [ + { + "Alias": "Prision Break", + "Name": "mp_prisonbreak" + }, + { + "Alias": "Octane", + "Name": "mp_dart" + }, + { + "Alias": "Tremor", + "Name": "mp_lonestar" + }, + { + "Alias": "Freight", + "Name": "mp_frag" + }, + { + "Alias": "Whiteout", + "Name": "mp_snow" + }, + { + "Alias": "Stormfront", + "Name": "mp_fahrenheit" + }, + { + "Alias": "Siege", + "Name": "mp_hashima" + }, + { + "Alias": "Warhawk", + "Name": "mp_warhawk" + }, + { + "Alias": "Sovereign", + "Name": "mp_sovereign" + }, + { + "Alias": "Overload", + "Name": "mp_zebra" + }, + { + "Alias": "Stonehaven", + "Name": "mp_skeleton" + }, + { + "Alias": "Chasm", + "Name": "mp_chasm" + }, + { + "Alias": "Flooded", + "Name": "mp_flooded" + }, + { + "Alias": "Strikezone", + "Name": "mp_strikezone" + }, + { + "Alias": "Free Fall", + "Name": "mp_descent_new" + }, + { + "Alias": "Unearthed", + "Name": "mp_dome_ns" + }, + { + "Alias": "Collision", + "Name": "mp_ca_impact" + }, + { + "Alias": "Behemoth", + "Name": "mp_ca_behemoth" + }, + { + "Alias": "Ruins", + "Name": "mp_battery3" + }, + { + "Alias": "Pharaoh", + "Name": "mp_dig" + }, + { + "Alias": "Favela", + "Name": "mp_favela_iw6" + }, + { + "Alias": "Mutiny", + "Name": "mp_pirate" + }, + { + "Alias": "Departed", + "Name": "mp_zulu" + }, + { + "Alias": "Dynasty", + "Name": "mp_conflict" + }, + { + "Alias": "Goldrush", + "Name": "mp_mine" + }, + { + "Alias": "Showtime", + "Name": "mp_shipment_ns" + }, + { + "Alias": "Subzero", + "Name": "mp_zerosub" + }, + { + "Alias": "Ignition", + "Name": "mp_boneyard_ns" + }, + { + "Alias": "Containment", + "Name": "mp_ca_red_river" + }, + { + "Alias": "Bayview", + "Name": "mp_ca_rumble" + }, + { + "Alias": "Fog", + "Name": "mp_swamp" + }, + { + "Alias": "Point of Contact", + "Name": "mp_alien_town" + }, + { + "Alias": "Nightfall", + "Name": "mp_alien_armory" + }, + { + "Alias": "Mayday", + "Name": "mp_alien_beacon" + }, + { + "Alias": "Awakening", + "Name": "mp_alien_dlc3" + }, + { + "Alias": "Exodus", + "Name": "mp_alien_last" + } + ] } ] } From c4f19e94efc88cab8e105d7ee98d3f84d5c3f93a Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 24 Jan 2021 11:47:19 -0600 Subject: [PATCH 032/143] implement custom tag (descriptor) feature allow override of level names through configuration few small fixes/improvements --- Application/IW4MServer.cs | 7 + Application/Main.cs | 11 +- Application/Misc/MetaService.cs | 115 ++- Plugins/Welcome/Plugin.cs | 47 +- SharedLibraryCore/Command.cs | 4 +- .../Commands/AddClientTagCommand.cs | 37 + SharedLibraryCore/Commands/ListClientTags.cs | 33 + SharedLibraryCore/Commands/NativeCommands.cs | 62 +- .../Commands/RemoveClientTagCommand.cs | 37 + .../Commands/SetClientTagCommand.cs | 49 + .../Commands/UnsetClientTagCommand.cs | 40 + .../Configuration/ApplicationConfiguration.cs | 6 + SharedLibraryCore/Database/DatabaseContext.cs | 8 +- SharedLibraryCore/Database/Models/EFMeta.cs | 15 +- SharedLibraryCore/Dtos/PlayerInfo.cs | 1 + SharedLibraryCore/Events/GameEvent.cs | 5 + SharedLibraryCore/Interfaces/IMetaService.cs | 33 +- ...teEFMetaToSupportNonClientMeta.Designer.cs | 929 +++++++++++++++++ ...3921_UpdateEFMetaToSupportNonClientMeta.cs | 52 + ...pdateEFMetaToSupportLinkedMeta.Designer.cs | 939 +++++++++++++++++ ...4170830_UpdateEFMetaToSupportLinkedMeta.cs | 43 + .../MySqlDatabaseContextModelSnapshot.cs | 22 +- ...teEFMetaToSupportNonClientMeta.Designer.cs | 946 +++++++++++++++++ ...4304_UpdateEFMetaToSupportNonClientMeta.cs | 52 + ...pdateEFMetaToSupportLinkedMeta.Designer.cs | 956 ++++++++++++++++++ ...4170956_UpdateEFMetaToSupportLinkedMeta.cs | 43 + .../PostgresqlDatabaseContextModelSnapshot.cs | 50 +- ...portNonClientMetaAndLinkedMeta.Designer.cs | 938 +++++++++++++++++ ...MetaToSupportNonClientMetaAndLinkedMeta.cs | 128 +++ .../SqliteDatabaseContextModelSnapshot.cs | 18 +- SharedLibraryCore/PartialEntities/EFClient.cs | 20 +- SharedLibraryCore/Server.cs | 11 + SharedLibraryCore/SharedLibraryCore.csproj | 6 + SharedLibraryCore/Utilities.cs | 8 +- .../Controllers/API/ClientController.cs | 2 - WebfrontCore/Controllers/ActionController.cs | 2 +- WebfrontCore/Controllers/ClientController.cs | 7 + .../ViewComponents/ServerListViewComponent.cs | 3 +- .../Views/Client/Privileged/Index.cshtml | 2 +- .../Views/Server/_ClientActivity.cshtml | 73 +- 40 files changed, 5576 insertions(+), 184 deletions(-) create mode 100644 SharedLibraryCore/Commands/AddClientTagCommand.cs create mode 100644 SharedLibraryCore/Commands/ListClientTags.cs create mode 100644 SharedLibraryCore/Commands/RemoveClientTagCommand.cs create mode 100644 SharedLibraryCore/Commands/SetClientTagCommand.cs create mode 100644 SharedLibraryCore/Commands/UnsetClientTagCommand.cs create mode 100644 SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs create mode 100644 SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs create mode 100644 SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 5398b481..a58f026f 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -300,6 +300,13 @@ namespace IW4MAdmin Time = DateTime.UtcNow }); + var clientTag = await _metaService.GetPersistentMeta(EFMeta.ClientTag, E.Origin); + + if (clientTag?.LinkedMeta != null) + { + E.Origin.Tag = clientTag.LinkedMeta.Value; + } + await E.Origin.OnJoin(E.Origin.IPAddress); } } diff --git a/Application/Main.cs b/Application/Main.cs index 3460dfc7..c09159ad 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -186,7 +186,7 @@ namespace IW4MAdmin.Application await Task.WhenAll(tasks); logger.LogInformation("Shutdown completed successfully"); - Console.Write(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); + Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); } @@ -318,6 +318,15 @@ namespace IW4MAdmin.Application appConfigHandler.Set(appConfig); appConfigHandler.Save(); } + + // register override level names + foreach (var (key, value) in appConfig.OverridePermissionLevelNames) + { + if (!Utilities.PermissionLevelOverrides.ContainsKey(key)) + { + Utilities.PermissionLevelOverrides.Add(key, value); + } + } // build the dependency list HandlePluginRegistration(appConfig, serviceCollection, masterRestClient); diff --git a/Application/Misc/MetaService.cs b/Application/Misc/MetaService.cs index fcf0cd48..7de83bf2 100644 --- a/Application/Misc/MetaService.cs +++ b/Application/Misc/MetaService.cs @@ -29,7 +29,7 @@ namespace IW4MAdmin.Application.Misc _contextFactory = contextFactory; } - public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client) + public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client, EFMeta linkedMeta = null) { // this seems to happen if the client disconnects before they've had time to authenticate and be added if (client.ClientId < 1) @@ -48,6 +48,7 @@ namespace IW4MAdmin.Application.Misc { existingMeta.Value = metaValue; existingMeta.Updated = DateTime.UtcNow; + existingMeta.LinkedMetaId = linkedMeta?.MetaId; } else @@ -57,13 +58,98 @@ namespace IW4MAdmin.Application.Misc ClientId = client.ClientId, Created = DateTime.UtcNow, Key = metaKey, - Value = metaValue + Value = metaValue, + LinkedMetaId = linkedMeta?.MetaId }); } await ctx.SaveChangesAsync(); } + public async Task AddPersistentMeta(string metaKey, string metaValue) + { + await using var ctx = _contextFactory.CreateContext(); + + var existingMeta = await ctx.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .ToListAsync(); + + var matchValues = existingMeta + .Where(meta => meta.Value == metaValue) + .ToArray(); + + if (matchValues.Any()) + { + foreach (var meta in matchValues) + { + _logger.LogDebug("Updating existing meta with key {key} and id {id}", meta.Key, meta.MetaId); + meta.Value = metaValue; + meta.Updated = DateTime.UtcNow; + } + + await ctx.SaveChangesAsync(); + } + + else + { + _logger.LogDebug("Adding new meta with key {key}", metaKey); + + ctx.EFMeta.Add(new EFMeta() + { + Created = DateTime.UtcNow, + Key = metaKey, + Value = metaValue + }); + + await ctx.SaveChangesAsync(); + } + } + + public async Task RemovePersistentMeta(string metaKey, EFClient client) + { + await using var context = _contextFactory.CreateContext(); + + var existingMeta = await context.EFMeta + .FirstOrDefaultAsync(meta => meta.Key == metaKey && meta.ClientId == client.ClientId); + + if (existingMeta == null) + { + _logger.LogDebug("No meta with key {key} found for client id {id}", metaKey, client.ClientId); + return; + } + + _logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, existingMeta.MetaId); + context.EFMeta.Remove(existingMeta); + await context.SaveChangesAsync(); + } + + public async Task RemovePersistentMeta(string metaKey, string metaValue = null) + { + await using var context = _contextFactory.CreateContext(enableTracking: false); + var existingMeta = await context.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .ToListAsync(); + + if (metaValue == null) + { + _logger.LogDebug("Removing all meta for key {key} with ids [{ids}] ", metaKey, string.Join(", ", existingMeta.Select(meta => meta.MetaId))); + existingMeta.ForEach(meta => context.Remove(existingMeta)); + await context.SaveChangesAsync(); + return; + } + + var foundMeta = existingMeta.FirstOrDefault(meta => meta.Value == metaValue); + + if (foundMeta != null) + { + _logger.LogDebug("Removing meta for key {key} with id {id}", metaKey, foundMeta.MetaId); + context.Remove(foundMeta); + await context.SaveChangesAsync(); + } + } + public async Task GetPersistentMeta(string metaKey, EFClient client) { await using var ctx = _contextFactory.CreateContext(enableTracking: false); @@ -76,11 +162,34 @@ namespace IW4MAdmin.Application.Misc MetaId = _meta.MetaId, Key = _meta.Key, ClientId = _meta.ClientId, - Value = _meta.Value + Value = _meta.Value, + LinkedMetaId = _meta.LinkedMetaId, + LinkedMeta = _meta.LinkedMetaId != null ? new EFMeta() + { + MetaId = _meta.LinkedMeta.MetaId, + Key = _meta.LinkedMeta.Key, + Value = _meta.LinkedMeta.Value + } : null }) .FirstOrDefaultAsync(); } + public async Task> GetPersistentMeta(string metaKey) + { + await using var context = _contextFactory.CreateContext(enableTracking: false); + return await context.EFMeta + .Where(meta => meta.Key == metaKey) + .Where(meta => meta.ClientId == null) + .Select(meta => new EFMeta + { + MetaId = meta.MetaId, + Key = meta.Key, + ClientId = meta.ClientId, + Value = meta.Value, + }) + .ToListAsync(); + } + public void AddRuntimeMeta(MetaType metaKey, Func>> metaAction) where T : PaginationRequest where V : IClientMeta { if (!_metaActions.ContainsKey(metaKey)) diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index 00716d9c..5d19ac1d 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -13,51 +13,12 @@ using System.Net; using Newtonsoft.Json.Linq; using System.Text.RegularExpressions; using static SharedLibraryCore.Database.Models.EFClient; +using Humanizer; namespace IW4MAdmin.Plugins.Welcome { public class Plugin : IPlugin { - String TimesConnected(EFClient P) - { - int connection = P.Connections; - String Prefix = String.Empty; - if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19)) - Prefix = "th"; - else - { - switch (connection % 10) - { - case 1: - Prefix = "st"; - break; - case 2: - Prefix = "nd"; - break; - case 3: - Prefix = "rd"; - break; - } - } - - switch (connection) - { - case 0: - case 1: - return "first"; - case 2: - return "second"; - case 3: - return "third"; - case 4: - return "fourth"; - case 5: - return "fifth"; - default: - return connection.ToString() + Prefix; - } - } - public string Author => "RaidMax"; public float Version => 1.0f; @@ -91,7 +52,7 @@ namespace IW4MAdmin.Plugins.Welcome if (E.Type == GameEvent.EventType.Join) { EFClient newPlayer = E.Origin; - if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked) + if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked || !string.IsNullOrEmpty(newPlayer.GetAdditionalProperty("ClientTag"))) E.Owner.Broadcast(await ProcessAnnouncement(_configHandler.Configuration().PrivilegedAnnouncementMessage, newPlayer)); newPlayer.Tell(await ProcessAnnouncement(_configHandler.Configuration().UserWelcomeMessage, newPlayer)); @@ -119,13 +80,13 @@ namespace IW4MAdmin.Plugins.Welcome private async Task ProcessAnnouncement(string msg, EFClient joining) { msg = msg.Replace("{{ClientName}}", joining.Name); - msg = msg.Replace("{{ClientLevel}}", Utilities.ConvertLevelToColor(joining.Level, joining.ClientPermission.Name)); + msg = msg.Replace("{{ClientLevel}}", $"{Utilities.ConvertLevelToColor(joining.Level, joining.ClientPermission.Name)}{(string.IsNullOrEmpty(joining.GetAdditionalProperty("ClientTag")) ? "" : $" ^7({joining.GetAdditionalProperty("ClientTag")}^7)")}"); // this prevents it from trying to evaluate it every message if (msg.Contains("{{ClientLocation}}")) { msg = msg.Replace("{{ClientLocation}}", await GetCountryName(joining.IPAddressString)); } - msg = msg.Replace("{{TimesConnected}}", TimesConnected(joining)); + msg = msg.Replace("{{TimesConnected}}", joining.Connections.Ordinalize()); return msg; } diff --git a/SharedLibraryCore/Command.cs b/SharedLibraryCore/Command.cs index 5a8b788d..7f61bd11 100644 --- a/SharedLibraryCore/Command.cs +++ b/SharedLibraryCore/Command.cs @@ -28,9 +28,9 @@ namespace SharedLibraryCore /// /// Executes the command /// - /// + /// /// - abstract public Task ExecuteAsync(GameEvent E); + abstract public Task ExecuteAsync(GameEvent gameEvent); /// /// Specifies the name and string that triggers the command diff --git a/SharedLibraryCore/Commands/AddClientTagCommand.cs b/SharedLibraryCore/Commands/AddClientTagCommand.cs new file mode 100644 index 00000000..c696f5ad --- /dev/null +++ b/SharedLibraryCore/Commands/AddClientTagCommand.cs @@ -0,0 +1,37 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class AddClientTagCommand : Command + { + private readonly IMetaService _metaService; + + public AddClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "addclienttag"; + Description = layout["COMMANDS_ADD_CLIENT_TAG_DESC"]; + Alias = "act"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + await _metaService.AddPersistentMeta(EFMeta.ClientTagName, gameEvent.Data); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_ADD_CLIENT_TAG_SUCCESS"].FormatExt(gameEvent.Data)); + } + } +} diff --git a/SharedLibraryCore/Commands/ListClientTags.cs b/SharedLibraryCore/Commands/ListClientTags.cs new file mode 100644 index 00000000..ef1f23f1 --- /dev/null +++ b/SharedLibraryCore/Commands/ListClientTags.cs @@ -0,0 +1,33 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + + public class ListClientTags : Command + { + private readonly IMetaService _metaService; + + public ListClientTags(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "listclienttags"; + Description = layout["COMMANDS_LIST_CLIENT_TAGS_DESC"]; + Alias = "lct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + var tags = await _metaService.GetPersistentMeta(EFMeta.ClientTagName); + gameEvent.Origin.Tell(tags.Select(tag => tag.Value)); + } + } +} diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 3926f83b..abd659b6 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -465,10 +465,11 @@ namespace SharedLibraryCore.Commands RequiresTarget = false; } - public override Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent gameEvent) { - string you = string.Format("{0} [^3#{1}^7] {2} ^7[^3@{3}^7] ^7[{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level, E.Origin.ClientPermission.Name), E.Origin.IPAddressString); - E.Origin.Tell(you); + var you = _translationLookup["COMMANDS_WHOAMI_FORMAT"].FormatExt(gameEvent.Origin.ClientNumber, gameEvent.Origin.ClientId, gameEvent.Origin.GuidString, + gameEvent.Origin.IPAddressString, gameEvent.Origin.ClientPermission.Name, string.IsNullOrEmpty(gameEvent.Origin.Tag) ? "" : $" {gameEvent.Origin.Tag}^7", gameEvent.Origin.Name); + gameEvent.Origin.Tell(you); return Task.CompletedTask; } @@ -488,46 +489,14 @@ namespace SharedLibraryCore.Commands RequiresTarget = false; } - public override Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent gameEvent) { - StringBuilder playerList = new StringBuilder(); - int count = 0; - for (int i = 0; i < E.Owner.Clients.Count; i++) - { - var P = E.Owner.Clients[i]; + var clientList = gameEvent.Owner.GetClientsAsList() + .Select(client => _translationLookup["COMMANDS_LIST_FORMAT"] + .FormatExt(client.ClientPermission.Name, string.IsNullOrEmpty(client.Tag) ? "" : $" {client.Tag}^7", client.ClientNumber, client.Name)) + .ToArray(); - if (P == null) - { - continue; - } - // todo: fix spacing - // todo: make this better :) - if (P.Masked) - { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(EFClient.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - EFClient.Permission.User.ToString().Length)); - } - else - { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); - } - - if (count == 2 || E.Owner.GetClientsAsList().Count == 1) - { - E.Origin.Tell(playerList.ToString()); - count = 0; - playerList = new StringBuilder(); - continue; - } - - count++; - } - - if (playerList.Length > 0) - { - E.Origin.Tell(playerList.ToString()); - } - - // todo: make no players response for webfront + gameEvent.Origin.Tell(clientList); return Task.CompletedTask; } @@ -737,7 +706,7 @@ namespace SharedLibraryCore.Commands { // can't promote a client to higher than your current perms // or your peer - gameEvent.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToString())); + gameEvent.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToLocalizedLevelName())); return; } @@ -991,9 +960,14 @@ namespace SharedLibraryCore.Commands rules.AddRange(E.Owner.ServerConfig.Rules); } - foreach (string r in rules) + var ruleFomat = rules.Select(r => $"- {r}"); + if (E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { - var _ = E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix) ? E.Owner.Broadcast($"- {r}") : E.Origin.Tell($"- {r}"); + E.Owner.Broadcast(ruleFomat); + } + else + { + E.Origin.Tell(ruleFomat); } } diff --git a/SharedLibraryCore/Commands/RemoveClientTagCommand.cs b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs new file mode 100644 index 00000000..10c52910 --- /dev/null +++ b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs @@ -0,0 +1,37 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class RemoveClientTag : Command + { + private readonly IMetaService _metaService; + + public RemoveClientTag(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "removeclienttag"; + Description = layout["COMMANDS_REMOVE_CLIENT_TAG_DESC"]; + Alias = "rct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + await _metaService.RemovePersistentMeta(EFMeta.ClientTagName, gameEvent.Data); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_REMOVE_CLIENT_TAG_SUCCESS"].FormatExt(gameEvent.Data)); + } + } +} diff --git a/SharedLibraryCore/Commands/SetClientTagCommand.cs b/SharedLibraryCore/Commands/SetClientTagCommand.cs new file mode 100644 index 00000000..c0952c8a --- /dev/null +++ b/SharedLibraryCore/Commands/SetClientTagCommand.cs @@ -0,0 +1,49 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class SetClientTagCommand : Command + { + private readonly IMetaService _metaService; + + + public SetClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "setclienttag"; + Description = layout["COMMANDS_SET_CLIENT_TAG_DESC"]; + Alias = "sct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + var availableTags = await _metaService.GetPersistentMeta(EFMeta.ClientTagName); + var matchingTag = availableTags.FirstOrDefault(tag => tag.Value == gameEvent.Data); + + if (matchingTag == null) + { + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SET_CLIENT_TAG_FAIL"].FormatExt(gameEvent.Data)); + return; + } + + gameEvent.Target.Tag = matchingTag.Value; + await _metaService.AddPersistentMeta(EFMeta.ClientTag, string.Empty, gameEvent.Target, matchingTag); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SET_CLIENT_TAG_SUCCESS"].FormatExt(matchingTag.Value)); + } + } +} diff --git a/SharedLibraryCore/Commands/UnsetClientTagCommand.cs b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs new file mode 100644 index 00000000..4dbd2a1c --- /dev/null +++ b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs @@ -0,0 +1,40 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibraryCore.Commands +{ + public class UnsetClientTagCommand : Command + { + private readonly IMetaService _metaService; + + + public UnsetClientTagCommand(CommandConfiguration config, ITranslationLookup layout, IMetaService metaService) : base(config, layout) + { + Name = "unsetclienttag"; + Description = layout["COMMANDS_UNSET_CLIENT_TAG_DESC"]; + Alias = "uct"; + Permission = EFClient.Permission.Owner; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGUMENT_TAG"], + Required = true + } + }; + + _metaService = metaService; + } + + public override async Task ExecuteAsync(GameEvent gameEvent) + { + gameEvent.Target.Tag = null; + await _metaService.RemovePersistentMeta(EFMeta.ClientTag, gameEvent.Target); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_UNSET_CLIENT_TAG_SUCCESS"]); + } + } +} diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index f74ee0e6..3ec1ad80 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -3,6 +3,8 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Linq; +using static SharedLibraryCore.Database.Models.EFClient; namespace SharedLibraryCore.Configuration { @@ -137,6 +139,10 @@ namespace SharedLibraryCore.Configuration {{"afk", "Away from keyboard"}, {"ci", "Connection interrupted. Reconnect"}}; [LocalizedDisplayName(("WEBFRONT_CONFIGURATION_ENABLE_PRIVILEGED_USER_PRIVACY"))] public bool EnablePrivilegedUserPrivacy { get; set; } + public Dictionary OverridePermissionLevelNames { get; set; } = Enum + .GetValues(typeof(Permission)) + .Cast() + .ToDictionary(perm => perm, perm => perm.ToString()); [UIHint("ServerConfiguration")] public ServerConfiguration[] Servers { get; set; } diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs index 354919df..c7e7a920 100644 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ b/SharedLibraryCore/Database/DatabaseContext.cs @@ -57,12 +57,12 @@ namespace SharedLibraryCore.Database public DatabaseContext(DbContextOptions options) : base(options) { - + } protected DatabaseContext(DbContextOptions options) : base(options) { - + } public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) @@ -123,6 +123,10 @@ namespace SharedLibraryCore.Database modelBuilder.Entity(ent => { ent.HasIndex(_meta => _meta.Key); + ent.HasIndex(_meta => _meta.LinkedMetaId); + ent.HasOne(_meta => _meta.LinkedMeta) + .WithMany() + .OnDelete(DeleteBehavior.SetNull); }); // force full name for database conversion diff --git a/SharedLibraryCore/Database/Models/EFMeta.cs b/SharedLibraryCore/Database/Models/EFMeta.cs index 3525fb28..792797ee 100644 --- a/SharedLibraryCore/Database/Models/EFMeta.cs +++ b/SharedLibraryCore/Database/Models/EFMeta.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Text; namespace SharedLibraryCore.Database.Models { @@ -11,15 +9,18 @@ namespace SharedLibraryCore.Database.Models /// public class EFMeta : SharedEntity { + public const string ClientTagName = nameof(ClientTagName); + public const string ClientTag = nameof(ClientTag); + [Key] public int MetaId { get; set; } [Required] public DateTime Created { get; set; } = DateTime.UtcNow; [Required] public DateTime Updated { get; set; } = DateTime.UtcNow; - [Required] - public int ClientId { get; set; } - [ForeignKey("ClientId")] // this is the client that the meta belongs to + public int? ClientId { get; set; } + // this is the client that the meta could belong to + [ForeignKey(nameof(ClientId))] public virtual EFClient Client { get; set; } [Required] [MinLength(3)] @@ -29,5 +30,9 @@ namespace SharedLibraryCore.Database.Models [Required] public string Value { get; set; } public string Extra { get; set; } + + public int? LinkedMetaId { get; set; } + [ForeignKey(nameof(LinkedMetaId))] + public virtual EFMeta LinkedMeta { get; set; } } } diff --git a/SharedLibraryCore/Dtos/PlayerInfo.cs b/SharedLibraryCore/Dtos/PlayerInfo.cs index 94b91561..eecaa615 100644 --- a/SharedLibraryCore/Dtos/PlayerInfo.cs +++ b/SharedLibraryCore/Dtos/PlayerInfo.cs @@ -11,6 +11,7 @@ namespace SharedLibraryCore.Dtos public string Name { get; set; } public int ClientId { get; set; } public string Level { get; set; } + public string Tag { get; set; } public int LevelInt { get; set; } public string IPAddress { get; set; } public long NetworkId { get; set; } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index d814ea9b..974617b5 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -261,6 +261,11 @@ namespace SharedLibraryCore _eventFinishedWaiter.Set(); } + public async Task WaitAsync() + { + return await WaitAsync(Utilities.DefaultCommandTimeout, new CancellationToken()); + } + /// /// asynchronously wait for GameEvent to be processed /// diff --git a/SharedLibraryCore/Interfaces/IMetaService.cs b/SharedLibraryCore/Interfaces/IMetaService.cs index 71e0ec23..42c06c8b 100644 --- a/SharedLibraryCore/Interfaces/IMetaService.cs +++ b/SharedLibraryCore/Interfaces/IMetaService.cs @@ -16,7 +16,31 @@ namespace SharedLibraryCore.Interfaces /// value of the meta data /// client to save the meta for /// - Task AddPersistentMeta(string metaKey, string metaValue, EFClient client); + Task AddPersistentMeta(string metaKey, string metaValue, EFClient client, EFMeta linkedMeta = null); + + /// + /// adds or updates meta key and value to the database + /// + /// key of meta data + /// value of the meta data + /// + Task AddPersistentMeta(string metaKey, string metaValue); + + /// + /// removes meta key with given value + /// + /// key of meta data + /// client to delete the meta for + /// + Task RemovePersistentMeta(string metaKey, EFClient client); + + /// + /// removes meta key with given value + /// + /// key of the meta data + /// value of the meta data + /// + Task RemovePersistentMeta(string metaKey, string metaValue = null); /// /// retrieves meta data for given client and key @@ -26,6 +50,13 @@ namespace SharedLibraryCore.Interfaces /// Task GetPersistentMeta(string metaKey, EFClient client); + /// + /// retrieves collection of meta for given key + /// + /// key to retrieve values for + /// + Task> GetPersistentMeta(string metaKey); + /// /// adds a meta task to the runtime meta list /// diff --git a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs new file mode 100644 index 00000000..933e6398 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -0,0 +1,929 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20210123023921_UpdateEFMetaToSupportNonClientMeta")] + partial class UpdateEFMetaToSupportNonClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CurrentSessionLength") + .HasColumnType("int"); + + b.Property("CurrentStrain") + .HasColumnType("double"); + + b.Property("CurrentViewAngleId") + .HasColumnType("int"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("Distance") + .HasColumnType("double"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("HitDestinationId") + .HasColumnType("int"); + + b.Property("HitLocation") + .HasColumnType("int"); + + b.Property("HitOriginId") + .HasColumnType("int"); + + b.Property("HitType") + .HasColumnType("int"); + + b.Property("Hits") + .HasColumnType("int"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("LastStrainAngleId") + .HasColumnType("int"); + + b.Property("RecoilOffset") + .HasColumnType("double"); + + b.Property("SessionAngleOffset") + .HasColumnType("double"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double"); + + b.Property("SessionSPM") + .HasColumnType("double"); + + b.Property("SessionScore") + .HasColumnType("int"); + + b.Property("SessionSnapHits") + .HasColumnType("int"); + + b.Property("StrainAngleBetween") + .HasColumnType("double"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + b.Property("AverageSnapValue") + .HasColumnType("double"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("MaxStrain") + .HasColumnType("double"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double"); + + b.Property("SPM") + .HasColumnType("double"); + + b.Property("Skill") + .HasColumnType("double"); + + b.Property("SnapHitCount") + .HasColumnType("int"); + + b.Property("TimePlayed") + .HasColumnType("int"); + + b.Property("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("int"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitOffsetAverage") + .HasColumnType("float"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("MaxAngleDistance") + .HasColumnType("float"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ActivityAmount") + .HasColumnType("int"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("Performance") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("RatingHistoryId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("IPAddress") + .HasColumnType("int"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Comment") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImpersonationEntityId") + .HasColumnType("int"); + + b.Property("OriginEntityId") + .HasColumnType("int"); + + b.Property("PreviousValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TargetEntityId") + .HasColumnType("int"); + + b.Property("TimeChanged") + .HasColumnType("datetime(6)"); + + b.Property("TypeOfChange") + .HasColumnType("int"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Extra") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AutomatedOffense") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Expires") + .HasColumnType("datetime(6)"); + + b.Property("IsEvadedOffense") + .HasColumnType("tinyint(1)"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("OffenderId") + .HasColumnType("int"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PunisherId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs new file mode 100644 index 00000000..1a748afd --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.MySql +{ + public partial class UpdateEFMetaToSupportNonClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "int", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs new file mode 100644 index 00000000..745b1b34 --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -0,0 +1,939 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20210124170830_UpdateEFMetaToSupportLinkedMeta")] + partial class UpdateEFMetaToSupportLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CurrentSessionLength") + .HasColumnType("int"); + + b.Property("CurrentStrain") + .HasColumnType("double"); + + b.Property("CurrentViewAngleId") + .HasColumnType("int"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("Distance") + .HasColumnType("double"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("HitDestinationId") + .HasColumnType("int"); + + b.Property("HitLocation") + .HasColumnType("int"); + + b.Property("HitOriginId") + .HasColumnType("int"); + + b.Property("HitType") + .HasColumnType("int"); + + b.Property("Hits") + .HasColumnType("int"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("LastStrainAngleId") + .HasColumnType("int"); + + b.Property("RecoilOffset") + .HasColumnType("double"); + + b.Property("SessionAngleOffset") + .HasColumnType("double"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double"); + + b.Property("SessionSPM") + .HasColumnType("double"); + + b.Property("SessionScore") + .HasColumnType("int"); + + b.Property("SessionSnapHits") + .HasColumnType("int"); + + b.Property("StrainAngleBetween") + .HasColumnType("double"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double"); + + b.Property("AverageSnapValue") + .HasColumnType("double"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("MaxStrain") + .HasColumnType("double"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double"); + + b.Property("SPM") + .HasColumnType("double"); + + b.Property("Skill") + .HasColumnType("double"); + + b.Property("SnapHitCount") + .HasColumnType("int"); + + b.Property("TimePlayed") + .HasColumnType("int"); + + b.Property("VisionAverage") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("int"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitOffsetAverage") + .HasColumnType("float"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("MaxAngleDistance") + .HasColumnType("float"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ActivityAmount") + .HasColumnType("int"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("Performance") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("RatingHistoryId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("IPAddress") + .HasColumnType("int"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Comment") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImpersonationEntityId") + .HasColumnType("int"); + + b.Property("OriginEntityId") + .HasColumnType("int"); + + b.Property("PreviousValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TargetEntityId") + .HasColumnType("int"); + + b.Property("TimeChanged") + .HasColumnType("datetime(6)"); + + b.Property("TypeOfChange") + .HasColumnType("int"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Extra") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("int"); + + b.Property("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AutomatedOffense") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Expires") + .HasColumnType("datetime(6)"); + + b.Property("IsEvadedOffense") + .HasColumnType("tinyint(1)"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("OffenderId") + .HasColumnType("int"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PunisherId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs new file mode 100644 index 00000000..30e37b9b --- /dev/null +++ b/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.MySql +{ + public partial class UpdateEFMetaToSupportLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LinkedMetaId", + table: "EFMeta", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId", + principalTable: "EFMeta", + principalColumn: "MetaId", + onDelete: ReferentialAction.SetNull); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropColumn( + name: "LinkedMetaId", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs index 49d3de31..933b9b72 100644 --- a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations.MySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => @@ -470,11 +470,11 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("Name") .IsRequired() - .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") .HasMaxLength(24); b.Property("SearchableName") - .HasColumnType("varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") .HasMaxLength(24); b.HasKey("AliasId"); @@ -609,7 +609,7 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("Active") .HasColumnType("tinyint(1)"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("int"); b.Property("Created") @@ -623,6 +623,9 @@ namespace SharedLibraryCore.Migrations.MySql .HasColumnType("varchar(32) CHARACTER SET utf8mb4") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("int"); + b.Property("Updated") .HasColumnType("datetime(6)"); @@ -636,6 +639,8 @@ namespace SharedLibraryCore.Migrations.MySql b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -898,9 +903,12 @@ namespace SharedLibraryCore.Migrations.MySql { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs new file mode 100644 index 00000000..cfb4d9e8 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -0,0 +1,946 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20210123024304_UpdateEFMetaToSupportNonClientMeta")] + partial class UpdateEFMetaToSupportNonClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("HitDestinationId") + .HasColumnType("integer"); + + b.Property("HitLocation") + .HasColumnType("integer"); + + b.Property("HitOriginId") + .HasColumnType("integer"); + + b.Property("HitType") + .HasColumnType("integer"); + + b.Property("Hits") + .HasColumnType("integer"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("LastStrainAngleId") + .HasColumnType("integer"); + + b.Property("RecoilOffset") + .HasColumnType("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitOffsetAverage") + .HasColumnType("real"); + + b.Property("Location") + .HasColumnType("integer"); + + b.Property("MaxAngleDistance") + .HasColumnType("real"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("text"); + + b.Property("ImpersonationEntityId") + .HasColumnType("integer"); + + b.Property("OriginEntityId") + .HasColumnType("integer"); + + b.Property("PreviousValue") + .HasColumnType("text"); + + b.Property("TargetEntityId") + .HasColumnType("integer"); + + b.Property("TimeChanged") + .HasColumnType("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("OffenderId") + .HasColumnType("integer"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("text"); + + b.Property("PunisherId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("X") + .HasColumnType("real"); + + b.Property("Y") + .HasColumnType("real"); + + b.Property("Z") + .HasColumnType("real"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs new file mode 100644 index 00000000..fc4f4aa3 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateEFMetaToSupportNonClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta"); + + migrationBuilder.AlterColumn( + name: "ClientId", + table: "EFMeta", + type: "integer", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + table: "EFMeta", + column: "ClientId", + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs new file mode 100644 index 00000000..cd28418d --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -0,0 +1,956 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20210124170956_UpdateEFMetaToSupportLinkedMeta")] + partial class UpdateEFMetaToSupportLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("HitDestinationId") + .HasColumnType("integer"); + + b.Property("HitLocation") + .HasColumnType("integer"); + + b.Property("HitOriginId") + .HasColumnType("integer"); + + b.Property("HitType") + .HasColumnType("integer"); + + b.Property("Hits") + .HasColumnType("integer"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("LastStrainAngleId") + .HasColumnType("integer"); + + b.Property("RecoilOffset") + .HasColumnType("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageRecoilOffset") + .HasColumnType("double precision"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("VisionAverage") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitOffsetAverage") + .HasColumnType("real"); + + b.Property("Location") + .HasColumnType("integer"); + + b.Property("MaxAngleDistance") + .HasColumnType("real"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("text"); + + b.Property("ImpersonationEntityId") + .HasColumnType("integer"); + + b.Property("OriginEntityId") + .HasColumnType("integer"); + + b.Property("PreviousValue") + .HasColumnType("text"); + + b.Property("TargetEntityId") + .HasColumnType("integer"); + + b.Property("TimeChanged") + .HasColumnType("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("integer"); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("OffenderId") + .HasColumnType("integer"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("text"); + + b.Property("PunisherId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("X") + .HasColumnType("real"); + + b.Property("Y") + .HasColumnType("real"); + + b.Property("Z") + .HasColumnType("real"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs new file mode 100644 index 00000000..55927c72 --- /dev/null +++ b/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Postgresql +{ + public partial class UpdateEFMetaToSupportLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LinkedMetaId", + table: "EFMeta", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId"); + + migrationBuilder.AddForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta", + column: "LinkedMetaId", + principalTable: "EFMeta", + principalColumn: "MetaId", + onDelete: ReferentialAction.SetNull); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_EFMeta_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropIndex( + name: "IX_EFMeta_LinkedMetaId", + table: "EFMeta"); + + migrationBuilder.DropColumn( + name: "LinkedMetaId", + table: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs index 5917c444..0d442753 100644 --- a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs @@ -15,8 +15,8 @@ namespace SharedLibraryCore.Migrations.Postgresql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "3.1.7") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 63); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => @@ -24,7 +24,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("SnapshotId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -121,7 +121,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ACSnapshotVector3Id") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -146,7 +146,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("KillId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -218,7 +218,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("MessageId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -254,7 +254,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("RatingHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -328,7 +328,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("HitLocationCountId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -367,7 +367,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("RatingId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -439,7 +439,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("StatisticId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -465,7 +465,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("AliasId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -509,7 +509,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("AliasLinkId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -524,7 +524,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ChangeHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -564,7 +564,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("ClientId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -619,12 +619,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("MetaId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("integer"); b.Property("Created") @@ -638,6 +638,9 @@ namespace SharedLibraryCore.Migrations.Postgresql .HasColumnType("character varying(32)") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("integer"); + b.Property("Updated") .HasColumnType("timestamp without time zone"); @@ -651,6 +654,8 @@ namespace SharedLibraryCore.Migrations.Postgresql b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -659,7 +664,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("PenaltyId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Active") .HasColumnType("boolean"); @@ -708,7 +713,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("Vector3Id") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("X") .HasColumnType("real"); @@ -915,9 +920,12 @@ namespace SharedLibraryCore.Migrations.Postgresql { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs new file mode 100644 index 00000000..8966c2d4 --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs @@ -0,0 +1,938 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SharedLibraryCore.Database.MigrationContext; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta")] + partial class UpdateEFMetaToSupportNonClientMetaAndLinkedMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10"); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + 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("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageRecoilOffset") + .HasColumnType("REAL"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("VisionAverage") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + 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("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + { + b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs new file mode 100644 index 00000000..5137722e --- /dev/null +++ b/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs @@ -0,0 +1,128 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace SharedLibraryCore.Migrations.Sqlite +{ + public partial class UpdateEFMetaToSupportNonClientMetaAndLinkedMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFMeta; + + DROP TABLE EFMeta; + + CREATE TABLE EFMeta ( + MetaId INTEGER NOT NULL + CONSTRAINT PK_EFMeta PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + ClientId INTEGER, + Created TEXT NOT NULL, + Extra TEXT, + [Key] TEXT NOT NULL, + Updated TEXT NOT NULL, + Value TEXT NOT NULL, + LinkedMetaId INTEGER CONSTRAINT IX_EFMeta_LinkedMetaId REFERENCES EFMeta (MetaId) ON DELETE SET NULL, + CONSTRAINT FK_EFMeta_EFClients_ClientId FOREIGN KEY ( + ClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE + ); + + INSERT INTO EFMeta ( + MetaId, + Active, + ClientId, + Created, + Extra, + [Key], + Updated, + Value + ) + SELECT MetaId, + Active, + ClientId, + Created, + Extra, + ""Key"", + Updated, + Value + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFMeta_ClientId ON EFMeta( + ""ClientId"" + ); + + CREATE INDEX IX_EFMeta_Key ON EFMeta ( + ""Key"" + ); + + CREATE INDEX IX_EFMeta_LinkedMetaId ON EFMeta ( + LinkedMetaId + ); + + PRAGMA foreign_keys = 1;"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@"PRAGMA foreign_keys = 0; + + CREATE TABLE sqlitestudio_temp_table AS SELECT * + FROM EFMeta; + + DROP TABLE EFMeta; + + CREATE TABLE EFMeta ( + MetaId INTEGER NOT NULL + CONSTRAINT PK_EFMeta PRIMARY KEY AUTOINCREMENT, + Active INTEGER NOT NULL, + ClientId INTEGER NOT NULL, + Created TEXT NOT NULL, + Extra TEXT, + [Key] TEXT NOT NULL, + Updated TEXT NOT NULL, + Value TEXT NOT NULL, + CONSTRAINT FK_EFMeta_EFClients_ClientId FOREIGN KEY ( + ClientId + ) + REFERENCES EFClients (ClientId) ON DELETE CASCADE + ); + + INSERT INTO EFMeta ( + MetaId, + Active, + ClientId, + Created, + Extra, + [Key], + Updated, + Value + ) + SELECT MetaId, + Active, + ClientId, + Created, + Extra, + ""Key"", + Updated, + Value + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + + CREATE INDEX IX_EFMeta_ClientId ON EFMeta( + ""ClientId"" + ); + + CREATE INDEX IX_EFMeta_Key ON EFMeta( + ""Key"" + ); + + PRAGMA foreign_keys = 1;"); + } + } +} diff --git a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index e8455691..90f555e4 100644 --- a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations.Sqlite { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.7"); + .HasAnnotation("ProductVersion", "3.1.10"); modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => { @@ -608,7 +608,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.Property("Active") .HasColumnType("INTEGER"); - b.Property("ClientId") + b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Created") @@ -622,6 +622,9 @@ namespace SharedLibraryCore.Migrations.Sqlite .HasColumnType("TEXT") .HasMaxLength(32); + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + b.Property("Updated") .HasColumnType("TEXT"); @@ -635,6 +638,8 @@ namespace SharedLibraryCore.Migrations.Sqlite b.HasIndex("Key"); + b.HasIndex("LinkedMetaId"); + b.ToTable("EFMeta"); }); @@ -897,9 +902,12 @@ namespace SharedLibraryCore.Migrations.Sqlite { b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") .WithMany("Meta") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("ClientId"); + + b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index 25b73f59..b0789462 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -152,6 +152,16 @@ namespace SharedLibraryCore.Database.Models return e; } + public void Tell(IEnumerable messages) + { + foreach(var message in messages) + { +#pragma warning disable 4014 + Tell(message).WaitAsync(); +#pragma warning restore 4014 + } + } + /// /// warn a client with given reason /// @@ -706,10 +716,16 @@ namespace SharedLibraryCore.Database.Models public ClientPermission ClientPermission => new ClientPermission() { Level = Level, - Name = Utilities.CurrentLocalization - .LocalizationIndex[$"GLOBAL_PERMISSION_{Level.ToString().ToUpper()}"] + Name = Level.ToLocalizedLevelName() }; + [NotMapped] + public string Tag + { + get => GetAdditionalProperty(EFMeta.ClientTag); + set => SetAdditionalProperty(EFMeta.ClientTag, value); + } + [NotMapped] private readonly SemaphoreSlim _processingEvent; diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 5449d828..f13e1239 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -140,6 +140,17 @@ namespace SharedLibraryCore Manager.AddEvent(e); return e; } + + public void Broadcast(IEnumerable messages, EFClient sender = null) + { + foreach (var message in messages) + { +#pragma warning disable 4014 + Broadcast(message, sender).WaitAsync(); +#pragma warning restore 4014 + } + } + /// /// Send a message to a particular players diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 35d7baec..8bbcf55b 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -59,6 +59,12 @@ + + + + + + diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index ab30705e..a3c2c785 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -59,6 +59,7 @@ namespace SharedLibraryCore /// fallback id for world events /// public const long WORLD_ID = -1; + public static Dictionary PermissionLevelOverrides { get; } = new Dictionary(); public static string HttpRequest(string location, string header, string headerValue) { @@ -219,9 +220,12 @@ namespace SharedLibraryCore return $"^{colorCode}{localizedLevel ?? level.ToString()}"; } - public static string ToLocalizedLevelName(this EFClient.Permission perm) + public static string ToLocalizedLevelName(this Permission permission) { - return CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"]; + var localized = CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{permission.ToString().ToUpper()}"]; + return PermissionLevelOverrides.ContainsKey(permission) && PermissionLevelOverrides[permission] != localized + ? PermissionLevelOverrides[permission] + : localized; } public async static Task ProcessMessageToken(this Server server, IList tokens, String str) diff --git a/WebfrontCore/Controllers/API/ClientController.cs b/WebfrontCore/Controllers/API/ClientController.cs index 90bb610b..14a8eca7 100644 --- a/WebfrontCore/Controllers/API/ClientController.cs +++ b/WebfrontCore/Controllers/API/ClientController.cs @@ -88,8 +88,6 @@ namespace WebfrontCore.Controllers.API return Unauthorized(); } - HttpContext.Request.Cookies.TryGetValue(".AspNetCore.Cookies", out var cookie); - if (Authorized) { return Ok(); diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index aadd4f31..774c1a3e 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -439,7 +439,7 @@ namespace WebfrontCore.Controllers private Dictionary GetPresetPenaltyReasons() => _appConfig.PresetPenaltyReasons.Values .Concat(_appConfig.GlobalRules) - .Concat(_appConfig.Servers.SelectMany(server => server.Rules)) + .Concat(_appConfig.Servers.SelectMany(server => server.Rules ?? new string[0])) .Distinct() .Select((value, index) => new { diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index 547d3b7a..86a7e353 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -36,6 +36,11 @@ namespace WebfrontCore.Controllers var activePenalties = (await Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId, client.IPAddress)); + var tag = await _metaService.GetPersistentMeta(EFMeta.ClientTag, client); + if (tag?.LinkedMeta != null) + { + client.SetAdditionalProperty(EFMeta.ClientTag, tag.LinkedMeta.Value); + } int displayLevelInt = (int)client.Level; string displayLevel = client.Level.ToLocalizedLevelName(); @@ -46,6 +51,8 @@ namespace WebfrontCore.Controllers displayLevel = Permission.User.ToLocalizedLevelName(); } + displayLevel = string.IsNullOrEmpty(client.Tag) ? displayLevel : $"{displayLevel} ({client.Tag})"; + var clientDto = new PlayerInfo() { Name = client.Name, diff --git a/WebfrontCore/ViewComponents/ServerListViewComponent.cs b/WebfrontCore/ViewComponents/ServerListViewComponent.cs index 224692ff..012f1872 100644 --- a/WebfrontCore/ViewComponents/ServerListViewComponent.cs +++ b/WebfrontCore/ViewComponents/ServerListViewComponent.cs @@ -29,7 +29,8 @@ namespace WebfrontCore.ViewComponents Name = p.Name, ClientId = p.ClientId, Level = p.Level.ToLocalizedLevelName(), - LevelInt = (int)p.Level + LevelInt = (int)p.Level, + Tag = p.Tag }).ToList(), ChatHistory = s.ChatHistory.ToList(), Online = !s.Throttled, diff --git a/WebfrontCore/Views/Client/Privileged/Index.cshtml b/WebfrontCore/Views/Client/Privileged/Index.cshtml index f29f32ce..f9a30351 100644 --- a/WebfrontCore/Views/Client/Privileged/Index.cshtml +++ b/WebfrontCore/Views/Client/Privileged/Index.cshtml @@ -7,7 +7,7 @@ foreach (var key in Model.Keys) {
- @key.ToString() + @Utilities.ToLocalizedLevelName(key)
diff --git a/WebfrontCore/Views/Server/_ClientActivity.cshtml b/WebfrontCore/Views/Server/_ClientActivity.cshtml index de43e762..5cea0f97 100644 --- a/WebfrontCore/Views/Server/_ClientActivity.cshtml +++ b/WebfrontCore/Views/Server/_ClientActivity.cshtml @@ -45,57 +45,48 @@ }
-
-
- @{ - for (int i = 0; i < half; i++) +
+
+ @for (var i = 0; i < half; i++) + { + if (i > Model.Players.Count - 1) { - if (i > Model.Players.Count - 1) - { - continue; - } + continue; + } - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; -
- @if (ViewBag.Authorized) - { - - } + //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); - - - + string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; - @if (ViewBag.Authorized) - { - - } -
-
+ + + + + @if (ViewBag.Authorized) + { + } }
-
- @{ - for (int i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) +
+ @for (var i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) + { + if (i > Model.Players.Count - 1) { - if (i > Model.Players.Count - 1) - { - continue; - } + continue; + } - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; + //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); -
- - - - @if (ViewBag.Authorized) - { - - } -
-
+ string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; + + + + + + @if (ViewBag.Authorized) + { + } }
From 191a68e7dd6a595452c222908489e8b7cd9675d4 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 24 Jan 2021 13:30:22 -0600 Subject: [PATCH 033/143] revert unintended commit file --- .../Views/Server/_ClientActivity.cshtml | 73 +++++++++++-------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/WebfrontCore/Views/Server/_ClientActivity.cshtml b/WebfrontCore/Views/Server/_ClientActivity.cshtml index 5cea0f97..de43e762 100644 --- a/WebfrontCore/Views/Server/_ClientActivity.cshtml +++ b/WebfrontCore/Views/Server/_ClientActivity.cshtml @@ -45,48 +45,57 @@ }
-
-
- @for (var i = 0; i < half; i++) - { - if (i > Model.Players.Count - 1) +
+
+ @{ + for (int i = 0; i < half; i++) { - continue; - } + if (i > Model.Players.Count - 1) + { + continue; + } - //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); + string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; +
+ @if (ViewBag.Authorized) + { + + } - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; + + + - - - - - @if (ViewBag.Authorized) - { - + @if (ViewBag.Authorized) + { + + } +
+
} }
-
- @for (var i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) - { - if (i > Model.Players.Count - 1) +
+ @{ + for (int i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++) { - continue; - } + if (i > Model.Players.Count - 1) + { + continue; + } - //Model.Players[i].Name = string.Join("", "DankMememachine12".Take(new Random().Next(14, 17))); + string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; - string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}"; - - - - - - @if (ViewBag.Authorized) - { - +
+ + + + @if (ViewBag.Authorized) + { + + } +
+
} }
From db2e1deb2fc7928be1029cee2921e1fd75615cd6 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 27 Feb 2021 09:40:25 -0600 Subject: [PATCH 034/143] modify rule shortcut to just have 1 list --- SharedLibraryCore/Utilities.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index a3c2c785..4d727247 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -1013,7 +1013,7 @@ namespace SharedLibraryCore return appConfig.PresetPenaltyReasons[reason.ToLower()]; } - var regex = Regex.Match(reason, @"(rule|serverrule)(\d+)", RegexOptions.IgnoreCase); + var regex = Regex.Match(reason, @"rule(\d+)", RegexOptions.IgnoreCase); if (!regex.Success) { return reason; @@ -1023,18 +1023,20 @@ namespace SharedLibraryCore .FirstOrDefault(configServer => configServer.IPAddress == server.IP && configServer.Port == server.Port); - var index = int.Parse(regex.Groups[2].ToString()) - 1; - - return regex.Groups[1].ToString().ToLower() switch + var allRules = appConfig.GlobalRules?.ToList() ?? new List(); + if (serverConfig?.Rules != null) { - "rule" => appConfig.GlobalRules?.Length > 0 && appConfig.GlobalRules.Length >= index - ? appConfig.GlobalRules[index] : - reason, - "serverrule" => serverConfig?.Rules?.Length > 0 && serverConfig.Rules?.Length >= index - ? serverConfig.Rules[index] : - reason, - _ => reason - }; + allRules.AddRange(serverConfig.Rules); + } + + var index = int.Parse(regex.Groups[1].ToString()) - 1; + + if (!allRules.Any() || index > allRules.Count - 1 || index < 0) + { + return reason; + } + + return allRules[index]; } } } From c5375b661baa821f16882c38bb3f0f8f7ec3fb2e Mon Sep 17 00:00:00 2001 From: RaidMax Date: Mon, 22 Mar 2021 11:09:25 -0500 Subject: [PATCH 035/143] huge commit for advanced stats feature. broke data out into its own library. may be breaking changes with existing plugins --- Application/Application.csproj | 2 +- Application/ApplicationManager.cs | 25 +- Application/DefaultSettings.json | 130 +- Application/EventParsers/BaseEventParser.cs | 3 +- Application/Extensions/StartupExtensions.cs | 19 +- .../Factories/DatabaseContextFactory.cs | 6 +- .../Factories/GameServerInstanceFactory.cs | 4 +- Application/Factories/ScriptCommandFactory.cs | 4 +- Application/IW4MServer.cs | 51 +- Application/Main.cs | 92 +- .../AdministeredPenaltyResourceQueryHelper.cs | 3 +- .../ReceivedPenaltyResourceQueryHelper.cs | 6 +- .../Meta/UpdatedAliasResourceQueryHelper.cs | 1 + Application/Migration/DatabaseHousekeeping.cs | 3 +- Application/Misc/BaseConfigurationHandler.cs | 5 + .../Misc/ClientNoticeMessageFormatter.cs | 2 +- Application/Misc/MetaService.cs | 2 + Application/Misc/PluginImporter.cs | 14 +- Application/Misc/ScriptCommand.cs | 3 +- Application/Misc/SerializationHelpers.cs | 1 + Application/RconParsers/BaseRConParser.cs | 1 + Data/Abstractions/IDataValueCache.cs | 12 + .../Abstractions}/IDatabaseContextFactory.cs | 4 +- Data/Abstractions/ILookupCache.cs | 14 + .../Abstractions}/IPropertyExtender.cs | 2 +- Data/Abstractions/IUniqueId.cs | 13 + .../Database => Data/Context}/ContextSeed.cs | 15 +- Data/Context/DatabaseContext.cs | 135 ++ Data/Data.csproj | 82 ++ Data/Extensions/Extensions.cs | 10 + Data/Helpers/DataValueCache.cs | 84 ++ Data/Helpers/LookupCache.cs | 114 ++ .../MigrationContext/MySqlDatabaseContext.cs | 8 +- .../PostgresqlDatabaseContext.cs | 17 +- .../MigrationContext/SqliteDatabaseContext.cs | 8 +- .../20180409183408_InitialCreate.Designer.cs | 6 +- .../MySql/20180409183408_InitialCreate.cs | 2 +- .../MySql/20180502195450_Update.Designer.cs | 6 +- .../Migrations/MySql/20180502195450_Update.cs | 2 +- .../20180516023249_AddEloField.Designer.cs | 6 +- .../MySql/20180516023249_AddEloField.cs | 2 +- .../20180517223349_AddRollingKDR.Designer.cs | 6 +- .../MySql/20180517223349_AddRollingKDR.cs | 2 +- ...tomatedOffenseAndRatingHistory.Designer.cs | 4 +- ...903_AddAutomatedOffenseAndRatingHistory.cs | 2 +- ...180601172317_AddActivityAmount.Designer.cs | 4 +- .../MySql/20180601172317_AddActivityAmount.cs | 2 +- .../20180602041758_AddClientMeta.Designer.cs | 4 +- .../MySql/20180602041758_AddClientMeta.cs | 2 +- ...0180605191706_AddEFACSnapshots.Designer.cs | 4 +- .../MySql/20180605191706_AddEFACSnapshots.cs | 2 +- ...20180614014303_IndexForEFAlias.Designer.cs | 4 +- .../MySql/20180614014303_IndexForEFAlias.cs | 2 +- ...902035612_AddFractionAndIsKill.Designer.cs | 4 +- .../20180902035612_AddFractionAndIsKill.cs | 2 +- ...154622_AddVisibilityPercentage.Designer.cs | 4 +- .../20180904154622_AddVisibilityPercentage.cs | 2 +- .../20180907020706_AddVision.Designer.cs | 4 +- .../MySql/20180907020706_AddVision.cs | 2 +- ...20180908004053_AddWhenToRating.Designer.cs | 4 +- .../MySql/20180908004053_AddWhenToRating.cs | 2 +- ...0180910221749_AddRatingIndexes.Designer.cs | 4 +- .../MySql/20180910221749_AddRatingIndexes.cs | 2 +- ...0911184224_AddEFAliasNameIndex.Designer.cs | 4 +- .../20180911184224_AddEFAliasNameIndex.cs | 2 +- ...0823_AddEFAliasNameMaxLength24.Designer.cs | 4 +- ...0180911190823_AddEFAliasNameMaxLength24.cs | 2 +- ...sCurrentValueToEFChangeHistory.Designer.cs | 4 +- ...ddPreviousCurrentValueToEFChangeHistory.cs | 2 +- ...3111_AddIndexToMessageTimeSent.Designer.cs | 4 +- ...0180915163111_AddIndexToMessageTimeSent.cs | 2 +- ...0180922231310_RemoveACSnapShot.Designer.cs | 4 +- .../MySql/20180922231310_RemoveACSnapShot.cs | 2 +- ...20180922231600_ReaddACSnapshot.Designer.cs | 4 +- .../MySql/20180922231600_ReaddACSnapshot.cs | 2 +- ..._MakePenaltyExpirationNullable.Designer.cs | 4 +- ...014171848_MakePenaltyExpirationNullable.cs | 2 +- ...125193243_MakeClientIPNullable.Designer.cs | 4 +- .../20181125193243_MakeClientIPNullable.cs | 2 +- ...ntToEFServerUpdateServerIdType.Designer.cs | 4 +- ...AddEndpointToEFServerUpdateServerIdType.cs | 2 +- ...1216214513_AddEvadePenaltyFlag.Designer.cs | 4 +- .../20181216214513_AddEvadePenaltyFlag.cs | 2 +- ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 4 +- ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 2 +- ...23142128_AddGameNameToEFServer.Designer.cs | 4 +- .../20190423142128_AddGameNameToEFServer.cs | 2 +- ...90615145212_AddAvgRecoilOffset.Designer.cs | 4 +- .../20190615145212_AddAvgRecoilOffset.cs | 2 +- ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 4 +- ...0190615214055_AddRecoilOffsetToSnapshot.cs | 2 +- ...90725000309_AlterEFRatingIndex.Designer.cs | 4 +- .../20190725000309_AlterEFRatingIndex.cs | 2 +- ...2174908_AddSearchNameToEFAlias.Designer.cs | 4 +- .../20190802174908_AddSearchNameToEFAlias.cs | 2 +- ...AvgSnapValueToClientStatistics.Designer.cs | 4 +- ...31210503_AvgSnapValueToClientStatistics.cs | 2 +- ...SnapHitCountToClientStatistics.Designer.cs | 4 +- ...80209_AddSnapHitCountToClientStatistics.cs | 2 +- ...unctionTableForSnapshotVector3.Designer.cs | 4 +- ...3620_UseJunctionTableForSnapshotVector3.cs | 2 +- ..._AddCurrentSnapValueToSnapshot.Designer.cs | 4 +- ...914011524_AddCurrentSnapValueToSnapshot.cs | 2 +- ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 4 +- ...0914012015_AddSessionSnapHitsToSnapshot.cs | 2 +- ...eClientHitLocationCountColumns.Designer.cs | 4 +- ...550_RenameClientHitLocationCountColumns.cs | 2 +- ...rceUniqueIndexForEFAliasIPName.Designer.cs | 4 +- ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 2 +- ...iveCoallationForAliasNameMySQL.Designer.cs | 4 +- ...aseSensitiveCoallationForAliasNameMySQL.cs | 2 +- ...140947_AddMissingActiveColumns.Designer.cs | 4 +- .../20191230140947_AddMissingActiveColumns.cs | 2 +- ...personationIdToEFChangeHistory.Designer.cs | 4 +- ...137_AddImpersonationIdToEFChangeHistory.cs | 2 +- ...21203304_AddHostnameToEFServer.Designer.cs | 4 +- .../20200521203304_AddHostnameToEFServer.cs | 2 +- ...9_AddIsPasswordProtectedColumn.Designer.cs | 4 +- ...0819224119_AddIsPasswordProtectedColumn.cs | 2 +- ...1114232340_UpdateEFRatingIndex.Designer.cs | 4 +- .../20201114232340_UpdateEFRatingIndex.cs | 2 +- ...dSentIngameFlagToClientMessage.Designer.cs | 4 +- ...023106_AddSentIngameFlagToClientMessage.cs | 2 +- ...024731_UpdateMigrationsToMySql.Designer.cs | 4 +- .../20201124024731_UpdateMigrationsToMySql.cs | 2 +- ...teEFMetaToSupportNonClientMeta.Designer.cs | 4 +- ...3921_UpdateEFMetaToSupportNonClientMeta.cs | 2 +- ...pdateEFMetaToSupportLinkedMeta.Designer.cs | 4 +- ...4170830_UpdateEFMetaToSupportLinkedMeta.cs | 2 +- ...0210315222843_AddAdvancedStats.Designer.cs | 1280 ++++++++++++++++ .../MySql/20210315222843_AddAdvancedStats.cs | 391 +++++ .../MySqlDatabaseContextModelSnapshot.cs | 1131 +++++++++----- .../20180409183408_InitialCreate.Designer.cs | 6 +- .../20180409183408_InitialCreate.cs | 2 +- .../20180502195450_Update.Designer.cs | 6 +- .../Postgresql}/20180502195450_Update.cs | 2 +- .../20180516023249_AddEloField.Designer.cs | 6 +- .../Postgresql}/20180516023249_AddEloField.cs | 2 +- .../20180517223349_AddRollingKDR.Designer.cs | 6 +- .../20180517223349_AddRollingKDR.cs | 2 +- ...tomatedOffenseAndRatingHistory.Designer.cs | 4 +- ...903_AddAutomatedOffenseAndRatingHistory.cs | 2 +- ...180601172317_AddActivityAmount.Designer.cs | 4 +- .../20180601172317_AddActivityAmount.cs | 2 +- .../20180602041758_AddClientMeta.Designer.cs | 4 +- .../20180602041758_AddClientMeta.cs | 2 +- ...0180605191706_AddEFACSnapshots.Designer.cs | 4 +- .../20180605191706_AddEFACSnapshots.cs | 2 +- ...20180614014303_IndexForEFAlias.Designer.cs | 4 +- .../20180614014303_IndexForEFAlias.cs | 2 +- ...902035612_AddFractionAndIsKill.Designer.cs | 4 +- .../20180902035612_AddFractionAndIsKill.cs | 2 +- ...154622_AddVisibilityPercentage.Designer.cs | 4 +- .../20180904154622_AddVisibilityPercentage.cs | 2 +- .../20180907020706_AddVision.Designer.cs | 4 +- .../Postgresql}/20180907020706_AddVision.cs | 2 +- ...20180908004053_AddWhenToRating.Designer.cs | 4 +- .../20180908004053_AddWhenToRating.cs | 2 +- ...0180910221749_AddRatingIndexes.Designer.cs | 4 +- .../20180910221749_AddRatingIndexes.cs | 2 +- ...0911184224_AddEFAliasNameIndex.Designer.cs | 4 +- .../20180911184224_AddEFAliasNameIndex.cs | 2 +- ...0823_AddEFAliasNameMaxLength24.Designer.cs | 4 +- ...0180911190823_AddEFAliasNameMaxLength24.cs | 2 +- ...sCurrentValueToEFChangeHistory.Designer.cs | 4 +- ...ddPreviousCurrentValueToEFChangeHistory.cs | 2 +- ...3111_AddIndexToMessageTimeSent.Designer.cs | 4 +- ...0180915163111_AddIndexToMessageTimeSent.cs | 2 +- ...0180922231310_RemoveACSnapShot.Designer.cs | 4 +- .../20180922231310_RemoveACSnapShot.cs | 2 +- ...20180922231600_ReaddACSnapshot.Designer.cs | 4 +- .../20180922231600_ReaddACSnapshot.cs | 2 +- ..._MakePenaltyExpirationNullable.Designer.cs | 4 +- ...014171848_MakePenaltyExpirationNullable.cs | 2 +- ...125193243_MakeClientIPNullable.Designer.cs | 4 +- .../20181125193243_MakeClientIPNullable.cs | 2 +- ...ntToEFServerUpdateServerIdType.Designer.cs | 4 +- ...AddEndpointToEFServerUpdateServerIdType.cs | 2 +- ...1216214513_AddEvadePenaltyFlag.Designer.cs | 4 +- .../20181216214513_AddEvadePenaltyFlag.cs | 2 +- ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 4 +- ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 2 +- ...23142128_AddGameNameToEFServer.Designer.cs | 4 +- .../20190423142128_AddGameNameToEFServer.cs | 2 +- ...90615145212_AddAvgRecoilOffset.Designer.cs | 4 +- .../20190615145212_AddAvgRecoilOffset.cs | 2 +- ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 4 +- ...0190615214055_AddRecoilOffsetToSnapshot.cs | 2 +- ...90725000309_AlterEFRatingIndex.Designer.cs | 4 +- .../20190725000309_AlterEFRatingIndex.cs | 2 +- ...2174908_AddSearchNameToEFAlias.Designer.cs | 4 +- .../20190802174908_AddSearchNameToEFAlias.cs | 2 +- ...AvgSnapValueToClientStatistics.Designer.cs | 4 +- ...31210503_AvgSnapValueToClientStatistics.cs | 2 +- ...SnapHitCountToClientStatistics.Designer.cs | 4 +- ...80209_AddSnapHitCountToClientStatistics.cs | 2 +- ...unctionTableForSnapshotVector3.Designer.cs | 4 +- ...3620_UseJunctionTableForSnapshotVector3.cs | 2 +- ..._AddCurrentSnapValueToSnapshot.Designer.cs | 4 +- ...914011524_AddCurrentSnapValueToSnapshot.cs | 2 +- ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 4 +- ...0914012015_AddSessionSnapHitsToSnapshot.cs | 2 +- ...eClientHitLocationCountColumns.Designer.cs | 4 +- ...550_RenameClientHitLocationCountColumns.cs | 2 +- ...rceUniqueIndexForEFAliasIPName.Designer.cs | 4 +- ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 2 +- ...iveCoallationForAliasNameMySQL.Designer.cs | 4 +- ...aseSensitiveCoallationForAliasNameMySQL.cs | 2 +- ...140947_AddMissingActiveColumns.Designer.cs | 4 +- .../20191230140947_AddMissingActiveColumns.cs | 2 +- ...personationIdToEFChangeHistory.Designer.cs | 4 +- ...137_AddImpersonationIdToEFChangeHistory.cs | 2 +- ...21203304_AddHostnameToEFServer.Designer.cs | 4 +- .../20200521203304_AddHostnameToEFServer.cs | 2 +- ...9_AddIsPasswordProtectedColumn.Designer.cs | 4 +- ...0819224119_AddIsPasswordProtectedColumn.cs | 2 +- ...1114232340_UpdateEFRatingIndex.Designer.cs | 4 +- .../20201114232340_UpdateEFRatingIndex.cs | 2 +- ...dSentIngameFlagToClientMessage.Designer.cs | 4 +- ...023106_AddSentIngameFlagToClientMessage.cs | 2 +- ..._UpdateMigrationsForPostgresql.Designer.cs | 4 +- ...125160058_UpdateMigrationsForPostgresql.cs | 2 +- ...teEFMetaToSupportNonClientMeta.Designer.cs | 4 +- ...4304_UpdateEFMetaToSupportNonClientMeta.cs | 2 +- ...pdateEFMetaToSupportLinkedMeta.Designer.cs | 4 +- ...4170956_UpdateEFMetaToSupportLinkedMeta.cs | 2 +- ...0210316004759_AddAdvancedStats.Designer.cs | 1305 +++++++++++++++++ .../20210316004759_AddAdvancedStats.cs | 391 +++++ .../PostgresqlDatabaseContextModelSnapshot.cs | 1171 +++++++++------ .../20180409183408_InitialCreate.Designer.cs | 6 +- .../Sqlite}/20180409183408_InitialCreate.cs | 2 +- .../Sqlite/20180502195450_Update.Designer.cs | 6 +- .../Sqlite}/20180502195450_Update.cs | 2 +- .../20180516023249_AddEloField.Designer.cs | 6 +- .../Sqlite}/20180516023249_AddEloField.cs | 2 +- .../20180517223349_AddRollingKDR.Designer.cs | 6 +- .../Sqlite}/20180517223349_AddRollingKDR.cs | 2 +- ...tomatedOffenseAndRatingHistory.Designer.cs | 4 +- ...903_AddAutomatedOffenseAndRatingHistory.cs | 2 +- ...180601172317_AddActivityAmount.Designer.cs | 4 +- .../20180601172317_AddActivityAmount.cs | 2 +- .../20180602041758_AddClientMeta.Designer.cs | 4 +- .../Sqlite}/20180602041758_AddClientMeta.cs | 2 +- ...0180605191706_AddEFACSnapshots.Designer.cs | 4 +- .../20180605191706_AddEFACSnapshots.cs | 2 +- ...20180614014303_IndexForEFAlias.Designer.cs | 4 +- .../Sqlite}/20180614014303_IndexForEFAlias.cs | 2 +- ...902035612_AddFractionAndIsKill.Designer.cs | 4 +- .../20180902035612_AddFractionAndIsKill.cs | 2 +- ...154622_AddVisibilityPercentage.Designer.cs | 4 +- .../20180904154622_AddVisibilityPercentage.cs | 2 +- .../20180907020706_AddVision.Designer.cs | 4 +- .../Sqlite}/20180907020706_AddVision.cs | 2 +- ...20180908004053_AddWhenToRating.Designer.cs | 4 +- .../Sqlite}/20180908004053_AddWhenToRating.cs | 2 +- ...0180910221749_AddRatingIndexes.Designer.cs | 4 +- .../20180910221749_AddRatingIndexes.cs | 2 +- ...0911184224_AddEFAliasNameIndex.Designer.cs | 4 +- .../20180911184224_AddEFAliasNameIndex.cs | 2 +- ...0823_AddEFAliasNameMaxLength24.Designer.cs | 4 +- ...0180911190823_AddEFAliasNameMaxLength24.cs | 2 +- ...sCurrentValueToEFChangeHistory.Designer.cs | 4 +- ...ddPreviousCurrentValueToEFChangeHistory.cs | 2 +- ...3111_AddIndexToMessageTimeSent.Designer.cs | 4 +- ...0180915163111_AddIndexToMessageTimeSent.cs | 2 +- ...0180922231310_RemoveACSnapShot.Designer.cs | 4 +- .../20180922231310_RemoveACSnapShot.cs | 2 +- ...20180922231600_ReaddACSnapshot.Designer.cs | 4 +- .../Sqlite}/20180922231600_ReaddACSnapshot.cs | 2 +- ..._MakePenaltyExpirationNullable.Designer.cs | 4 +- ...014171848_MakePenaltyExpirationNullable.cs | 2 +- ...125193243_MakeClientIPNullable.Designer.cs | 4 +- .../20181125193243_MakeClientIPNullable.cs | 2 +- ...ntToEFServerUpdateServerIdType.Designer.cs | 4 +- ...AddEndpointToEFServerUpdateServerIdType.cs | 2 +- ...1216214513_AddEvadePenaltyFlag.Designer.cs | 4 +- .../20181216214513_AddEvadePenaltyFlag.cs | 2 +- ...ddIndexToEFMeta-KeyAndClientId.Designer.cs | 4 +- ...2234742_AddIndexToEFMeta-KeyAndClientId.cs | 2 +- ...23142128_AddGameNameToEFServer.Designer.cs | 4 +- .../20190423142128_AddGameNameToEFServer.cs | 2 +- ...90615145212_AddAvgRecoilOffset.Designer.cs | 4 +- .../20190615145212_AddAvgRecoilOffset.cs | 2 +- ...4055_AddRecoilOffsetToSnapshot.Designer.cs | 4 +- ...0190615214055_AddRecoilOffsetToSnapshot.cs | 2 +- ...90725000309_AlterEFRatingIndex.Designer.cs | 4 +- .../20190725000309_AlterEFRatingIndex.cs | 2 +- ...2174908_AddSearchNameToEFAlias.Designer.cs | 4 +- .../20190802174908_AddSearchNameToEFAlias.cs | 2 +- ...AvgSnapValueToClientStatistics.Designer.cs | 4 +- ...31210503_AvgSnapValueToClientStatistics.cs | 2 +- ...SnapHitCountToClientStatistics.Designer.cs | 4 +- ...80209_AddSnapHitCountToClientStatistics.cs | 2 +- ...unctionTableForSnapshotVector3.Designer.cs | 4 +- ...3620_UseJunctionTableForSnapshotVector3.cs | 2 +- ..._AddCurrentSnapValueToSnapshot.Designer.cs | 4 +- ...914011524_AddCurrentSnapValueToSnapshot.cs | 2 +- ...5_AddSessionSnapHitsToSnapshot.Designer.cs | 4 +- ...0914012015_AddSessionSnapHitsToSnapshot.cs | 2 +- ...eClientHitLocationCountColumns.Designer.cs | 4 +- ...550_RenameClientHitLocationCountColumns.cs | 2 +- ...rceUniqueIndexForEFAliasIPName.Designer.cs | 4 +- ...0713_EnforceUniqueIndexForEFAliasIPName.cs | 2 +- ...iveCoallationForAliasNameMySQL.Designer.cs | 4 +- ...aseSensitiveCoallationForAliasNameMySQL.cs | 2 +- ...140947_AddMissingActiveColumns.Designer.cs | 4 +- .../20191230140947_AddMissingActiveColumns.cs | 2 +- ...personationIdToEFChangeHistory.Designer.cs | 4 +- ...137_AddImpersonationIdToEFChangeHistory.cs | 2 +- ...21203304_AddHostnameToEFServer.Designer.cs | 4 +- .../20200521203304_AddHostnameToEFServer.cs | 2 +- ...9_AddIsPasswordProtectedColumn.Designer.cs | 4 +- ...0819224119_AddIsPasswordProtectedColumn.cs | 2 +- ...1114232340_UpdateEFRatingIndex.Designer.cs | 4 +- .../20201114232340_UpdateEFRatingIndex.cs | 2 +- ...dSentIngameFlagToClientMessage.Designer.cs | 4 +- ...023106_AddSentIngameFlagToClientMessage.cs | 2 +- ...portNonClientMetaAndLinkedMeta.Designer.cs | 4 +- ...MetaToSupportNonClientMetaAndLinkedMeta.cs | 2 +- ...AdditionalClientStatsAndZScore.Designer.cs | 1067 +++++++++----- ...31432_AddAdditionalClientStatsAndZScore.cs | 273 ++++ ...210310231004_AddRankingHistory.Designer.cs | 1279 ++++++++++++++++ .../20210310231004_AddRankingHistory.cs | 74 + .../SqliteDatabaseContextModelSnapshot.cs | 1277 ++++++++++++++++ Data/Models/AuditFields.cs | 12 + .../Models/Client}/EFACSnapshotVector3.cs | 8 +- .../Models => Data/Models/Client}/EFClient.cs | 48 +- .../Models/Client}/EFClientKill.cs | 53 +- .../Models/Client}/EFClientMessage.cs | 6 +- .../Models/Client/Stats}/EFACSnapshot.cs | 13 +- .../Client/Stats/EFClientHitStatistic.cs | 91 ++ .../Client/Stats/EFClientRankingHistory.cs | 31 + .../Client/Stats}/EFClientRatingHistory.cs | 8 +- .../Client/Stats}/EFClientStatistics.cs | 14 +- .../Client/Stats}/EFHitLocationCount.cs | 8 +- .../Models/Client/Stats}/EFRating.cs | 6 +- .../Client/Stats/Reference/EFHitLocation.cs | 21 + Data/Models/Client/Stats/Reference/EFMap.cs | 21 + .../Client/Stats/Reference/EFMeansOfDeath.cs | 21 + .../Models/Client/Stats/Reference/EFWeapon.cs | 21 + .../Stats/Reference/EFWeaponAttachment.cs | 21 + .../Reference/EFWeaponAttachmentCombo.cs | 35 + .../Configuration/StatsModelConfiguration.cs | 92 ++ .../Database => Data}/Models/EFAlias.cs | 2 +- .../Database => Data}/Models/EFAliasLink.cs | 4 +- .../Models/EFChangeHistory.cs | 2 +- .../Database => Data}/Models/EFMeta.cs | 5 +- .../Database => Data}/Models/EFPenalty.cs | 21 +- Data/Models/Reference.cs | 19 + .../Models => Data/Models/Server}/EFServer.cs | 14 +- .../Models/Server}/EFServerStatistics.cs | 5 +- .../Database => Data}/Models/SharedEntity.cs | 18 +- .../Helpers => Data/Models}/Vector3.cs | 65 +- IW4MAdmin.sln | 58 +- .../AutomessageFeed/AutomessageFeed.csproj | 2 +- .../IW4ScriptCommands.csproj | 2 +- Plugins/LiveRadar/LiveRadar.csproj | 7 +- Plugins/LiveRadar/Plugin.cs | 10 +- Plugins/LiveRadar/RadarEvent.cs | 4 +- Plugins/Login/Login.csproj | 8 +- Plugins/ProfanityDeterment/Plugin.cs | 3 +- .../ProfanityDeterment.csproj | 2 +- Plugins/Stats/Cheat/Detection.cs | 66 +- Plugins/Stats/Cheat/DetectionPenaltyResult.cs | 2 +- Plugins/Stats/Cheat/Strain.cs | 5 +- Plugins/Stats/Cheat/Thresholds.cs | 6 +- .../IClientStatisticCalculator.cs | 11 + .../Client/Abstractions/IHitInfoBuilder.cs | 10 + .../IServerDistributionCalculator.cs | 11 + .../Client/Abstractions/IWeaponNameParser.cs | 10 + Plugins/Stats/Client/Game/AttachmentInfo.cs | 11 + Plugins/Stats/Client/Game/HitInfo.cs | 27 + Plugins/Stats/Client/Game/WeaponInfo.cs | 11 + Plugins/Stats/Client/HitCalculator.cs | 611 ++++++++ Plugins/Stats/Client/HitInfoBuilder.cs | 64 + .../Client/ServerDistributionCalculator.cs | 150 ++ Plugins/Stats/Client/WeaponNameParser.cs | 75 + Plugins/Stats/Commands/MostKillsCommand.cs | 3 +- Plugins/Stats/Commands/MostPlayedCommand.cs | 4 +- Plugins/Stats/Commands/ResetStats.cs | 6 +- Plugins/Stats/Commands/TopStats.cs | 34 +- Plugins/Stats/Commands/ViewStats.cs | 8 +- Plugins/Stats/Config/StatsConfiguration.cs | 80 +- .../Config/WeaponNameParserConfiguration.cs | 11 + Plugins/Stats/Dtos/AdvancedStatsInfo.cs | 28 + Plugins/Stats/Dtos/StatsInfoRequest.cs | 1 + Plugins/Stats/Dtos/TopStatsInfo.cs | 6 +- Plugins/Stats/Extensions.cs | 196 +++ .../AdvancedClientStatsResourceQueryHelper.cs | 156 ++ .../Helpers}/ChatResourceQueryHelper.cs | 18 +- Plugins/Stats/Helpers/ServerStats.cs | 13 +- Plugins/Stats/Helpers/StatManager.cs | 555 +++++-- .../Stats/Helpers/StatsResourceQueryHelper.cs | 7 +- Plugins/Stats/Helpers/WeaponNameExtensions.cs | 10 + Plugins/Stats/Models/ModelConfiguration.cs | 43 - Plugins/Stats/Plugin.cs | 57 +- Plugins/Stats/Stats.csproj | 4 +- .../Extensions/SearchQueryExtensions.cs | 77 - Plugins/Web/StatsWeb/StatsWeb.csproj | 35 - .../ViewComponents/TopPlayersViewComponent.cs | 28 - .../Stats/Components/TopPlayers/_List.cshtml | 91 -- .../Web/StatsWeb/Views/_ViewImports.cshtml | 3 - .../icons/0_no-place/menu_div_no_place.png | Bin 12836 -> 0 bytes .../icons/1_iron/menu_div_iron_sub03.png | Bin 18393 -> 0 bytes .../icons/2_bronze/menu_div_bronze_sub03.png | Bin 18593 -> 0 bytes .../icons/3_silver/menu_div_silver_sub03.png | Bin 17540 -> 0 bytes .../icons/4_gold/menu_div_gold_sub03.png | Bin 19996 -> 0 bytes .../5_platinum/menu_div_platinum_sub03.png | Bin 20952 -> 0 bytes .../6_semipro/menu_div_semipro_sub03.png | Bin 21663 -> 0 bytes .../images/icons/7_pro/menu_div_pro_sub03.png | Bin 21238 -> 0 bytes Plugins/Welcome/Plugin.cs | 8 +- Plugins/Welcome/Welcome.csproj | 8 +- SharedLibraryCore/BaseController.cs | 6 +- .../Commands/AddClientTagCommand.cs | 1 + SharedLibraryCore/Commands/ListClientTags.cs | 1 + SharedLibraryCore/Commands/NativeCommands.cs | 6 +- .../Commands/RemoveClientTagCommand.cs | 1 + .../Commands/SetClientTagCommand.cs | 1 + .../Commands/UnsetClientTagCommand.cs | 1 + .../Configuration/ApplicationConfiguration.cs | 2 +- .../Configuration/CommandProperties.cs | 2 +- ...ultConfiguration.cs => DefaultSettings.cs} | 3 +- .../Configuration/GameStringConfiguration.cs | 24 + SharedLibraryCore/Database/DatabaseContext.cs | 196 --- .../Meta/Responses/ReceivedPenaltyResponse.cs | 4 +- SharedLibraryCore/Dtos/PenaltyInfo.cs | 8 +- SharedLibraryCore/Dtos/PlayerInfo.cs | 4 +- SharedLibraryCore/Dtos/ServerInfo.cs | 1 + SharedLibraryCore/Interfaces/IAuditFields.cs | 9 + .../IClientNoticeMessageFormatter.cs | 2 +- SharedLibraryCore/Interfaces/IGameServer.cs | 1 + .../Interfaces/IManagerCommand.cs | 2 +- SharedLibraryCore/Interfaces/IMetaService.cs | 3 +- .../Interfaces/IPluginImporter.cs | 2 +- SharedLibraryCore/Localization/Permission.cs | 2 +- SharedLibraryCore/PartialEntities/EFAlias.cs | 7 - SharedLibraryCore/PartialEntities/EFClient.cs | 51 +- .../PartialEntities/EFPenalty.cs | 22 - .../AuditInformationRepository.cs | 3 +- SharedLibraryCore/Server.cs | 1 + .../Services/ChangeHistoryService.cs | 7 +- SharedLibraryCore/Services/ClientService.cs | 28 +- SharedLibraryCore/Services/PenaltyService.cs | 4 +- SharedLibraryCore/SharedLibraryCore.csproj | 24 +- SharedLibraryCore/Utilities.cs | 56 +- Tests/ApplicationTests/StatsWebTests.cs | 269 ---- .../Controllers}/API/StatsController.cs | 0 .../Validation/FindClientRequestValidator.cs | 4 +- WebfrontCore/Controllers/ActionController.cs | 8 +- .../{ => Client}/ClientController.cs | 27 +- .../Client/ClientStatisticsController.cs | 38 + .../Client/Legacy}/StatsController.cs | 49 +- WebfrontCore/Controllers/ConsoleController.cs | 1 + WebfrontCore/Controllers/HomeController.cs | 42 +- WebfrontCore/Controllers/PenaltyController.cs | 10 +- .../Middleware/ClaimsPermissionRemoval.cs | 8 +- WebfrontCore/Startup.cs | 27 +- .../PenaltyListViewComponent.cs | 2 +- .../ViewComponents/TopPlayersViewComponent.cs | 42 + WebfrontCore/ViewModels/PenaltyFilterInfo.cs | 4 +- WebfrontCore/Views/Client/Find/Index.cshtml | 2 +- .../Views/Client}/Message/Find.cshtml | 0 .../Views/Client}/Message/_Item.cshtml | 0 .../Views/Client/Profile/Index.cshtml | 60 +- .../Meta/_AdministeredPenaltyResponse.cshtml | 2 +- .../Meta/_ReceivedPenaltyResponse.cshtml | 3 +- .../Views/Client/Statistics/Advanced.cshtml | 457 ++++++ .../Components/TopPlayers/_List.cshtml | 151 ++ .../Views/Client/Statistics}/Index.cshtml | 4 +- .../Views/Client}/_MessageContext.cshtml | 0 .../Views/Client}/_PenaltyInfo.cshtml | 2 +- WebfrontCore/Views/Penalty/List.cshtml | 10 +- WebfrontCore/Views/Shared/_Layout.cshtml | 5 +- WebfrontCore/WebfrontCore.csproj | 25 +- WebfrontCore/bundleconfig.json | 7 +- WebfrontCore/libman.json | 4 + WebfrontCore/wwwroot/css/src/main.scss | 43 +- .../images/stats/hit_location_model.png | Bin 0 -> 182329 bytes .../wwwroot/images/stats/ranks/rank_0.png | Bin 0 -> 12029 bytes .../wwwroot/images/stats/ranks/rank_1.png | Bin 0 -> 13569 bytes .../wwwroot/images/stats/ranks/rank_10.png | Bin 0 -> 18442 bytes .../wwwroot/images/stats/ranks/rank_11.png | Bin 0 -> 19296 bytes .../wwwroot/images/stats/ranks/rank_12.png | Bin 0 -> 20286 bytes .../wwwroot/images/stats/ranks/rank_13.png | Bin 0 -> 16339 bytes .../wwwroot/images/stats/ranks/rank_14.png | Bin 0 -> 16204 bytes .../wwwroot/images/stats/ranks/rank_15.png | Bin 0 -> 16724 bytes .../wwwroot/images/stats/ranks/rank_16.png | Bin 0 -> 15764 bytes .../wwwroot/images/stats/ranks/rank_17.png | Bin 0 -> 16098 bytes .../wwwroot/images/stats/ranks/rank_18.png | Bin 0 -> 16631 bytes .../wwwroot/images/stats/ranks/rank_19.png | Bin 0 -> 16675 bytes .../wwwroot/images/stats/ranks/rank_2.png | Bin 0 -> 15340 bytes .../wwwroot/images/stats/ranks/rank_20.png | Bin 0 -> 16976 bytes .../wwwroot/images/stats/ranks/rank_21.png | Bin 0 -> 17439 bytes .../wwwroot/images/stats/ranks/rank_22.png | Bin 0 -> 16379 bytes .../wwwroot/images/stats/ranks/rank_23.png | Bin 0 -> 16697 bytes .../wwwroot/images/stats/ranks/rank_24.png | Bin 0 -> 17089 bytes .../wwwroot/images/stats/ranks/rank_3.png | Bin 0 -> 17097 bytes .../wwwroot/images/stats/ranks/rank_4.png | Bin 0 -> 13993 bytes .../wwwroot/images/stats/ranks/rank_5.png | Bin 0 -> 15888 bytes .../wwwroot/images/stats/ranks/rank_6.png | Bin 0 -> 17501 bytes .../wwwroot/images/stats/ranks/rank_7.png | Bin 0 -> 16914 bytes .../wwwroot/images/stats/ranks/rank_8.png | Bin 0 -> 17491 bytes .../wwwroot/images/stats/ranks/rank_9.png | Bin 0 -> 19131 bytes WebfrontCore/wwwroot/js/advanced_stats.js | 406 +++++ WebfrontCore/wwwroot/js/stats.js | 12 +- 505 files changed, 13671 insertions(+), 3271 deletions(-) create mode 100644 Data/Abstractions/IDataValueCache.cs rename {SharedLibraryCore/Interfaces => Data/Abstractions}/IDatabaseContextFactory.cs (86%) create mode 100644 Data/Abstractions/ILookupCache.cs rename {SharedLibraryCore/Interfaces => Data/Abstractions}/IPropertyExtender.cs (94%) create mode 100644 Data/Abstractions/IUniqueId.cs rename {SharedLibraryCore/Database => Data/Context}/ContextSeed.cs (82%) create mode 100644 Data/Context/DatabaseContext.cs create mode 100644 Data/Data.csproj create mode 100644 Data/Extensions/Extensions.cs create mode 100644 Data/Helpers/DataValueCache.cs create mode 100644 Data/Helpers/LookupCache.cs rename {SharedLibraryCore/Database => Data}/MigrationContext/MySqlDatabaseContext.cs (80%) rename {SharedLibraryCore/Database => Data}/MigrationContext/PostgresqlDatabaseContext.cs (70%) rename {SharedLibraryCore/Database => Data}/MigrationContext/SqliteDatabaseContext.cs (80%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180409183408_InitialCreate.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180409183408_InitialCreate.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180502195450_Update.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180502195450_Update.cs (95%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180516023249_AddEloField.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180516023249_AddEloField.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180517223349_AddRollingKDR.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180601172317_AddActivityAmount.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180602041758_AddClientMeta.cs (97%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180605191706_AddEFACSnapshots.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180614014303_IndexForEFAlias.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180907020706_AddVision.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180907020706_AddVision.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180908004053_AddWhenToRating.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180910221749_AddRatingIndexes.cs (96%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs (92%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs (94%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs (95%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180922231310_RemoveACSnapShot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20180922231600_ReaddACSnapshot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181125193243_MakeClientIPNullable.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs (92%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs (94%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs (92%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs (91%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs (97%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs (95%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs (98%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs (94%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs (92%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs (95%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs (94%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs (93%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs (97%) rename {SharedLibraryCore => Data}/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs (96%) create mode 100644 Data/Migrations/MySql/20210315222843_AddAdvancedStats.Designer.cs create mode 100644 Data/Migrations/MySql/20210315222843_AddAdvancedStats.cs rename {SharedLibraryCore => Data}/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs (62%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180409183408_InitialCreate.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180502195450_Update.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180502195450_Update.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180516023249_AddEloField.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180517223349_AddRollingKDR.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180531212903_AddAutomatedOffenseAndRatingHistory.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180601172317_AddActivityAmount.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180602041758_AddClientMeta.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180605191706_AddEFACSnapshots.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180614014303_IndexForEFAlias.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180902035612_AddFractionAndIsKill.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180904154622_AddVisibilityPercentage.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180907020706_AddVision.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180907020706_AddVision.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180908004053_AddWhenToRating.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180910221749_AddRatingIndexes.cs (96%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180911184224_AddEFAliasNameIndex.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180911190823_AddEFAliasNameMaxLength24.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180915163111_AddIndexToMessageTimeSent.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180922231310_RemoveACSnapShot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20180922231600_ReaddACSnapshot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20181014171848_MakePenaltyExpirationNullable.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20181125193243_MakeClientIPNullable.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20181216214513_AddEvadePenaltyFlag.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190423142128_AddGameNameToEFServer.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190615145212_AddAvgRecoilOffset.cs (91%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190615214055_AddRecoilOffsetToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190725000309_AlterEFRatingIndex.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190802174908_AddSearchNameToEFAlias.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190831210503_AvgSnapValueToClientStatistics.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190901180209_AddSnapHitCountToClientStatistics.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190901223620_UseJunctionTableForSnapshotVector3.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190914011524_AddCurrentSnapValueToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20190914012015_AddSessionSnapHitsToSnapshot.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20191004172550_RenameClientHitLocationCountColumns.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20191230140947_AddMissingActiveColumns.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20200423225137_AddImpersonationIdToEFChangeHistory.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20200521203304_AddHostnameToEFServer.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20200819224119_AddIsPasswordProtectedColumn.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20201114232340_UpdateEFRatingIndex.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Sqlite => Data/Migrations/Postgresql}/20201118023106_AddSentIngameFlagToClientMessage.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs (96%) create mode 100644 Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.Designer.cs create mode 100644 Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.cs rename {SharedLibraryCore => Data}/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs (61%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180409183408_InitialCreate.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180502195450_Update.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180502195450_Update.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180516023249_AddEloField.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180517223349_AddRollingKDR.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180531212903_AddAutomatedOffenseAndRatingHistory.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180601172317_AddActivityAmount.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180602041758_AddClientMeta.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180605191706_AddEFACSnapshots.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180614014303_IndexForEFAlias.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180902035612_AddFractionAndIsKill.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180904154622_AddVisibilityPercentage.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180907020706_AddVision.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180907020706_AddVision.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180908004053_AddWhenToRating.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180910221749_AddRatingIndexes.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180911184224_AddEFAliasNameIndex.cs (91%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180911190823_AddEFAliasNameMaxLength24.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180915163111_AddIndexToMessageTimeSent.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180922231310_RemoveACSnapShot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20180922231600_ReaddACSnapshot.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20181014171848_MakePenaltyExpirationNullable.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20181125193243_MakeClientIPNullable.cs (97%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20181216214513_AddEvadePenaltyFlag.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190423142128_AddGameNameToEFServer.cs (91%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190615145212_AddAvgRecoilOffset.cs (91%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190615214055_AddRecoilOffsetToSnapshot.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190725000309_AlterEFRatingIndex.cs (96%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190802174908_AddSearchNameToEFAlias.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190831210503_AvgSnapValueToClientStatistics.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190901180209_AddSnapHitCountToClientStatistics.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190901223620_UseJunctionTableForSnapshotVector3.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190914011524_AddCurrentSnapValueToSnapshot.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20190914012015_AddSessionSnapHitsToSnapshot.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20191004172550_RenameClientHitLocationCountColumns.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs (98%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs (94%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20191230140947_AddMissingActiveColumns.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20200423225137_AddImpersonationIdToEFChangeHistory.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20200521203304_AddHostnameToEFServer.cs (91%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20200819224119_AddIsPasswordProtectedColumn.cs (95%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20201114232340_UpdateEFRatingIndex.cs (93%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs (99%) rename {SharedLibraryCore/Migrations/Postgresql => Data/Migrations/Sqlite}/20201118023106_AddSentIngameFlagToClientMessage.cs (92%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs (99%) rename {SharedLibraryCore => Data}/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs (98%) rename SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs => Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.Designer.cs (65%) create mode 100644 Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.cs create mode 100644 Data/Migrations/Sqlite/20210310231004_AddRankingHistory.Designer.cs create mode 100644 Data/Migrations/Sqlite/20210310231004_AddRankingHistory.cs create mode 100644 Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs create mode 100644 Data/Models/AuditFields.cs rename {Plugins/Stats/Models => Data/Models/Client}/EFACSnapshotVector3.cs (73%) rename {SharedLibraryCore/Database/Models => Data/Models/Client}/EFClient.cs (50%) rename {Plugins/Stats/Models => Data/Models/Client}/EFClientKill.cs (51%) rename {Plugins/Stats/Models => Data/Models/Client}/EFClientMessage.cs (86%) rename {Plugins/Stats/Models => Data/Models/Client/Stats}/EFACSnapshot.cs (87%) create mode 100644 Data/Models/Client/Stats/EFClientHitStatistic.cs create mode 100644 Data/Models/Client/Stats/EFClientRankingHistory.cs rename {Plugins/Stats/Models => Data/Models/Client/Stats}/EFClientRatingHistory.cs (69%) rename {Plugins/Stats/Models => Data/Models/Client/Stats}/EFClientStatistics.cs (90%) rename {Plugins/Stats/Models => Data/Models/Client/Stats}/EFHitLocationCount.cs (81%) rename {Plugins/Stats/Models => Data/Models/Client/Stats}/EFRating.cs (91%) create mode 100644 Data/Models/Client/Stats/Reference/EFHitLocation.cs create mode 100644 Data/Models/Client/Stats/Reference/EFMap.cs create mode 100644 Data/Models/Client/Stats/Reference/EFMeansOfDeath.cs create mode 100644 Data/Models/Client/Stats/Reference/EFWeapon.cs create mode 100644 Data/Models/Client/Stats/Reference/EFWeaponAttachment.cs create mode 100644 Data/Models/Client/Stats/Reference/EFWeaponAttachmentCombo.cs create mode 100644 Data/Models/Configuration/StatsModelConfiguration.cs rename {SharedLibraryCore/Database => Data}/Models/EFAlias.cs (94%) rename {SharedLibraryCore/Database => Data}/Models/EFAliasLink.cs (81%) rename {SharedLibraryCore/Database => Data}/Models/EFChangeHistory.cs (95%) rename {SharedLibraryCore/Database => Data}/Models/EFMeta.cs (94%) rename {SharedLibraryCore/Database => Data}/Models/EFPenalty.cs (73%) create mode 100644 Data/Models/Reference.cs rename {Plugins/Stats/Models => Data/Models/Server}/EFServer.cs (57%) rename {Plugins/Stats/Models => Data/Models/Server}/EFServerStatistics.cs (75%) rename {SharedLibraryCore/Database => Data}/Models/SharedEntity.cs (63%) rename {SharedLibraryCore/Helpers => Data/Models}/Vector3.cs (64%) create mode 100644 Plugins/Stats/Client/Abstractions/IClientStatisticCalculator.cs create mode 100644 Plugins/Stats/Client/Abstractions/IHitInfoBuilder.cs create mode 100644 Plugins/Stats/Client/Abstractions/IServerDistributionCalculator.cs create mode 100644 Plugins/Stats/Client/Abstractions/IWeaponNameParser.cs create mode 100644 Plugins/Stats/Client/Game/AttachmentInfo.cs create mode 100644 Plugins/Stats/Client/Game/HitInfo.cs create mode 100644 Plugins/Stats/Client/Game/WeaponInfo.cs create mode 100644 Plugins/Stats/Client/HitCalculator.cs create mode 100644 Plugins/Stats/Client/HitInfoBuilder.cs create mode 100644 Plugins/Stats/Client/ServerDistributionCalculator.cs create mode 100644 Plugins/Stats/Client/WeaponNameParser.cs create mode 100644 Plugins/Stats/Config/WeaponNameParserConfiguration.cs create mode 100644 Plugins/Stats/Dtos/AdvancedStatsInfo.cs create mode 100644 Plugins/Stats/Extensions.cs create mode 100644 Plugins/Stats/Helpers/AdvancedClientStatsResourceQueryHelper.cs rename Plugins/{Web/StatsWeb => Stats/Helpers}/ChatResourceQueryHelper.cs (96%) create mode 100644 Plugins/Stats/Helpers/WeaponNameExtensions.cs delete mode 100644 Plugins/Stats/Models/ModelConfiguration.cs delete mode 100644 Plugins/Web/StatsWeb/Extensions/SearchQueryExtensions.cs delete mode 100644 Plugins/Web/StatsWeb/StatsWeb.csproj delete mode 100644 Plugins/Web/StatsWeb/ViewComponents/TopPlayersViewComponent.cs delete mode 100644 Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml delete mode 100644 Plugins/Web/StatsWeb/Views/_ViewImports.cshtml delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/0_no-place/menu_div_no_place.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/1_iron/menu_div_iron_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/2_bronze/menu_div_bronze_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/3_silver/menu_div_silver_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/4_gold/menu_div_gold_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/5_platinum/menu_div_platinum_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/6_semipro/menu_div_semipro_sub03.png delete mode 100644 Plugins/Web/StatsWeb/wwwroot/images/icons/7_pro/menu_div_pro_sub03.png rename SharedLibraryCore/Configuration/{DefaultConfiguration.cs => DefaultSettings.cs} (80%) create mode 100644 SharedLibraryCore/Configuration/GameStringConfiguration.cs delete mode 100644 SharedLibraryCore/Database/DatabaseContext.cs create mode 100644 SharedLibraryCore/Interfaces/IAuditFields.cs delete mode 100644 SharedLibraryCore/PartialEntities/EFAlias.cs delete mode 100644 SharedLibraryCore/PartialEntities/EFPenalty.cs delete mode 100644 Tests/ApplicationTests/StatsWebTests.cs rename {Plugins/Web/StatsWeb => WebfrontCore/Controllers}/API/StatsController.cs (100%) rename WebfrontCore/Controllers/{ => Client}/ClientController.cs (86%) create mode 100644 WebfrontCore/Controllers/Client/ClientStatisticsController.cs rename {Plugins/Web/StatsWeb/Controllers => WebfrontCore/Controllers/Client/Legacy}/StatsController.cs (78%) create mode 100644 WebfrontCore/ViewComponents/TopPlayersViewComponent.cs rename {Plugins/Web/StatsWeb/Views/Stats => WebfrontCore/Views/Client}/Message/Find.cshtml (100%) rename {Plugins/Web/StatsWeb/Views/Stats => WebfrontCore/Views/Client}/Message/_Item.cshtml (100%) create mode 100644 WebfrontCore/Views/Client/Statistics/Advanced.cshtml create mode 100644 WebfrontCore/Views/Client/Statistics/Components/TopPlayers/_List.cshtml rename {Plugins/Web/StatsWeb/Views/Stats => WebfrontCore/Views/Client/Statistics}/Index.cshtml (97%) rename {Plugins/Web/StatsWeb/Views/Stats => WebfrontCore/Views/Client}/_MessageContext.cshtml (100%) rename {Plugins/Web/StatsWeb/Views/Stats => WebfrontCore/Views/Client}/_PenaltyInfo.cshtml (91%) create mode 100644 WebfrontCore/wwwroot/images/stats/hit_location_model.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_0.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_1.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_10.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_11.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_12.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_13.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_14.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_15.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_16.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_17.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_18.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_19.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_2.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_20.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_21.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_22.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_23.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_24.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_3.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_4.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_5.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_6.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_7.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_8.png create mode 100644 WebfrontCore/wwwroot/images/stats/ranks/rank_9.png create mode 100644 WebfrontCore/wwwroot/js/advanced_stats.js diff --git a/Application/Application.csproj b/Application/Application.csproj index 00b23616..8e83b788 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -56,7 +56,7 @@ - Always + PreserveNewest PreserveNewest diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 7ecafa7b..35ff09ba 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -6,7 +6,6 @@ using SharedLibraryCore; using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration.Validation; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Exceptions; using SharedLibraryCore.Helpers; @@ -21,6 +20,8 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Context; using IW4MAdmin.Application.Migration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -291,6 +292,15 @@ namespace IW4MAdmin.Application IsRunning = true; ExternalIPAddress = await Utilities.GetExternalIP(); + #region DATABASE + _logger.LogInformation("Beginning database migration sync"); + Console.WriteLine(_translationLookup["MANAGER_MIGRATION_START"]); + await ContextSeed.Seed(_serviceProvider.GetRequiredService(), _tokenSource.Token); + await DatabaseHousekeeping.RemoveOldRatings(_serviceProvider.GetRequiredService(), _tokenSource.Token); + _logger.LogInformation("Finished database migration sync"); + Console.WriteLine(_translationLookup["MANAGER_MIGRATION_END"]); + #endregion + #region PLUGINS foreach (var plugin in Plugins) { @@ -331,7 +341,7 @@ namespace IW4MAdmin.Application // copy over default config if it doesn't exist if (!_appConfig.Servers?.Any() ?? true) { - var defaultConfig = new BaseConfigurationHandler("DefaultSettings").Configuration(); + var defaultConfig = new BaseConfigurationHandler("DefaultSettings").Configuration(); //ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate()); //var newConfig = ConfigHandler.Configuration(); @@ -424,15 +434,6 @@ namespace IW4MAdmin.Application #endregion - #region DATABASE - _logger.LogInformation("Beginning database migration sync"); - Console.WriteLine(_translationLookup["MANAGER_MIGRATION_START"]); - await ContextSeed.Seed(_serviceProvider.GetRequiredService(), _tokenSource.Token); - await DatabaseHousekeeping.RemoveOldRatings(_serviceProvider.GetRequiredService(), _tokenSource.Token); - _logger.LogInformation("Finished database migration sync"); - Console.WriteLine(_translationLookup["MANAGER_MIGRATION_END"]); - #endregion - #region COMMANDS if (await ClientSvc.HasOwnerAsync(_tokenSource.Token)) { @@ -517,7 +518,7 @@ namespace IW4MAdmin.Application // add the start event for this server var e = new GameEvent() { - Type = GameEvent.EventType.Start, + Type = EventType.Start, Data = $"{ServerInstance.GameName} started", Owner = ServerInstance }; diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json index 811565d1..eeff723d 100644 --- a/Application/DefaultSettings.json +++ b/Application/DefaultSettings.json @@ -16,7 +16,13 @@ "Keep grenade launcher use to a minimum", "Balance teams at ALL times" ], - "DisallowedClientNames": [ "Unknown Soldier", "VickNet", "UnknownSoldier", "CHEATER", "Play77" ], + "DisallowedClientNames": [ + "Unknown Soldier", + "VickNet", + "UnknownSoldier", + "CHEATER", + "Play77" + ], "QuickMessages": [ { "Game": "IW4", @@ -248,222 +254,178 @@ "Alias": "Rust", "Name": "mp_rust" }, - { "Alias": "Terminal", "Name": "mp_terminal" }, - { "Alias": "Crash", "Name": "mp_crash" }, - { "Alias": "Afghan", "Name": "mp_afghan" }, - { "Alias": "Derail", "Name": "mp_derail" }, - { "Alias": "Estate", "Name": "mp_estate" }, - { "Alias": "Favela", "Name": "mp_favela" }, - { "Alias": "Highrise", "Name": "mp_highrise" }, - { "Alias": "Invasion", "Name": "mp_invasion" }, - { "Alias": "Karachi", "Name": "mp_checkpoint" }, - { "Alias": "Quarry", "Name": "mp_quarry" }, - { "Alias": "Rundown", "Name": "mp_rundown" }, - { "Alias": "Scrapyard", "Name": "mp_boneyard" }, - { "Alias": "Skidrow", "Name": "mp_nightshift" }, - { "Alias": "Sub Base", "Name": "mp_subbase" }, - { "Alias": "Underpass", "Name": "mp_underpass" }, - { "Alias": "Wasteland", "Name": "mp_brecourt" }, - { "Alias": "Overgrown", "Name": "mp_overgrown" }, - { "Alias": "Strike", "Name": "mp_strike" }, - { "Alias": "Vacant", "Name": "mp_vacant" }, - { "Alias": "Carnival", "Name": "mp_abandon" }, - { "Alias": "Trailer Park", "Name": "mp_trailerpark" }, - { "Alias": "Fuel", "Name": "mp_fuel2" }, - { "Alias": "Storm", "Name": "mp_storm" }, - { "Alias": "Bailout", "Name": "mp_complex" }, - { "Alias": "Salvage", "Name": "mp_compact" }, - { "Alias": "Nuketown", "Name": "mp_nuked" }, - { "Alias": "Test map", "Name": "iw4_credits" }, - { "Alias": "Killhouse", "Name": "mp_killhouse" }, - { "Alias": "Bog", "Name": "mp_bog_sh" }, - { "Alias": "Freighter", "Name": "mp_cargoship_sh" }, - { "Alias": "Cargoship", "Name": "mp_cargoship" }, - { "Alias": "Shipment", "Name": "mp_shipment" }, - { "Alias": "Shipment - Long", "Name": "mp_shipment_long" }, - { "Alias": "Rust - Long", "Name": "mp_rust_long" }, - { "Alias": "Firing Range", "Name": "mp_firingrange" }, - { "Alias": "Chemical Plant", "Name": "mp_storm_spring" }, - { "Alias": "Tropical Favela", "Name": "mp_fav_tropical" }, - { "Alias": "Tropical Estate", "Name": "mp_estate_tropical" }, - { "Alias": "Tropical Crash", "Name": "mp_crash_tropical" }, - { "Alias": "Forgotten City", "Name": "mp_bloc_sh" }, - { "Alias": "Crossfire", "Name": "mp_cross_fire" }, - { "Alias": "Bloc", "Name": "mp_bloc" }, - { "Alias": "Oilrig", "Name": "oilrig" }, - { "Name": "Village", "Alias": "co_hunted" @@ -519,7 +481,7 @@ }, { "Alias": "Havana", - "Name": "mp_cairo" + "Name": "mp_cairo" }, { "Alias": "Hazard", @@ -885,5 +847,79 @@ } ] } - ] + ], + "GameStrings": { + "IW4": { + "torso_upper": "Upper Torso", + "torso_lower": "Lower Torso", + "right_leg_upper": "Upper Right Leg", + "right_leg_lower": "Lower Right Leg", + "right_hand": "Right Hand", + "right_foot": "Right Foot", + "right_arm_upper": "Upper Right Arm", + "right_arm_lower": "Lower Right Arm", + "left_leg_upper": "Upper Left Leg", + "left_leg_lower": "Lower Left Leg", + "left_hand": "Left Hand", + "left_foot": "Left Foot", + "left_arm_upper": "Upper Left Arm", + "left_arm_lower": "Lower Left Arm", + "acog": "ACOG Sight", + "eotech": "Holographic Sight", + "fmj": "FMJ", + "gl": "Grenade Launcher", + "heartbeat": "Heartbeat Sensor", + "reflex": "Red Dot Sight", + "rof": "Rapid Fire", + "thermal": "Thermal", + "xmags": "Extended Mags", + "m4": "M4A1", + "m40a3": "M40A3", + "ak47": "AK-47", + "ak47classic": "AK-47 Classic", + "fn2000": "F2000", + "masada": "ACR", + "famas": "FAMAS", + "fal": "FAL", + "scar": "SCAR-H", + "tavor": "TAR-21", + "m16": "M16A4", + "mp5k": "MP5K", + "ump45": "UMP45", + "kriss": "Vector", + "uzi": "Mini-Uzi", + "rpd": "RPD", + "sa80": "L86 LSW", + "mg4": "MG4", + "aug": "AUG HBAR", + "cheytac": "Intervention", + "barrett": "Barrett .50cal", + "wa2000": "WA2000", + "m21": "M21 EBR", + "pp2000": "PP2000", + "glock": "G18", + "beretta": "M93 Raffica", + "tmp": "TMP", + "spas12": "SPAS-12", + "aa12": "AA-12", + "model1887": "Model 1887", + "usp": "USP .45", + "coltanaconda": ".44 Magnum", + "deserteagle": "Desert Eagle", + "deserteaglegold": "Desert Eagle Gold", + "at4": "AT4-HS", + "m79": "Thumper", + "rpg": "RPG-7", + "concussion": "Stun", + "throwingknife": "Throwing Knife", + "ffar": "Airstrike", + "pavelow": "Pave Low", + "cobra": "Attack Helicopter", + "ac130": "AC-130", + "remotemissile": "Predator Missile", + "artillery": "Precision Airstrike", + "player": "", + "attach": "" + } + } } diff --git a/Application/EventParsers/BaseEventParser.cs b/Application/EventParsers/BaseEventParser.cs index 2bb40fbb..ddb3578c 100644 --- a/Application/EventParsers/BaseEventParser.cs +++ b/Application/EventParsers/BaseEventParser.cs @@ -5,6 +5,7 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; +using Data.Models; using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -310,7 +311,7 @@ namespace IW4MAdmin.Application.EventParsers } } - if (eventType.Contains("ExitLevel")) + if (eventType.Contains("ExitLevel") || eventType.Contains("ShutdownGame")) { return new GameEvent() { diff --git a/Application/Extensions/StartupExtensions.cs b/Application/Extensions/StartupExtensions.cs index b59a4b0b..4e0e2242 100644 --- a/Application/Extensions/StartupExtensions.cs +++ b/Application/Extensions/StartupExtensions.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using Data.MigrationContext; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -10,7 +11,6 @@ using Serilog; using Serilog.Events; using SharedLibraryCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database.MigrationContext; using ILogger = Serilog.ILogger; namespace IW4MAdmin.Application.Extensions @@ -32,13 +32,12 @@ namespace IW4MAdmin.Application.Extensions .ReadFrom.Configuration(configuration) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning); - if (Utilities.IsDevelopment) { loggerConfig = loggerConfig.WriteTo.Console( outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Server} {Level:u3}] {Message:lj}{NewLine}{Exception}") - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .MinimumLevel.Debug(); } @@ -67,10 +66,10 @@ namespace IW4MAdmin.Application.Extensions {DataSource = Path.Join(currentPath, "Database", "Database.db")}; var connectionString = connectionStringBuilder.ToString(); - var builder = new DbContextOptionsBuilder() - .UseSqlite(connectionString); - - services.AddSingleton((DbContextOptions) builder.Options); + services.AddSingleton(sp => (DbContextOptions) new DbContextOptionsBuilder() + .UseSqlite(connectionString) + .UseLoggerFactory(sp.GetRequiredService()) + .EnableSensitiveDataLogging().Options); return services; } @@ -90,7 +89,11 @@ namespace IW4MAdmin.Application.Extensions services.AddSingleton(sp => (DbContextOptions) new DbContextOptionsBuilder() .UseNpgsql(appConfig.ConnectionString + (appendTimeout ? ";Command Timeout=0" : ""), - postgresqlOptions => postgresqlOptions.EnableRetryOnFailure()) + postgresqlOptions => + { + postgresqlOptions.EnableRetryOnFailure(); + postgresqlOptions.SetPostgresVersion(new Version("9.4")); + }) .UseLoggerFactory(sp.GetRequiredService()).Options); return services; default: diff --git a/Application/Factories/DatabaseContextFactory.cs b/Application/Factories/DatabaseContextFactory.cs index 87b33f8f..604d8e6c 100644 --- a/Application/Factories/DatabaseContextFactory.cs +++ b/Application/Factories/DatabaseContextFactory.cs @@ -1,9 +1,9 @@ using System; +using Data.Abstractions; +using Data.Context; +using Data.MigrationContext; using Microsoft.EntityFrameworkCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; -using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Factories { diff --git a/Application/Factories/GameServerInstanceFactory.cs b/Application/Factories/GameServerInstanceFactory.cs index 8cadbc73..dbf4b82b 100644 --- a/Application/Factories/GameServerInstanceFactory.cs +++ b/Application/Factories/GameServerInstanceFactory.cs @@ -1,4 +1,6 @@ using System; +using Data.Abstractions; +using Data.Models.Server; using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore; using SharedLibraryCore.Configuration; @@ -37,7 +39,7 @@ namespace IW4MAdmin.Application.Factories /// public Server CreateServer(ServerConfiguration config, IManager manager) { - return new IW4MServer(config, _translationLookup, _metaService, _serviceProvider, _serviceProvider.GetRequiredService()); + return new IW4MServer(config, _translationLookup, _metaService, _serviceProvider, _serviceProvider.GetRequiredService(), _serviceProvider.GetRequiredService>()); } } } diff --git a/Application/Factories/ScriptCommandFactory.cs b/Application/Factories/ScriptCommandFactory.cs index d2e3a38b..ce6ea26e 100644 --- a/Application/Factories/ScriptCommandFactory.cs +++ b/Application/Factories/ScriptCommandFactory.cs @@ -6,9 +6,9 @@ using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; +using Data.Models.Client; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using static SharedLibraryCore.Database.Models.EFClient; namespace IW4MAdmin.Application.Factories { @@ -32,7 +32,7 @@ namespace IW4MAdmin.Application.Factories public IManagerCommand CreateScriptCommand(string name, string alias, string description, string permission, bool isTargetRequired, IEnumerable<(string, bool)> args, Action executeAction) { - var permissionEnum = Enum.Parse(permission); + var permissionEnum = Enum.Parse(permission); var argsArray = args.Select(_arg => new CommandArgument { Name = _arg.Item1, diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index a58f026f..c3d103be 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -15,10 +15,14 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Data.Abstractions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog.Context; using static SharedLibraryCore.Database.Models.EFClient; +using Data.Models; +using Data.Models.Server; +using static Data.Models.Client.EFClient; namespace IW4MAdmin { @@ -34,13 +38,15 @@ namespace IW4MAdmin public int Id { get; private set; } private readonly IServiceProvider _serviceProvider; private readonly IClientNoticeMessageFormatter _messageFormatter; + private readonly ILookupCache _serverCache; public IW4MServer( ServerConfiguration serverConfiguration, ITranslationLookup lookup, IMetaService metaService, IServiceProvider serviceProvider, - IClientNoticeMessageFormatter messageFormatter) : base(serviceProvider.GetRequiredService>(), + IClientNoticeMessageFormatter messageFormatter, + ILookupCache serverCache) : base(serviceProvider.GetRequiredService>(), serviceProvider.GetRequiredService(), serverConfiguration, serviceProvider.GetRequiredService(), @@ -51,6 +57,7 @@ namespace IW4MAdmin _metaService = metaService; _serviceProvider = serviceProvider; _messageFormatter = messageFormatter; + _serverCache = serverCache; } public override async Task OnClientConnected(EFClient clientFromLog) @@ -250,6 +257,28 @@ namespace IW4MAdmin { ServerLogger.LogDebug("processing event of type {type}", E.Type); + if (E.Type == GameEvent.EventType.Start) + { + var existingServer = (await _serverCache + .FirstAsync(server => server.Id == EndPoint)); + + var serverId = await GetIdForServer(E.Owner); + + if (existingServer == null) + { + var server = new EFServer() + { + Port = Port, + EndPoint = ToString(), + ServerId = serverId, + GameName = (Reference.Game?)GameName, + HostName = Hostname + }; + + await _serverCache.AddAsync(server); + } + } + if (E.Type == GameEvent.EventType.ConnectionLost) { var exception = E.Extra as Exception; @@ -734,6 +763,25 @@ namespace IW4MAdmin updatedClients.ToList() }; } + + private async Task GetIdForServer(Server server) + { + if ($"{server.IP}:{server.Port.ToString()}" == "66.150.121.184:28965") + { + return 886229536; + } + + // todo: this is not stable and will need to be migrated again... + long id = HashCode.Combine(server.IP, server.Port); + id = id < 0 ? Math.Abs(id) : id; + + var serverId = (await _serverCache + .FirstAsync(_server => _server.ServerId == server.EndPoint || + _server.EndPoint == server.ToString() || + _server.ServerId == id))?.ServerId; + + return !serverId.HasValue ? id : serverId.Value; + } private void UpdateMap(string mapname) { @@ -1113,6 +1161,7 @@ namespace IW4MAdmin this, GenerateUriForLog(LogPath, ServerConfig.GameLogServerUrl?.AbsoluteUri), gameLogReaderFactory); + await _serverCache.InitializeAsync(); _ = Task.Run(() => LogEvent.PollForChanges()); if (!Utilities.IsDevelopment) diff --git a/Application/Main.cs b/Application/Main.cs index c09159ad..8bd61a37 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -23,10 +23,18 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Helpers; using IW4MAdmin.Application.Extensions; using IW4MAdmin.Application.Localization; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; +using IW4MAdmin.Plugins.Stats.Client.Abstractions; +using IW4MAdmin.Plugins.Stats.Client; +using IW4MAdmin.Plugins.Stats.Client.Game; +using Stats.Client.Abstractions; +using Stats.Client; +using Stats.Helpers; namespace IW4MAdmin.Application { @@ -80,13 +88,13 @@ namespace IW4MAdmin.Application /// private static async Task LaunchAsync(string[] args) { - restart: + restart: ITranslationLookup translationLookup = null; var logger = BuildDefaultLogger(new ApplicationConfiguration()); Utilities.DefaultLogger = logger; IServiceCollection services = null; logger.LogInformation("Begin IW4MAdmin startup. Version is {version} {@args}", Version, args); - + try { // do any needed housekeeping file/folder migrations @@ -96,7 +104,7 @@ namespace IW4MAdmin.Application services = ConfigureServices(args); serviceProvider = services.BuildServiceProvider(); var versionChecker = serviceProvider.GetRequiredService(); - ServerManager = (ApplicationManager)serviceProvider.GetRequiredService(); + ServerManager = (ApplicationManager) serviceProvider.GetRequiredService(); translationLookup = serviceProvider.GetRequiredService(); await versionChecker.CheckVersion(); @@ -105,8 +113,12 @@ namespace IW4MAdmin.Application catch (Exception e) { - string failMessage = translationLookup == null ? "Failed to initialize IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; - string exitMessage = translationLookup == null ? "Press enter to exit..." : translationLookup["MANAGER_EXIT"]; + string failMessage = translationLookup == null + ? "Failed to initialize IW4MAdmin" + : translationLookup["MANAGER_INIT_FAIL"]; + string exitMessage = translationLookup == null + ? "Press enter to exit..." + : translationLookup["MANAGER_EXIT"]; logger.LogCritical(e, "Failed to initialize IW4MAdmin"); Console.WriteLine(failMessage); @@ -120,7 +132,8 @@ namespace IW4MAdmin.Application { if (translationLookup != null) { - Console.WriteLine(translationLookup[configException.Message].FormatExt(configException.ConfigurationFileName)); + Console.WriteLine(translationLookup[configException.Message] + .FormatExt(configException.ConfigurationFileName)); } foreach (string error in configException.Errors) @@ -148,7 +161,9 @@ namespace IW4MAdmin.Application catch (Exception e) { logger.LogCritical(e, "Failed to launch IW4MAdmin"); - string failMessage = translationLookup == null ? "Failed to launch IW4MAdmin" : translationLookup["MANAGER_INIT_FAIL"]; + string failMessage = translationLookup == null + ? "Failed to launch IW4MAdmin" + : translationLookup["MANAGER_INIT_FAIL"]; Console.WriteLine($"{failMessage}: {e.GetExceptionInfo()}"); } @@ -166,9 +181,9 @@ namespace IW4MAdmin.Application /// private static async Task RunApplicationTasksAsync(ILogger logger, IServiceCollection services) { - var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront ? - WebfrontCore.Program.Init(ServerManager, serviceProvider, services, ServerManager.CancellationToken) : - Task.CompletedTask; + var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront + ? WebfrontCore.Program.Init(ServerManager, serviceProvider, services, ServerManager.CancellationToken) + : Task.CompletedTask; // we want to run this one on a manual thread instead of letting the thread pool handle it, // because we can't exit early from waiting on console input, and it prevents us from restarting @@ -179,7 +194,8 @@ namespace IW4MAdmin.Application { ServerManager.Start(), webfrontTask, - serviceProvider.GetRequiredService().RunUploadStatus(ServerManager.CancellationToken) + serviceProvider.GetRequiredService() + .RunUploadStatus(ServerManager.CancellationToken) }; logger.LogDebug("Starting webfront and input tasks"); @@ -231,11 +247,12 @@ namespace IW4MAdmin.Application } } catch (OperationCanceledException) - { } + { + } } - private static IServiceCollection HandlePluginRegistration(ApplicationConfiguration appConfig, - IServiceCollection serviceCollection, + private static IServiceCollection HandlePluginRegistration(ApplicationConfiguration appConfig, + IServiceCollection serviceCollection, IMasterApi masterApi) { var defaultLogger = BuildDefaultLogger(appConfig); @@ -248,33 +265,44 @@ namespace IW4MAdmin.Application .BuildServiceProvider(); var pluginImporter = pluginServiceProvider.GetRequiredService(); - + // we need to register the rest client with regular collection serviceCollection.AddSingleton(masterApi); - + // register the native commands foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes() - .Where(_command => _command.BaseType == typeof(Command))) + .Where(_command => _command.BaseType == typeof(Command))) { defaultLogger.LogDebug("Registered native command type {name}", commandType.Name); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } // register the plugin implementations - var pluginImplementations = pluginImporter.DiscoverAssemblyPluginImplementations(); - foreach (var pluginType in pluginImplementations.Item1) + var (plugins, commands, configurations) = pluginImporter.DiscoverAssemblyPluginImplementations(); + foreach (var pluginType in plugins) { defaultLogger.LogDebug("Registered plugin type {name}", pluginType.FullName); serviceCollection.AddSingleton(typeof(IPlugin), pluginType); } // register the plugin commands - foreach (var commandType in pluginImplementations.Item2) + foreach (var commandType in commands) { defaultLogger.LogDebug("Registered plugin command type {name}", commandType.FullName); serviceCollection.AddSingleton(typeof(IManagerCommand), commandType); } + foreach (var configurationType in configurations) + { + defaultLogger.LogDebug("Registered plugin config type {name}", configurationType.Name); + var configInstance = (IBaseConfiguration) Activator.CreateInstance(configurationType); + var handlerType = typeof(BaseConfigurationHandler<>).MakeGenericType(configurationType); + var handlerInstance = Activator.CreateInstance(handlerType, new[] {configInstance.Name()}); + var genericInterfaceType = typeof(IConfigurationHandler<>).MakeGenericType(configurationType); + + serviceCollection.AddSingleton(genericInterfaceType, handlerInstance); + } + // register any script plugins foreach (var scriptPlugin in pluginImporter.DiscoverScriptPlugins()) { @@ -284,10 +312,9 @@ namespace IW4MAdmin.Application // register any eventable types foreach (var assemblyType in typeof(Program).Assembly.GetTypes() .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType)) - .Union(pluginImplementations - .Item1.SelectMany(_asm => _asm.Assembly.GetTypes()) - .Distinct() - .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType)))) + .Union(plugins.SelectMany(_asm => _asm.Assembly.GetTypes()) + .Distinct() + .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType)))) { var instance = Activator.CreateInstance(assemblyType) as IRegisterEvent; serviceCollection.AddSingleton(instance); @@ -295,7 +322,7 @@ namespace IW4MAdmin.Application return serviceCollection; } - + /// /// Configures the dependency injection services @@ -310,7 +337,7 @@ namespace IW4MAdmin.Application ? new Uri("http://127.0.0.1:8080") : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; var masterRestClient = RestClient.For(masterUri); - var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig); + var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig); if (appConfig == null) { @@ -327,13 +354,14 @@ namespace IW4MAdmin.Application Utilities.PermissionLevelOverrides.Add(key, value); } } - + // build the dependency list HandlePluginRegistration(appConfig, serviceCollection, masterRestClient); serviceCollection .AddBaseLogger(appConfig) .AddSingleton(_serviceProvider => serviceCollection) + .AddSingleton, BaseConfigurationHandler>() .AddSingleton((IConfigurationHandler) appConfigHandler) .AddSingleton( new BaseConfigurationHandler("CommandConfiguration") as @@ -372,6 +400,12 @@ namespace IW4MAdmin.Application .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(typeof(ILookupCache<>), typeof(LookupCache<>)) + .AddSingleton(typeof(IDataValueCache<,>), typeof(DataValueCache<,>)) .AddSingleton(translationLookup) .AddDatabaseContextOptions(appConfig); @@ -386,7 +420,7 @@ namespace IW4MAdmin.Application return serviceCollection; } - + private static ILogger BuildDefaultLogger(ApplicationConfiguration appConfig) { var collection = new ServiceCollection() @@ -396,4 +430,4 @@ namespace IW4MAdmin.Application return collection.GetRequiredService>(); } } -} +} \ No newline at end of file diff --git a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs index 616e19de..da9f8015 100644 --- a/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs +++ b/Application/Meta/AdministeredPenaltyResourceQueryHelper.cs @@ -1,8 +1,9 @@ using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; diff --git a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs index f63ad068..d9c8bbdd 100644 --- a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs +++ b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs @@ -1,10 +1,10 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SharedLibraryCore; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; diff --git a/Application/Meta/UpdatedAliasResourceQueryHelper.cs b/Application/Meta/UpdatedAliasResourceQueryHelper.cs index 4765cbf0..8dbce96e 100644 --- a/Application/Meta/UpdatedAliasResourceQueryHelper.cs +++ b/Application/Meta/UpdatedAliasResourceQueryHelper.cs @@ -6,6 +6,7 @@ using SharedLibraryCore.Interfaces; using SharedLibraryCore.QueryHelper; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; diff --git a/Application/Migration/DatabaseHousekeeping.cs b/Application/Migration/DatabaseHousekeeping.cs index eec18006..d4331dd9 100644 --- a/Application/Migration/DatabaseHousekeeping.cs +++ b/Application/Migration/DatabaseHousekeeping.cs @@ -2,7 +2,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using IW4MAdmin.Plugins.Stats.Models; +using Data.Abstractions; +using Data.Models.Client.Stats; using SharedLibraryCore.Database; using SharedLibraryCore.Interfaces; diff --git a/Application/Misc/BaseConfigurationHandler.cs b/Application/Misc/BaseConfigurationHandler.cs index 23d8295b..9aaedb06 100644 --- a/Application/Misc/BaseConfigurationHandler.cs +++ b/Application/Misc/BaseConfigurationHandler.cs @@ -22,6 +22,11 @@ namespace IW4MAdmin.Application.Misc Build(); } + public BaseConfigurationHandler() : this(typeof(T).Name) + { + + } + public string FileName { get; } public void Build() diff --git a/Application/Misc/ClientNoticeMessageFormatter.cs b/Application/Misc/ClientNoticeMessageFormatter.cs index d4885c6d..3ab5c120 100644 --- a/Application/Misc/ClientNoticeMessageFormatter.cs +++ b/Application/Misc/ClientNoticeMessageFormatter.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Data.Models; using SharedLibraryCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Application.Misc diff --git a/Application/Misc/MetaService.cs b/Application/Misc/MetaService.cs index 7de83bf2..47f0bd1d 100644 --- a/Application/Misc/MetaService.cs +++ b/Application/Misc/MetaService.cs @@ -7,8 +7,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; +using Data.Models; namespace IW4MAdmin.Application.Misc { diff --git a/Application/Misc/PluginImporter.cs b/Application/Misc/PluginImporter.cs index 79318b40..453b6b98 100644 --- a/Application/Misc/PluginImporter.cs +++ b/Application/Misc/PluginImporter.cs @@ -63,11 +63,12 @@ namespace IW4MAdmin.Application.Misc /// discovers all the C# assembly plugins and commands /// /// - public (IEnumerable, IEnumerable) DiscoverAssemblyPluginImplementations() + public (IEnumerable, IEnumerable, IEnumerable) DiscoverAssemblyPluginImplementations() { - string pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}"; + var pluginDir = $"{Utilities.OperatingDirectory}{PLUGIN_DIR}{Path.DirectorySeparatorChar}"; var pluginTypes = Enumerable.Empty(); var commandTypes = Enumerable.Empty(); + var configurationTypes = Enumerable.Empty(); if (Directory.Exists(pluginDir)) { @@ -92,10 +93,17 @@ namespace IW4MAdmin.Application.Misc .Where(_assemblyType => _assemblyType.IsClass && _assemblyType.BaseType == typeof(Command)); _logger.LogDebug("Discovered {count} plugin commands", commandTypes.Count()); + + configurationTypes = assemblies + .SelectMany(asm => asm.GetTypes()) + .Where(asmType => + asmType.IsClass && asmType.GetInterface(nameof(IBaseConfiguration), false) != null); + + _logger.LogDebug("Discovered {count} configuration implementations", configurationTypes.Count()); } } - return (pluginTypes, commandTypes); + return (pluginTypes, commandTypes, configurationTypes); } private IEnumerable GetRemoteAssemblies() diff --git a/Application/Misc/ScriptCommand.cs b/Application/Misc/ScriptCommand.cs index b4fe43a1..26d756e0 100644 --- a/Application/Misc/ScriptCommand.cs +++ b/Application/Misc/ScriptCommand.cs @@ -4,6 +4,7 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using System; using System.Threading.Tasks; +using Data.Models.Client; using Microsoft.Extensions.Logging; using static SharedLibraryCore.Database.Models.EFClient; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -18,7 +19,7 @@ namespace IW4MAdmin.Application.Misc private readonly Action _executeAction; private readonly ILogger _logger; - public ScriptCommand(string name, string alias, string description, bool isTargetRequired, Permission permission, + public ScriptCommand(string name, string alias, string description, bool isTargetRequired, EFClient.Permission permission, CommandArgument[] args, Action executeAction, CommandConfiguration config, ITranslationLookup layout, ILogger logger) : base(config, layout) { diff --git a/Application/Misc/SerializationHelpers.cs b/Application/Misc/SerializationHelpers.cs index d2753daf..bfb7e0b9 100644 --- a/Application/Misc/SerializationHelpers.cs +++ b/Application/Misc/SerializationHelpers.cs @@ -4,6 +4,7 @@ using SharedLibraryCore; using SharedLibraryCore.Database.Models; using System; using System.Net; +using Data.Models; using static SharedLibraryCore.Database.Models.EFClient; using static SharedLibraryCore.GameEvent; diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index 45b763c9..da5c3bad 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Data.Models; using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; using ILogger = Microsoft.Extensions.Logging.ILogger; diff --git a/Data/Abstractions/IDataValueCache.cs b/Data/Abstractions/IDataValueCache.cs new file mode 100644 index 00000000..a76bd28f --- /dev/null +++ b/Data/Abstractions/IDataValueCache.cs @@ -0,0 +1,12 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace Data.Abstractions +{ + public interface IDataValueCache where T : class + { + void SetCacheItem(Func, Task> itemGetter, string keyName, TimeSpan? expirationTime = null); + Task GetCacheItem(string keyName); + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/IDatabaseContextFactory.cs b/Data/Abstractions/IDatabaseContextFactory.cs similarity index 86% rename from SharedLibraryCore/Interfaces/IDatabaseContextFactory.cs rename to Data/Abstractions/IDatabaseContextFactory.cs index 179f4afb..cd455c14 100644 --- a/SharedLibraryCore/Interfaces/IDatabaseContextFactory.cs +++ b/Data/Abstractions/IDatabaseContextFactory.cs @@ -1,6 +1,6 @@ -using SharedLibraryCore.Database; +using Data.Context; -namespace SharedLibraryCore.Interfaces +namespace Data.Abstractions { /// /// describes the capabilities of the database context factory diff --git a/Data/Abstractions/ILookupCache.cs b/Data/Abstractions/ILookupCache.cs new file mode 100644 index 00000000..70b27572 --- /dev/null +++ b/Data/Abstractions/ILookupCache.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Data.Abstractions +{ + public interface ILookupCache where T : class + { + Task InitializeAsync(); + Task AddAsync(T item); + Task FirstAsync(Func query); + IEnumerable GetAll(); + } +} diff --git a/SharedLibraryCore/Interfaces/IPropertyExtender.cs b/Data/Abstractions/IPropertyExtender.cs similarity index 94% rename from SharedLibraryCore/Interfaces/IPropertyExtender.cs rename to Data/Abstractions/IPropertyExtender.cs index 7ca1df8c..33275498 100644 --- a/SharedLibraryCore/Interfaces/IPropertyExtender.cs +++ b/Data/Abstractions/IPropertyExtender.cs @@ -1,4 +1,4 @@ -namespace SharedLibraryCore.Interfaces +namespace Data.Abstractions { /// /// describes the capability of extending properties by name diff --git a/Data/Abstractions/IUniqueId.cs b/Data/Abstractions/IUniqueId.cs new file mode 100644 index 00000000..65b73fb6 --- /dev/null +++ b/Data/Abstractions/IUniqueId.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Data.Abstractions +{ + public interface IUniqueId + { + [NotMapped] + long Id { get; } + + [NotMapped] + string Value { get; } + } +} diff --git a/SharedLibraryCore/Database/ContextSeed.cs b/Data/Context/ContextSeed.cs similarity index 82% rename from SharedLibraryCore/Database/ContextSeed.cs rename to Data/Context/ContextSeed.cs index 770230fb..c9acf06f 100644 --- a/SharedLibraryCore/Database/ContextSeed.cs +++ b/Data/Context/ContextSeed.cs @@ -1,13 +1,12 @@ -using Microsoft.EntityFrameworkCore; -using SharedLibraryCore.Database.Models; -using System; -using System.Linq; +using System; using System.Threading; using System.Threading.Tasks; -using SharedLibraryCore.Interfaces; -using static SharedLibraryCore.Database.Models.EFClient; +using Data.Abstractions; +using Data.Models; +using Data.Models.Client; +using Microsoft.EntityFrameworkCore; -namespace SharedLibraryCore.Database +namespace Data.Context { public static class ContextSeed { @@ -30,7 +29,7 @@ namespace SharedLibraryCore.Database Connections = 0, FirstConnection = DateTime.UtcNow, LastConnection = DateTime.UtcNow, - Level = Permission.Console, + Level = EFClient.Permission.Console, Masked = true, NetworkId = 0, AliasLink = link, diff --git a/Data/Context/DatabaseContext.cs b/Data/Context/DatabaseContext.cs new file mode 100644 index 00000000..041912ed --- /dev/null +++ b/Data/Context/DatabaseContext.cs @@ -0,0 +1,135 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Threading; +using System.Threading.Tasks; +using Data.Extensions; +using Data.Models; +using Data.Models.Client; +using Data.Models.Client.Stats; +using Data.Models.Client.Stats.Reference; +using Data.Models.Server; + +namespace Data.Context +{ + public abstract class DatabaseContext : DbContext + { + public DbSet Clients { get; set; } + public DbSet Aliases { get; set; } + public DbSet AliasLinks { get; set; } + public DbSet Penalties { get; set; } + public DbSet EFMeta { get; set; } + public DbSet EFChangeHistory { get; set; } + + #region STATS + + public DbSet Vector3s { get; set; } + public DbSet SnapshotVector3s { get; set; } + public DbSet ACSnapshots { get; set; } + public DbSet Servers { get; set; } + public DbSet ClientKills { get; set; } + public DbSet ClientMessages { get; set; } + + public DbSet ServerStatistics { get; set; } + public DbSet HitLocations { get; set; } + public DbSet HitStatistics { get; set; } + public DbSet Weapons { get; set; } + public DbSet WeaponAttachments { get; set; } + public DbSet Maps { get; set; } + + #endregion + + private void SetAuditColumns() + { + return; + } + + public DatabaseContext() + { + if (!MigrationExtensions.IsMigration) + { + throw new InvalidOperationException(); + } + } + + public DatabaseContext(DbContextOptions options) : base(options) + { + } + + protected DatabaseContext(DbContextOptions options) : base(options) + { + } + + public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, + CancellationToken cancellationToken = default) + { + SetAuditColumns(); + return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + public override int SaveChanges() + { + SetAuditColumns(); + return base.SaveChanges(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + // make network id unique + modelBuilder.Entity(entity => { entity.HasIndex(e => e.NetworkId).IsUnique(); }); + + modelBuilder.Entity(entity => + { + entity.HasOne(p => p.Offender) + .WithMany(c => c.ReceivedPenalties) + .HasForeignKey(c => c.OffenderId) + .OnDelete(DeleteBehavior.Restrict); + + entity.HasOne(p => p.Punisher) + .WithMany(p => p.AdministeredPenalties) + .HasForeignKey(c => c.PunisherId) + .OnDelete(DeleteBehavior.Restrict); + + entity.Property(p => p.Expires) + .IsRequired(false); + }); + + modelBuilder.Entity(entity => + { + entity.HasMany(e => e.Children) + .WithOne(a => a.Link) + .HasForeignKey(k => k.LinkId) + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity(ent => + { + ent.Property(a => a.IPAddress).IsRequired(false); + ent.HasIndex(a => a.IPAddress); + ent.Property(a => a.Name).HasMaxLength(24); + ent.HasIndex(a => a.Name); + ent.Property(_alias => _alias.SearchableName).HasMaxLength(24); + ent.HasIndex(_alias => _alias.SearchableName); + ent.HasIndex(_alias => new {_alias.Name, _alias.IPAddress}).IsUnique(); + }); + + modelBuilder.Entity(ent => + { + ent.HasIndex(_meta => _meta.Key); + ent.HasIndex(_meta => _meta.LinkedMetaId); + ent.HasOne(_meta => _meta.LinkedMeta) + .WithMany() + .OnDelete(DeleteBehavior.SetNull); + }); + + // force full name for database conversion + modelBuilder.Entity().ToTable("EFClients"); + modelBuilder.Entity().ToTable("EFAlias"); + modelBuilder.Entity().ToTable("EFAliasLinks"); + modelBuilder.Entity().ToTable("EFPenalties"); + + Models.Configuration.StatsModelConfiguration.Configure(modelBuilder); + + base.OnModelCreating(modelBuilder); + } + } +} \ No newline at end of file diff --git a/Data/Data.csproj b/Data/Data.csproj new file mode 100644 index 00000000..671d685a --- /dev/null +++ b/Data/Data.csproj @@ -0,0 +1,82 @@ + + + + netcoreapp3.1 + Debug;Release;Prerelease + AnyCPU + true + RaidMax.IW4MAdmin.Data + RaidMax.IW4MAdmin.Data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles + + + + + + + + + + + + diff --git a/Data/Extensions/Extensions.cs b/Data/Extensions/Extensions.cs new file mode 100644 index 00000000..0ca9d9fd --- /dev/null +++ b/Data/Extensions/Extensions.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace Data.Extensions +{ + public static class MigrationExtensions + { + public static bool IsMigration => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Migration"; + } +} \ No newline at end of file diff --git a/Data/Helpers/DataValueCache.cs b/Data/Helpers/DataValueCache.cs new file mode 100644 index 00000000..f6ac8937 --- /dev/null +++ b/Data/Helpers/DataValueCache.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Data.Abstractions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Data.Helpers +{ + public class DataValueCache : IDataValueCache where T : class + { + private readonly ILogger _logger; + private readonly IDatabaseContextFactory _contextFactory; + private readonly Dictionary _cacheStates = new Dictionary(); + private const int DefaultExpireMinutes = 15; + + private class CacheState + { + public string Key { get; set; } + public DateTime LastRetrieval { get; set; } + public TimeSpan ExpirationTime { get; set; } + public Func, Task> Getter { get; set; } + public V Value { get; set; } + public bool IsExpired => (DateTime.Now - LastRetrieval.Add(ExpirationTime)).TotalSeconds > 0; + } + + public DataValueCache(ILogger> logger, IDatabaseContextFactory contextFactory) + { + _logger = logger; + _contextFactory = contextFactory; + } + + public void SetCacheItem(Func, Task> getter, string key, TimeSpan? expirationTime = null) + { + if (_cacheStates.ContainsKey(key)) + { + _logger.LogDebug("Cache key {key} is already added", key); + return; + } + + var state = new CacheState() + { + Key = key, + Getter = getter, + ExpirationTime = expirationTime ?? TimeSpan.FromMinutes(DefaultExpireMinutes) + }; + + _cacheStates.Add(key, state); + } + + public async Task GetCacheItem(string keyName) + { + if (!_cacheStates.ContainsKey(keyName)) + { + throw new ArgumentException("No cache found for key {key}", keyName); + } + + var state = _cacheStates[keyName]; + + if (state.IsExpired) + { + await RunCacheUpdate(state); + } + + return state.Value; + } + + private async Task RunCacheUpdate(CacheState state) + { + try + { + await using var context = _contextFactory.CreateContext(false); + var set = context.Set(); + var value = await state.Getter(set); + state.Value = value; + state.LastRetrieval = DateTime.Now; + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not get cached value for {key}", state.Key); + } + } + } +} \ No newline at end of file diff --git a/Data/Helpers/LookupCache.cs b/Data/Helpers/LookupCache.cs new file mode 100644 index 00000000..fd45b8bc --- /dev/null +++ b/Data/Helpers/LookupCache.cs @@ -0,0 +1,114 @@ +using Data.Abstractions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Data.Helpers +{ + public class LookupCache : ILookupCache where T : class, IUniqueId + { + private readonly ILogger _logger; + private readonly IDatabaseContextFactory _contextFactory; + private Dictionary _cachedItems; + private readonly SemaphoreSlim _onOperation = new SemaphoreSlim(1, 1); + + public LookupCache(ILogger> logger, IDatabaseContextFactory contextFactory) + { + _logger = logger; + _contextFactory = contextFactory; + } + + public async Task AddAsync(T item) + { + await _onOperation.WaitAsync(); + T existingItem = null; + + if (_cachedItems.ContainsKey(item.Id)) + { + existingItem = _cachedItems[item.Id]; + } + + if (existingItem != null) + { + _logger.LogDebug("Cached item already added for {type} {id} {value}", typeof(T).Name, item.Id, + item.Value); + _onOperation.Release(); + return existingItem; + } + + try + { + _logger.LogDebug("Adding new {type} with {id} {value}", typeof(T).Name, item.Id, item.Value); + await using var context = _contextFactory.CreateContext(); + context.Set().Add(item); + await context.SaveChangesAsync(); + _cachedItems.Add(item.Id, item); + return item; + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not add item to cache for {type}", typeof(T).Name); + throw new Exception("Could not add item to cache"); + } + finally + { + if (_onOperation.CurrentCount == 0) + { + _onOperation.Release(); + } + } + } + + public async Task FirstAsync(Func query) + { + await _onOperation.WaitAsync(); + + try + { + var cachedResult = _cachedItems.Values.Where(query); + + if (cachedResult.Any()) + { + return cachedResult.FirstOrDefault(); + } + } + + catch + { + } + + finally + { + if (_onOperation.CurrentCount == 0) + { + _onOperation.Release(1); + } + } + + return null; + } + + public IEnumerable GetAll() + { + return _cachedItems.Values; + } + + public async Task InitializeAsync() + { + try + { + await using var context = _contextFactory.CreateContext(); + _cachedItems = await context.Set().ToDictionaryAsync(item => item.Id); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not initialize caching for {cacheType}", typeof(T).Name); + } + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs b/Data/MigrationContext/MySqlDatabaseContext.cs similarity index 80% rename from SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs rename to Data/MigrationContext/MySqlDatabaseContext.cs index 88fd9cef..785869c8 100644 --- a/SharedLibraryCore/Database/MigrationContext/MySqlDatabaseContext.cs +++ b/Data/MigrationContext/MySqlDatabaseContext.cs @@ -1,13 +1,15 @@ using System; +using Data.Context; +using Data.Extensions; using Microsoft.EntityFrameworkCore; -namespace SharedLibraryCore.Database.MigrationContext +namespace Data.MigrationContext { public class MySqlDatabaseContext : DatabaseContext { public MySqlDatabaseContext() { - if (!Utilities.IsMigration) + if (!MigrationExtensions.IsMigration) { throw new InvalidOperationException(); } @@ -20,7 +22,7 @@ namespace SharedLibraryCore.Database.MigrationContext protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - if (Utilities.IsMigration) + if (MigrationExtensions.IsMigration) { optionsBuilder.UseMySql("Server=127.0.0.1;Database=IW4MAdmin_Migration;Uid=root;Pwd=password;") .EnableDetailedErrors(true) diff --git a/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs b/Data/MigrationContext/PostgresqlDatabaseContext.cs similarity index 70% rename from SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs rename to Data/MigrationContext/PostgresqlDatabaseContext.cs index cf6c57b8..d3df902e 100644 --- a/SharedLibraryCore/Database/MigrationContext/PostgresqlDatabaseContext.cs +++ b/Data/MigrationContext/PostgresqlDatabaseContext.cs @@ -1,33 +1,34 @@ using System; +using Data.Context; +using Data.Extensions; using Microsoft.EntityFrameworkCore; -namespace SharedLibraryCore.Database.MigrationContext +namespace Data.MigrationContext { public class PostgresqlDatabaseContext : DatabaseContext { public PostgresqlDatabaseContext() { - if (!Utilities.IsMigration) + if (!MigrationExtensions.IsMigration) { throw new InvalidOperationException(); } } - + public PostgresqlDatabaseContext(DbContextOptions options) : base(options) { - } - + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - if (Utilities.IsMigration) + if (MigrationExtensions.IsMigration) { optionsBuilder.UseNpgsql( - "Host=127.0.0.1;Database=IW4MAdmin_Migration;Username=postgres;Password=password;") + "Host=127.0.0.1;Database=IW4MAdmin_Migration;Username=postgres;Password=password;", + options => options.SetPostgresVersion(new Version("9.4"))) .EnableDetailedErrors(true) .EnableSensitiveDataLogging(true); } } - } } \ No newline at end of file diff --git a/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs b/Data/MigrationContext/SqliteDatabaseContext.cs similarity index 80% rename from SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs rename to Data/MigrationContext/SqliteDatabaseContext.cs index 89a8274c..22421a7e 100644 --- a/SharedLibraryCore/Database/MigrationContext/SqliteDatabaseContext.cs +++ b/Data/MigrationContext/SqliteDatabaseContext.cs @@ -1,13 +1,15 @@ using System; +using Data.Context; +using Data.Extensions; using Microsoft.EntityFrameworkCore; -namespace SharedLibraryCore.Database.MigrationContext +namespace Data.MigrationContext { public class SqliteDatabaseContext : DatabaseContext { public SqliteDatabaseContext() { - if (!Utilities.IsMigration) + if (!MigrationExtensions.IsMigration) { throw new InvalidOperationException(); } @@ -20,7 +22,7 @@ namespace SharedLibraryCore.Database.MigrationContext protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - if (Utilities.IsMigration) + if (MigrationExtensions.IsMigration) { optionsBuilder.UseSqlite("Data Source=IW4MAdmin_Migration.db") .EnableDetailedErrors(true) diff --git a/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs b/Data/Migrations/MySql/20180409183408_InitialCreate.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs rename to Data/Migrations/MySql/20180409183408_InitialCreate.Designer.cs index 686e0fb5..72836bff 100644 --- a/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.Designer.cs +++ b/Data/Migrations/MySql/20180409183408_InitialCreate.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180409183408_InitialCreate")] diff --git a/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs b/Data/Migrations/MySql/20180409183408_InitialCreate.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs rename to Data/Migrations/MySql/20180409183408_InitialCreate.cs index 32e488c7..4e4ec530 100644 --- a/SharedLibraryCore/Migrations/MySql/20180409183408_InitialCreate.cs +++ b/Data/Migrations/MySql/20180409183408_InitialCreate.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class InitialCreate : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs b/Data/Migrations/MySql/20180502195450_Update.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs rename to Data/Migrations/MySql/20180502195450_Update.Designer.cs index 576eeed1..200a84a1 100644 --- a/SharedLibraryCore/Migrations/MySql/20180502195450_Update.Designer.cs +++ b/Data/Migrations/MySql/20180502195450_Update.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180502195450_Update")] diff --git a/SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs b/Data/Migrations/MySql/20180502195450_Update.cs similarity index 95% rename from SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs rename to Data/Migrations/MySql/20180502195450_Update.cs index fc7795f5..f331a64d 100644 --- a/SharedLibraryCore/Migrations/MySql/20180502195450_Update.cs +++ b/Data/Migrations/MySql/20180502195450_Update.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class Update : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs b/Data/Migrations/MySql/20180516023249_AddEloField.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs rename to Data/Migrations/MySql/20180516023249_AddEloField.Designer.cs index 7cda630b..95b08e7b 100644 --- a/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.Designer.cs +++ b/Data/Migrations/MySql/20180516023249_AddEloField.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180516023249_AddEloField")] diff --git a/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs b/Data/Migrations/MySql/20180516023249_AddEloField.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs rename to Data/Migrations/MySql/20180516023249_AddEloField.cs index ccf1b51e..0412f35d 100644 --- a/SharedLibraryCore/Migrations/MySql/20180516023249_AddEloField.cs +++ b/Data/Migrations/MySql/20180516023249_AddEloField.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEloField : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs b/Data/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs rename to Data/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs index 0e6991cf..ac6e8758 100644 --- a/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs +++ b/Data/Migrations/MySql/20180517223349_AddRollingKDR.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180517223349_AddRollingKDR")] diff --git a/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs b/Data/Migrations/MySql/20180517223349_AddRollingKDR.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs rename to Data/Migrations/MySql/20180517223349_AddRollingKDR.cs index 638a2743..5fe056cd 100644 --- a/SharedLibraryCore/Migrations/MySql/20180517223349_AddRollingKDR.cs +++ b/Data/Migrations/MySql/20180517223349_AddRollingKDR.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddRollingKDR : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs rename to Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs index 442b7098..61813c53 100644 --- a/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs +++ b/Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] diff --git a/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs rename to Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs index b497989a..d83629a3 100644 --- a/SharedLibraryCore/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs +++ b/Data/Migrations/MySql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddAutomatedOffenseAndRatingHistory : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs b/Data/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs rename to Data/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs index 0e4bdd5b..103fa6b6 100644 --- a/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs +++ b/Data/Migrations/MySql/20180601172317_AddActivityAmount.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180601172317_AddActivityAmount")] diff --git a/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs b/Data/Migrations/MySql/20180601172317_AddActivityAmount.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs rename to Data/Migrations/MySql/20180601172317_AddActivityAmount.cs index a8ff56ff..82dade0a 100644 --- a/SharedLibraryCore/Migrations/MySql/20180601172317_AddActivityAmount.cs +++ b/Data/Migrations/MySql/20180601172317_AddActivityAmount.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddActivityAmount : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs b/Data/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs rename to Data/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs index 66dc5702..13a91e90 100644 --- a/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs +++ b/Data/Migrations/MySql/20180602041758_AddClientMeta.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180602041758_AddClientMeta")] diff --git a/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs b/Data/Migrations/MySql/20180602041758_AddClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs rename to Data/Migrations/MySql/20180602041758_AddClientMeta.cs index 9566c210..54e510e2 100644 --- a/SharedLibraryCore/Migrations/MySql/20180602041758_AddClientMeta.cs +++ b/Data/Migrations/MySql/20180602041758_AddClientMeta.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs b/Data/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs rename to Data/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs index 7d586f1b..ac4de91f 100644 --- a/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs +++ b/Data/Migrations/MySql/20180605191706_AddEFACSnapshots.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180605191706_AddEFACSnapshots")] diff --git a/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs b/Data/Migrations/MySql/20180605191706_AddEFACSnapshots.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs rename to Data/Migrations/MySql/20180605191706_AddEFACSnapshots.cs index e6c7e721..6011345d 100644 --- a/SharedLibraryCore/Migrations/MySql/20180605191706_AddEFACSnapshots.cs +++ b/Data/Migrations/MySql/20180605191706_AddEFACSnapshots.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEFACSnapshots : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs b/Data/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs rename to Data/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs index 24cee69e..cfbd70c5 100644 --- a/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs +++ b/Data/Migrations/MySql/20180614014303_IndexForEFAlias.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180614014303_IndexForEFAlias")] diff --git a/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs b/Data/Migrations/MySql/20180614014303_IndexForEFAlias.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs rename to Data/Migrations/MySql/20180614014303_IndexForEFAlias.cs index 4137b988..95fe7acd 100644 --- a/SharedLibraryCore/Migrations/MySql/20180614014303_IndexForEFAlias.cs +++ b/Data/Migrations/MySql/20180614014303_IndexForEFAlias.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class IndexForEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs b/Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs rename to Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs index 76646c90..cb2f8150 100644 --- a/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs +++ b/Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180902035612_AddFractionAndIsKill")] diff --git a/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs b/Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs rename to Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs index 529a79c4..7c3e2034 100644 --- a/SharedLibraryCore/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs +++ b/Data/Migrations/MySql/20180902035612_AddFractionAndIsKill.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddFractionAndIsKill : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs b/Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs rename to Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs index b9ec66ff..94bd439c 100644 --- a/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs +++ b/Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180904154622_AddVisibilityPercentage")] diff --git a/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs b/Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs rename to Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs index d4a8132e..0cb44ec8 100644 --- a/SharedLibraryCore/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs +++ b/Data/Migrations/MySql/20180904154622_AddVisibilityPercentage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddVisibilityPercentage : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs b/Data/Migrations/MySql/20180907020706_AddVision.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs rename to Data/Migrations/MySql/20180907020706_AddVision.Designer.cs index ade98e4e..f8658f5a 100644 --- a/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.Designer.cs +++ b/Data/Migrations/MySql/20180907020706_AddVision.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180907020706_AddVision")] diff --git a/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs b/Data/Migrations/MySql/20180907020706_AddVision.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs rename to Data/Migrations/MySql/20180907020706_AddVision.cs index 8085963a..19bc5e3f 100644 --- a/SharedLibraryCore/Migrations/MySql/20180907020706_AddVision.cs +++ b/Data/Migrations/MySql/20180907020706_AddVision.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddVision : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs b/Data/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs rename to Data/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs index 2d700dce..6a4c0bb9 100644 --- a/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs +++ b/Data/Migrations/MySql/20180908004053_AddWhenToRating.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180908004053_AddWhenToRating")] diff --git a/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs b/Data/Migrations/MySql/20180908004053_AddWhenToRating.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs rename to Data/Migrations/MySql/20180908004053_AddWhenToRating.cs index 63e84cc3..59a98152 100644 --- a/SharedLibraryCore/Migrations/MySql/20180908004053_AddWhenToRating.cs +++ b/Data/Migrations/MySql/20180908004053_AddWhenToRating.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddWhenToRating : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs b/Data/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs rename to Data/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs index 15b4bd6d..f37f1321 100644 --- a/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs +++ b/Data/Migrations/MySql/20180910221749_AddRatingIndexes.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180910221749_AddRatingIndexes")] diff --git a/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs b/Data/Migrations/MySql/20180910221749_AddRatingIndexes.cs similarity index 96% rename from SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs rename to Data/Migrations/MySql/20180910221749_AddRatingIndexes.cs index fc26e0d7..f81d83dc 100644 --- a/SharedLibraryCore/Migrations/MySql/20180910221749_AddRatingIndexes.cs +++ b/Data/Migrations/MySql/20180910221749_AddRatingIndexes.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddRatingIndexes : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs b/Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs rename to Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs index e740317a..0d74c86a 100644 --- a/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs +++ b/Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180911184224_AddEFAliasNameIndex")] diff --git a/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs b/Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs similarity index 92% rename from SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs rename to Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs index f810fc9f..7e62a4f0 100644 --- a/SharedLibraryCore/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs +++ b/Data/Migrations/MySql/20180911184224_AddEFAliasNameIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEFAliasNameIndex : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs rename to Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs index 2c099c6e..6580d156 100644 --- a/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs +++ b/Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180911190823_AddEFAliasNameMaxLength24")] diff --git a/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs b/Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs similarity index 94% rename from SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs rename to Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs index 7e03a909..0b281c63 100644 --- a/SharedLibraryCore/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs +++ b/Data/Migrations/MySql/20180911190823_AddEFAliasNameMaxLength24.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEFAliasNameMaxLength24 : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs rename to Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs index 68be3dbe..5cc66330 100644 --- a/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs +++ b/Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs similarity index 95% rename from SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs rename to Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs index a910959c..ee1aa976 100644 --- a/SharedLibraryCore/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs +++ b/Data/Migrations/MySql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddPreviousCurrentValueToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs rename to Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs index 27b20cb9..a4847787 100644 --- a/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs +++ b/Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180915163111_AddIndexToMessageTimeSent")] diff --git a/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs b/Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs rename to Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs index 18e39938..4baf71ce 100644 --- a/SharedLibraryCore/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs +++ b/Data/Migrations/MySql/20180915163111_AddIndexToMessageTimeSent.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddIndexToMessageTimeSent : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs b/Data/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs rename to Data/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs index f0cc690b..64f28ed5 100644 --- a/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs +++ b/Data/Migrations/MySql/20180922231310_RemoveACSnapShot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180922231310_RemoveACSnapShot")] diff --git a/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs b/Data/Migrations/MySql/20180922231310_RemoveACSnapShot.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs rename to Data/Migrations/MySql/20180922231310_RemoveACSnapShot.cs index d1804ad0..5e85477a 100644 --- a/SharedLibraryCore/Migrations/MySql/20180922231310_RemoveACSnapShot.cs +++ b/Data/Migrations/MySql/20180922231310_RemoveACSnapShot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class RemoveACSnapShot : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs b/Data/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs rename to Data/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs index acb00ec6..3dbc6574 100644 --- a/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs +++ b/Data/Migrations/MySql/20180922231600_ReaddACSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20180922231600_ReaddACSnapshot")] diff --git a/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs b/Data/Migrations/MySql/20180922231600_ReaddACSnapshot.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs rename to Data/Migrations/MySql/20180922231600_ReaddACSnapshot.cs index da730312..ff9797dd 100644 --- a/SharedLibraryCore/Migrations/MySql/20180922231600_ReaddACSnapshot.cs +++ b/Data/Migrations/MySql/20180922231600_ReaddACSnapshot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class ReaddACSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs rename to Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs index 387e3e69..eb274592 100644 --- a/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs +++ b/Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181014171848_MakePenaltyExpirationNullable")] diff --git a/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs b/Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs rename to Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs index d1ab3570..8b007788 100644 --- a/SharedLibraryCore/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs +++ b/Data/Migrations/MySql/20181014171848_MakePenaltyExpirationNullable.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class MakePenaltyExpirationNullable : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs b/Data/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs rename to Data/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs index 62ca0ffb..5afe44ec 100644 --- a/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs +++ b/Data/Migrations/MySql/20181125193243_MakeClientIPNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181125193243_MakeClientIPNullable")] diff --git a/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs b/Data/Migrations/MySql/20181125193243_MakeClientIPNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs rename to Data/Migrations/MySql/20181125193243_MakeClientIPNullable.cs index 8e858b04..60a3221b 100644 --- a/SharedLibraryCore/Migrations/MySql/20181125193243_MakeClientIPNullable.cs +++ b/Data/Migrations/MySql/20181125193243_MakeClientIPNullable.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class MakeClientIPNullable : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs rename to Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs index f6a21ff9..d6b4d6ed 100644 --- a/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs +++ b/Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] diff --git a/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs similarity index 92% rename from SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs rename to Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs index 52d1d831..a41c8a2d 100644 --- a/SharedLibraryCore/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs +++ b/Data/Migrations/MySql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEndpointToEFServerUpdateServerIdType : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs b/Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs rename to Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs index 2f6186b8..44e2f1b7 100644 --- a/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs +++ b/Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20181216214513_AddEvadePenaltyFlag")] diff --git a/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs b/Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs rename to Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs index 0037aae5..a5913a04 100644 --- a/SharedLibraryCore/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs +++ b/Data/Migrations/MySql/20181216214513_AddEvadePenaltyFlag.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddEvadePenaltyFlag : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs rename to Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs index a114d3a9..06b12894 100644 --- a/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs +++ b/Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] diff --git a/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs similarity index 94% rename from SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs rename to Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs index 3b9621cd..e5d1e9a9 100644 --- a/SharedLibraryCore/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs +++ b/Data/Migrations/MySql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddIndexToEFMetaKeyAndClientId : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs b/Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs rename to Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs index 0ff15914..eb142757 100644 --- a/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs +++ b/Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190423142128_AddGameNameToEFServer")] diff --git a/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs b/Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs rename to Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs index 45b6a189..b5e1fe02 100644 --- a/SharedLibraryCore/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs +++ b/Data/Migrations/MySql/20190423142128_AddGameNameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddGameNameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs b/Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs rename to Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs index 2023a061..a2af60ed 100644 --- a/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs +++ b/Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190615145212_AddAvgRecoilOffset")] diff --git a/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs b/Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs similarity index 91% rename from SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs rename to Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs index d74bfd95..7ddea78f 100644 --- a/SharedLibraryCore/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs +++ b/Data/Migrations/MySql/20190615145212_AddAvgRecoilOffset.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddAvgRecoilOffset : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs rename to Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs index 25f0f3f3..694e823e 100644 --- a/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs +++ b/Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190615214055_AddRecoilOffsetToSnapshot")] diff --git a/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs b/Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs rename to Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs index 481e74bd..44aa0fbd 100644 --- a/SharedLibraryCore/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs +++ b/Data/Migrations/MySql/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddRecoilOffsetToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs b/Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs rename to Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs index d26ad7cf..4b1a6f97 100644 --- a/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs +++ b/Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190725000309_AlterEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs b/Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs similarity index 97% rename from SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs rename to Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs index d198ee2d..994bcfc5 100644 --- a/SharedLibraryCore/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs +++ b/Data/Migrations/MySql/20190725000309_AlterEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AlterEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs b/Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs rename to Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs index 2498fc41..55550d32 100644 --- a/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs +++ b/Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190802174908_AddSearchNameToEFAlias")] diff --git a/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs b/Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs similarity index 95% rename from SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs rename to Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs index 249713b6..6a2650cc 100644 --- a/SharedLibraryCore/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs +++ b/Data/Migrations/MySql/20190802174908_AddSearchNameToEFAlias.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddSearchNameToEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs rename to Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs index ca976673..ad2c5382 100644 --- a/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs +++ b/Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190831210503_AvgSnapValueToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs b/Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs rename to Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs index ddd0278a..0ac58e12 100644 --- a/SharedLibraryCore/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs +++ b/Data/Migrations/MySql/20190831210503_AvgSnapValueToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AvgSnapValueToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs rename to Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs index 46ca9d25..16cb66b7 100644 --- a/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs +++ b/Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190901180209_AddSnapHitCountToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs b/Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs rename to Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs index 0b102af3..fd6258da 100644 --- a/SharedLibraryCore/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs +++ b/Data/Migrations/MySql/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddSnapHitCountToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs rename to Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs index a16f5ed5..435383a4 100644 --- a/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs +++ b/Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] diff --git a/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs b/Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs rename to Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs index 82d20240..e256200b 100644 --- a/SharedLibraryCore/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs +++ b/Data/Migrations/MySql/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class UseJunctionTableForSnapshotVector3 : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs rename to Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs index 4f4d44ab..0c9a6fd9 100644 --- a/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs +++ b/Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] diff --git a/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs b/Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs rename to Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs index 9b225d5d..cd9755a8 100644 --- a/SharedLibraryCore/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs +++ b/Data/Migrations/MySql/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddCurrentSnapValueToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs rename to Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs index 97118961..3bbec379 100644 --- a/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs +++ b/Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] diff --git a/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs b/Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs rename to Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs index e4b2340b..45cbc9b7 100644 --- a/SharedLibraryCore/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs +++ b/Data/Migrations/MySql/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddSessionSnapHitsToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs rename to Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs index 91727ea7..a56222c6 100644 --- a/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs +++ b/Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191004172550_RenameClientHitLocationCountColumns")] diff --git a/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs b/Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs rename to Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs index 4ebe4ccd..cec9d7cf 100644 --- a/SharedLibraryCore/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs +++ b/Data/Migrations/MySql/20191004172550_RenameClientHitLocationCountColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class RenameClientHitLocationCountColumns : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs rename to Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs index d156f99b..a36575e9 100644 --- a/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs +++ b/Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] diff --git a/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs similarity index 98% rename from SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs rename to Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs index bd5c6a82..e5e781c5 100644 --- a/SharedLibraryCore/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs +++ b/Data/Migrations/MySql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class EnforceUniqueIndexForEFAliasIPName : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs rename to Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs index 59ca1e24..0f86740a 100644 --- a/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs +++ b/Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] diff --git a/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs similarity index 94% rename from SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs rename to Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs index e91b3f53..0fad88fe 100644 --- a/SharedLibraryCore/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs +++ b/Data/Migrations/MySql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs b/Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs rename to Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs index 01a9b9f2..de6cd57d 100644 --- a/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs +++ b/Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20191230140947_AddMissingActiveColumns")] diff --git a/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs b/Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs rename to Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs index 13afb77f..0b7eb0c7 100644 --- a/SharedLibraryCore/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs +++ b/Data/Migrations/MySql/20191230140947_AddMissingActiveColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddMissingActiveColumns : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs rename to Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs index b3cf9f08..54d7c9a0 100644 --- a/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs +++ b/Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs rename to Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs index b1d337d9..1fa955a2 100644 --- a/SharedLibraryCore/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs +++ b/Data/Migrations/MySql/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddImpersonationIdToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs b/Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs rename to Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs index 0de748a5..cadc4929 100644 --- a/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs +++ b/Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200521203304_AddHostnameToEFServer")] diff --git a/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs b/Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs rename to Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs index 7f0e8657..88e94533 100644 --- a/SharedLibraryCore/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs +++ b/Data/Migrations/MySql/20200521203304_AddHostnameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddHostnameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs rename to Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs index 2dbf60c8..8e777ea4 100644 --- a/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs +++ b/Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20200819224119_AddIsPasswordProtectedColumn")] diff --git a/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs b/Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs similarity index 95% rename from SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs rename to Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs index 410ad8ff..7db2d353 100644 --- a/SharedLibraryCore/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs +++ b/Data/Migrations/MySql/20200819224119_AddIsPasswordProtectedColumn.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddIsPasswordProtectedColumn : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs b/Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs rename to Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs index 72108831..6cb95a41 100644 --- a/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs +++ b/Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20201114232340_UpdateEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs b/Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs similarity index 94% rename from SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs rename to Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs index 510663d0..34b82fcd 100644 --- a/SharedLibraryCore/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs +++ b/Data/Migrations/MySql/20201114232340_UpdateEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class UpdateEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs rename to Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs index d807ea9b..67be6ad1 100644 --- a/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs +++ b/Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20201118023106_AddSentIngameFlagToClientMessage")] diff --git a/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs b/Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs similarity index 93% rename from SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs rename to Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs index 56a27833..3493dc75 100644 --- a/SharedLibraryCore/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs +++ b/Data/Migrations/MySql/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class AddSentIngameFlagToClientMessage : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs b/Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs rename to Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs index ae78d67b..c1664272 100644 --- a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs +++ b/Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20201124024731_UpdateMigrationsToMySql")] diff --git a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs b/Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs rename to Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs index 83b7e2a2..64815bff 100644 --- a/SharedLibraryCore/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs +++ b/Data/Migrations/MySql/20201124024731_UpdateMigrationsToMySql.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class UpdateMigrationsToMySql : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs rename to Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs index 933e6398..a38ded01 100644 --- a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs +++ b/Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20210123023921_UpdateEFMetaToSupportNonClientMeta")] diff --git a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs b/Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs rename to Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs index 1a748afd..80289108 100644 --- a/SharedLibraryCore/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs +++ b/Data/Migrations/MySql/20210123023921_UpdateEFMetaToSupportNonClientMeta.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class UpdateEFMetaToSupportNonClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs rename to Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs index 745b1b34..bf502a4d 100644 --- a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs +++ b/Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] [Migration("20210124170830_UpdateEFMetaToSupportLinkedMeta")] diff --git a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs b/Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs similarity index 96% rename from SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs rename to Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs index 30e37b9b..2794932d 100644 --- a/SharedLibraryCore/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs +++ b/Data/Migrations/MySql/20210124170830_UpdateEFMetaToSupportLinkedMeta.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { public partial class UpdateEFMetaToSupportLinkedMeta : Migration { diff --git a/Data/Migrations/MySql/20210315222843_AddAdvancedStats.Designer.cs b/Data/Migrations/MySql/20210315222843_AddAdvancedStats.Designer.cs new file mode 100644 index 00000000..2af10efa --- /dev/null +++ b/Data/Migrations/MySql/20210315222843_AddAdvancedStats.Designer.cs @@ -0,0 +1,1280 @@ +// +using System; +using Data.MigrationContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Data.Migrations.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20210315222843_AddAdvancedStats")] + partial class AddAdvancedStats + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CurrentSessionLength") + .HasColumnType("int"); + + b.Property("CurrentStrain") + .HasColumnType("double"); + + b.Property("CurrentViewAngleId") + .HasColumnType("int"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("Distance") + .HasColumnType("double"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("HitDestinationId") + .HasColumnType("int"); + + b.Property("HitLocation") + .HasColumnType("int"); + + b.Property("HitOriginId") + .HasColumnType("int"); + + b.Property("HitType") + .HasColumnType("int"); + + b.Property("Hits") + .HasColumnType("int"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("LastStrainAngleId") + .HasColumnType("int"); + + b.Property("RecoilOffset") + .HasColumnType("double"); + + b.Property("SessionAngleOffset") + .HasColumnType("double"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double"); + + b.Property("SessionSPM") + .HasColumnType("double"); + + b.Property("SessionScore") + .HasColumnType("int"); + + b.Property("SessionSnapHits") + .HasColumnType("int"); + + b.Property("StrainAngleBetween") + .HasColumnType("double"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationId"); + + b.HasIndex("HitOriginId"); + + b.HasIndex("LastStrainAngleId"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.Property("ClientHitStatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("DamageInflicted") + .HasColumnType("int"); + + b.Property("DamageReceived") + .HasColumnType("int"); + + b.Property("DeathCount") + .HasColumnType("int"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitLocationId") + .HasColumnType("int"); + + b.Property("KillCount") + .HasColumnType("int"); + + b.Property("MeansOfDeathId") + .HasColumnType("int"); + + b.Property("ReceivedHitCount") + .HasColumnType("int"); + + b.Property("Score") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("SuicideCount") + .HasColumnType("int"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("UsageSeconds") + .HasColumnType("int"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.HasKey("ClientHitStatisticId"); + + b.HasIndex("ClientId"); + + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + + b.HasIndex("ServerId"); + + b.HasIndex("WeaponAttachmentComboId"); + + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("PerformanceMetric") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("ZScore") + .HasColumnType("double"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AverageSnapValue") + .HasColumnType("double"); + + b.Property("Deaths") + .HasColumnType("int"); + + b.Property("EloRating") + .HasColumnType("double"); + + b.Property("Kills") + .HasColumnType("int"); + + b.Property("MaxStrain") + .HasColumnType("double"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double"); + + b.Property("SPM") + .HasColumnType("double"); + + b.Property("Skill") + .HasColumnType("double"); + + b.Property("SnapHitCount") + .HasColumnType("int"); + + b.Property("TimePlayed") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ZScore") + .HasColumnType("double"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("int"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitOffsetAverage") + .HasColumnType("float"); + + b.Property("Location") + .HasColumnType("int"); + + b.Property("MaxAngleDistance") + .HasColumnType("float"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ActivityAmount") + .HasColumnType("int"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("Performance") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("RatingHistoryId") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => + { + b.Property("HitLocationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("HitLocationId"); + + b.HasIndex("Name"); + + b.ToTable("EFHitLocations"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Attachment1Id") + .HasColumnType("int"); + + b.Property("Attachment2Id") + .HasColumnType("int"); + + b.Property("Attachment3Id") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)"); + + b.Property("IPAddress") + .HasColumnType("int"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("varchar(24) CHARACTER SET utf8mb4") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("Data.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Comment") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImpersonationEntityId") + .HasColumnType("int"); + + b.Property("OriginEntityId") + .HasColumnType("int"); + + b.Property("PreviousValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TargetEntityId") + .HasColumnType("int"); + + b.Property("TimeChanged") + .HasColumnType("datetime(6)"); + + b.Property("TypeOfChange") + .HasColumnType("int"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.Property("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Extra") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Key") + .IsRequired() + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("int"); + + b.Property("Updated") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AutomatedOffense") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Expires") + .HasColumnType("datetime(6)"); + + b.Property("IsEvadedOffense") + .HasColumnType("tinyint(1)"); + + b.Property("LinkId") + .HasColumnType("int"); + + b.Property("OffenderId") + .HasColumnType("int"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PunisherId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.HasOne("Data.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("Data.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/MySql/20210315222843_AddAdvancedStats.cs b/Data/Migrations/MySql/20210315222843_AddAdvancedStats.cs new file mode 100644 index 00000000..f9bcc9f5 --- /dev/null +++ b/Data/Migrations/MySql/20210315222843_AddAdvancedStats.cs @@ -0,0 +1,391 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Data.Migrations.MySql +{ + public partial class AddAdvancedStats : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "VisionAverage", + table: "EFClientStatistics"); + + migrationBuilder.AddColumn( + name: "UpdatedAt", + table: "EFClientStatistics", + nullable: true); + + migrationBuilder.AddColumn( + name: "ZScore", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.CreateTable( + name: "EFClientRankingHistory", + columns: table => new + { + ClientRankingHistoryId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + Newest = table.Column(nullable: false), + Ranking = table.Column(nullable: true), + ZScore = table.Column(nullable: true), + PerformanceMetric = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientRankingHistory", x => x.ClientRankingHistoryId); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFHitLocations", + columns: table => new + { + HitLocationId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFHitLocations", x => x.HitLocationId); + }); + + migrationBuilder.CreateTable( + name: "EFMaps", + columns: table => new + { + MapId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMaps", x => x.MapId); + }); + + migrationBuilder.CreateTable( + name: "EFMeansOfDeath", + columns: table => new + { + MeansOfDeathId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeansOfDeath", x => x.MeansOfDeathId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachments", + columns: table => new + { + WeaponAttachmentId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachments", x => x.WeaponAttachmentId); + }); + + migrationBuilder.CreateTable( + name: "EFWeapons", + columns: table => new + { + WeaponId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeapons", x => x.WeaponId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachmentCombos", + columns: table => new + { + WeaponAttachmentComboId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Game = table.Column(nullable: false), + Attachment1Id = table.Column(nullable: false), + Attachment2Id = table.Column(nullable: true), + Attachment3Id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachmentCombos", x => x.WeaponAttachmentComboId); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment1Id", + column: x => x.Attachment1Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment2Id", + column: x => x.Attachment2Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment3Id", + column: x => x.Attachment3Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFClientHitStatistics", + columns: table => new + { + ClientHitStatisticId = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + HitLocationId = table.Column(nullable: true), + MeansOfDeathId = table.Column(nullable: true), + WeaponId = table.Column(nullable: true), + WeaponAttachmentComboId = table.Column(nullable: true), + HitCount = table.Column(nullable: false), + KillCount = table.Column(nullable: false), + DamageInflicted = table.Column(nullable: false), + ReceivedHitCount = table.Column(nullable: false), + DeathCount = table.Column(nullable: false), + DamageReceived = table.Column(nullable: false), + SuicideCount = table.Column(nullable: false), + UsageSeconds = table.Column(nullable: true), + Score = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientHitStatistics", x => x.ClientHitStatisticId); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFHitLocations_HitLocationId", + column: x => x.HitLocationId, + principalTable: "EFHitLocations", + principalColumn: "HitLocationId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFMeansOfDeath_MeansOfDeathId", + column: x => x.MeansOfDeathId, + principalTable: "EFMeansOfDeath", + principalColumn: "MeansOfDeathId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeaponAttachmentCombos_WeaponAttachm~", + column: x => x.WeaponAttachmentComboId, + principalTable: "EFWeaponAttachmentCombos", + principalColumn: "WeaponAttachmentComboId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeapons_WeaponId", + column: x => x.WeaponId, + principalTable: "EFWeapons", + principalColumn: "WeaponId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ZScore", + table: "EFClientStatistics", + column: "ZScore"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ClientId_TimePlayed_ZScore", + table: "EFClientStatistics", + columns: new[] { "ClientId", "TimePlayed", "ZScore" }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ClientId", + table: "EFClientHitStatistics", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_HitLocationId", + table: "EFClientHitStatistics", + column: "HitLocationId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_MeansOfDeathId", + table: "EFClientHitStatistics", + column: "MeansOfDeathId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ServerId", + table: "EFClientHitStatistics", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponAttachmentComboId", + table: "EFClientHitStatistics", + column: "WeaponAttachmentComboId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponId", + table: "EFClientHitStatistics", + column: "WeaponId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ClientId", + table: "EFClientRankingHistory", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_Ranking", + table: "EFClientRankingHistory", + column: "Ranking"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ServerId", + table: "EFClientRankingHistory", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_UpdatedDateTime", + table: "EFClientRankingHistory", + column: "UpdatedDateTime"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ZScore", + table: "EFClientRankingHistory", + column: "ZScore"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocations_Name", + table: "EFHitLocations", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment1Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment1Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment2Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment2Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment3Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeapons_Name", + table: "EFWeapons", + column: "Name"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFClientHitStatistics"); + + migrationBuilder.DropTable( + name: "EFClientRankingHistory"); + + migrationBuilder.DropTable( + name: "EFMaps"); + + migrationBuilder.DropTable( + name: "EFHitLocations"); + + migrationBuilder.DropTable( + name: "EFMeansOfDeath"); + + migrationBuilder.DropTable( + name: "EFWeaponAttachmentCombos"); + + migrationBuilder.DropTable( + name: "EFWeapons"); + + migrationBuilder.DropTable( + name: "EFWeaponAttachments"); + + migrationBuilder.DropIndex( + name: "IX_EFClientStatistics_ZScore", + table: "EFClientStatistics"); + + migrationBuilder.DropIndex( + name: "IX_EFClientStatistics_ClientId_TimePlayed_ZScore", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "UpdatedAt", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "ZScore", + table: "EFClientStatistics"); + + migrationBuilder.AddColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + type: "double", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "VisionAverage", + table: "EFClientStatistics", + type: "double", + nullable: false, + defaultValue: 0.0); + } + } +} diff --git a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/Data/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs similarity index 62% rename from SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs rename to Data/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs index 933b9b72..39862696 100644 --- a/SharedLibraryCore/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs +++ b/Data/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs @@ -1,11 +1,11 @@ // using System; +using Data.MigrationContext; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations.MySql +namespace Data.Migrations.MySql { [DbContext(typeof(MySqlDatabaseContext))] partial class MySqlDatabaseContextModelSnapshot : ModelSnapshot @@ -17,7 +17,191 @@ namespace SharedLibraryCore.Migrations.MySql .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 64); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("SnapshotId") + .HasColumnType("int"); + + b.Property("Vector3Id") + .HasColumnType("int"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AliasLinkId") + .HasColumnType("int"); + + b.Property("Connections") + .HasColumnType("int"); + + b.Property("CurrentAliasId") + .HasColumnType("int"); + + b.Property("FirstConnection") + .HasColumnType("datetime(6)"); + + b.Property("LastConnection") + .HasColumnType("datetime(6)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Masked") + .HasColumnType("tinyint(1)"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PasswordSalt") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalConnectionTime") + .HasColumnType("int"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("AttackerId") + .HasColumnType("int"); + + b.Property("Damage") + .HasColumnType("int"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("int"); + + b.Property("DeathType") + .HasColumnType("int"); + + b.Property("Fraction") + .HasColumnType("double"); + + b.Property("HitLoc") + .HasColumnType("int"); + + b.Property("IsKill") + .HasColumnType("tinyint(1)"); + + b.Property("KillOriginVector3Id") + .HasColumnType("int"); + + b.Property("Map") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("int"); + + b.Property("VisibilityPercentage") + .HasColumnType("double"); + + b.Property("Weapon") + .HasColumnType("int"); + + b.Property("When") + .HasColumnType("datetime(6)"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SentIngame") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("datetime(6)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => { b.Property("SnapshotId") .ValueGeneratedOnAdd() @@ -113,137 +297,126 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFACSnapshot"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => { - b.Property("ACSnapshotVector3Id") + b.Property("ClientHitStatisticId") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("Active") - .HasColumnType("tinyint(1)"); - - b.Property("SnapshotId") - .HasColumnType("int"); - - b.Property("Vector3Id") - .HasColumnType("int"); - - b.HasKey("ACSnapshotVector3Id"); - - b.HasIndex("SnapshotId"); - - b.HasIndex("Vector3Id"); - - b.ToTable("EFACSnapshotVector3"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => - { - b.Property("KillId") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - b.Property("Active") - .HasColumnType("tinyint(1)"); - - b.Property("AttackerId") - .HasColumnType("int"); - - b.Property("Damage") - .HasColumnType("int"); - - b.Property("DeathOriginVector3Id") - .HasColumnType("int"); - - b.Property("DeathType") - .HasColumnType("int"); - - b.Property("Fraction") - .HasColumnType("double"); - - b.Property("HitLoc") - .HasColumnType("int"); - - b.Property("IsKill") - .HasColumnType("tinyint(1)"); - - b.Property("KillOriginVector3Id") - .HasColumnType("int"); - - b.Property("Map") - .HasColumnType("int"); - - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("VictimId") - .HasColumnType("int"); - - b.Property("ViewAnglesVector3Id") - .HasColumnType("int"); - - b.Property("VisibilityPercentage") - .HasColumnType("double"); - - b.Property("Weapon") - .HasColumnType("int"); - - b.Property("When") - .HasColumnType("datetime(6)"); - - 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("MessageId") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - b.Property("Active") - .HasColumnType("tinyint(1)"); - b.Property("ClientId") .HasColumnType("int"); - b.Property("Message") - .HasColumnType("longtext CHARACTER SET utf8mb4"); - - b.Property("SentIngame") - .HasColumnType("tinyint(1)"); - - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("TimeSent") + b.Property("CreatedDateTime") .HasColumnType("datetime(6)"); - b.HasKey("MessageId"); + b.Property("DamageInflicted") + .HasColumnType("int"); + + b.Property("DamageReceived") + .HasColumnType("int"); + + b.Property("DeathCount") + .HasColumnType("int"); + + b.Property("HitCount") + .HasColumnType("int"); + + b.Property("HitLocationId") + .HasColumnType("int"); + + b.Property("KillCount") + .HasColumnType("int"); + + b.Property("MeansOfDeathId") + .HasColumnType("int"); + + b.Property("ReceivedHitCount") + .HasColumnType("int"); + + b.Property("Score") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("SuicideCount") + .HasColumnType("int"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("UsageSeconds") + .HasColumnType("int"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.HasKey("ClientHitStatisticId"); b.HasIndex("ClientId"); + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + b.HasIndex("ServerId"); - b.HasIndex("TimeSent"); + b.HasIndex("WeaponAttachmentComboId"); - b.ToTable("EFClientMessages"); + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Newest") + .HasColumnType("tinyint(1)"); + + b.Property("PerformanceMetric") + .HasColumnType("double"); + + b.Property("Ranking") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("ZScore") + .HasColumnType("double"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => { b.Property("RatingHistoryId") .ValueGeneratedOnAdd() @@ -262,7 +435,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFClientRatingHistory"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => { b.Property("ClientId") .HasColumnType("int"); @@ -273,9 +446,6 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("Active") .HasColumnType("tinyint(1)"); - b.Property("AverageRecoilOffset") - .HasColumnType("double"); - b.Property("AverageSnapValue") .HasColumnType("double"); @@ -306,17 +476,24 @@ namespace SharedLibraryCore.Migrations.MySql b.Property("TimePlayed") .HasColumnType("int"); - b.Property("VisionAverage") + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ZScore") .HasColumnType("double"); b.HasKey("ClientId", "ServerId"); b.HasIndex("ServerId"); + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + b.ToTable("EFClientStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => { b.Property("HitLocationCountId") .ValueGeneratedOnAdd() @@ -354,7 +531,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFHitLocationCounts"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => { b.Property("RatingId") .ValueGeneratedOnAdd() @@ -397,60 +574,166 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFRating"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => { - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("Active") - .HasColumnType("tinyint(1)"); - - b.Property("EndPoint") - .HasColumnType("longtext CHARACTER SET utf8mb4"); - - b.Property("GameName") - .HasColumnType("int"); - - b.Property("HostName") - .HasColumnType("longtext CHARACTER SET utf8mb4"); - - b.Property("IsPasswordProtected") - .HasColumnType("tinyint(1)"); - - b.Property("Port") - .HasColumnType("int"); - - b.HasKey("ServerId"); - - b.ToTable("EFServers"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => - { - b.Property("StatisticId") + b.Property("HitLocationId") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("Active") - .HasColumnType("tinyint(1)"); + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); - b.Property("ServerId") - .HasColumnType("bigint"); + b.Property("Game") + .HasColumnType("int"); - b.Property("TotalKills") - .HasColumnType("bigint"); + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); - b.Property("TotalPlayTime") - .HasColumnType("bigint"); + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); - b.HasKey("StatisticId"); + b.HasKey("HitLocationId"); - b.HasIndex("ServerId"); + b.HasIndex("Name"); - b.ToTable("EFServerStatistics"); + b.ToTable("EFHitLocations"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Attachment1Id") + .HasColumnType("int"); + + b.Property("Attachment2Id") + .HasColumnType("int"); + + b.Property("Attachment3Id") + .HasColumnType("int"); + + b.Property("CreatedDateTime") + .HasColumnType("datetime(6)"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("UpdatedDateTime") + .HasColumnType("datetime(6)"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => { b.Property("AliasId") .ValueGeneratedOnAdd() @@ -493,7 +776,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFAlias"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + modelBuilder.Entity("Data.Models.EFAliasLink", b => { b.Property("AliasLinkId") .ValueGeneratedOnAdd() @@ -507,7 +790,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFAliasLinks"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + modelBuilder.Entity("Data.Models.EFChangeHistory", b => { b.Property("ChangeHistoryId") .ValueGeneratedOnAdd() @@ -546,61 +829,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFChangeHistory"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.Property("ClientId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Active") - .HasColumnType("tinyint(1)"); - - b.Property("AliasLinkId") - .HasColumnType("int"); - - b.Property("Connections") - .HasColumnType("int"); - - b.Property("CurrentAliasId") - .HasColumnType("int"); - - b.Property("FirstConnection") - .HasColumnType("datetime(6)"); - - b.Property("LastConnection") - .HasColumnType("datetime(6)"); - - b.Property("Level") - .HasColumnType("int"); - - b.Property("Masked") - .HasColumnType("tinyint(1)"); - - b.Property("NetworkId") - .HasColumnType("bigint"); - - b.Property("Password") - .HasColumnType("longtext CHARACTER SET utf8mb4"); - - b.Property("PasswordSalt") - .HasColumnType("longtext CHARACTER SET utf8mb4"); - - b.Property("TotalConnectionTime") - .HasColumnType("int"); - - b.HasKey("ClientId"); - - b.HasIndex("AliasLinkId"); - - b.HasIndex("CurrentAliasId"); - - b.HasIndex("NetworkId") - .IsUnique(); - - b.ToTable("EFClients"); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.EFMeta", b => { b.Property("MetaId") .ValueGeneratedOnAdd() @@ -644,7 +873,7 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFMeta"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { b.Property("PenaltyId") .ValueGeneratedOnAdd() @@ -692,7 +921,60 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("EFPenalties"); }); - modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("EndPoint") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("GameName") + .HasColumnType("int"); + + b.Property("HostName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IsPasswordProtected") + .HasColumnType("tinyint(1)"); + + b.Property("Port") + .HasColumnType("int"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => { b.Property("Vector3Id") .ValueGeneratedOnAdd() @@ -712,225 +994,284 @@ namespace SharedLibraryCore.Migrations.MySql b.ToTable("Vector3"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") - .WithMany() - .HasForeignKey("CurrentViewAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") - .WithMany() - .HasForeignKey("HitDestinationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") - .WithMany() - .HasForeignKey("HitOriginId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") - .WithMany() - .HasForeignKey("LastStrainAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") .WithMany("PredictedViewAngles") .HasForeignKey("SnapshotId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + b.HasOne("Data.Models.Vector3", "Vector") .WithMany() .HasForeignKey("Vector3Id") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + modelBuilder.Entity("Data.Models.Client.EFClient", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") - .WithMany() - .HasForeignKey("AttackerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") - .WithMany() - .HasForeignKey("VictimId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("EFClientStatisticsClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) - .WithMany("HitLocations") - .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") - .WithMany("Ratings") - .HasForeignKey("RatingHistoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") - .WithMany("Children") - .HasForeignKey("LinkId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + b.HasOne("Data.Models.EFAliasLink", "AliasLink") .WithMany() .HasForeignKey("AliasLinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + b.HasOne("Data.Models.EFAlias", "CurrentAlias") .WithMany() .HasForeignKey("CurrentAliasId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") .WithMany("Meta") .HasForeignKey("ClientId"); - b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + b.HasOne("Data.Models.EFMeta", "LinkedMeta") .WithMany() .HasForeignKey("LinkedMetaId") .OnDelete(DeleteBehavior.SetNull); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + b.HasOne("Data.Models.EFAliasLink", "Link") .WithMany("ReceivedPenalties") .HasForeignKey("LinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + b.HasOne("Data.Models.Client.EFClient", "Offender") .WithMany("ReceivedPenalties") .HasForeignKey("OffenderId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + b.HasOne("Data.Models.Client.EFClient", "Punisher") .WithMany("AdministeredPenalties") .HasForeignKey("PunisherId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs b/Data/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs rename to Data/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs index 8bbe0b2e..3451fa60 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs +++ b/Data/Migrations/Postgresql/20180409183408_InitialCreate.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180409183408_InitialCreate")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs b/Data/Migrations/Postgresql/20180409183408_InitialCreate.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs rename to Data/Migrations/Postgresql/20180409183408_InitialCreate.cs index 4727c927..875817e6 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.cs +++ b/Data/Migrations/Postgresql/20180409183408_InitialCreate.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class InitialCreate : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs b/Data/Migrations/Postgresql/20180502195450_Update.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs rename to Data/Migrations/Postgresql/20180502195450_Update.Designer.cs index 7650eb20..8e824e9b 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.Designer.cs +++ b/Data/Migrations/Postgresql/20180502195450_Update.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180502195450_Update")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs b/Data/Migrations/Postgresql/20180502195450_Update.cs similarity index 95% rename from SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs rename to Data/Migrations/Postgresql/20180502195450_Update.cs index eebdb16d..7bb8993e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.cs +++ b/Data/Migrations/Postgresql/20180502195450_Update.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class Update : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs b/Data/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs rename to Data/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs index f887c6f4..a26a6fa5 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs +++ b/Data/Migrations/Postgresql/20180516023249_AddEloField.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180516023249_AddEloField")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs b/Data/Migrations/Postgresql/20180516023249_AddEloField.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs rename to Data/Migrations/Postgresql/20180516023249_AddEloField.cs index 0b6eb37a..c9717454 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.cs +++ b/Data/Migrations/Postgresql/20180516023249_AddEloField.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEloField : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs b/Data/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs rename to Data/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs index 96739576..b8d9eff9 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs +++ b/Data/Migrations/Postgresql/20180517223349_AddRollingKDR.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180517223349_AddRollingKDR")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs b/Data/Migrations/Postgresql/20180517223349_AddRollingKDR.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs rename to Data/Migrations/Postgresql/20180517223349_AddRollingKDR.cs index 83b39456..61f513f0 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.cs +++ b/Data/Migrations/Postgresql/20180517223349_AddRollingKDR.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddRollingKDR : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs rename to Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs index fcf2a27e..4c8f1831 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs +++ b/Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs rename to Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs index 1b597008..7f09e127 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs +++ b/Data/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddAutomatedOffenseAndRatingHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs b/Data/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs rename to Data/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs index a2baa449..345efb90 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs +++ b/Data/Migrations/Postgresql/20180601172317_AddActivityAmount.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180601172317_AddActivityAmount")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs b/Data/Migrations/Postgresql/20180601172317_AddActivityAmount.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs rename to Data/Migrations/Postgresql/20180601172317_AddActivityAmount.cs index 61ab0518..91462a0c 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.cs +++ b/Data/Migrations/Postgresql/20180601172317_AddActivityAmount.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddActivityAmount : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs b/Data/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs rename to Data/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs index 7d17e01e..0ed37dd2 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs +++ b/Data/Migrations/Postgresql/20180602041758_AddClientMeta.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180602041758_AddClientMeta")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs b/Data/Migrations/Postgresql/20180602041758_AddClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs rename to Data/Migrations/Postgresql/20180602041758_AddClientMeta.cs index 5fff4b5c..0a0e5336 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.cs +++ b/Data/Migrations/Postgresql/20180602041758_AddClientMeta.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs b/Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs rename to Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs index dde715ca..7638414c 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs +++ b/Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180605191706_AddEFACSnapshots")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs b/Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs rename to Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs index bdf00e1c..39295860 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs +++ b/Data/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEFACSnapshots : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs b/Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs rename to Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs index b55a67c9..350e0907 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs +++ b/Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180614014303_IndexForEFAlias")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs b/Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs rename to Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs index de188ae2..023cbc32 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs +++ b/Data/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class IndexForEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs b/Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs rename to Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs index 454d1a42..ae0d6e45 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs +++ b/Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180902035612_AddFractionAndIsKill")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs b/Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs rename to Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs index be6423b4..078e7ed7 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs +++ b/Data/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddFractionAndIsKill : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs b/Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs rename to Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs index afba0742..8399d5c5 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs +++ b/Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180904154622_AddVisibilityPercentage")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs b/Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs rename to Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs index 01407acc..edf762e2 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs +++ b/Data/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddVisibilityPercentage : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs b/Data/Migrations/Postgresql/20180907020706_AddVision.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs rename to Data/Migrations/Postgresql/20180907020706_AddVision.Designer.cs index eb6d0fcb..1c27a829 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.Designer.cs +++ b/Data/Migrations/Postgresql/20180907020706_AddVision.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180907020706_AddVision")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs b/Data/Migrations/Postgresql/20180907020706_AddVision.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs rename to Data/Migrations/Postgresql/20180907020706_AddVision.cs index 80ac8fe6..e8ad8ca9 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.cs +++ b/Data/Migrations/Postgresql/20180907020706_AddVision.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddVision : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs b/Data/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs rename to Data/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs index 9411e8d1..83dfcb77 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs +++ b/Data/Migrations/Postgresql/20180908004053_AddWhenToRating.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180908004053_AddWhenToRating")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs b/Data/Migrations/Postgresql/20180908004053_AddWhenToRating.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs rename to Data/Migrations/Postgresql/20180908004053_AddWhenToRating.cs index 1af6caa4..2a1ee398 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.cs +++ b/Data/Migrations/Postgresql/20180908004053_AddWhenToRating.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddWhenToRating : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs b/Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs rename to Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs index 06dfdf36..60b19bf8 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs +++ b/Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180910221749_AddRatingIndexes")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs b/Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs similarity index 96% rename from SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs rename to Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs index 5f634a08..0bf904ba 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs +++ b/Data/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddRatingIndexes : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs b/Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs rename to Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs index e8acef8c..368de2c2 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs +++ b/Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180911184224_AddEFAliasNameIndex")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs b/Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs similarity index 92% rename from SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs rename to Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs index ab34699e..9eacd55e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs +++ b/Data/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEFAliasNameIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs rename to Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs index 8aabb7cc..dc157f40 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs +++ b/Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180911190823_AddEFAliasNameMaxLength24")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs b/Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs similarity index 94% rename from SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs rename to Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs index 6389196c..6b7dedc9 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs +++ b/Data/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEFAliasNameMaxLength24 : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs rename to Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs index cb9cc3c0..86563a50 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs +++ b/Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs similarity index 95% rename from SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs rename to Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs index 195bbda0..a73b27f9 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs +++ b/Data/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddPreviousCurrentValueToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs rename to Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs index 30151d62..2148bbbd 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs +++ b/Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180915163111_AddIndexToMessageTimeSent")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs b/Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs rename to Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs index 9e82c11d..befe3b6f 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs +++ b/Data/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddIndexToMessageTimeSent : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs b/Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs rename to Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs index d8731227..e4abed3e 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs +++ b/Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180922231310_RemoveACSnapShot")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs b/Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs rename to Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs index 60d4622a..d323c010 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs +++ b/Data/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class RemoveACSnapShot : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs b/Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs rename to Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs index e7917a40..ee70ee2a 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs +++ b/Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20180922231600_ReaddACSnapshot")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs b/Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs rename to Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs index 849f683d..692464b1 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs +++ b/Data/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class ReaddACSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs rename to Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs index 97e85323..7074cdb4 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs +++ b/Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20181014171848_MakePenaltyExpirationNullable")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs b/Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs rename to Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs index 7a1815e5..7e8b135e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs +++ b/Data/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class MakePenaltyExpirationNullable : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs b/Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs rename to Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs index 9ce5daa4..87d84283 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs +++ b/Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20181125193243_MakeClientIPNullable")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs b/Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs rename to Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs index 0d201fe5..d42d43bc 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs +++ b/Data/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class MakeClientIPNullable : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs rename to Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs index df4a6f0e..df8769fa 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs +++ b/Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs similarity index 92% rename from SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs rename to Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs index 284d5fa3..4316ea65 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs +++ b/Data/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEndpointToEFServerUpdateServerIdType : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs b/Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs rename to Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs index f006af9e..57ec2be7 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs +++ b/Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20181216214513_AddEvadePenaltyFlag")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs b/Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs rename to Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs index 0d49cc07..e28d3e18 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs +++ b/Data/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddEvadePenaltyFlag : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs rename to Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs index 81f02781..c6201e32 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs +++ b/Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs similarity index 94% rename from SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs rename to Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs index 10b7fbd9..7020b88b 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs +++ b/Data/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddIndexToEFMetaKeyAndClientId : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs b/Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs rename to Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs index f57d2e45..7bc3148f 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs +++ b/Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190423142128_AddGameNameToEFServer")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs b/Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs rename to Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs index ded914a9..a1213ae4 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs +++ b/Data/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddGameNameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs b/Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs rename to Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs index 789c7b13..7dd07039 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs +++ b/Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190615145212_AddAvgRecoilOffset")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs b/Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs similarity index 91% rename from SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs rename to Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs index ccd978c6..b773ce7a 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs +++ b/Data/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddAvgRecoilOffset : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs rename to Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs index 54190afc..3ba79fe2 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs +++ b/Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190615214055_AddRecoilOffsetToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs b/Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs rename to Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs index 5256281c..b795ec0a 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs +++ b/Data/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddRecoilOffsetToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs b/Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs rename to Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs index 52a49551..12e9502e 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs +++ b/Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190725000309_AlterEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs b/Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs similarity index 97% rename from SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs rename to Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs index 74d61590..35227abd 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs +++ b/Data/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AlterEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs b/Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs rename to Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs index 02226b02..8c2ecafa 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs +++ b/Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190802174908_AddSearchNameToEFAlias")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs b/Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs similarity index 95% rename from SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs rename to Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs index c9dc245b..ea9518eb 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs +++ b/Data/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddSearchNameToEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs rename to Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs index b0c541ff..db84c9cd 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs +++ b/Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190831210503_AvgSnapValueToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs b/Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs rename to Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs index 944173d5..63bc2285 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs +++ b/Data/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AvgSnapValueToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs rename to Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs index c4100f24..9073923b 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs +++ b/Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190901180209_AddSnapHitCountToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs b/Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs rename to Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs index 96c9161d..68c7a0bc 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs +++ b/Data/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddSnapHitCountToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs rename to Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs index 631b0a20..457053ea 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs +++ b/Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs b/Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs rename to Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs index b4a816b8..5ba63045 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs +++ b/Data/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class UseJunctionTableForSnapshotVector3 : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs rename to Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs index 9ffe59a6..662afbc4 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs +++ b/Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs b/Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs rename to Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs index 3dc2405b..5a67832e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs +++ b/Data/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddCurrentSnapValueToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs rename to Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs index 8bcd882a..6ee298ee 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs +++ b/Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs b/Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs rename to Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs index 4f233b2f..c867a1e1 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs +++ b/Data/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddSessionSnapHitsToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs rename to Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs index fe2cc55a..da6301d6 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs +++ b/Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20191004172550_RenameClientHitLocationCountColumns")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs b/Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs rename to Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs index 92c6fe9b..acb9222d 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs +++ b/Data/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class RenameClientHitLocationCountColumns : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs rename to Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs index 84f64a95..8eec0d3f 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs +++ b/Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs rename to Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs index 5e713f81..38e762ff 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs +++ b/Data/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class EnforceUniqueIndexForEFAliasIPName : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs rename to Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs index 525481e7..190001b9 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs +++ b/Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs similarity index 94% rename from SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs rename to Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs index 38b6b619..c276533a 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs +++ b/Data/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs b/Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs rename to Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs index c6bf3eee..3eb09d83 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs +++ b/Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20191230140947_AddMissingActiveColumns")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs b/Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs rename to Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs index 58ee70ea..6e6262bc 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs +++ b/Data/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddMissingActiveColumns : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs rename to Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs index 5497e0c8..b268d8f4 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs +++ b/Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs rename to Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs index cadd981f..9fde7662 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs +++ b/Data/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddImpersonationIdToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs b/Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs rename to Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs index c25872e6..62ee61ca 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs +++ b/Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20200521203304_AddHostnameToEFServer")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs b/Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs similarity index 92% rename from SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs rename to Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs index 79c48c9b..db12b317 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs +++ b/Data/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddHostnameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs rename to Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs index ac88256b..ac804832 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs +++ b/Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20200819224119_AddIsPasswordProtectedColumn")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs b/Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs similarity index 95% rename from SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs rename to Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs index 506be9b7..a4d42d66 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs +++ b/Data/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddIsPasswordProtectedColumn : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs b/Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs rename to Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs index 9c968e9a..7f584512 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs +++ b/Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20201114232340_UpdateEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs b/Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs rename to Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs index 2f476b00..b6bdeb85 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs +++ b/Data/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class UpdateEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs rename to Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs index 1aa80f9b..f1cb660c 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs +++ b/Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20201118023106_AddSentIngameFlagToClientMessage")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs b/Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs similarity index 93% rename from SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs rename to Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs index 48300e72..df056f48 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs +++ b/Data/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Postgresql { public partial class AddSentIngameFlagToClientMessage : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs b/Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs rename to Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs index 7f27b9c0..63d5b10f 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs +++ b/Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.Designer.cs @@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20201125160058_UpdateMigrationsForPostgresql")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs b/Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs rename to Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs index c44a5008..fb0cacfe 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs +++ b/Data/Migrations/Postgresql/20201125160058_UpdateMigrationsForPostgresql.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { public partial class UpdateMigrationsForPostgresql : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs b/Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs rename to Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs index cfb4d9e8..bc582025 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs +++ b/Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.Designer.cs @@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20210123024304_UpdateEFMetaToSupportNonClientMeta")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs b/Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs rename to Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs index fc4f4aa3..67b80f10 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs +++ b/Data/Migrations/Postgresql/20210123024304_UpdateEFMetaToSupportNonClientMeta.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { public partial class UpdateEFMetaToSupportNonClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs b/Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs rename to Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs index cd28418d..f8357d9e 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs +++ b/Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.Designer.cs @@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] [Migration("20210124170956_UpdateEFMetaToSupportLinkedMeta")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs b/Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs similarity index 96% rename from SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs rename to Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs index 55927c72..c05e87f3 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs +++ b/Data/Migrations/Postgresql/20210124170956_UpdateEFMetaToSupportLinkedMeta.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { public partial class UpdateEFMetaToSupportLinkedMeta : Migration { diff --git a/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.Designer.cs b/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.Designer.cs new file mode 100644 index 00000000..4bbe438a --- /dev/null +++ b/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.Designer.cs @@ -0,0 +1,1305 @@ +// +using System; +using Data.MigrationContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Data.Migrations.Postgresql +{ + [DbContext(typeof(PostgresqlDatabaseContext))] + [Migration("20210316004759_AddAdvancedStats")] + partial class AddAdvancedStats + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) + .HasAnnotation("ProductVersion", "3.1.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CurrentSessionLength") + .HasColumnType("integer"); + + b.Property("CurrentStrain") + .HasColumnType("double precision"); + + b.Property("CurrentViewAngleId") + .HasColumnType("integer"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("Distance") + .HasColumnType("double precision"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("HitDestinationId") + .HasColumnType("integer"); + + b.Property("HitLocation") + .HasColumnType("integer"); + + b.Property("HitOriginId") + .HasColumnType("integer"); + + b.Property("HitType") + .HasColumnType("integer"); + + b.Property("Hits") + .HasColumnType("integer"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("LastStrainAngleId") + .HasColumnType("integer"); + + b.Property("RecoilOffset") + .HasColumnType("double precision"); + + b.Property("SessionAngleOffset") + .HasColumnType("double precision"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("double precision"); + + b.Property("SessionSPM") + .HasColumnType("double precision"); + + b.Property("SessionScore") + .HasColumnType("integer"); + + b.Property("SessionSnapHits") + .HasColumnType("integer"); + + b.Property("StrainAngleBetween") + .HasColumnType("double precision"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationId"); + + b.HasIndex("HitOriginId"); + + b.HasIndex("LastStrainAngleId"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.Property("ClientHitStatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("DamageInflicted") + .HasColumnType("integer"); + + b.Property("DamageReceived") + .HasColumnType("integer"); + + b.Property("DeathCount") + .HasColumnType("integer"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitLocationId") + .HasColumnType("integer"); + + b.Property("KillCount") + .HasColumnType("integer"); + + b.Property("MeansOfDeathId") + .HasColumnType("integer"); + + b.Property("ReceivedHitCount") + .HasColumnType("integer"); + + b.Property("Score") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("SuicideCount") + .HasColumnType("integer"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("UsageSeconds") + .HasColumnType("integer"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.HasKey("ClientHitStatisticId"); + + b.HasIndex("ClientId"); + + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + + b.HasIndex("ServerId"); + + b.HasIndex("WeaponAttachmentComboId"); + + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("PerformanceMetric") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ZScore") + .HasColumnType("double precision"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AverageSnapValue") + .HasColumnType("double precision"); + + b.Property("Deaths") + .HasColumnType("integer"); + + b.Property("EloRating") + .HasColumnType("double precision"); + + b.Property("Kills") + .HasColumnType("integer"); + + b.Property("MaxStrain") + .HasColumnType("double precision"); + + b.Property("RollingWeightedKDR") + .HasColumnType("double precision"); + + b.Property("SPM") + .HasColumnType("double precision"); + + b.Property("Skill") + .HasColumnType("double precision"); + + b.Property("SnapHitCount") + .HasColumnType("integer"); + + b.Property("TimePlayed") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ZScore") + .HasColumnType("double precision"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("integer"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("bigint"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitOffsetAverage") + .HasColumnType("real"); + + b.Property("Location") + .HasColumnType("integer"); + + b.Property("MaxAngleDistance") + .HasColumnType("real"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ActivityAmount") + .HasColumnType("integer"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("Performance") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("RatingHistoryId") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => + { + b.Property("HitLocationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("HitLocationId"); + + b.HasIndex("Name"); + + b.ToTable("EFHitLocations"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Attachment1Id") + .HasColumnType("integer"); + + b.Property("Attachment2Id") + .HasColumnType("integer"); + + b.Property("Attachment3Id") + .HasColumnType("integer"); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IPAddress") + .HasColumnType("integer"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("character varying(24)") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("Data.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Comment") + .HasColumnType("character varying(128)") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("text"); + + b.Property("ImpersonationEntityId") + .HasColumnType("integer"); + + b.Property("OriginEntityId") + .HasColumnType("integer"); + + b.Property("PreviousValue") + .HasColumnType("text"); + + b.Property("TargetEntityId") + .HasColumnType("integer"); + + b.Property("TimeChanged") + .HasColumnType("timestamp without time zone"); + + b.Property("TypeOfChange") + .HasColumnType("integer"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.Property("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Created") + .HasColumnType("timestamp without time zone"); + + b.Property("Extra") + .HasColumnType("text"); + + b.Property("Key") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("integer"); + + b.Property("Updated") + .HasColumnType("timestamp without time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AutomatedOffense") + .HasColumnType("text"); + + b.Property("Expires") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEvadedOffense") + .HasColumnType("boolean"); + + b.Property("LinkId") + .HasColumnType("integer"); + + b.Property("OffenderId") + .HasColumnType("integer"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("text"); + + b.Property("PunisherId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("X") + .HasColumnType("real"); + + b.Property("Y") + .HasColumnType("real"); + + b.Property("Z") + .HasColumnType("real"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.HasOne("Data.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("Data.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.cs b/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.cs new file mode 100644 index 00000000..dc966abb --- /dev/null +++ b/Data/Migrations/Postgresql/20210316004759_AddAdvancedStats.cs @@ -0,0 +1,391 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Data.Migrations.Postgresql +{ + public partial class AddAdvancedStats : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "VisionAverage", + table: "EFClientStatistics"); + + migrationBuilder.AddColumn( + name: "UpdatedAt", + table: "EFClientStatistics", + nullable: true); + + migrationBuilder.AddColumn( + name: "ZScore", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.CreateTable( + name: "EFClientRankingHistory", + columns: table => new + { + ClientRankingHistoryId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + Newest = table.Column(nullable: false), + Ranking = table.Column(nullable: true), + ZScore = table.Column(nullable: true), + PerformanceMetric = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientRankingHistory", x => x.ClientRankingHistoryId); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFHitLocations", + columns: table => new + { + HitLocationId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFHitLocations", x => x.HitLocationId); + }); + + migrationBuilder.CreateTable( + name: "EFMaps", + columns: table => new + { + MapId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMaps", x => x.MapId); + }); + + migrationBuilder.CreateTable( + name: "EFMeansOfDeath", + columns: table => new + { + MeansOfDeathId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeansOfDeath", x => x.MeansOfDeathId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachments", + columns: table => new + { + WeaponAttachmentId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachments", x => x.WeaponAttachmentId); + }); + + migrationBuilder.CreateTable( + name: "EFWeapons", + columns: table => new + { + WeaponId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeapons", x => x.WeaponId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachmentCombos", + columns: table => new + { + WeaponAttachmentComboId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Game = table.Column(nullable: false), + Attachment1Id = table.Column(nullable: false), + Attachment2Id = table.Column(nullable: true), + Attachment3Id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachmentCombos", x => x.WeaponAttachmentComboId); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment1Id", + column: x => x.Attachment1Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment2Id", + column: x => x.Attachment2Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment3Id", + column: x => x.Attachment3Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFClientHitStatistics", + columns: table => new + { + ClientHitStatisticId = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + HitLocationId = table.Column(nullable: true), + MeansOfDeathId = table.Column(nullable: true), + WeaponId = table.Column(nullable: true), + WeaponAttachmentComboId = table.Column(nullable: true), + HitCount = table.Column(nullable: false), + KillCount = table.Column(nullable: false), + DamageInflicted = table.Column(nullable: false), + ReceivedHitCount = table.Column(nullable: false), + DeathCount = table.Column(nullable: false), + DamageReceived = table.Column(nullable: false), + SuicideCount = table.Column(nullable: false), + UsageSeconds = table.Column(nullable: true), + Score = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientHitStatistics", x => x.ClientHitStatisticId); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFHitLocations_HitLocationId", + column: x => x.HitLocationId, + principalTable: "EFHitLocations", + principalColumn: "HitLocationId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFMeansOfDeath_MeansOfDeathId", + column: x => x.MeansOfDeathId, + principalTable: "EFMeansOfDeath", + principalColumn: "MeansOfDeathId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeaponAttachmentCombos_WeaponAttach~", + column: x => x.WeaponAttachmentComboId, + principalTable: "EFWeaponAttachmentCombos", + principalColumn: "WeaponAttachmentComboId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeapons_WeaponId", + column: x => x.WeaponId, + principalTable: "EFWeapons", + principalColumn: "WeaponId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ZScore", + table: "EFClientStatistics", + column: "ZScore"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ClientId_TimePlayed_ZScore", + table: "EFClientStatistics", + columns: new[] { "ClientId", "TimePlayed", "ZScore" }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ClientId", + table: "EFClientHitStatistics", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_HitLocationId", + table: "EFClientHitStatistics", + column: "HitLocationId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_MeansOfDeathId", + table: "EFClientHitStatistics", + column: "MeansOfDeathId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ServerId", + table: "EFClientHitStatistics", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponAttachmentComboId", + table: "EFClientHitStatistics", + column: "WeaponAttachmentComboId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponId", + table: "EFClientHitStatistics", + column: "WeaponId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ClientId", + table: "EFClientRankingHistory", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_Ranking", + table: "EFClientRankingHistory", + column: "Ranking"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ServerId", + table: "EFClientRankingHistory", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_UpdatedDateTime", + table: "EFClientRankingHistory", + column: "UpdatedDateTime"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ZScore", + table: "EFClientRankingHistory", + column: "ZScore"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocations_Name", + table: "EFHitLocations", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment1Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment1Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment2Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment2Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment3Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeapons_Name", + table: "EFWeapons", + column: "Name"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFClientHitStatistics"); + + migrationBuilder.DropTable( + name: "EFClientRankingHistory"); + + migrationBuilder.DropTable( + name: "EFMaps"); + + migrationBuilder.DropTable( + name: "EFHitLocations"); + + migrationBuilder.DropTable( + name: "EFMeansOfDeath"); + + migrationBuilder.DropTable( + name: "EFWeaponAttachmentCombos"); + + migrationBuilder.DropTable( + name: "EFWeapons"); + + migrationBuilder.DropTable( + name: "EFWeaponAttachments"); + + migrationBuilder.DropIndex( + name: "IX_EFClientStatistics_ZScore", + table: "EFClientStatistics"); + + migrationBuilder.DropIndex( + name: "IX_EFClientStatistics_ClientId_TimePlayed_ZScore", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "UpdatedAt", + table: "EFClientStatistics"); + + migrationBuilder.DropColumn( + name: "ZScore", + table: "EFClientStatistics"); + + migrationBuilder.AddColumn( + name: "AverageRecoilOffset", + table: "EFClientStatistics", + type: "double precision", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "VisionAverage", + table: "EFClientStatistics", + type: "double precision", + nullable: false, + defaultValue: 0.0); + } + } +} diff --git a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs b/Data/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs similarity index 61% rename from SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs rename to Data/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs index 0d442753..85451b47 100644 --- a/SharedLibraryCore/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs +++ b/Data/Migrations/Postgresql/PostgresqlDatabaseContextModelSnapshot.cs @@ -1,12 +1,12 @@ // using System; +using Data.MigrationContext; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Postgresql { [DbContext(typeof(PostgresqlDatabaseContext))] partial class PostgresqlDatabaseContextModelSnapshot : ModelSnapshot @@ -15,16 +15,204 @@ namespace SharedLibraryCore.Migrations.Postgresql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) .HasAnnotation("ProductVersion", "3.1.10") .HasAnnotation("Relational:MaxIdentifierLength", 63); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("SnapshotId") + .HasColumnType("integer"); + + b.Property("Vector3Id") + .HasColumnType("integer"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AliasLinkId") + .HasColumnType("integer"); + + b.Property("Connections") + .HasColumnType("integer"); + + b.Property("CurrentAliasId") + .HasColumnType("integer"); + + b.Property("FirstConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("LastConnection") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Masked") + .HasColumnType("boolean"); + + b.Property("NetworkId") + .HasColumnType("bigint"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("TotalConnectionTime") + .HasColumnType("integer"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("AttackerId") + .HasColumnType("integer"); + + b.Property("Damage") + .HasColumnType("integer"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("integer"); + + b.Property("DeathType") + .HasColumnType("integer"); + + b.Property("Fraction") + .HasColumnType("double precision"); + + b.Property("HitLoc") + .HasColumnType("integer"); + + b.Property("IsKill") + .HasColumnType("boolean"); + + b.Property("KillOriginVector3Id") + .HasColumnType("integer"); + + b.Property("Map") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("VictimId") + .HasColumnType("integer"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("integer"); + + b.Property("VisibilityPercentage") + .HasColumnType("double precision"); + + b.Property("Weapon") + .HasColumnType("integer"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("SentIngame") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TimeSent") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => { b.Property("SnapshotId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -116,145 +304,133 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFACSnapshot"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => { - b.Property("ACSnapshotVector3Id") + b.Property("ClientHitStatisticId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("SnapshotId") - .HasColumnType("integer"); - - b.Property("Vector3Id") - .HasColumnType("integer"); - - b.HasKey("ACSnapshotVector3Id"); - - b.HasIndex("SnapshotId"); - - b.HasIndex("Vector3Id"); - - b.ToTable("EFACSnapshotVector3"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => - { - b.Property("KillId") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("AttackerId") - .HasColumnType("integer"); - - b.Property("Damage") - .HasColumnType("integer"); - - b.Property("DeathOriginVector3Id") - .HasColumnType("integer"); - - b.Property("DeathType") - .HasColumnType("integer"); - - b.Property("Fraction") - .HasColumnType("double precision"); - - b.Property("HitLoc") - .HasColumnType("integer"); - - b.Property("IsKill") - .HasColumnType("boolean"); - - b.Property("KillOriginVector3Id") - .HasColumnType("integer"); - - b.Property("Map") - .HasColumnType("integer"); - - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("VictimId") - .HasColumnType("integer"); - - b.Property("ViewAnglesVector3Id") - .HasColumnType("integer"); - - b.Property("VisibilityPercentage") - .HasColumnType("double precision"); - - b.Property("Weapon") - .HasColumnType("integer"); - - b.Property("When") - .HasColumnType("timestamp without time zone"); - - 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("MessageId") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - - b.Property("Active") - .HasColumnType("boolean"); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("ClientId") .HasColumnType("integer"); - b.Property("Message") - .HasColumnType("text"); - - b.Property("SentIngame") - .HasColumnType("boolean"); - - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("TimeSent") + b.Property("CreatedDateTime") .HasColumnType("timestamp without time zone"); - b.HasKey("MessageId"); + b.Property("DamageInflicted") + .HasColumnType("integer"); + + b.Property("DamageReceived") + .HasColumnType("integer"); + + b.Property("DeathCount") + .HasColumnType("integer"); + + b.Property("HitCount") + .HasColumnType("integer"); + + b.Property("HitLocationId") + .HasColumnType("integer"); + + b.Property("KillCount") + .HasColumnType("integer"); + + b.Property("MeansOfDeathId") + .HasColumnType("integer"); + + b.Property("ReceivedHitCount") + .HasColumnType("integer"); + + b.Property("Score") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("SuicideCount") + .HasColumnType("integer"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("UsageSeconds") + .HasColumnType("integer"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("integer"); + + b.Property("WeaponId") + .HasColumnType("integer"); + + b.HasKey("ClientHitStatisticId"); b.HasIndex("ClientId"); + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + b.HasIndex("ServerId"); - b.HasIndex("TimeSent"); + b.HasIndex("WeaponAttachmentComboId"); - b.ToTable("EFClientMessages"); + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("ClientId") + .HasColumnType("integer"); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Newest") + .HasColumnType("boolean"); + + b.Property("PerformanceMetric") + .HasColumnType("double precision"); + + b.Property("Ranking") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ZScore") + .HasColumnType("double precision"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => { b.Property("RatingHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -269,7 +445,7 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFClientRatingHistory"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => { b.Property("ClientId") .HasColumnType("integer"); @@ -280,9 +456,6 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("Active") .HasColumnType("boolean"); - b.Property("AverageRecoilOffset") - .HasColumnType("double precision"); - b.Property("AverageSnapValue") .HasColumnType("double precision"); @@ -313,22 +486,29 @@ namespace SharedLibraryCore.Migrations.Postgresql b.Property("TimePlayed") .HasColumnType("integer"); - b.Property("VisionAverage") + b.Property("UpdatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ZScore") .HasColumnType("double precision"); b.HasKey("ClientId", "ServerId"); b.HasIndex("ServerId"); + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + b.ToTable("EFClientStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => { b.Property("HitLocationCountId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -362,12 +542,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFHitLocationCounts"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => { b.Property("RatingId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -406,66 +586,177 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFRating"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => { - b.Property("ServerId") - .HasColumnType("bigint"); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("EndPoint") - .HasColumnType("text"); - - b.Property("GameName") - .HasColumnType("integer"); - - b.Property("HostName") - .HasColumnType("text"); - - b.Property("IsPasswordProtected") - .HasColumnType("boolean"); - - b.Property("Port") - .HasColumnType("integer"); - - b.HasKey("ServerId"); - - b.ToTable("EFServers"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => - { - b.Property("StatisticId") + b.Property("HitLocationId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); - b.Property("Active") - .HasColumnType("boolean"); + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); - b.Property("ServerId") - .HasColumnType("bigint"); + b.Property("Game") + .HasColumnType("integer"); - b.Property("TotalKills") - .HasColumnType("bigint"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("TotalPlayTime") - .HasColumnType("bigint"); + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); - b.HasKey("StatisticId"); + b.HasKey("HitLocationId"); - b.HasIndex("ServerId"); + b.HasIndex("Name"); - b.ToTable("EFServerStatistics"); + b.ToTable("EFHitLocations"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Attachment1Id") + .HasColumnType("integer"); + + b.Property("Attachment2Id") + .HasColumnType("integer"); + + b.Property("Attachment3Id") + .HasColumnType("integer"); + + b.Property("CreatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Game") + .HasColumnType("integer"); + + b.Property("UpdatedDateTime") + .HasColumnType("timestamp without time zone"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => { b.Property("AliasId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -504,12 +795,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFAlias"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + modelBuilder.Entity("Data.Models.EFAliasLink", b => { b.Property("AliasLinkId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -519,12 +810,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFAliasLinks"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + modelBuilder.Entity("Data.Models.EFChangeHistory", b => { b.Property("ChangeHistoryId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -559,67 +850,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFChangeHistory"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.Property("ClientId") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - - b.Property("Active") - .HasColumnType("boolean"); - - b.Property("AliasLinkId") - .HasColumnType("integer"); - - b.Property("Connections") - .HasColumnType("integer"); - - b.Property("CurrentAliasId") - .HasColumnType("integer"); - - b.Property("FirstConnection") - .HasColumnType("timestamp without time zone"); - - b.Property("LastConnection") - .HasColumnType("timestamp without time zone"); - - b.Property("Level") - .HasColumnType("integer"); - - b.Property("Masked") - .HasColumnType("boolean"); - - b.Property("NetworkId") - .HasColumnType("bigint"); - - b.Property("Password") - .HasColumnType("text"); - - b.Property("PasswordSalt") - .HasColumnType("text"); - - b.Property("TotalConnectionTime") - .HasColumnType("integer"); - - b.HasKey("ClientId"); - - b.HasIndex("AliasLinkId"); - - b.HasIndex("CurrentAliasId"); - - b.HasIndex("NetworkId") - .IsUnique(); - - b.ToTable("EFClients"); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.EFMeta", b => { b.Property("MetaId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -659,12 +895,12 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFMeta"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { b.Property("PenaltyId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("Active") .HasColumnType("boolean"); @@ -708,12 +944,66 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("EFPenalties"); }); - modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("EndPoint") + .HasColumnType("text"); + + b.Property("GameName") + .HasColumnType("integer"); + + b.Property("HostName") + .HasColumnType("text"); + + b.Property("IsPasswordProtected") + .HasColumnType("boolean"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("bigint"); + + b.Property("TotalKills") + .HasColumnType("bigint"); + + b.Property("TotalPlayTime") + .HasColumnType("bigint"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => { b.Property("Vector3Id") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn); b.Property("X") .HasColumnType("real"); @@ -729,225 +1019,284 @@ namespace SharedLibraryCore.Migrations.Postgresql b.ToTable("Vector3"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") - .WithMany() - .HasForeignKey("CurrentViewAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") - .WithMany() - .HasForeignKey("HitDestinationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") - .WithMany() - .HasForeignKey("HitOriginId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") - .WithMany() - .HasForeignKey("LastStrainAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") .WithMany("PredictedViewAngles") .HasForeignKey("SnapshotId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + b.HasOne("Data.Models.Vector3", "Vector") .WithMany() .HasForeignKey("Vector3Id") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + modelBuilder.Entity("Data.Models.Client.EFClient", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") - .WithMany() - .HasForeignKey("AttackerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") - .WithMany() - .HasForeignKey("VictimId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("EFClientStatisticsClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) - .WithMany("HitLocations") - .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") - .WithMany("Ratings") - .HasForeignKey("RatingHistoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") - .WithMany("Children") - .HasForeignKey("LinkId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + b.HasOne("Data.Models.EFAliasLink", "AliasLink") .WithMany() .HasForeignKey("AliasLinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + b.HasOne("Data.Models.EFAlias", "CurrentAlias") .WithMany() .HasForeignKey("CurrentAliasId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") .WithMany("Meta") .HasForeignKey("ClientId"); - b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + b.HasOne("Data.Models.EFMeta", "LinkedMeta") .WithMany() .HasForeignKey("LinkedMetaId") .OnDelete(DeleteBehavior.SetNull); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + b.HasOne("Data.Models.EFAliasLink", "Link") .WithMany("ReceivedPenalties") .HasForeignKey("LinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + b.HasOne("Data.Models.Client.EFClient", "Offender") .WithMany("ReceivedPenalties") .HasForeignKey("OffenderId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + b.HasOne("Data.Models.Client.EFClient", "Punisher") .WithMany("AdministeredPenalties") .HasForeignKey("PunisherId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs b/Data/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs rename to Data/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs index e71e66ac..969ca1b9 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs +++ b/Data/Migrations/Sqlite/20180409183408_InitialCreate.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180409183408_InitialCreate")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs b/Data/Migrations/Sqlite/20180409183408_InitialCreate.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs rename to Data/Migrations/Sqlite/20180409183408_InitialCreate.cs index acd57084..7b546334 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180409183408_InitialCreate.cs +++ b/Data/Migrations/Sqlite/20180409183408_InitialCreate.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class InitialCreate : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs b/Data/Migrations/Sqlite/20180502195450_Update.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs rename to Data/Migrations/Sqlite/20180502195450_Update.Designer.cs index 9ca5b7e3..bad1e03c 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180502195450_Update.Designer.cs +++ b/Data/Migrations/Sqlite/20180502195450_Update.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180502195450_Update")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs b/Data/Migrations/Sqlite/20180502195450_Update.cs similarity index 95% rename from SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs rename to Data/Migrations/Sqlite/20180502195450_Update.cs index 79b42416..e3b16650 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180502195450_Update.cs +++ b/Data/Migrations/Sqlite/20180502195450_Update.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class Update : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs b/Data/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs rename to Data/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs index debb8507..7ce4d36f 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs +++ b/Data/Migrations/Sqlite/20180516023249_AddEloField.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180516023249_AddEloField")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs b/Data/Migrations/Sqlite/20180516023249_AddEloField.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs rename to Data/Migrations/Sqlite/20180516023249_AddEloField.cs index 088d71f7..078a22cd 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180516023249_AddEloField.cs +++ b/Data/Migrations/Sqlite/20180516023249_AddEloField.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEloField : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs b/Data/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs rename to Data/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs index 0888266d..d163970b 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs +++ b/Data/Migrations/Sqlite/20180517223349_AddRollingKDR.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.MigrationContext; +using Data; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180517223349_AddRollingKDR")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs b/Data/Migrations/Sqlite/20180517223349_AddRollingKDR.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs rename to Data/Migrations/Sqlite/20180517223349_AddRollingKDR.cs index 8b971689..82dd4618 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180517223349_AddRollingKDR.cs +++ b/Data/Migrations/Sqlite/20180517223349_AddRollingKDR.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddRollingKDR : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs b/Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs rename to Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs index db0edba5..2964b1a2 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs +++ b/Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180531212903_AddAutomatedOffenseAndRatingHistory")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs b/Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs similarity index 98% rename from SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs rename to Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs index eeff0d6e..703a8ab6 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180531212903_AddAutomatedOffenseAndRatingHistory.cs +++ b/Data/Migrations/Sqlite/20180531212903_AddAutomatedOffenseAndRatingHistory.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddAutomatedOffenseAndRatingHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs b/Data/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs rename to Data/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs index 52414186..468e50f1 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs +++ b/Data/Migrations/Sqlite/20180601172317_AddActivityAmount.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180601172317_AddActivityAmount")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs b/Data/Migrations/Sqlite/20180601172317_AddActivityAmount.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs rename to Data/Migrations/Sqlite/20180601172317_AddActivityAmount.cs index 332f10bb..a8ff76b9 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180601172317_AddActivityAmount.cs +++ b/Data/Migrations/Sqlite/20180601172317_AddActivityAmount.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddActivityAmount : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs b/Data/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs rename to Data/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs index ca057232..fe3503a8 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs +++ b/Data/Migrations/Sqlite/20180602041758_AddClientMeta.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180602041758_AddClientMeta")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs b/Data/Migrations/Sqlite/20180602041758_AddClientMeta.cs similarity index 97% rename from SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs rename to Data/Migrations/Sqlite/20180602041758_AddClientMeta.cs index 31c8e15d..08dbdbf3 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180602041758_AddClientMeta.cs +++ b/Data/Migrations/Sqlite/20180602041758_AddClientMeta.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddClientMeta : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs b/Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs rename to Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs index 9a941e7d..d1529495 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs +++ b/Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180605191706_AddEFACSnapshots")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs b/Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs rename to Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs index d989c1e8..b719bb8d 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180605191706_AddEFACSnapshots.cs +++ b/Data/Migrations/Sqlite/20180605191706_AddEFACSnapshots.cs @@ -4,7 +4,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEFACSnapshots : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs b/Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs rename to Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs index 553c7183..3300e12f 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs +++ b/Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.Designer.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; using System; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180614014303_IndexForEFAlias")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs b/Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs rename to Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs index 81ffaf1a..289a5697 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180614014303_IndexForEFAlias.cs +++ b/Data/Migrations/Sqlite/20180614014303_IndexForEFAlias.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class IndexForEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs b/Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs rename to Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs index a79bb713..c477fef6 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs +++ b/Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180902035612_AddFractionAndIsKill")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs b/Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs similarity index 97% rename from SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs rename to Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs index ae30df08..1fe4ab13 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180902035612_AddFractionAndIsKill.cs +++ b/Data/Migrations/Sqlite/20180902035612_AddFractionAndIsKill.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddFractionAndIsKill : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs b/Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs rename to Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs index c2f06539..93a6ae30 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs +++ b/Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180904154622_AddVisibilityPercentage")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs b/Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs rename to Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs index 77b24262..7d5842f9 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180904154622_AddVisibilityPercentage.cs +++ b/Data/Migrations/Sqlite/20180904154622_AddVisibilityPercentage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddVisibilityPercentage : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs b/Data/Migrations/Sqlite/20180907020706_AddVision.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs rename to Data/Migrations/Sqlite/20180907020706_AddVision.Designer.cs index 7b996dc6..0521e398 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180907020706_AddVision.Designer.cs +++ b/Data/Migrations/Sqlite/20180907020706_AddVision.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180907020706_AddVision")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs b/Data/Migrations/Sqlite/20180907020706_AddVision.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs rename to Data/Migrations/Sqlite/20180907020706_AddVision.cs index 17ce2ea9..ded66273 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180907020706_AddVision.cs +++ b/Data/Migrations/Sqlite/20180907020706_AddVision.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddVision : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs b/Data/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs rename to Data/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs index fe43268f..ad650da0 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs +++ b/Data/Migrations/Sqlite/20180908004053_AddWhenToRating.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180908004053_AddWhenToRating")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs b/Data/Migrations/Sqlite/20180908004053_AddWhenToRating.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs rename to Data/Migrations/Sqlite/20180908004053_AddWhenToRating.cs index f6482236..3610472f 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180908004053_AddWhenToRating.cs +++ b/Data/Migrations/Sqlite/20180908004053_AddWhenToRating.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddWhenToRating : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs b/Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs rename to Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs index 9b3b9e99..bbacef28 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs +++ b/Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180910221749_AddRatingIndexes")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs b/Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs similarity index 95% rename from SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs rename to Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs index 781d5bba..07ea61fc 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180910221749_AddRatingIndexes.cs +++ b/Data/Migrations/Sqlite/20180910221749_AddRatingIndexes.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddRatingIndexes : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs b/Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs rename to Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs index e9feb60e..2d4d694c 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs +++ b/Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180911184224_AddEFAliasNameIndex")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs b/Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs similarity index 91% rename from SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs rename to Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs index 90247335..5ccab445 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180911184224_AddEFAliasNameIndex.cs +++ b/Data/Migrations/Sqlite/20180911184224_AddEFAliasNameIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEFAliasNameIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs b/Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs rename to Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs index f6275417..6abeea81 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs +++ b/Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180911190823_AddEFAliasNameMaxLength24")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs b/Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs rename to Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs index 53ef00b9..7a16d9c4 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180911190823_AddEFAliasNameMaxLength24.cs +++ b/Data/Migrations/Sqlite/20180911190823_AddEFAliasNameMaxLength24.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEFAliasNameMaxLength24 : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs b/Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs rename to Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs index ba6dcaf7..72aba35e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs +++ b/Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180912015012_AddPreviousCurrentValueToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs b/Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs similarity index 94% rename from SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs rename to Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs index c7c7a911..fb3ee809 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs +++ b/Data/Migrations/Sqlite/20180912015012_AddPreviousCurrentValueToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddPreviousCurrentValueToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs b/Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs rename to Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs index 3ec9944c..4a5a0c63 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs +++ b/Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180915163111_AddIndexToMessageTimeSent")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs b/Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs rename to Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs index 93186b38..d24bead5 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180915163111_AddIndexToMessageTimeSent.cs +++ b/Data/Migrations/Sqlite/20180915163111_AddIndexToMessageTimeSent.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddIndexToMessageTimeSent : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs b/Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs rename to Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs index 1c7aac12..ecbd0cfe 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs +++ b/Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180922231310_RemoveACSnapShot")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs b/Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs rename to Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs index b767126f..6688d46f 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180922231310_RemoveACSnapShot.cs +++ b/Data/Migrations/Sqlite/20180922231310_RemoveACSnapShot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class RemoveACSnapShot : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs b/Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs rename to Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs index 3c43b4bf..f37f18b7 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs +++ b/Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20180922231600_ReaddACSnapshot")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs b/Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs rename to Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs index b0938c85..ad668b2b 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20180922231600_ReaddACSnapshot.cs +++ b/Data/Migrations/Sqlite/20180922231600_ReaddACSnapshot.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class ReaddACSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs b/Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs rename to Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs index 62deb8a6..b0a0be75 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs +++ b/Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20181014171848_MakePenaltyExpirationNullable")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs b/Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs similarity index 98% rename from SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs rename to Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs index 6fb055ef..3eac0d00 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181014171848_MakePenaltyExpirationNullable.cs +++ b/Data/Migrations/Sqlite/20181014171848_MakePenaltyExpirationNullable.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class MakePenaltyExpirationNullable : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs b/Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs rename to Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs index 9ec28f7f..96a12275 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs +++ b/Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20181125193243_MakeClientIPNullable")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs b/Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs similarity index 97% rename from SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs rename to Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs index 9999193f..a81d86d0 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181125193243_MakeClientIPNullable.cs +++ b/Data/Migrations/Sqlite/20181125193243_MakeClientIPNullable.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class MakeClientIPNullable : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs b/Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs rename to Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs index 8042335f..cfce8c22 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs +++ b/Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20181127144417_AddEndpointToEFServerUpdateServerIdType")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs b/Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs rename to Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs index 3f6871f1..8d9e6169 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs +++ b/Data/Migrations/Sqlite/20181127144417_AddEndpointToEFServerUpdateServerIdType.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEndpointToEFServerUpdateServerIdType : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs b/Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs rename to Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs index 389817fd..0fd3f553 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs +++ b/Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20181216214513_AddEvadePenaltyFlag")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs b/Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs rename to Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs index eaf9fbf3..5d69bffe 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20181216214513_AddEvadePenaltyFlag.cs +++ b/Data/Migrations/Sqlite/20181216214513_AddEvadePenaltyFlag.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddEvadePenaltyFlag : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs rename to Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs index 6f1aa63e..608600cf 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs +++ b/Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs similarity index 94% rename from SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs rename to Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs index ef8fbff1..cb3ff6d6 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs +++ b/Data/Migrations/Sqlite/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddIndexToEFMetaKeyAndClientId : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs b/Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs rename to Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs index 2522be0f..dc0c4941 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs +++ b/Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190423142128_AddGameNameToEFServer")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs b/Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs similarity index 91% rename from SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs rename to Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs index f9bca4c5..bebb186c 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190423142128_AddGameNameToEFServer.cs +++ b/Data/Migrations/Sqlite/20190423142128_AddGameNameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddGameNameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs b/Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs rename to Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs index 04bcc51c..0e78cde1 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs +++ b/Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190615145212_AddAvgRecoilOffset")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs b/Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs similarity index 91% rename from SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs rename to Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs index a884a9fe..735c8f5b 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190615145212_AddAvgRecoilOffset.cs +++ b/Data/Migrations/Sqlite/20190615145212_AddAvgRecoilOffset.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddAvgRecoilOffset : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs b/Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs rename to Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs index 51fa8efd..a26566a1 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs +++ b/Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190615214055_AddRecoilOffsetToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs b/Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs rename to Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs index b7ef1b24..2b57056a 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190615214055_AddRecoilOffsetToSnapshot.cs +++ b/Data/Migrations/Sqlite/20190615214055_AddRecoilOffsetToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddRecoilOffsetToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs b/Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs rename to Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs index 1a953f48..81879a90 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs +++ b/Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190725000309_AlterEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs b/Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs similarity index 96% rename from SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs rename to Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs index c85535b7..50d0cb96 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190725000309_AlterEFRatingIndex.cs +++ b/Data/Migrations/Sqlite/20190725000309_AlterEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AlterEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs b/Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs rename to Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs index 576968f2..069939e7 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs +++ b/Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190802174908_AddSearchNameToEFAlias")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs b/Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs similarity index 94% rename from SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs rename to Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs index d7311093..ef154051 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190802174908_AddSearchNameToEFAlias.cs +++ b/Data/Migrations/Sqlite/20190802174908_AddSearchNameToEFAlias.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddSearchNameToEFAlias : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs b/Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs rename to Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs index da616783..6dcb4532 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs +++ b/Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190831210503_AvgSnapValueToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs b/Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs rename to Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs index 625b3ca1..0aea6fa6 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190831210503_AvgSnapValueToClientStatistics.cs +++ b/Data/Migrations/Sqlite/20190831210503_AvgSnapValueToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AvgSnapValueToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs b/Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs rename to Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs index a199c814..40c168ec 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs +++ b/Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190901180209_AddSnapHitCountToClientStatistics")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs b/Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs rename to Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs index d3ddd2c5..10579fc7 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190901180209_AddSnapHitCountToClientStatistics.cs +++ b/Data/Migrations/Sqlite/20190901180209_AddSnapHitCountToClientStatistics.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddSnapHitCountToClientStatistics : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs b/Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs rename to Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs index 4c012301..aa7e8584 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs +++ b/Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190901223620_UseJunctionTableForSnapshotVector3")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs b/Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs similarity index 98% rename from SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs rename to Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs index 9f23f776..8f8c5ff5 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190901223620_UseJunctionTableForSnapshotVector3.cs +++ b/Data/Migrations/Sqlite/20190901223620_UseJunctionTableForSnapshotVector3.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class UseJunctionTableForSnapshotVector3 : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs b/Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs rename to Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs index 54a1a989..c0203170 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs +++ b/Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190914011524_AddCurrentSnapValueToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs b/Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs rename to Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs index e0d23b6d..3da2b5a9 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190914011524_AddCurrentSnapValueToSnapshot.cs +++ b/Data/Migrations/Sqlite/20190914011524_AddCurrentSnapValueToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddCurrentSnapValueToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs b/Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs rename to Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs index 9ddf2969..70c21140 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs +++ b/Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20190914012015_AddSessionSnapHitsToSnapshot")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs b/Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs rename to Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs index 687fe3ed..cf3a3d1c 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20190914012015_AddSessionSnapHitsToSnapshot.cs +++ b/Data/Migrations/Sqlite/20190914012015_AddSessionSnapHitsToSnapshot.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddSessionSnapHitsToSnapshot : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs b/Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs rename to Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs index 200be1d0..f294aca6 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs +++ b/Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20191004172550_RenameClientHitLocationCountColumns")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs b/Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs similarity index 99% rename from SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs rename to Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs index ec56f701..bf1e7967 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191004172550_RenameClientHitLocationCountColumns.cs +++ b/Data/Migrations/Sqlite/20191004172550_RenameClientHitLocationCountColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class RenameClientHitLocationCountColumns : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs b/Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs rename to Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs index 7000be7a..3e91ebef 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs +++ b/Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20191030000713_EnforceUniqueIndexForEFAliasIPName")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs b/Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs similarity index 98% rename from SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs rename to Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs index f8d77113..3f9652e1 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs +++ b/Data/Migrations/Sqlite/20191030000713_EnforceUniqueIndexForEFAliasIPName.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class EnforceUniqueIndexForEFAliasIPName : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs b/Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs rename to Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs index 840ea878..62e6845a 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs +++ b/Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs b/Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs similarity index 94% rename from SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs rename to Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs index ae96a8c4..e58ca32e 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs +++ b/Data/Migrations/Sqlite/20191225202141_SetCaseSensitiveCoallationForAliasNameMySQL.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class SetCaseSensitiveCoallationForAliasNameMySQL : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs b/Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs rename to Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs index e412d2c7..dcebb574 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs +++ b/Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20191230140947_AddMissingActiveColumns")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs b/Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs rename to Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs index c1ce223a..f1292963 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20191230140947_AddMissingActiveColumns.cs +++ b/Data/Migrations/Sqlite/20191230140947_AddMissingActiveColumns.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddMissingActiveColumns : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs b/Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs rename to Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs index 6a74f44c..7512ca9f 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs +++ b/Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20200423225137_AddImpersonationIdToEFChangeHistory")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs b/Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs rename to Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs index b2e74946..d2a62b0a 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200423225137_AddImpersonationIdToEFChangeHistory.cs +++ b/Data/Migrations/Sqlite/20200423225137_AddImpersonationIdToEFChangeHistory.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddImpersonationIdToEFChangeHistory : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs b/Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs rename to Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs index 4bcbd7b7..89d5572e 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs +++ b/Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20200521203304_AddHostnameToEFServer")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs b/Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs similarity index 91% rename from SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs rename to Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs index 3fa054c4..8211d5c1 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200521203304_AddHostnameToEFServer.cs +++ b/Data/Migrations/Sqlite/20200521203304_AddHostnameToEFServer.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddHostnameToEFServer : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs b/Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs rename to Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs index cb82b6fb..e4c0a039 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs +++ b/Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20200819224119_AddIsPasswordProtectedColumn")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs b/Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs similarity index 95% rename from SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs rename to Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs index 0fb89d05..4f6231dd 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20200819224119_AddIsPasswordProtectedColumn.cs +++ b/Data/Migrations/Sqlite/20200819224119_AddIsPasswordProtectedColumn.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddIsPasswordProtectedColumn : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs b/Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs rename to Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs index 1a50b70f..e0fde6cb 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs +++ b/Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20201114232340_UpdateEFRatingIndex")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs b/Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs similarity index 93% rename from SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs rename to Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs index 779a1dc6..220f4acb 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201114232340_UpdateEFRatingIndex.cs +++ b/Data/Migrations/Sqlite/20201114232340_UpdateEFRatingIndex.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class UpdateEFRatingIndex : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs b/Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs rename to Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs index c43c421f..81eb862d 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs +++ b/Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20201118023106_AddSentIngameFlagToClientMessage")] diff --git a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs b/Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs similarity index 92% rename from SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs rename to Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs index eb652b89..6fbc1576 100644 --- a/SharedLibraryCore/Migrations/Postgresql/20201118023106_AddSentIngameFlagToClientMessage.cs +++ b/Data/Migrations/Sqlite/20201118023106_AddSentIngameFlagToClientMessage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Postgresql +namespace Data.Migrations.Sqlite { public partial class AddSentIngameFlagToClientMessage : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs b/Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs similarity index 99% rename from SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs rename to Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs index 8966c2d4..9c4e5de2 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs +++ b/Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.Designer.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; +using Data.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] [Migration("20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta")] diff --git a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs b/Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs similarity index 98% rename from SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs rename to Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs index 5137722e..0a6f6411 100644 --- a/SharedLibraryCore/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs +++ b/Data/Migrations/Sqlite/20210124164906_UpdateEFMetaToSupportNonClientMetaAndLinkedMeta.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore.Migrations; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { public partial class UpdateEFMetaToSupportNonClientMetaAndLinkedMeta : Migration { diff --git a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.Designer.cs similarity index 65% rename from SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs rename to Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.Designer.cs index 90f555e4..246a50c0 100644 --- a/SharedLibraryCore/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.Designer.cs @@ -1,22 +1,208 @@ // using System; +using Data.MigrationContext; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SharedLibraryCore.Database.MigrationContext; -namespace SharedLibraryCore.Migrations.Sqlite +namespace Data.Migrations.Sqlite { [DbContext(typeof(SqliteDatabaseContext))] - partial class SqliteDatabaseContextModelSnapshot : ModelSnapshot + [Migration("20210301231432_AddAdditionalClientStatsAndZScore")] + partial class AddAdditionalClientStatsAndZScore { - protected override void BuildModel(ModelBuilder modelBuilder) + protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "3.1.10"); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => { b.Property("SnapshotId") .ValueGeneratedOnAdd() @@ -112,137 +298,81 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFACSnapshot"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => { - b.Property("ACSnapshotVector3Id") + b.Property("ClientHitStatisticId") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); - b.Property("Active") - .HasColumnType("INTEGER"); - - b.Property("SnapshotId") - .HasColumnType("INTEGER"); - - b.Property("Vector3Id") - .HasColumnType("INTEGER"); - - b.HasKey("ACSnapshotVector3Id"); - - b.HasIndex("SnapshotId"); - - b.HasIndex("Vector3Id"); - - b.ToTable("EFACSnapshotVector3"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => - { - b.Property("KillId") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Active") - .HasColumnType("INTEGER"); - - b.Property("AttackerId") - .HasColumnType("INTEGER"); - - b.Property("Damage") - .HasColumnType("INTEGER"); - - b.Property("DeathOriginVector3Id") - .HasColumnType("INTEGER"); - - b.Property("DeathType") - .HasColumnType("INTEGER"); - - b.Property("Fraction") - .HasColumnType("REAL"); - - b.Property("HitLoc") - .HasColumnType("INTEGER"); - - b.Property("IsKill") - .HasColumnType("INTEGER"); - - b.Property("KillOriginVector3Id") - .HasColumnType("INTEGER"); - - b.Property("Map") - .HasColumnType("INTEGER"); - - b.Property("ServerId") - .HasColumnType("INTEGER"); - - b.Property("VictimId") - .HasColumnType("INTEGER"); - - b.Property("ViewAnglesVector3Id") - .HasColumnType("INTEGER"); - - b.Property("VisibilityPercentage") - .HasColumnType("REAL"); - - b.Property("Weapon") - .HasColumnType("INTEGER"); - - b.Property("When") - .HasColumnType("TEXT"); - - 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("MessageId") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Active") - .HasColumnType("INTEGER"); - b.Property("ClientId") .HasColumnType("INTEGER"); - b.Property("Message") + b.Property("CreatedDateTime") .HasColumnType("TEXT"); - b.Property("SentIngame") + b.Property("DamageInflicted") .HasColumnType("INTEGER"); - b.Property("ServerId") + b.Property("DamageReceived") .HasColumnType("INTEGER"); - b.Property("TimeSent") + b.Property("DeathCount") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitLocationId") + .HasColumnType("INTEGER"); + + b.Property("KillCount") + .HasColumnType("INTEGER"); + + b.Property("MeansOfDeathId") + .HasColumnType("INTEGER"); + + b.Property("ReceivedHitCount") + .HasColumnType("INTEGER"); + + b.Property("Score") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SuicideCount") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") .HasColumnType("TEXT"); - b.HasKey("MessageId"); + b.Property("UsageSeconds") + .HasColumnType("INTEGER"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.HasKey("ClientHitStatisticId"); b.HasIndex("ClientId"); + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + b.HasIndex("ServerId"); - b.HasIndex("TimeSent"); + b.HasIndex("WeaponAttachmentComboId"); - b.ToTable("EFClientMessages"); + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => { b.Property("RatingHistoryId") .ValueGeneratedOnAdd() @@ -261,7 +391,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFClientRatingHistory"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => { b.Property("ClientId") .HasColumnType("INTEGER"); @@ -272,9 +402,6 @@ namespace SharedLibraryCore.Migrations.Sqlite b.Property("Active") .HasColumnType("INTEGER"); - b.Property("AverageRecoilOffset") - .HasColumnType("REAL"); - b.Property("AverageSnapValue") .HasColumnType("REAL"); @@ -305,17 +432,24 @@ namespace SharedLibraryCore.Migrations.Sqlite b.Property("TimePlayed") .HasColumnType("INTEGER"); - b.Property("VisionAverage") + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("ZScore") .HasColumnType("REAL"); b.HasKey("ClientId", "ServerId"); b.HasIndex("ServerId"); + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + b.ToTable("EFClientStatistics"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => { b.Property("HitLocationCountId") .ValueGeneratedOnAdd() @@ -353,7 +487,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFHitLocationCounts"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => { b.Property("RatingId") .ValueGeneratedOnAdd() @@ -396,60 +530,166 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFRating"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => { - b.Property("ServerId") - .HasColumnType("INTEGER"); - - b.Property("Active") - .HasColumnType("INTEGER"); - - b.Property("EndPoint") - .HasColumnType("TEXT"); - - b.Property("GameName") - .HasColumnType("INTEGER"); - - b.Property("HostName") - .HasColumnType("TEXT"); - - b.Property("IsPasswordProtected") - .HasColumnType("INTEGER"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.HasKey("ServerId"); - - b.ToTable("EFServers"); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b => - { - b.Property("StatisticId") + b.Property("HitLocationId") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); - b.Property("Active") + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") .HasColumnType("INTEGER"); - b.Property("ServerId") - .HasColumnType("INTEGER"); + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); - b.Property("TotalKills") - .HasColumnType("INTEGER"); + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); - b.Property("TotalPlayTime") - .HasColumnType("INTEGER"); + b.HasKey("HitLocationId"); - b.HasKey("StatisticId"); + b.HasIndex("Name"); - b.HasIndex("ServerId"); - - b.ToTable("EFServerStatistics"); + b.ToTable("EFHitLocations"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attachment1Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment2Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment3Id") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => { b.Property("AliasId") .ValueGeneratedOnAdd() @@ -492,7 +732,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFAlias"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b => + modelBuilder.Entity("Data.Models.EFAliasLink", b => { b.Property("AliasLinkId") .ValueGeneratedOnAdd() @@ -506,7 +746,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFAliasLinks"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b => + modelBuilder.Entity("Data.Models.EFChangeHistory", b => { b.Property("ChangeHistoryId") .ValueGeneratedOnAdd() @@ -545,61 +785,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFChangeHistory"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.Property("ClientId") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Active") - .HasColumnType("INTEGER"); - - b.Property("AliasLinkId") - .HasColumnType("INTEGER"); - - b.Property("Connections") - .HasColumnType("INTEGER"); - - b.Property("CurrentAliasId") - .HasColumnType("INTEGER"); - - b.Property("FirstConnection") - .HasColumnType("TEXT"); - - b.Property("LastConnection") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("INTEGER"); - - b.Property("Masked") - .HasColumnType("INTEGER"); - - b.Property("NetworkId") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT"); - - b.Property("PasswordSalt") - .HasColumnType("TEXT"); - - b.Property("TotalConnectionTime") - .HasColumnType("INTEGER"); - - b.HasKey("ClientId"); - - b.HasIndex("AliasLinkId"); - - b.HasIndex("CurrentAliasId"); - - b.HasIndex("NetworkId") - .IsUnique(); - - b.ToTable("EFClients"); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.EFMeta", b => { b.Property("MetaId") .ValueGeneratedOnAdd() @@ -643,7 +829,7 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFMeta"); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { b.Property("PenaltyId") .ValueGeneratedOnAdd() @@ -691,7 +877,60 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("EFPenalties"); }); - modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b => + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => { b.Property("Vector3Id") .ValueGeneratedOnAdd() @@ -711,225 +950,271 @@ namespace SharedLibraryCore.Migrations.Sqlite b.ToTable("Vector3"); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b => + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle") - .WithMany() - .HasForeignKey("CurrentViewAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination") - .WithMany() - .HasForeignKey("HitDestinationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin") - .WithMany() - .HasForeignKey("HitOriginId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle") - .WithMany() - .HasForeignKey("LastStrainAngleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshotVector3", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", "Snapshot") + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") .WithMany("PredictedViewAngles") .HasForeignKey("SnapshotId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Helpers.Vector3", "Vector") + b.HasOne("Data.Models.Vector3", "Vector") .WithMany() .HasForeignKey("Vector3Id") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b => + modelBuilder.Entity("Data.Models.Client.EFClient", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker") - .WithMany() - .HasForeignKey("AttackerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim") - .WithMany() - .HasForeignKey("VictimId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("ServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") - .WithMany() - .HasForeignKey("EFClientStatisticsClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server") - .WithMany() - .HasForeignKey("EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", null) - .WithMany("HitLocations") - .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b => - { - b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory") - .WithMany("Ratings") - .HasForeignKey("RatingHistoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - 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) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") - .WithMany("Children") - .HasForeignKey("LinkId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b => - { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink") + b.HasOne("Data.Models.EFAliasLink", "AliasLink") .WithMany() .HasForeignKey("AliasLinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias") + b.HasOne("Data.Models.EFAlias", "CurrentAlias") .WithMany() .HasForeignKey("CurrentAliasId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b => + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client") + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") .WithMany("Meta") .HasForeignKey("ClientId"); - b.HasOne("SharedLibraryCore.Database.Models.EFMeta", "LinkedMeta") + b.HasOne("Data.Models.EFMeta", "LinkedMeta") .WithMany() .HasForeignKey("LinkedMetaId") .OnDelete(DeleteBehavior.SetNull); }); - modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + modelBuilder.Entity("Data.Models.EFPenalty", b => { - b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link") + b.HasOne("Data.Models.EFAliasLink", "Link") .WithMany("ReceivedPenalties") .HasForeignKey("LinkId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender") + b.HasOne("Data.Models.Client.EFClient", "Offender") .WithMany("ReceivedPenalties") .HasForeignKey("OffenderId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher") + b.HasOne("Data.Models.Client.EFClient", "Punisher") .WithMany("AdministeredPenalties") .HasForeignKey("PunisherId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.cs b/Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.cs new file mode 100644 index 00000000..da480a02 --- /dev/null +++ b/Data/Migrations/Sqlite/20210301231432_AddAdditionalClientStatsAndZScore.cs @@ -0,0 +1,273 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Data.Migrations.Sqlite +{ + public partial class AddAdditionalClientStatsAndZScore : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UpdatedAt", + table: "EFClientStatistics", + nullable: true); + + migrationBuilder.AddColumn( + name: "ZScore", + table: "EFClientStatistics", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.CreateTable( + name: "EFHitLocations", + columns: table => new + { + HitLocationId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFHitLocations", x => x.HitLocationId); + }); + + migrationBuilder.CreateTable( + name: "EFMaps", + columns: table => new + { + MapId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMaps", x => x.MapId); + }); + + migrationBuilder.CreateTable( + name: "EFMeansOfDeath", + columns: table => new + { + MeansOfDeathId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeansOfDeath", x => x.MeansOfDeathId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachments", + columns: table => new + { + WeaponAttachmentId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachments", x => x.WeaponAttachmentId); + }); + + migrationBuilder.CreateTable( + name: "EFWeapons", + columns: table => new + { + WeaponId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Name = table.Column(nullable: false), + Game = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeapons", x => x.WeaponId); + }); + + migrationBuilder.CreateTable( + name: "EFWeaponAttachmentCombos", + columns: table => new + { + WeaponAttachmentComboId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + Game = table.Column(nullable: false), + Attachment1Id = table.Column(nullable: false), + Attachment2Id = table.Column(nullable: true), + Attachment3Id = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFWeaponAttachmentCombos", x => x.WeaponAttachmentComboId); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment1Id", + column: x => x.Attachment1Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment2Id", + column: x => x.Attachment2Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFWeaponAttachmentCombos_EFWeaponAttachments_Attachment3Id", + column: x => x.Attachment3Id, + principalTable: "EFWeaponAttachments", + principalColumn: "WeaponAttachmentId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "EFClientHitStatistics", + columns: table => new + { + ClientHitStatisticId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + HitLocationId = table.Column(nullable: true), + MeansOfDeathId = table.Column(nullable: true), + WeaponId = table.Column(nullable: true), + WeaponAttachmentComboId = table.Column(nullable: true), + HitCount = table.Column(nullable: false), + KillCount = table.Column(nullable: false), + DamageInflicted = table.Column(nullable: false), + ReceivedHitCount = table.Column(nullable: false), + DeathCount = table.Column(nullable: false), + DamageReceived = table.Column(nullable: false), + SuicideCount = table.Column(nullable: false), + UsageSeconds = table.Column(nullable: true), + Score = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientHitStatistics", x => x.ClientHitStatisticId); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFHitLocations_HitLocationId", + column: x => x.HitLocationId, + principalTable: "EFHitLocations", + principalColumn: "HitLocationId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFMeansOfDeath_MeansOfDeathId", + column: x => x.MeansOfDeathId, + principalTable: "EFMeansOfDeath", + principalColumn: "MeansOfDeathId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeaponAttachmentCombos_WeaponAttachmentComboId", + column: x => x.WeaponAttachmentComboId, + principalTable: "EFWeaponAttachmentCombos", + principalColumn: "WeaponAttachmentComboId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_EFClientHitStatistics_EFWeapons_WeaponId", + column: x => x.WeaponId, + principalTable: "EFWeapons", + principalColumn: "WeaponId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ZScore", + table: "EFClientStatistics", + column: "ZScore"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientStatistics_ClientId_TimePlayed_ZScore", + table: "EFClientStatistics", + columns: new[] { "ClientId", "TimePlayed", "ZScore" }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ClientId", + table: "EFClientHitStatistics", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_HitLocationId", + table: "EFClientHitStatistics", + column: "HitLocationId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_MeansOfDeathId", + table: "EFClientHitStatistics", + column: "MeansOfDeathId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_ServerId", + table: "EFClientHitStatistics", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponAttachmentComboId", + table: "EFClientHitStatistics", + column: "WeaponAttachmentComboId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientHitStatistics_WeaponId", + table: "EFClientHitStatistics", + column: "WeaponId"); + + migrationBuilder.CreateIndex( + name: "IX_EFHitLocations_Name", + table: "EFHitLocations", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment1Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment1Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment2Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment2Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeaponAttachmentCombos_Attachment3Id", + table: "EFWeaponAttachmentCombos", + column: "Attachment3Id"); + + migrationBuilder.CreateIndex( + name: "IX_EFWeapons_Name", + table: "EFWeapons", + column: "Name"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.Designer.cs b/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.Designer.cs new file mode 100644 index 00000000..e4fe819a --- /dev/null +++ b/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.Designer.cs @@ -0,0 +1,1279 @@ +// +using System; +using Data.MigrationContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Data.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20210310231004_AddRankingHistory")] + partial class AddRankingHistory + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10"); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationId"); + + b.HasIndex("HitOriginId"); + + b.HasIndex("LastStrainAngleId"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.Property("ClientHitStatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("DamageInflicted") + .HasColumnType("INTEGER"); + + b.Property("DamageReceived") + .HasColumnType("INTEGER"); + + b.Property("DeathCount") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitLocationId") + .HasColumnType("INTEGER"); + + b.Property("KillCount") + .HasColumnType("INTEGER"); + + b.Property("MeansOfDeathId") + .HasColumnType("INTEGER"); + + b.Property("ReceivedHitCount") + .HasColumnType("INTEGER"); + + b.Property("Score") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SuicideCount") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("UsageSeconds") + .HasColumnType("INTEGER"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.HasKey("ClientHitStatisticId"); + + b.HasIndex("ClientId"); + + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + + b.HasIndex("ServerId"); + + b.HasIndex("WeaponAttachmentComboId"); + + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("PerformanceMetric") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => + { + b.Property("HitLocationId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("HitLocationId"); + + b.HasIndex("Name"); + + b.ToTable("EFHitLocations"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attachment1Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment2Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment3Id") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("Data.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.Property("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.HasOne("Data.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("Data.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.cs b/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.cs new file mode 100644 index 00000000..2196f757 --- /dev/null +++ b/Data/Migrations/Sqlite/20210310231004_AddRankingHistory.cs @@ -0,0 +1,74 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Data.Migrations.Sqlite +{ + public partial class AddRankingHistory : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFClientRankingHistory", + columns: table => new + { + ClientRankingHistoryId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedDateTime = table.Column(nullable: false), + UpdatedDateTime = table.Column(nullable: true), + ClientId = table.Column(nullable: false), + ServerId = table.Column(nullable: true), + Newest = table.Column(nullable: false), + Ranking = table.Column(nullable: true), + ZScore = table.Column(nullable: true), + PerformanceMetric = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFClientRankingHistory", x => x.ClientRankingHistoryId); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFClientRankingHistory_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ClientId", + table: "EFClientRankingHistory", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_Ranking", + table: "EFClientRankingHistory", + column: "Ranking"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ServerId", + table: "EFClientRankingHistory", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_UpdatedDateTime", + table: "EFClientRankingHistory", + column: "UpdatedDateTime"); + + migrationBuilder.CreateIndex( + name: "IX_EFClientRankingHistory_ZScore", + table: "EFClientRankingHistory", + column: "ZScore"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFClientRankingHistory"); + } + } +} diff --git a/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs new file mode 100644 index 00000000..02302175 --- /dev/null +++ b/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -0,0 +1,1277 @@ +// +using System; +using Data.MigrationContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Data.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + partial class SqliteDatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.10"); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + b.HasKey("ClientId"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("NetworkId") + .IsUnique(); + + b.ToTable("EFClients"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + 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("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationId"); + + b.HasIndex("HitOriginId"); + + b.HasIndex("LastStrainAngleId"); + + b.ToTable("EFACSnapshot"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.Property("ClientHitStatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("DamageInflicted") + .HasColumnType("INTEGER"); + + b.Property("DamageReceived") + .HasColumnType("INTEGER"); + + b.Property("DeathCount") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitLocationId") + .HasColumnType("INTEGER"); + + b.Property("KillCount") + .HasColumnType("INTEGER"); + + b.Property("MeansOfDeathId") + .HasColumnType("INTEGER"); + + b.Property("ReceivedHitCount") + .HasColumnType("INTEGER"); + + b.Property("Score") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SuicideCount") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("UsageSeconds") + .HasColumnType("INTEGER"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.HasKey("ClientHitStatisticId"); + + b.HasIndex("ClientId"); + + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + + b.HasIndex("ServerId"); + + b.HasIndex("WeaponAttachmentComboId"); + + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("PerformanceMetric") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + + b.ToTable("EFClientStatistics"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnName("EFClientStatisticsClientId") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsServerId") + .HasColumnName("EFClientStatisticsServerId") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => + { + b.Property("HitLocationId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("HitLocationId"); + + b.HasIndex("Name"); + + b.ToTable("EFHitLocations"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attachment1Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment2Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment3Id") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasMaxLength(24); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress") + .IsUnique(); + + b.ToTable("EFAlias"); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks"); + }); + + modelBuilder.Entity("Data.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.Property("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics"); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.HasOne("Data.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("Data.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Models/AuditFields.cs b/Data/Models/AuditFields.cs new file mode 100644 index 00000000..43dcfecf --- /dev/null +++ b/Data/Models/AuditFields.cs @@ -0,0 +1,12 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Stats.Models +{ + public class AuditFields + { + [Required] + public DateTime CreatedDateTime { get; set; } = DateTime.UtcNow; + public DateTime? UpdatedDateTime { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Models/EFACSnapshotVector3.cs b/Data/Models/Client/EFACSnapshotVector3.cs similarity index 73% rename from Plugins/Stats/Models/EFACSnapshotVector3.cs rename to Data/Models/Client/EFACSnapshotVector3.cs index 1401f5aa..8751c3eb 100644 --- a/Plugins/Stats/Models/EFACSnapshotVector3.cs +++ b/Data/Models/Client/EFACSnapshotVector3.cs @@ -1,9 +1,9 @@ -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Helpers; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Numerics; +using Data.Models.Client.Stats; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client { public class EFACSnapshotVector3 : SharedEntity { diff --git a/SharedLibraryCore/Database/Models/EFClient.cs b/Data/Models/Client/EFClient.cs similarity index 50% rename from SharedLibraryCore/Database/Models/EFClient.cs rename to Data/Models/Client/EFClient.cs index 0117b84f..89703050 100644 --- a/SharedLibraryCore/Database/Models/EFClient.cs +++ b/Data/Models/Client/EFClient.cs @@ -3,10 +3,54 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace SharedLibraryCore.Database.Models +namespace Data.Models.Client { - public partial class EFClient : SharedEntity + public class EFClient : SharedEntity { + public enum Permission + { + /// + /// client has been banned + /// + Banned = -1, + /// + /// default client state upon first connect + /// + User = 0, + /// + /// client has been flagged + /// + Flagged = 1, + /// + /// client is trusted + /// + Trusted = 2, + /// + /// client is a moderator + /// + Moderator = 3, + /// + /// client is an administrator + /// + Administrator = 4, + /// + /// client is a senior administrator + /// + SeniorAdmin = 5, + /// + /// client is a owner + /// + Owner = 6, + /// + /// not used + /// + Creator = 7, + /// + /// reserved for default account + /// + Console = 8 + } + [Key] public int ClientId { get; set; } public long NetworkId { get; set; } diff --git a/Plugins/Stats/Models/EFClientKill.cs b/Data/Models/Client/EFClientKill.cs similarity index 51% rename from Plugins/Stats/Models/EFClientKill.cs rename to Data/Models/Client/EFClientKill.cs index 29f6dcc6..1c84f5c3 100644 --- a/Plugins/Stats/Models/EFClientKill.cs +++ b/Data/Models/Client/EFClientKill.cs @@ -1,52 +1,41 @@ using System; - -using SharedLibraryCore.Database.Models; -using System.ComponentModel.DataAnnotations.Schema; -using SharedLibraryCore.Helpers; -using System.ComponentModel.DataAnnotations; using System.Collections.Generic; -using static SharedLibraryCore.Server; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Server; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client { public class EFClientKill : SharedEntity { - [Key] - public long KillId { get; set; } + [Key] public long KillId { get; set; } public int VictimId { get; set; } - [ForeignKey("VictimId")] - public virtual EFClient Victim { get; set; } + [ForeignKey("VictimId")] public virtual EFClient Victim { get; set; } public int AttackerId { get; set; } - [ForeignKey("AttackerId")] - public virtual EFClient Attacker { get; set; } + [ForeignKey("AttackerId")] public virtual EFClient Attacker { get; set; } public long ServerId { get; set; } - [ForeignKey("ServerId")] - public virtual EFServer Server { get; set; } - public IW4Info.HitLocation HitLoc { get; set; } - public IW4Info.MeansOfDeath DeathType { get; set; } + [ForeignKey("ServerId")] public virtual EFServer Server { get; set; } + public int HitLoc { get; set; } + public int DeathType { get; set; } public int Damage { get; set; } - public IW4Info.WeaponName Weapon { get; set; } + public int Weapon { get; set; } public Vector3 KillOrigin { get; set; } public Vector3 DeathOrigin { get; set; } public Vector3 ViewAngles { get; set; } public DateTime When { get; set; } public double Fraction { get; set; } public bool IsKill { get; set; } + public double VisibilityPercentage { get; set; } + // http://wiki.modsrepository.com/index.php?title=Call_of_Duty_5:_Gameplay_standards for conversion to meters - [NotMapped] - public double Distance => Vector3.Distance(KillOrigin, DeathOrigin) * 0.0254; - public IW4Info.MapName Map { get; set; } - [NotMapped] - public long TimeOffset { get; set; } - [NotMapped] - public bool IsKillstreakKill { get; set; } - [NotMapped] - public float AdsPercent { get; set; } - [NotMapped] - public List AnglesList { get; set; } - [NotMapped] - public Game GameName { get; set; } + [NotMapped] public double Distance => Vector3.Distance(KillOrigin, DeathOrigin) * 0.0254; + public int Map { get; set; } + [NotMapped] public long TimeOffset { get; set; } + [NotMapped] public bool IsKillstreakKill { get; set; } + [NotMapped] public float AdsPercent { get; set; } + [NotMapped] public List AnglesList { get; set; } + [NotMapped] public int GameName { get; set; } /// /// Indicates if the attacker was alive after last captured angle @@ -60,4 +49,4 @@ namespace IW4MAdmin.Plugins.Stats.Models [NotMapped] public long TimeSinceLastAttack { get; set; } } -} +} \ No newline at end of file diff --git a/Plugins/Stats/Models/EFClientMessage.cs b/Data/Models/Client/EFClientMessage.cs similarity index 86% rename from Plugins/Stats/Models/EFClientMessage.cs rename to Data/Models/Client/EFClientMessage.cs index 49c2a931..d491e477 100644 --- a/Plugins/Stats/Models/EFClientMessage.cs +++ b/Data/Models/Client/EFClientMessage.cs @@ -1,9 +1,9 @@ -using SharedLibraryCore.Database.Models; -using System; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Server; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client { public class EFClientMessage : SharedEntity { diff --git a/Plugins/Stats/Models/EFACSnapshot.cs b/Data/Models/Client/Stats/EFACSnapshot.cs similarity index 87% rename from Plugins/Stats/Models/EFACSnapshot.cs rename to Data/Models/Client/Stats/EFACSnapshot.cs index 7c2abdac..f59f8720 100644 --- a/Plugins/Stats/Models/EFACSnapshot.cs +++ b/Data/Models/Client/Stats/EFACSnapshot.cs @@ -1,12 +1,11 @@ -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Helpers; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; +using System.Numerics; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client.Stats { /// /// This class houses the information for anticheat snapshots (used for validating a ban) @@ -47,9 +46,9 @@ namespace IW4MAdmin.Plugins.Stats.Models public int CurrentViewAngleId { get; set; } [ForeignKey("CurrentViewAngleId")] public Vector3 CurrentViewAngle { get; set; } - public IW4Info.WeaponName WeaponId { get; set; } - public IW4Info.HitLocation HitLocation { get; set; } - public IW4Info.MeansOfDeath HitType { get; set; } + public int WeaponId { get; set; } + public int HitLocation { get; set; } + public int HitType { get; set; } public virtual ICollection PredictedViewAngles { get; set; } [NotMapped] diff --git a/Data/Models/Client/Stats/EFClientHitStatistic.cs b/Data/Models/Client/Stats/EFClientHitStatistic.cs new file mode 100644 index 00000000..ad25716b --- /dev/null +++ b/Data/Models/Client/Stats/EFClientHitStatistic.cs @@ -0,0 +1,91 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Client.Stats.Reference; +using Data.Models.Server; +using Stats.Models; + +namespace Data.Models.Client.Stats +{ + public class EFClientHitStatistic : AuditFields + { + [Key] + public int ClientHitStatisticId { get; set; } + + [Required] + public int ClientId { get; set; } + + [ForeignKey(nameof(ClientId))] + public virtual EFClient Client { get; set; } + + public long? ServerId { get; set; } + + [ForeignKey(nameof(ServerId))] + public virtual EFServer Server { get; set; } + + public int? HitLocationId { get; set; } + + [ForeignKey(nameof(HitLocationId))] + public virtual EFHitLocation HitLocation { get; set; } + + public int? MeansOfDeathId { get; set; } + + [ForeignKey(nameof(MeansOfDeathId))] + public virtual EFMeansOfDeath MeansOfDeath { get; set; } + + public int? WeaponId { get; set; } + + [ForeignKey(nameof(WeaponId))] + public virtual EFWeapon Weapon { get; set; } + + public int? WeaponAttachmentComboId { get; set; } + + [ForeignKey(nameof(WeaponAttachmentComboId))] + public virtual EFWeaponAttachmentCombo WeaponAttachmentCombo { get; set; } + + /// + /// how many hits the player got + /// + public int HitCount { get; set; } + + /// + /// how many kills the player got + /// + public int KillCount { get; set; } + + /// + /// how much damage the player inflicted + /// + public int DamageInflicted { get; set; } + + /// + /// how many hits the player received + /// + public int ReceivedHitCount { get; set; } + + /// + /// how many kills the player received + /// + public int DeathCount { get; set; } + + /// + /// how much damage the player received + /// + public int DamageReceived { get; set; } + + /// + /// how many times the player killed themself + /// + public int SuicideCount { get; set; } + + /// + /// estimation of time spent with the configuration + /// + public int? UsageSeconds { get; set; } + + /// + /// total in-game score + /// + public int? Score { get; set; } + } +} diff --git a/Data/Models/Client/Stats/EFClientRankingHistory.cs b/Data/Models/Client/Stats/EFClientRankingHistory.cs new file mode 100644 index 00000000..1991a5b3 --- /dev/null +++ b/Data/Models/Client/Stats/EFClientRankingHistory.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Server; +using Stats.Models; + +namespace Data.Models.Client.Stats +{ + public class EFClientRankingHistory: AuditFields + { + public const int MaxRankingCount = 30; + + [Key] + public long ClientRankingHistoryId { get; set; } + + [Required] + public int ClientId { get; set; } + + [ForeignKey(nameof(ClientId))] + public virtual EFClient Client { get; set; } + + public long? ServerId { get; set; } + + [ForeignKey(nameof(ServerId))] + public virtual EFServer Server { get; set; } + + public bool Newest { get; set; } + public int? Ranking { get; set; } + public double? ZScore { get; set; } + public double? PerformanceMetric { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Models/EFClientRatingHistory.cs b/Data/Models/Client/Stats/EFClientRatingHistory.cs similarity index 69% rename from Plugins/Stats/Models/EFClientRatingHistory.cs rename to Data/Models/Client/Stats/EFClientRatingHistory.cs index 51d04d0e..e5e37c6e 100644 --- a/Plugins/Stats/Models/EFClientRatingHistory.cs +++ b/Data/Models/Client/Stats/EFClientRatingHistory.cs @@ -1,12 +1,8 @@ -using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore.Database.Models; -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Text; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client.Stats { public class EFClientRatingHistory : SharedEntity { diff --git a/Plugins/Stats/Models/EFClientStatistics.cs b/Data/Models/Client/Stats/EFClientStatistics.cs similarity index 90% rename from Plugins/Stats/Models/EFClientStatistics.cs rename to Data/Models/Client/Stats/EFClientStatistics.cs index 83f1524b..ed6d01c1 100644 --- a/Plugins/Stats/Models/EFClientStatistics.cs +++ b/Data/Models/Client/Stats/EFClientStatistics.cs @@ -4,9 +4,9 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Threading; -using SharedLibraryCore.Database.Models; +using Data.Models.Server; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client.Stats { public class EFClientStatistics : SharedEntity { @@ -31,16 +31,16 @@ namespace IW4MAdmin.Plugins.Stats.Models [Required] public int Deaths { get; set; } public double EloRating { get; set; } + public double ZScore { get; set; } + public DateTime? UpdatedAt { get; set; } public virtual ICollection HitLocations { get; set; } public double RollingWeightedKDR { get; set; } - public double VisionAverage { get; set; } - public double AverageRecoilOffset { get; set; } public double AverageSnapValue { get; set; } public int SnapHitCount { get; set; } [NotMapped] public double Performance { - get => Math.Round((EloRating + Skill) / 2.0, 2); + get => Math.Round(EloRating * 1/3.0 + Skill * 2/3.0, 2); } [NotMapped] public double KDR @@ -83,7 +83,7 @@ namespace IW4MAdmin.Plugins.Stats.Models DeathStreak = 0; LastScore = 0; SessionScores.Add(0); - Team = IW4Info.Team.None; + Team = 0; } [NotMapped] public int SessionScore @@ -103,7 +103,7 @@ namespace IW4MAdmin.Plugins.Stats.Models [NotMapped] private readonly List SessionScores = new List() { 0 }; [NotMapped] - public IW4Info.Team Team { get; set; } + public int Team { get; set; } [NotMapped] public DateTime LastStatHistoryUpdate { get; set; } = DateTime.UtcNow; [NotMapped] diff --git a/Plugins/Stats/Models/EFHitLocationCount.cs b/Data/Models/Client/Stats/EFHitLocationCount.cs similarity index 81% rename from Plugins/Stats/Models/EFHitLocationCount.cs rename to Data/Models/Client/Stats/EFHitLocationCount.cs index 726dc9b4..cc8bd042 100644 --- a/Plugins/Stats/Models/EFHitLocationCount.cs +++ b/Data/Models/Client/Stats/EFHitLocationCount.cs @@ -1,15 +1,15 @@ -using SharedLibraryCore.Database.Models; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Server; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client.Stats { public class EFHitLocationCount : SharedEntity { [Key] public int HitLocationCountId { get; set; } [Required] - public IW4Info.HitLocation Location { get; set; } + public int Location { get; set; } [Required] public int HitCount { get; set; } [Required] diff --git a/Plugins/Stats/Models/EFRating.cs b/Data/Models/Client/Stats/EFRating.cs similarity index 91% rename from Plugins/Stats/Models/EFRating.cs rename to Data/Models/Client/Stats/EFRating.cs index 9aae5f4e..2e50b08c 100644 --- a/Plugins/Stats/Models/EFRating.cs +++ b/Data/Models/Client/Stats/EFRating.cs @@ -1,9 +1,9 @@ -using SharedLibraryCore.Database.Models; -using System; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Server; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Client.Stats { public class EFRating : SharedEntity { diff --git a/Data/Models/Client/Stats/Reference/EFHitLocation.cs b/Data/Models/Client/Stats/Reference/EFHitLocation.cs new file mode 100644 index 00000000..dde2dcf8 --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFHitLocation.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Data.Abstractions; +using Stats.Models; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFHitLocation : AuditFields, IUniqueId + { + [Key] + public int HitLocationId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + public long Id => HitLocationId; + public string Value => Name; + } +} \ No newline at end of file diff --git a/Data/Models/Client/Stats/Reference/EFMap.cs b/Data/Models/Client/Stats/Reference/EFMap.cs new file mode 100644 index 00000000..2f765b7a --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFMap.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Data.Abstractions; +using Stats.Models; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFMap : AuditFields, IUniqueId + { + [Key] + public int MapId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + public long Id => MapId; + public string Value => Name; + } +} \ No newline at end of file diff --git a/Data/Models/Client/Stats/Reference/EFMeansOfDeath.cs b/Data/Models/Client/Stats/Reference/EFMeansOfDeath.cs new file mode 100644 index 00000000..ba3c0d55 --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFMeansOfDeath.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Data.Abstractions; +using Stats.Models; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFMeansOfDeath: AuditFields, IUniqueId + { + [Key] + public int MeansOfDeathId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + public long Id => MeansOfDeathId; + public string Value => Name; + } +} \ No newline at end of file diff --git a/Data/Models/Client/Stats/Reference/EFWeapon.cs b/Data/Models/Client/Stats/Reference/EFWeapon.cs new file mode 100644 index 00000000..54b67443 --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFWeapon.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Data.Abstractions; +using Stats.Models; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFWeapon : AuditFields, IUniqueId + { + [Key] + public int WeaponId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + public long Id => WeaponId; + public string Value => Name; + } +} \ No newline at end of file diff --git a/Data/Models/Client/Stats/Reference/EFWeaponAttachment.cs b/Data/Models/Client/Stats/Reference/EFWeaponAttachment.cs new file mode 100644 index 00000000..0d92ea52 --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFWeaponAttachment.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Data.Abstractions; +using Stats.Models; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFWeaponAttachment : AuditFields, IUniqueId + { + [Key] + public int WeaponAttachmentId { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + public long Id => WeaponAttachmentId; + public string Value => Name; + } +} diff --git a/Data/Models/Client/Stats/Reference/EFWeaponAttachmentCombo.cs b/Data/Models/Client/Stats/Reference/EFWeaponAttachmentCombo.cs new file mode 100644 index 00000000..1560bf94 --- /dev/null +++ b/Data/Models/Client/Stats/Reference/EFWeaponAttachmentCombo.cs @@ -0,0 +1,35 @@ +using Data.Abstractions; +using Stats.Models; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Data.Models.Client.Stats.Reference +{ + public class EFWeaponAttachmentCombo : AuditFields, IUniqueId + { + [Key] + public int WeaponAttachmentComboId { get; set; } + + [Required] + public Models.Reference.Game Game { get; set; } + + [Required] + public int Attachment1Id { get; set; } + + [ForeignKey(nameof(Attachment1Id))] + public virtual EFWeaponAttachment Attachment1 { get; set; } + + public int? Attachment2Id { get; set; } + + [ForeignKey(nameof(Attachment2Id))] + public virtual EFWeaponAttachment Attachment2 { get; set; } + + public int? Attachment3Id { get; set; } + + [ForeignKey(nameof(Attachment3Id))] + public virtual EFWeaponAttachment Attachment3 { get; set; } + + public long Id => WeaponAttachmentComboId; + public string Value => $"{Attachment1Id}{Attachment2Id}{Attachment3Id}"; + } +} diff --git a/Data/Models/Configuration/StatsModelConfiguration.cs b/Data/Models/Configuration/StatsModelConfiguration.cs new file mode 100644 index 00000000..ad172a2e --- /dev/null +++ b/Data/Models/Configuration/StatsModelConfiguration.cs @@ -0,0 +1,92 @@ +using Data.Models.Client; +using Data.Models.Client.Stats; +using Data.Models.Client.Stats.Reference; +using Data.Models.Server; +using Microsoft.EntityFrameworkCore; + +namespace Data.Models.Configuration +{ + public class StatsModelConfiguration + { + public static void Configure(ModelBuilder builder) + { + builder.Entity(entity => + { + entity.HasKey(cs => new {cs.ClientId, cs.ServerId}); + entity.HasIndex(cs => new {cs.ClientId, cs.TimePlayed, PerformancePercentile = cs.ZScore}); + entity.HasIndex(cs => new {PerformancePercentile = cs.ZScore}); + entity.ToTable("EFClientStatistics"); + }); + + + // fix linking from SQLCe + builder.Entity(entity => + { + entity.Property(c => c.EFClientStatisticsClientId) + .HasColumnName("EFClientStatisticsClientId"); + entity.Property(c => c.EFClientStatisticsServerId) + .HasColumnName("EFClientStatisticsServerId"); + + entity.ToTable("EFHitLocationCounts"); + }); + + + builder.Entity(entity => + { + entity.HasIndex(p => new {p.Performance, p.Ranking, p.When}); + entity.HasIndex(p => new {p.When, p.ServerId, p.Performance, p.ActivityAmount}); + entity.ToTable(nameof(EFRating)); + }); + + + builder.Entity(entity => + { + entity.HasIndex(p => p.TimeSent); + entity.ToTable("EFClientMessages"); + }); + + builder.Entity(entity => { entity.ToTable(nameof(EFClientStatistics)); }); + + builder.Entity(entity => { entity.ToTable(nameof(EFRating)); }); + + builder.Entity(entity => { entity.ToTable(nameof(EFClientRatingHistory)); }); + + builder.Entity(entity => { entity.ToTable("EFHitLocationCounts"); }); + + builder.Entity(entity => { entity.ToTable("EFServerStatistics"); }); + + builder.Entity(entity => { entity.ToTable("EFServers"); }); + + builder.Entity(entity => { entity.ToTable("EFClientKills"); }); + + builder.Entity().ToTable(nameof(Vector3)); + builder.Entity().ToTable(nameof(EFACSnapshot)); + builder.Entity().ToTable(nameof(EFACSnapshotVector3)); + + builder.Entity(entity => + { + entity.HasIndex(loc => loc.Name); + entity.ToTable("EFHitLocations"); + }); + + builder.Entity(entity => + { + entity.HasIndex(weapon => weapon.Name); + entity.ToTable("EFWeapons"); + }); + + builder.Entity(entity => { entity.ToTable("EFMaps"); }); + builder.Entity(entity => { entity.ToTable("EFClientHitStatistics"); }); + builder.Entity(entity => { entity.ToTable("EFWeaponAttachments"); }); + builder.Entity(entity => { entity.ToTable("EFWeaponAttachmentCombos"); }); + builder.Entity(entity => { entity.ToTable("EFMeansOfDeath"); }); + builder.Entity(entity => + { + entity.ToTable(nameof(EFClientRankingHistory)); + entity.HasIndex(ranking => ranking.Ranking); + entity.HasIndex(ranking => ranking.ZScore); + entity.HasIndex(ranking => ranking.UpdatedDateTime); + }); + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/Models/EFAlias.cs b/Data/Models/EFAlias.cs similarity index 94% rename from SharedLibraryCore/Database/Models/EFAlias.cs rename to Data/Models/EFAlias.cs index b8eee0eb..7f9bbd35 100644 --- a/SharedLibraryCore/Database/Models/EFAlias.cs +++ b/Data/Models/EFAlias.cs @@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { public partial class EFAlias : SharedEntity { diff --git a/SharedLibraryCore/Database/Models/EFAliasLink.cs b/Data/Models/EFAliasLink.cs similarity index 81% rename from SharedLibraryCore/Database/Models/EFAliasLink.cs rename to Data/Models/EFAliasLink.cs index b6b08eb1..3cb4c559 100644 --- a/SharedLibraryCore/Database/Models/EFAliasLink.cs +++ b/Data/Models/EFAliasLink.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { public class EFAliasLink : SharedEntity { diff --git a/SharedLibraryCore/Database/Models/EFChangeHistory.cs b/Data/Models/EFChangeHistory.cs similarity index 95% rename from SharedLibraryCore/Database/Models/EFChangeHistory.cs rename to Data/Models/EFChangeHistory.cs index fae53ab0..733b01fc 100644 --- a/SharedLibraryCore/Database/Models/EFChangeHistory.cs +++ b/Data/Models/EFChangeHistory.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { /// /// This class models the change to different entities diff --git a/SharedLibraryCore/Database/Models/EFMeta.cs b/Data/Models/EFMeta.cs similarity index 94% rename from SharedLibraryCore/Database/Models/EFMeta.cs rename to Data/Models/EFMeta.cs index 792797ee..2d2f81ac 100644 --- a/SharedLibraryCore/Database/Models/EFMeta.cs +++ b/Data/Models/EFMeta.cs @@ -1,8 +1,9 @@ -using System; +using Data.Models.Client; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { /// /// This class encapsulates any meta fields as a simple string diff --git a/SharedLibraryCore/Database/Models/EFPenalty.cs b/Data/Models/EFPenalty.cs similarity index 73% rename from SharedLibraryCore/Database/Models/EFPenalty.cs rename to Data/Models/EFPenalty.cs index 5aa370ce..2102ec0f 100644 --- a/SharedLibraryCore/Database/Models/EFPenalty.cs +++ b/Data/Models/EFPenalty.cs @@ -1,11 +1,26 @@ -using System; +using Data.Models.Client; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { - public partial class EFPenalty : SharedEntity + public class EFPenalty : SharedEntity { + public enum PenaltyType + { + Report, + Warning, + Flag, + Kick, + TempBan, + Ban, + Unban, + Any, + Unflag, + Other = 100 + } + [Key] public int PenaltyId { get; set; } [Required] diff --git a/Data/Models/Reference.cs b/Data/Models/Reference.cs new file mode 100644 index 00000000..6322d6df --- /dev/null +++ b/Data/Models/Reference.cs @@ -0,0 +1,19 @@ +namespace Data.Models +{ + public class Reference + { + public enum Game + { + COD = -1, + UKN = 0, + IW3 = 1, + IW4 = 2, + IW5 = 3, + IW6 = 4, + T4 = 5, + T5 = 6, + T6 = 7, + T7 = 8 + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Models/EFServer.cs b/Data/Models/Server/EFServer.cs similarity index 57% rename from Plugins/Stats/Models/EFServer.cs rename to Data/Models/Server/EFServer.cs index c547278d..70a49cd4 100644 --- a/Plugins/Stats/Models/EFServer.cs +++ b/Data/Models/Server/EFServer.cs @@ -1,12 +1,10 @@ - -using SharedLibraryCore.Database.Models; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using static SharedLibraryCore.Server; +using Data.Abstractions; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Server { - public class EFServer : SharedEntity + public class EFServer : SharedEntity, IUniqueId { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] @@ -14,8 +12,10 @@ namespace IW4MAdmin.Plugins.Stats.Models [Required] public int Port { get; set; } public string EndPoint { get; set; } - public Game? GameName { get; set; } + public Reference.Game? GameName { get; set; } public string HostName { get; set; } public bool IsPasswordProtected { get; set; } + public long Id => ServerId; + public string Value => EndPoint; } } diff --git a/Plugins/Stats/Models/EFServerStatistics.cs b/Data/Models/Server/EFServerStatistics.cs similarity index 75% rename from Plugins/Stats/Models/EFServerStatistics.cs rename to Data/Models/Server/EFServerStatistics.cs index c60f5908..9cc22e62 100644 --- a/Plugins/Stats/Models/EFServerStatistics.cs +++ b/Data/Models/Server/EFServerStatistics.cs @@ -1,8 +1,7 @@ -using SharedLibraryCore.Database.Models; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace IW4MAdmin.Plugins.Stats.Models +namespace Data.Models.Server { public class EFServerStatistics : SharedEntity { diff --git a/SharedLibraryCore/Database/Models/SharedEntity.cs b/Data/Models/SharedEntity.cs similarity index 63% rename from SharedLibraryCore/Database/Models/SharedEntity.cs rename to Data/Models/SharedEntity.cs index cd7c2b94..bd5271ce 100644 --- a/SharedLibraryCore/Database/Models/SharedEntity.cs +++ b/Data/Models/SharedEntity.cs @@ -1,9 +1,7 @@ -using SharedLibraryCore.Interfaces; -using System; +using Data.Abstractions; using System.Collections.Concurrent; -using System.ComponentModel.DataAnnotations.Schema; -namespace SharedLibraryCore.Database.Models +namespace Data.Models { public class SharedEntity : IPropertyExtender { @@ -35,17 +33,5 @@ namespace SharedLibraryCore.Database.Models _additionalProperties.TryAdd(name, value); } } - - ///// - ///// Specifies when the entity was created - ///// - //[Column(TypeName="datetime")] - //public DateTime CreatedDateTime { get; set; } - - ///// - ///// Specifies when the entity was updated - ///// - //[Column(TypeName = "datetime")] - //public DateTime? UpdatedDateTime { get;set; } } } diff --git a/SharedLibraryCore/Helpers/Vector3.cs b/Data/Models/Vector3.cs similarity index 64% rename from SharedLibraryCore/Helpers/Vector3.cs rename to Data/Models/Vector3.cs index 4bdf3c9d..c4c53af5 100644 --- a/SharedLibraryCore/Helpers/Vector3.cs +++ b/Data/Models/Vector3.cs @@ -1,17 +1,12 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; -namespace SharedLibraryCore.Helpers +namespace Data.Models { public class Vector3 { - [Key] - public int Vector3Id { get; set; } + [Key] public int Vector3Id { get; set; } public float X { get; protected set; } public float Y { get; protected set; } public float Z { get; protected set; } @@ -19,7 +14,6 @@ namespace SharedLibraryCore.Helpers // this is for EF and really should be somewhere else public Vector3() { - } public Vector3(float x, float y, float z) @@ -46,7 +40,9 @@ namespace SharedLibraryCore.Helpers public static Vector3 Parse(string s) { - bool valid = Regex.Match(s, @"\((-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+),\ (-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+),\ (-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+)\)").Success; + bool valid = Regex.Match(s, + @"\((-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+),\ (-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+),\ (-?[0-9]+\.?[0-9]*|-?[0-9]+\.?[0-9]*e-[0-9]+)\)") + .Success; if (!valid) { throw new FormatException("Vector3 is not in correct format"); @@ -55,9 +51,13 @@ namespace SharedLibraryCore.Helpers string removeParenthesis = s.Substring(1, s.Length - 2); string[] eachPoint = removeParenthesis.Split(','); - return new Vector3(float.Parse(eachPoint[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture), - float.Parse(eachPoint[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture), - float.Parse(eachPoint[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture)); + return new Vector3( + float.Parse(eachPoint[0], System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture), + float.Parse(eachPoint[1], System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture), + float.Parse(eachPoint[2], System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture)); } public static double Distance(Vector3 a, Vector3 b) @@ -76,44 +76,7 @@ namespace SharedLibraryCore.Helpers return Math.Sqrt((dx * dx) + (dy * dy)); } - - public static double SnapDistance(Vector3 a, Vector3 b, Vector3 c) - { - a = a.FixIW4Angles(); - b = b.FixIW4Angles(); - c = c.FixIW4Angles(); - - float preserveDirectionAngle(float a1, float b1) - { - float difference = b1 - a1; - while (difference < -180) difference += 360; - while (difference > 180) difference -= 360; - return difference; - } - - var directions = new[] - { - new Vector3() - { - X = preserveDirectionAngle(b.X, a.X), - Y = preserveDirectionAngle(b.Y, a.Y) - }, - new Vector3() - { - X = preserveDirectionAngle(c.X, b.X), - Y = preserveDirectionAngle(c.Y, b.Y) - } - }; - - var distance = new Vector3 - { - X = Math.Abs(directions[1].X - directions[0].X), - Y = Math.Abs(directions[1].Y - directions[0].Y) - }; - - return Math.Sqrt((distance.X * distance.X) + (distance.Y * distance.Y)); - } - + public static double ViewAngleDistance(Vector3 a, Vector3 b, Vector3 c) { double dabX = Math.Abs(a.X - b.X); @@ -147,4 +110,4 @@ namespace SharedLibraryCore.Helpers public double AngleBetween(Vector3 a) => Math.Acos(this.DotProduct(a) / (a.Magnitude() * this.Magnitude())); } -} +} \ No newline at end of file diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 1cc50347..e8a9d1c1 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -39,18 +39,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug Plugins\ScriptPlugins\ParserPIW5.js = Plugins\ScriptPlugins\ParserPIW5.js Plugins\ScriptPlugins\ParserPT6.js = Plugins\ScriptPlugins\ParserPT6.js Plugins\ScriptPlugins\ParserRektT5M.js = Plugins\ScriptPlugins\ParserRektT5M.js + Plugins\ScriptPlugins\ParserT4.js = Plugins\ScriptPlugins\ParserT4.js Plugins\ScriptPlugins\ParserT7.js = Plugins\ScriptPlugins\ParserT7.js Plugins\ScriptPlugins\ParserTeknoMW3.js = Plugins\ScriptPlugins\ParserTeknoMW3.js Plugins\ScriptPlugins\SampleScriptPluginCommand.js = Plugins\ScriptPlugins\SampleScriptPluginCommand.js Plugins\ScriptPlugins\SharedGUIDKick.js = Plugins\ScriptPlugins\SharedGUIDKick.js Plugins\ScriptPlugins\VPNDetection.js = Plugins\ScriptPlugins\VPNDetection.js - Plugins\ScriptPlugins\ParserT4.js = Plugins\ScriptPlugins\ParserT4.js EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{A848FCF1-8527-4AA8-A1AA-50D29695C678}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StatsWeb", "Plugins\Web\StatsWeb\StatsWeb.csproj", "{776B348B-F818-4A0F-A625-D0AF8BAD3E9B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutomessageFeed", "Plugins\AutomessageFeed\AutomessageFeed.csproj", "{F5815359-CFC7-44B4-9A3B-C04BACAD5836}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveRadar", "Plugins\LiveRadar\LiveRadar.csproj", "{00A1FED2-2254-4AF7-A5DB-2357FA7C88CD}" @@ -59,6 +55,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3065279E EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationTests", "Tests\ApplicationTests\ApplicationTests.csproj", "{581FA7AF-FEF6-483C-A7D0-2D13EF50801B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Data", "Data\Data.csproj", "{81689023-E55E-48ED-B7A8-53F4E21BBF2D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -267,30 +265,6 @@ Global {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.Build.0 = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|x64.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|x64.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|x86.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Debug|x86.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|Any CPU.Build.0 = Prerelease|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|Mixed Platforms.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|Mixed Platforms.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|x64.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|x64.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|x86.ActiveCfg = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Prerelease|x86.Build.0 = Debug|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|Any CPU.Build.0 = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|x64.ActiveCfg = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|x64.Build.0 = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|x86.ActiveCfg = Release|Any CPU - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B}.Release|x86.Build.0 = Release|Any CPU {F5815359-CFC7-44B4-9A3B-C04BACAD5836}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5815359-CFC7-44B4-9A3B-C04BACAD5836}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5815359-CFC7-44B4-9A3B-C04BACAD5836}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -362,6 +336,30 @@ Global {581FA7AF-FEF6-483C-A7D0-2D13EF50801B}.Release|x64.Build.0 = Release|Any CPU {581FA7AF-FEF6-483C-A7D0-2D13EF50801B}.Release|x86.ActiveCfg = Release|Any CPU {581FA7AF-FEF6-483C-A7D0-2D13EF50801B}.Release|x86.Build.0 = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|x64.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|x64.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|x86.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Debug|x86.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|Mixed Platforms.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|Mixed Platforms.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|x64.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|x64.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|x86.ActiveCfg = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|x86.Build.0 = Debug|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|Any CPU.Build.0 = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|x64.ActiveCfg = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|x64.Build.0 = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|x86.ActiveCfg = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Release|x86.Build.0 = Release|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU + {81689023-E55E-48ED-B7A8-53F4E21BBF2D}.Prerelease|Any CPU.Build.0 = Prerelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -373,8 +371,6 @@ Global {D9F2ED28-6FA5-40CA-9912-E7A849147AB1} = {26E8B310-269E-46D4-A612-24601F16065F} {6C706CE5-A206-4E46-8712-F8C48D526091} = {26E8B310-269E-46D4-A612-24601F16065F} {3F9ACC27-26DB-49FA-BCD2-50C54A49C9FA} = {26E8B310-269E-46D4-A612-24601F16065F} - {A848FCF1-8527-4AA8-A1AA-50D29695C678} = {26E8B310-269E-46D4-A612-24601F16065F} - {776B348B-F818-4A0F-A625-D0AF8BAD3E9B} = {A848FCF1-8527-4AA8-A1AA-50D29695C678} {F5815359-CFC7-44B4-9A3B-C04BACAD5836} = {26E8B310-269E-46D4-A612-24601F16065F} {00A1FED2-2254-4AF7-A5DB-2357FA7C88CD} = {26E8B310-269E-46D4-A612-24601F16065F} {581FA7AF-FEF6-483C-A7D0-2D13EF50801B} = {3065279E-17F0-4CE0-AF5B-014E04263D77} diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj index 78bf21a1..f7b0ad0d 100644 --- a/Plugins/AutomessageFeed/AutomessageFeed.csproj +++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj index 24f83fe5..0f23e151 100644 --- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj +++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj @@ -10,7 +10,7 @@ - + diff --git a/Plugins/LiveRadar/LiveRadar.csproj b/Plugins/LiveRadar/LiveRadar.csproj index c767d453..77c28bf4 100644 --- a/Plugins/LiveRadar/LiveRadar.csproj +++ b/Plugins/LiveRadar/LiveRadar.csproj @@ -15,9 +15,6 @@ - - - @@ -25,6 +22,10 @@ + + + + diff --git a/Plugins/LiveRadar/Plugin.cs b/Plugins/LiveRadar/Plugin.cs index 245129af..7c921a14 100644 --- a/Plugins/LiveRadar/Plugin.cs +++ b/Plugins/LiveRadar/Plugin.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -24,12 +25,14 @@ namespace LiveRadar private bool addedPage; private readonly object lockObject = new object(); private readonly ILogger _logger; + private readonly ApplicationConfiguration _appConfig; - public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory) + public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory, ApplicationConfiguration appConfig) { _configurationHandler = configurationHandlerFactory.GetConfigurationHandler("LiveRadarConfiguration"); _botGuidLookups = new Dictionary(); _logger = logger; + _appConfig = appConfig; } public Task OnEventAsync(GameEvent E, Server S) @@ -64,6 +67,11 @@ namespace LiveRadar { try { + if (((string) E.Extra).IsBotGuid() && _appConfig.IgnoreBots) + { + return Task.CompletedTask; + } + string botKey = $"BotGuid_{E.Extra}"; long generatedBotGuid; diff --git a/Plugins/LiveRadar/RadarEvent.cs b/Plugins/LiveRadar/RadarEvent.cs index dc2354c0..3dcf8bfa 100644 --- a/Plugins/LiveRadar/RadarEvent.cs +++ b/Plugins/LiveRadar/RadarEvent.cs @@ -1,5 +1,5 @@ -using SharedLibraryCore; -using SharedLibraryCore.Helpers; +using Data.Models; +using SharedLibraryCore; using System; using System.Linq; diff --git a/Plugins/Login/Login.csproj b/Plugins/Login/Login.csproj index 03a890c1..406a1f32 100644 --- a/Plugins/Login/Login.csproj +++ b/Plugins/Login/Login.csproj @@ -18,12 +18,12 @@ TRACE;DEBUG; + + + + - - - - diff --git a/Plugins/ProfanityDeterment/Plugin.cs b/Plugins/ProfanityDeterment/Plugin.cs index de2fda40..be0f752b 100644 --- a/Plugins/ProfanityDeterment/Plugin.cs +++ b/Plugins/ProfanityDeterment/Plugin.cs @@ -2,9 +2,8 @@ using System.Reflection; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Data.Models; using SharedLibraryCore; -using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; namespace IW4MAdmin.Plugins.ProfanityDeterment diff --git a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj index 3c4a7c0e..d3d0fbb9 100644 --- a/Plugins/ProfanityDeterment/ProfanityDeterment.csproj +++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj @@ -16,7 +16,7 @@ - + diff --git a/Plugins/Stats/Cheat/Detection.cs b/Plugins/Stats/Cheat/Detection.cs index f5357939..64172b1e 100644 --- a/Plugins/Stats/Cheat/Detection.cs +++ b/Plugins/Stats/Cheat/Detection.cs @@ -1,12 +1,15 @@ -using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Data.Models; +using Data.Models.Client; +using Data.Models.Client.Stats; using Microsoft.Extensions.Logging; +using SharedLibraryCore; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Plugins.Stats.Cheat @@ -66,6 +69,33 @@ namespace IW4MAdmin.Plugins.Stats.Cheat Tracker = new ChangeTracking(); TrackedHits = new List(); } + + private static double SnapDistance(Vector3 a, Vector3 b, Vector3 c) + { + a = a.FixIW4Angles(); + b = b.FixIW4Angles(); + c = c.FixIW4Angles(); + + + float preserveDirectionAngle(float a1, float b1) + { + float difference = b1 - a1; + while (difference < -180) difference += 360; + while (difference > 180) difference -= 360; + return difference; + } + + var directions = new[] + { + new Vector3(preserveDirectionAngle(b.X, a.X),preserveDirectionAngle(b.Y, a.Y), 0), + new Vector3( preserveDirectionAngle(c.X, b.X), preserveDirectionAngle(c.Y, b.Y), 0) + }; + + var distance = new Vector3(Math.Abs(directions[1].X - directions[0].X), + Math.Abs(directions[1].Y - directions[0].Y), 0); + + return Math.Sqrt((distance.X * distance.X) + (distance.Y * distance.Y)); + } /// /// Analyze kill and see if performed by a cheater @@ -76,12 +106,12 @@ namespace IW4MAdmin.Plugins.Stats.Cheat { var results = new List(); - if ((hit.DeathType != IW4Info.MeansOfDeath.MOD_PISTOL_BULLET && - hit.DeathType != IW4Info.MeansOfDeath.MOD_RIFLE_BULLET && - hit.DeathType != IW4Info.MeansOfDeath.MOD_HEAD_SHOT) || - hit.HitLoc == IW4Info.HitLocation.none || hit.TimeOffset - LastOffset < 0 || + if ((hit.DeathType != (int)IW4Info.MeansOfDeath.MOD_PISTOL_BULLET && + hit.DeathType != (int)IW4Info.MeansOfDeath.MOD_RIFLE_BULLET && + hit.DeathType != (int)IW4Info.MeansOfDeath.MOD_HEAD_SHOT) || + hit.HitLoc == (int)IW4Info.HitLocation.none || hit.TimeOffset - LastOffset < 0 || // hack: prevents false positives - (LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50)) + ((int)LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50)) { return new[] {new DetectionPenaltyResult() { @@ -89,9 +119,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat }}; } - LastWeapon = hit.Weapon; + LastWeapon = (IW4Info.WeaponName)(hit.Weapon); - HitLocationCount[hit.HitLoc].Count++; + HitLocationCount[(IW4Info.HitLocation)hit.HitLoc].Count++; HitCount++; if (hit.IsKill) @@ -116,7 +146,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat { ClientStats.SnapHitCount++; sessionSnapHits++; - var currentSnapDistance = Vector3.SnapDistance(hit.AnglesList[0], hit.AnglesList[1], hit.ViewAngles); + var currentSnapDistance = SnapDistance(hit.AnglesList[0], hit.AnglesList[1], hit.ViewAngles); double previousAverage = ClientStats.AverageSnapValue; ClientStats.AverageSnapValue = (previousAverage * (ClientStats.SnapHitCount - 1) + currentSnapDistance) / ClientStats.SnapHitCount; double previousSessionAverage = sessionAverageSnapAmount; @@ -211,7 +241,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat } // SESSION - var sessionHitLoc = HitLocationCount[hit.HitLoc]; + var sessionHitLoc = HitLocationCount[(IW4Info.HitLocation)hit.HitLoc]; sessionHitLoc.Offset = (sessionHitLoc.Offset * (sessionHitLoc.Count - 1) + realAgainstPredict) / sessionHitLoc.Count; int totalSessionHits = HitLocationCount.Sum(_hit => _hit.Value.Count); @@ -229,7 +259,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat Value = weightedSessionAverage, HitCount = HitCount, Type = DetectionType.Offset, - Location = hitLoc.Location + Location = (IW4Info.HitLocation)hitLoc.Location }); } @@ -278,8 +308,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat bool shouldIgnoreDetection = false; try { - shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[hit.GameName][DetectionType.Recoil] - .Any(_weaponRegex => Regex.IsMatch(hit.Weapon.ToString(), _weaponRegex)); + shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[(Server.Game)hit.GameName][DetectionType.Recoil] + .Any(_weaponRegex => Regex.IsMatch(((IW4Info.WeaponName)(hit.Weapon)).ToString(), _weaponRegex)); } catch (KeyNotFoundException) @@ -310,8 +340,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat try { shouldIgnoreDetection = false; - shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[hit.GameName][DetectionType.Button] - .Any(_weaponRegex => Regex.IsMatch(hit.Weapon.ToString(), _weaponRegex)); + shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[(Server.Game)hit.GameName][DetectionType.Button] + .Any(_weaponRegex => Regex.IsMatch(((IW4Info.WeaponName)(hit.Weapon)).ToString(), _weaponRegex)); } catch (KeyNotFoundException) @@ -423,8 +453,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat try { shouldIgnoreDetection = false; // reset previous value - shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[hit.GameName][DetectionType.Chest] - .Any(_weaponRegex => Regex.IsMatch(hit.Weapon.ToString(), _weaponRegex)); + shouldIgnoreDetection = Plugin.Config.Configuration().AnticheatConfiguration.IgnoredDetectionSpecification[(Server.Game)hit.GameName][DetectionType.Chest] + .Any(_weaponRegex => Regex.IsMatch(((IW4Info.WeaponName)(hit.Weapon)).ToString(), _weaponRegex)); } catch (KeyNotFoundException) diff --git a/Plugins/Stats/Cheat/DetectionPenaltyResult.cs b/Plugins/Stats/Cheat/DetectionPenaltyResult.cs index 1f1edf2d..ae9be54d 100644 --- a/Plugins/Stats/Cheat/DetectionPenaltyResult.cs +++ b/Plugins/Stats/Cheat/DetectionPenaltyResult.cs @@ -1,4 +1,4 @@ -using SharedLibraryCore.Database.Models; +using Data.Models; namespace IW4MAdmin.Plugins.Stats.Cheat { diff --git a/Plugins/Stats/Cheat/Strain.cs b/Plugins/Stats/Cheat/Strain.cs index 7fe4b1d5..e06caf22 100644 --- a/Plugins/Stats/Cheat/Strain.cs +++ b/Plugins/Stats/Cheat/Strain.cs @@ -1,9 +1,6 @@ using SharedLibraryCore; -using SharedLibraryCore.Helpers; -using SharedLibraryCore.Interfaces; using System; -using System.Collections.Generic; -using System.Text; +using Data.Models; namespace IW4MAdmin.Plugins.Stats.Cheat { diff --git a/Plugins/Stats/Cheat/Thresholds.cs b/Plugins/Stats/Cheat/Thresholds.cs index 37f2c960..f9b0fa94 100644 --- a/Plugins/Stats/Cheat/Thresholds.cs +++ b/Plugins/Stats/Cheat/Thresholds.cs @@ -1,19 +1,19 @@ using Stats.Config; using System; -using static SharedLibraryCore.Database.Models.EFPenalty; +using Data.Models; namespace IW4MAdmin.Plugins.Stats.Cheat { public static class DistributionHelper { - public static double CalculateMaxValue(this DistributionConfiguration config, PenaltyType penaltyType, int sampleSize) + public static double CalculateMaxValue(this DistributionConfiguration config, EFPenalty.PenaltyType penaltyType, int sampleSize) { switch (config.Type) { case DistributionConfiguration.DistributionType.Normal: break; case DistributionConfiguration.DistributionType.LogNormal: - double deviationNumber = penaltyType == PenaltyType.Flag ? 3.0 : 4.0; + double deviationNumber = penaltyType == EFPenalty.PenaltyType.Flag ? 3.0 : 4.0; double marginOfError = 1.644 / (config.StandardDeviation / Math.Sqrt(sampleSize)); double maxValue = (config.StandardDeviation * deviationNumber) + marginOfError; return maxValue; diff --git a/Plugins/Stats/Client/Abstractions/IClientStatisticCalculator.cs b/Plugins/Stats/Client/Abstractions/IClientStatisticCalculator.cs new file mode 100644 index 00000000..872278b9 --- /dev/null +++ b/Plugins/Stats/Client/Abstractions/IClientStatisticCalculator.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using SharedLibraryCore; + +namespace IW4MAdmin.Plugins.Stats.Client.Abstractions +{ + public interface IClientStatisticCalculator + { + Task GatherDependencies(); + Task CalculateForEvent(GameEvent gameEvent); + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/Abstractions/IHitInfoBuilder.cs b/Plugins/Stats/Client/Abstractions/IHitInfoBuilder.cs new file mode 100644 index 00000000..93ff90c0 --- /dev/null +++ b/Plugins/Stats/Client/Abstractions/IHitInfoBuilder.cs @@ -0,0 +1,10 @@ +using IW4MAdmin.Plugins.Stats.Client.Game; +using SharedLibraryCore; + +namespace Stats.Client.Abstractions +{ + public interface IHitInfoBuilder + { + HitInfo Build(string[] log, int entityId, bool isSelf, bool isVictim, Server.Game gameName); + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/Abstractions/IServerDistributionCalculator.cs b/Plugins/Stats/Client/Abstractions/IServerDistributionCalculator.cs new file mode 100644 index 00000000..9630c123 --- /dev/null +++ b/Plugins/Stats/Client/Abstractions/IServerDistributionCalculator.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace Stats.Client.Abstractions +{ + public interface IServerDistributionCalculator + { + Task Initialize(); + Task GetZScoreForServer(long serverId, double value); + Task GetRatingForZScore(double? value); + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/Abstractions/IWeaponNameParser.cs b/Plugins/Stats/Client/Abstractions/IWeaponNameParser.cs new file mode 100644 index 00000000..17367af1 --- /dev/null +++ b/Plugins/Stats/Client/Abstractions/IWeaponNameParser.cs @@ -0,0 +1,10 @@ +using SharedLibraryCore; +using Stats.Client.Game; + +namespace Stats.Client.Abstractions +{ + public interface IWeaponNameParser + { + WeaponInfo Parse(string weaponName, Server.Game gameName); + } +} diff --git a/Plugins/Stats/Client/Game/AttachmentInfo.cs b/Plugins/Stats/Client/Game/AttachmentInfo.cs new file mode 100644 index 00000000..8b60870a --- /dev/null +++ b/Plugins/Stats/Client/Game/AttachmentInfo.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Stats.Client.Game +{ + public class AttachmentInfo + { + public string Name { get; set; } + } +} diff --git a/Plugins/Stats/Client/Game/HitInfo.cs b/Plugins/Stats/Client/Game/HitInfo.cs new file mode 100644 index 00000000..55d0dcb3 --- /dev/null +++ b/Plugins/Stats/Client/Game/HitInfo.cs @@ -0,0 +1,27 @@ +using Data.Models; +using Stats.Client.Game; + +namespace IW4MAdmin.Plugins.Stats.Client.Game +{ + public enum HitType + { + Unknown, + Kill, + Damage, + WasKilled, + WasDamaged, + Suicide + } + + public class HitInfo + { + public Reference.Game Game { get; set; } + public int EntityId { get; set; } + public bool IsVictim { get; set; } + public HitType HitType { get; set; } + public int Damage { get; set; } + public string Location { get; set; } + public string MeansOfDeath { get; set; } + public WeaponInfo Weapon { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/Game/WeaponInfo.cs b/Plugins/Stats/Client/Game/WeaponInfo.cs new file mode 100644 index 00000000..09aea1b1 --- /dev/null +++ b/Plugins/Stats/Client/Game/WeaponInfo.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Stats.Client.Game +{ + public class WeaponInfo + { + public string RawName { get; set; } + public string Name { get; set; } + public IList Attachments { get; set; } = new List(); + } +} diff --git a/Plugins/Stats/Client/HitCalculator.cs b/Plugins/Stats/Client/HitCalculator.cs new file mode 100644 index 00000000..8b23a0a4 --- /dev/null +++ b/Plugins/Stats/Client/HitCalculator.cs @@ -0,0 +1,611 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; +using Data.Models.Client.Stats; +using Data.Models.Client.Stats.Reference; +using Data.Models.Server; +using IW4MAdmin.Plugins.Stats.Client.Abstractions; +using IW4MAdmin.Plugins.Stats.Client.Game; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using SharedLibraryCore; +using SharedLibraryCore.Database.Models; +using Stats.Client.Abstractions; +using Stats.Client.Game; + +namespace IW4MAdmin.Plugins.Stats.Client +{ + public class HitState + { + public HitState() + { + OnTransaction = new SemaphoreSlim(1, 1); + } + + ~HitState() + { + OnTransaction.Dispose(); + } + + public List Hits { get; set; } + public DateTime? LastUsage { get; set; } + public int? LastWeaponId { get; set; } + public EFServer Server { get; set; } + public SemaphoreSlim OnTransaction { get; } + public int UpdateCount { get; set; } + } + + public class HitCalculator : IClientStatisticCalculator + { + private readonly IDatabaseContextFactory _contextFactory; + private readonly ILogger _logger; + + private readonly ConcurrentDictionary _clientHitStatistics = + new ConcurrentDictionary(); + + private readonly SemaphoreSlim _onTransaction = new SemaphoreSlim(1, 1); + + private readonly ILookupCache _serverCache; + private readonly ILookupCache _hitLocationCache; + private readonly ILookupCache _weaponCache; + private readonly ILookupCache _attachmentCache; + private readonly ILookupCache _attachmentComboCache; + private readonly ILookupCache _modCache; + private readonly IHitInfoBuilder _hitInfoBuilder; + private readonly IServerDistributionCalculator _serverDistributionCalculator; + + private readonly TimeSpan _maxActiveTime = TimeSpan.FromMinutes(2); + private const int MaxUpdatesBeforePersist = 20; + private const string SessionScores = nameof(SessionScores); + + public HitCalculator(ILogger logger, IDatabaseContextFactory contextFactory, + ILookupCache hitLocationCache, ILookupCache weaponCache, + ILookupCache attachmentCache, + ILookupCache attachmentComboCache, + ILookupCache serverCache, ILookupCache modCache, IHitInfoBuilder hitInfoBuilder, + IServerDistributionCalculator serverDistributionCalculator) + { + _contextFactory = contextFactory; + _logger = logger; + _hitLocationCache = hitLocationCache; + _weaponCache = weaponCache; + _attachmentCache = attachmentCache; + _attachmentComboCache = attachmentComboCache; + _serverCache = serverCache; + _hitInfoBuilder = hitInfoBuilder; + _modCache = modCache; + _serverDistributionCalculator = serverDistributionCalculator; + } + + public async Task GatherDependencies() + { + await _hitLocationCache.InitializeAsync(); + await _weaponCache.InitializeAsync(); + await _attachmentCache.InitializeAsync(); + await _attachmentComboCache.InitializeAsync(); + await _serverCache.InitializeAsync(); + await _modCache.InitializeAsync(); + } + + public async Task CalculateForEvent(GameEvent gameEvent) + { + if (gameEvent.Type == GameEvent.EventType.Connect) + { + // if no servers have been cached yet we need to pull them here + // as they could have gotten added after we've initialized + if (!_serverCache.GetAll().Any()) + { + await _serverCache.InitializeAsync(); + } + + gameEvent.Origin.SetAdditionalProperty(SessionScores, new List<(int, DateTime)>()); + return; + } + + if (gameEvent.Type == GameEvent.EventType.Disconnect) + { + _clientHitStatistics.Remove(gameEvent.Origin.ClientId, out var state); + + if (state == null) + { + _logger.LogWarning("No client hit state available for disconnecting client {client}", + gameEvent.Origin.ToString()); + return; + } + + try + { + await state.OnTransaction.WaitAsync(); + HandleDisconnectCalculations(gameEvent.Origin, state); + await UpdateClientStatistics(gameEvent.Origin.ClientId, state); + } + + catch (Exception ex) + { + _logger.LogError(ex, "Could not handle disconnect calculations for client {client}", + gameEvent.Origin.ToString()); + } + + finally + { + if (state.OnTransaction.CurrentCount == 0) + { + state.OnTransaction.Release(); + } + } + + return; + } + + if (gameEvent.Type == GameEvent.EventType.MapEnd) + { + foreach (var client in gameEvent.Owner.GetClientsAsList()) + { + var scores = client.GetAdditionalProperty>(SessionScores); + scores?.Add((client.Score, DateTime.Now)); + } + } + + if (gameEvent.Type != GameEvent.EventType.Kill && gameEvent.Type != GameEvent.EventType.Damage) + { + return; + } + + var eventRegex = gameEvent.Type == GameEvent.EventType.Kill + ? gameEvent.Owner.EventParser.Configuration.Kill + : gameEvent.Owner.EventParser.Configuration.Damage; + + var match = eventRegex.PatternMatcher.Match(gameEvent.Data); + + if (!match.Success) + { + _logger.LogWarning("Log for event type {type} does not match pattern {logLine}", gameEvent.Type, + gameEvent.Data); + return; + } + + var attackerHitInfo = _hitInfoBuilder.Build(match.Values.Skip(1).ToArray(), gameEvent.Origin.ClientId, + gameEvent.Origin.ClientId == gameEvent.Target.ClientId, false, gameEvent.Owner.GameName); + var victimHitInfo = _hitInfoBuilder.Build(match.Values.Skip(1).ToArray(), gameEvent.Target.ClientId, + gameEvent.Origin.ClientId == gameEvent.Target.ClientId, true, gameEvent.Owner.GameName); + + foreach (var hitInfo in new[] {attackerHitInfo, victimHitInfo}) + { + try + { + await _onTransaction.WaitAsync(); + if (!_clientHitStatistics.ContainsKey(hitInfo.EntityId)) + { + _logger.LogDebug("Starting to track hits for {client}", hitInfo.EntityId); + var clientHits = await GetHitsForClient(hitInfo.EntityId); + _clientHitStatistics.TryAdd(hitInfo.EntityId, new HitState() + { + Hits = clientHits, + Server = (await _serverCache + .FirstAsync(server => + server.EndPoint == gameEvent.Owner.ToString() && server.HostName != null)) + }); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not retrieve previous hit data for client {client}"); + continue; + } + + finally + { + if (_onTransaction.CurrentCount == 0) + { + _onTransaction.Release(); + } + } + + var state = _clientHitStatistics[hitInfo.EntityId]; + + try + { + await _onTransaction.WaitAsync(); + var calculatedHits = await RunTasksForHitInfo(hitInfo, state.Server.ServerId); + + foreach (var clientHit in calculatedHits) + { + RunCalculation(clientHit, hitInfo, state); + } + } + + catch (Exception ex) + { + _logger.LogError(ex, "Could not update hit calculations for {client}", hitInfo.EntityId); + } + + finally + { + if (_onTransaction.CurrentCount == 0) + { + _onTransaction.Release(); + } + } + } + } + + + + private async Task> RunTasksForHitInfo(HitInfo hitInfo, long? serverId) + { + var weapon = await GetOrAddWeapon(hitInfo.Weapon, hitInfo.Game); + var attachments = + await Task.WhenAll(hitInfo.Weapon.Attachments.Select(attachment => + GetOrAddAttachment(attachment, hitInfo.Game))); + var attachmentCombo = await GetOrAddAttachmentCombo(attachments, hitInfo.Game); + var matchingLocation = await GetOrAddHitLocation(hitInfo.Location, hitInfo.Game); + var meansOfDeath = await GetOrAddMeansOfDeath(hitInfo.MeansOfDeath, hitInfo.Game); + + var baseTasks = new[] + { + // just the client + GetOrAddClientHit(hitInfo.EntityId, null), + // client and server + GetOrAddClientHit(hitInfo.EntityId, serverId), + // just the location + GetOrAddClientHit(hitInfo.EntityId, null, matchingLocation.HitLocationId), + // location and server + GetOrAddClientHit(hitInfo.EntityId, serverId, matchingLocation.HitLocationId), + // per weapon + GetOrAddClientHit(hitInfo.EntityId, null, null, weapon.WeaponId), + // per weapon and server + GetOrAddClientHit(hitInfo.EntityId, serverId, null, weapon.WeaponId), + // means of death aggregate + GetOrAddClientHit(hitInfo.EntityId, meansOfDeathId: meansOfDeath.MeansOfDeathId), + // means of death per server aggregate + GetOrAddClientHit(hitInfo.EntityId, serverId, + meansOfDeathId: meansOfDeath.MeansOfDeathId) + }; + + var allTasks = baseTasks.AsEnumerable(); + + if (attachmentCombo != null) + { + allTasks = allTasks + // per weapon per attachment combo + .Append(GetOrAddClientHit(hitInfo.EntityId, null, null, + weapon.WeaponId, attachmentCombo.WeaponAttachmentComboId)) + .Append(GetOrAddClientHit(hitInfo.EntityId, serverId, null, + weapon.WeaponId, attachmentCombo.WeaponAttachmentComboId)); + } + + return await Task.WhenAll(allTasks); + } + + private void RunCalculation(EFClientHitStatistic clientHit, HitInfo hitInfo, HitState hitState) + { + if (hitInfo.HitType == HitType.Kill || hitInfo.HitType == HitType.Damage) + { + if (clientHit.WeaponId != null) // we only want to calculate usage time for weapons + { + var timeElapsed = DateTime.Now - hitState.LastUsage; + var isSameWeapon = clientHit.WeaponId == hitState.LastWeaponId; + + clientHit.UsageSeconds ??= 60; + + if (timeElapsed.HasValue && timeElapsed <= _maxActiveTime) + { + clientHit.UsageSeconds + += // if it's the same weapon we can count the entire elapsed time + // otherwise we split it to make a best guess + (int) Math.Round(timeElapsed.Value.TotalSeconds / (isSameWeapon ? 1.0 : 2.0)); + } + + hitState.LastUsage = DateTime.Now; + } + + clientHit.DamageInflicted += hitInfo.Damage; + clientHit.HitCount++; + } + + if (hitInfo.HitType == HitType.Kill) + { + clientHit.KillCount++; + } + + if (hitInfo.HitType == HitType.WasKilled || hitInfo.HitType == HitType.WasDamaged || + hitInfo.HitType == HitType.Suicide) + { + clientHit.ReceivedHitCount++; + clientHit.DamageReceived += hitInfo.Damage; + } + + if (hitInfo.HitType == HitType.WasKilled) + { + clientHit.DeathCount++; + } + } + + private async Task> GetHitsForClient(int clientId) + { + try + { + await using var context = _contextFactory.CreateContext(); + var hitLocations = await context.Set() + .Where(stat => stat.ClientId == clientId) + .ToListAsync(); + + return !hitLocations.Any() ? new List() : hitLocations; + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not retrieve {hitName} for client with id {id}", + nameof(EFClientHitStatistic), clientId); + } + + return new List(); + } + + private async Task UpdateClientStatistics(int clientId, HitState locState = null) + { + if (!_clientHitStatistics.ContainsKey(clientId) && locState == null) + { + _logger.LogError("No {statsName} found for id {id}", nameof(EFClientHitStatistic), clientId); + return; + } + + var state = locState ?? _clientHitStatistics[clientId]; + + try + { + await using var context = _contextFactory.CreateContext(); + context.Set().UpdateRange(state.Hits); + await context.SaveChangesAsync(); + } + + catch (Exception ex) + { + _logger.LogError(ex, "Could not update hit location stats for id {id}", clientId); + } + } + + private async Task GetOrAddClientHit(int clientId, long? serverId = null, + int? hitLocationId = null, int? weaponId = null, int? attachmentComboId = null, + int? meansOfDeathId = null) + { + var state = _clientHitStatistics[clientId]; + await state.OnTransaction.WaitAsync(); + + var hitStat = state.Hits + .FirstOrDefault(hit => hit.HitLocationId == hitLocationId + && hit.WeaponId == weaponId + && hit.WeaponAttachmentComboId == attachmentComboId + && hit.MeansOfDeathId == meansOfDeathId + && hit.ServerId == serverId); + + if (hitStat != null) + { + state.OnTransaction.Release(); + return hitStat; + } + + hitStat = new EFClientHitStatistic() + { + ClientId = clientId, + ServerId = serverId, + WeaponId = weaponId, + WeaponAttachmentComboId = attachmentComboId, + HitLocationId = hitLocationId, + MeansOfDeathId = meansOfDeathId + }; + + try + { + /*if (state.UpdateCount > MaxUpdatesBeforePersist) + { + await UpdateClientStatistics(clientId); + state.UpdateCount = 0; + } + + state.UpdateCount++;*/ + state.Hits.Add(hitStat); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not add {statsName} for {id}", nameof(EFClientHitStatistic), + clientId); + state.Hits.Remove(hitStat); + } + finally + { + if (state.OnTransaction.CurrentCount == 0) + { + state.OnTransaction.Release(); + } + } + + return hitStat; + } + + private async Task GetOrAddHitLocation(string location, Reference.Game game) + { + var matchingLocation = (await _hitLocationCache + .FirstAsync(loc => loc.Name == location && loc.Game == game)); + + if (matchingLocation != null) + { + return matchingLocation; + } + + var hitLocation = new EFHitLocation() + { + Name = location, + Game = game + }; + + hitLocation = await _hitLocationCache.AddAsync(hitLocation); + + return hitLocation; + } + + private async Task GetOrAddWeapon(WeaponInfo weapon, Reference.Game game) + { + var matchingWeapon = (await _weaponCache + .FirstAsync(wep => wep.Name == weapon.Name && wep.Game == game)); + + if (matchingWeapon != null) + { + return matchingWeapon; + } + + matchingWeapon = new EFWeapon() + { + Name = weapon.Name, + Game = game + }; + + matchingWeapon = await _weaponCache.AddAsync(matchingWeapon); + + return matchingWeapon; + } + + private async Task GetOrAddAttachment(AttachmentInfo attachment, Reference.Game game) + { + var matchingAttachment = (await _attachmentCache + .FirstAsync(attach => attach.Name == attachment.Name && attach.Game == game)); + + if (matchingAttachment != null) + { + return matchingAttachment; + } + + matchingAttachment = new EFWeaponAttachment() + { + Name = attachment.Name, + Game = game + }; + + matchingAttachment = await _attachmentCache.AddAsync(matchingAttachment); + + return matchingAttachment; + } + + private async Task GetOrAddAttachmentCombo(EFWeaponAttachment[] attachments, + Reference.Game game) + { + if (!attachments.Any()) + { + return null; + } + + var allAttachments = attachments.ToList(); + + if (allAttachments.Count() < 3) + { + for (var i = allAttachments.Count(); i <= 3; i++) + { + allAttachments.Add(null); + } + } + + var matchingAttachmentCombo = (await _attachmentComboCache.FirstAsync(combo => + combo.Game == game + && combo.Attachment1Id == allAttachments[0].Id + && combo.Attachment2Id == allAttachments[1]?.Id + && combo.Attachment3Id == allAttachments[2]?.Id)); + + if (matchingAttachmentCombo != null) + { + return matchingAttachmentCombo; + } + + matchingAttachmentCombo = new EFWeaponAttachmentCombo() + { + Game = game, + Attachment1Id = (int) allAttachments[0].Id, + Attachment2Id = (int?) allAttachments[1]?.Id, + Attachment3Id = (int?) allAttachments[2]?.Id, + }; + + matchingAttachmentCombo = await _attachmentComboCache.AddAsync(matchingAttachmentCombo); + + return matchingAttachmentCombo; + } + + private async Task GetOrAddMeansOfDeath(string meansOfDeath, Reference.Game game) + { + var matchingMod = (await _modCache + .FirstAsync(mod => mod.Name == meansOfDeath && mod.Game == game)); + + if (matchingMod != null) + { + return matchingMod; + } + + var mod = new EFMeansOfDeath() + { + Name = meansOfDeath, + Game = game + }; + + mod = await _modCache.AddAsync(mod); + + return mod; + } + + private void HandleDisconnectCalculations(EFClient client, HitState state) + { + // todo: this not added to states fast connect/disconnect + var serverStats = state.Hits.FirstOrDefault(stat => + stat.ServerId == state.Server.ServerId && stat.WeaponId == null && + stat.WeaponAttachmentComboId == null && stat.HitLocationId == null && stat.MeansOfDeathId == null); + + if (serverStats == null) + { + _logger.LogWarning("No server hits were found for {serverId} on disconnect for {client}", + state.Server.ServerId, client.ToString()); + return; + } + + var aggregate = state.Hits.FirstOrDefault(stat => stat.WeaponId == null && + stat.WeaponAttachmentComboId == null && + stat.HitLocationId == null && + stat.MeansOfDeathId == null && + stat.ServerId == null); + + if (aggregate == null) + { + _logger.LogWarning("No aggregate found for {serverId} on disconnect for {client}", + state.Server.ServerId, client.ToString()); + return; + } + + var sessionScores = client.GetAdditionalProperty>(SessionScores); + + if (sessionScores == null) + { + _logger.LogWarning($"No session scores available for {client}"); + return; + } + + foreach (var stat in new[] {serverStats, aggregate}) + { + stat.Score ??= 0; + + if (sessionScores.Count == 0) + { + stat.Score += client.Score; + } + + else + { + stat.Score += sessionScores.Sum(item => item.Item1) + + (sessionScores.Last().Item1 == client.Score && + (DateTime.Now - sessionScores.Last().Item2).TotalMinutes < 1 + ? 0 + : client.Score); + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/HitInfoBuilder.cs b/Plugins/Stats/Client/HitInfoBuilder.cs new file mode 100644 index 00000000..e203b3b4 --- /dev/null +++ b/Plugins/Stats/Client/HitInfoBuilder.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using Data.Models; +using IW4MAdmin.Plugins.Stats.Client.Game; +using Microsoft.Extensions.Logging; +using SharedLibraryCore; +using SharedLibraryCore.Interfaces; +using Stats.Client.Abstractions; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Stats.Client +{ + public class HitInfoBuilder : IHitInfoBuilder + { + private readonly IWeaponNameParser _weaponNameParser; + private readonly ILogger _logger; + private const int MaximumDamage = 1000; + + public HitInfoBuilder(ILogger logger, IWeaponNameParser weaponNameParser) + { + _weaponNameParser = weaponNameParser; + _logger = logger; + } + + public HitInfo Build(string[] log, int entityId, bool isSelf, bool isVictim, Server.Game gameName) + { + var eventType = log[(uint) ParserRegex.GroupType.EventType].First(); + HitType hitType; + + if (isVictim) + { + if (isSelf) + { + hitType = HitType.Suicide; + } + + else + { + hitType = eventType == 'D' ? HitType.WasDamaged : HitType.WasKilled; + } + } + + else + { + hitType = eventType == 'D' ? HitType.Damage : HitType.Kill; + } + + var hitInfo = new HitInfo() + { + EntityId = entityId, + IsVictim = isVictim, + HitType = hitType, + Damage = Math.Min(MaximumDamage, int.Parse(log[(uint) ParserRegex.GroupType.Damage])), + Location = log[(uint) ParserRegex.GroupType.HitLocation], + Weapon = _weaponNameParser.Parse(log[(uint) ParserRegex.GroupType.Weapon], gameName), + MeansOfDeath = log[(uint)ParserRegex.GroupType.MeansOfDeath], + Game = (Reference.Game)gameName + }; + + //_logger.LogDebug("Generated new hitInfo {@hitInfo}", hitInfo); + return hitInfo; + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/ServerDistributionCalculator.cs b/Plugins/Stats/Client/ServerDistributionCalculator.cs new file mode 100644 index 00000000..aa54753f --- /dev/null +++ b/Plugins/Stats/Client/ServerDistributionCalculator.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client; +using Data.Models.Client.Stats; +using IW4MAdmin.Plugins.Stats; +using IW4MAdmin.Plugins.Stats.Config; +using Microsoft.EntityFrameworkCore; +using SharedLibraryCore; +using SharedLibraryCore.Interfaces; +using Stats.Client.Abstractions; +using Stats.Helpers; + +namespace Stats.Client +{ + public class ServerDistributionCalculator : IServerDistributionCalculator + { + private readonly IDatabaseContextFactory _contextFactory; + + private readonly IDataValueCache> + _distributionCache; + + private readonly IDataValueCache + _maxZScoreCache; + + private readonly IConfigurationHandler _configurationHandler; + private readonly List _serverIds = new List(); + + private const string DistributionCacheKey = nameof(DistributionCacheKey); + private const string MaxZScoreCacheKey = nameof(MaxZScoreCacheKey); + + public ServerDistributionCalculator(IDatabaseContextFactory contextFactory, + IDataValueCache> distributionCache, + IDataValueCache maxZScoreCache, + IConfigurationHandlerFactory configFactory) + { + _contextFactory = contextFactory; + _distributionCache = distributionCache; + _maxZScoreCache = maxZScoreCache; + _configurationHandler = configFactory.GetConfigurationHandler("StatsPluginSettings"); + } + + public async Task Initialize() + { + await LoadServers(); + _distributionCache.SetCacheItem((async set => + { + var validPlayTime = _configurationHandler.Configuration()?.TopPlayersMinPlayTime ?? 3600 * 3; + + var distributions = new Dictionary(); + + await LoadServers(); + + foreach (var serverId in _serverIds) + { + var performance = await set + .Where(s => s.ServerId == serverId) + .Where(s => s.Skill > 0) + .Where(s => s.EloRating > 0) + .Where(s => s.Client.Level != EFClient.Permission.Banned) + .Where(s => s.TimePlayed >= validPlayTime) + .Where(s => s.UpdatedAt >= Extensions.FifteenDaysAgo()) + .Select(s => s.EloRating * 1/3.0 + s.Skill * 2/3.0).ToListAsync(); + var distributionParams = performance.GenerateDistributionParameters(); + distributions.Add(serverId, distributionParams); + } + + return distributions; + }), DistributionCacheKey, Utilities.IsDevelopment ? TimeSpan.FromMinutes(5) : TimeSpan.FromHours(1)); + + _maxZScoreCache.SetCacheItem(async set => + { + var validPlayTime = _configurationHandler.Configuration()?.TopPlayersMinPlayTime ?? 3600 * 3; + + var zScore = await set + .Where(AdvancedClientStatsResourceQueryHelper.GetRankingFunc(validPlayTime)) + .Where(s => s.Skill > 0) + .Where(s => s.EloRating > 0) + .MaxAsync(s => (double?)s.ZScore); + return zScore ?? 0; + }, MaxZScoreCacheKey, Utilities.IsDevelopment ? TimeSpan.FromMinutes(5) : TimeSpan.FromMinutes(30)); + + await _distributionCache.GetCacheItem(DistributionCacheKey); + await _maxZScoreCache.GetCacheItem(MaxZScoreCacheKey); + + /*foreach (var serverId in _serverIds) + { + await using var ctx = _contextFactory.CreateContext(enableTracking: true); + + var a = await ctx.Set() + .Where(s => s.ServerId == serverId) + //.Where(s=> s.ClientId == 216105) + .Where(s => s.Skill > 0) + .Where(s => s.EloRating > 0) + .Where(s => s.Client.Level != EFClient.Permission.Banned) + .Where(s => s.TimePlayed >= 3600 * 3) + .Where(s => s.UpdatedAt >= Extensions.FifteenDaysAgo()) + .ToListAsync(); + + var b = a.Distinct(); + + foreach (var item in b) + { + await Plugin.Manager.UpdateHistoricalRanking(item.ClientId, item, item.ServerId); + //item.ZScore = await GetZScoreForServer(serverId, item.Performance); + //item.UpdatedAt = DateTime.UtcNow; + } + + await ctx.SaveChangesAsync(); + }*/ + } + + private async Task LoadServers() + { + if (_serverIds.Count == 0) + { + await using var context = _contextFactory.CreateContext(false); + _serverIds.AddRange(await context.Servers + .Where(s => s.EndPoint != null && s.HostName != null) + .Select(s => s.ServerId) + .ToListAsync()); + } + } + + public async Task GetZScoreForServer(long serverId, double value) + { + var serverParams = await _distributionCache.GetCacheItem(DistributionCacheKey); + if (!serverParams.ContainsKey(serverId)) + { + return 0.0; + } + + var sdParams = serverParams[serverId]; + if (sdParams.Sigma == 0) + { + return 0.0; + } + var zScore = (Math.Log(value) - sdParams.Mean) / sdParams.Sigma; + return zScore; + } + + public async Task GetRatingForZScore(double? value) + { + var maxZScore = await _maxZScoreCache.GetCacheItem(MaxZScoreCacheKey); + return maxZScore == 0 ? 0 : value.GetRatingForZScore(maxZScore); + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Client/WeaponNameParser.cs b/Plugins/Stats/Client/WeaponNameParser.cs new file mode 100644 index 00000000..62e1503f --- /dev/null +++ b/Plugins/Stats/Client/WeaponNameParser.cs @@ -0,0 +1,75 @@ +using Microsoft.Extensions.Logging; +using Stats.Client.Abstractions; +using Stats.Client.Game; +using System.Collections.Generic; +using System.Linq; +using IW4MAdmin.Plugins.Stats.Config; +using SharedLibraryCore; +using SharedLibraryCore.Interfaces; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Stats.Client +{ + public class WeaponNameParser : IWeaponNameParser + { + private readonly ILogger _logger; + private readonly StatsConfiguration _config; + + public WeaponNameParser(ILogger logger, IConfigurationHandler config) + { + _logger = logger; + _config = config.Configuration(); + } + + public WeaponInfo Parse(string weaponName, Server.Game gameName) + { + var configForGame = _config.WeaponNameParserConfigurations + ?.FirstOrDefault(config => config.Game == gameName); + + if (configForGame == null) + { + _logger.LogWarning("No weapon parser config available for game {game}", gameName); + return new WeaponInfo() + { + Name = "Unknown" + }; + } + + var splitWeaponName = weaponName.Split(configForGame.Delimiters); + + if (!splitWeaponName.Any()) + { + _logger.LogError("Could not parse weapon name {weapon}", weaponName); + + return new WeaponInfo() + { + Name = "Unknown" + }; + } + + // remove the _mp suffix + var filtered = splitWeaponName.Where(part => part != configForGame.WeaponSuffix); + var baseName = splitWeaponName.First(); + var attachments = new List(); + + if (filtered.Count() > 1) + { + attachments.AddRange(filtered.Skip(1)); + } + + var weaponInfo = new WeaponInfo() + { + RawName = weaponName, + Name = baseName, + Attachments = attachments.Select(attachment => new AttachmentInfo() + { + Name = attachment + }).ToList() + }; + + // _logger.LogDebug("Parsed weapon info {@info}", weaponInfo); + + return weaponInfo; + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Commands/MostKillsCommand.cs b/Plugins/Stats/Commands/MostKillsCommand.cs index 71d081cc..b6f34294 100644 --- a/Plugins/Stats/Commands/MostKillsCommand.cs +++ b/Plugins/Stats/Commands/MostKillsCommand.cs @@ -3,8 +3,9 @@ using System; using System.Linq; using System.Threading.Tasks; using SharedLibraryCore; -using IW4MAdmin.Plugins.Stats.Models; using System.Collections.Generic; +using Data.Abstractions; +using Data.Models.Client.Stats; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; diff --git a/Plugins/Stats/Commands/MostPlayedCommand.cs b/Plugins/Stats/Commands/MostPlayedCommand.cs index 9ad77736..b93ebc28 100644 --- a/Plugins/Stats/Commands/MostPlayedCommand.cs +++ b/Plugins/Stats/Commands/MostPlayedCommand.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Threading.Tasks; using SharedLibraryCore; -using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore.Database; using System.Collections.Generic; +using Data.Abstractions; +using Data.Models.Client.Stats; using SharedLibraryCore.Database.Models; using IW4MAdmin.Plugins.Stats.Helpers; using SharedLibraryCore.Configuration; diff --git a/Plugins/Stats/Commands/ResetStats.cs b/Plugins/Stats/Commands/ResetStats.cs index 320b319c..69395cea 100644 --- a/Plugins/Stats/Commands/ResetStats.cs +++ b/Plugins/Stats/Commands/ResetStats.cs @@ -1,12 +1,12 @@ -using IW4MAdmin.Plugins.Stats.Models; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using SharedLibraryCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client.Stats; namespace IW4MAdmin.Plugins.Stats.Commands { diff --git a/Plugins/Stats/Commands/TopStats.cs b/Plugins/Stats/Commands/TopStats.cs index 19b33f99..81a9a05b 100644 --- a/Plugins/Stats/Commands/TopStats.cs +++ b/Plugins/Stats/Commands/TopStats.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Threading.Tasks; using SharedLibraryCore; -using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore.Database; using System.Collections.Generic; +using Data.Abstractions; +using Data.Models.Client.Stats; using SharedLibraryCore.Database.Models; using IW4MAdmin.Plugins.Stats.Helpers; using SharedLibraryCore.Configuration; @@ -16,7 +16,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands { class TopStats : Command { - public static async Task> GetTopStats(Server s, ITranslationLookup translationLookup, IDatabaseContextFactory contextFactory) + public static async Task> GetTopStats(Server s, ITranslationLookup translationLookup) { long serverId = StatManager.GetIdForServer(s); var topStatsText = new List() @@ -24,30 +24,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands $"^5--{translationLookup["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--" }; - await using var context = contextFactory.CreateContext(false); - var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15); - int minPlayTime = Plugin.Config.Configuration().TopPlayersMinPlayTime; - - var iqStats = (from stats in context.Set() - join client in context.Clients - on stats.ClientId equals client.ClientId - join alias in context.Aliases - on client.CurrentAliasId equals alias.AliasId - where stats.ServerId == serverId - where stats.TimePlayed >= minPlayTime - where client.Level != EFClient.Permission.Banned - where client.LastConnection >= fifteenDaysAgo - orderby (stats.EloRating + stats.Skill) / 2.0d descending - select new - { - stats.KDR, - stats.Performance, - alias.Name - }) - .Take(5); - - var statsList = (await iqStats.ToListAsync()) - .Select(stats => $"^3{stats.Name}^7 - ^5{stats.KDR} ^7{translationLookup["PLUGINS_STATS_TEXT_KDR"]} | ^5{stats.Performance} ^7{translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"]}"); + var stats = await Plugin.Manager.GetTopStats(0, 5, serverId); + var statsList = stats.Select(stats => $"^3{stats.Name}^7 - ^5{stats.KDR} ^7{translationLookup["PLUGINS_STATS_TEXT_KDR"]} | ^5{stats.Performance} ^7{translationLookup["PLUGINS_STATS_COMMANDS_PERFORMANCE"]}"); topStatsText.AddRange(statsList); @@ -81,7 +59,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands public override async Task ExecuteAsync(GameEvent E) { - var topStats = await GetTopStats(E.Owner, _translationLookup, _contextFactory); + var topStats = await GetTopStats(E.Owner, _translationLookup); if (!E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)) { foreach (var stat in topStats) diff --git a/Plugins/Stats/Commands/ViewStats.cs b/Plugins/Stats/Commands/ViewStats.cs index 2ace6997..96c409f4 100644 --- a/Plugins/Stats/Commands/ViewStats.cs +++ b/Plugins/Stats/Commands/ViewStats.cs @@ -1,8 +1,8 @@ using SharedLibraryCore; -using IW4MAdmin.Plugins.Stats.Models; using System.Linq; using System.Threading.Tasks; -using SharedLibraryCore.Database; +using Data.Abstractions; +using Data.Models.Client.Stats; using Microsoft.EntityFrameworkCore; using IW4MAdmin.Plugins.Stats.Helpers; using SharedLibraryCore.Database.Models; @@ -56,7 +56,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands // getting stats for a particular client if (E.Target != null) { - var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Target.ClientId); + var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Target.ClientId, serverId); var performanceRankingString = performanceRanking == 0 ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; @@ -84,7 +84,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands // getting self stats else { - var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Origin.ClientId); + var performanceRanking = await Plugin.Manager.GetClientOverallRanking(E.Origin.ClientId, serverId); var performanceRankingString = performanceRanking == 0 ? _translationLookup["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{_translationLookup["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}"; diff --git a/Plugins/Stats/Config/StatsConfiguration.cs b/Plugins/Stats/Config/StatsConfiguration.cs index c4d091b3..d1438822 100644 --- a/Plugins/Stats/Config/StatsConfiguration.cs +++ b/Plugins/Stats/Config/StatsConfiguration.cs @@ -9,16 +9,32 @@ namespace IW4MAdmin.Plugins.Stats.Config { public class StatsConfiguration : IBaseConfiguration { - [Obsolete] - public bool? EnableAntiCheat { get; set; } + [Obsolete] public bool? EnableAntiCheat { get; set; } public List KillstreakMessages { get; set; } public List DeathstreakMessages { get; set; } public int TopPlayersMinPlayTime { get; set; } public bool StoreClientKills { get; set; } public int MostKillsMaxInactivityDays { get; set; } = 30; public int MostKillsClientLimit { get; set; } = 5; - [Obsolete] - public IDictionary ServerDetectionTypes { get; set; } + public bool EnableAdvancedMetrics { get; set; } = true; + + public WeaponNameParserConfiguration[] WeaponNameParserConfigurations { get; set; } = new[] + { + new WeaponNameParserConfiguration() + { + Game = Server.Game.IW4, + WeaponSuffix = "mp", + Delimiters = new[] {'_'} + }, + new WeaponNameParserConfiguration() + { + Game = Server.Game.T6, + WeaponSuffix = "mp", + Delimiters = new[] {'_', '+'} + } + }; + + [Obsolete] public IDictionary ServerDetectionTypes { get; set; } public AnticheatConfiguration AnticheatConfiguration { get; set; } = new AnticheatConfiguration(); #pragma warning disable CS0612 // Type or member is obsolete @@ -41,41 +57,47 @@ namespace IW4MAdmin.Plugins.Stats.Config #pragma warning restore CS0612 // Type or member is obsolete public string Name() => "StatsPluginSettings"; + public IBaseConfiguration Generate() { - AnticheatConfiguration.Enable = Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_SETUP_ENABLEAC"]); + AnticheatConfiguration.Enable = + Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_SETUP_ENABLEAC"]); KillstreakMessages = new List() { - new StreakMessageConfiguration(){ + new StreakMessageConfiguration() + { Count = -1, Message = "Try not to kill yourself anymore" }, - new StreakMessageConfiguration() { - Count = 5, - Message = "Great job! You're on a ^55 killstreak!" - }, - new StreakMessageConfiguration() - { - Count = 10, - Message = "Amazing! ^510 kills ^7without dying!" - }, - new StreakMessageConfiguration(){ - Count = 25, - Message = "You better call in that nuke, ^525 killstreak^7!" - } + new StreakMessageConfiguration() + { + Count = 5, + Message = "Great job! You're on a ^55 killstreak!" + }, + new StreakMessageConfiguration() + { + Count = 10, + Message = "Amazing! ^510 kills ^7without dying!" + }, + new StreakMessageConfiguration() + { + Count = 25, + Message = "You better call in that nuke, ^525 killstreak^7!" + } }; DeathstreakMessages = new List() { - new StreakMessageConfiguration() - { - Count = 5, - Message = "Pick it up soldier, you've died ^55 times ^7in a row..." - }, - new StreakMessageConfiguration(){ - Count = 10, - Message = "Seriously? ^510 deaths ^7without getting a kill?" - }, + new StreakMessageConfiguration() + { + Count = 5, + Message = "Pick it up soldier, you've died ^55 times ^7in a row..." + }, + new StreakMessageConfiguration() + { + Count = 10, + Message = "Seriously? ^510 deaths ^7without getting a kill?" + }, }; TopPlayersMinPlayTime = 3600 * 3; @@ -84,4 +106,4 @@ namespace IW4MAdmin.Plugins.Stats.Config return this; } } -} +} \ No newline at end of file diff --git a/Plugins/Stats/Config/WeaponNameParserConfiguration.cs b/Plugins/Stats/Config/WeaponNameParserConfiguration.cs new file mode 100644 index 00000000..d824ad9e --- /dev/null +++ b/Plugins/Stats/Config/WeaponNameParserConfiguration.cs @@ -0,0 +1,11 @@ +using SharedLibraryCore; + +namespace Stats.Config +{ + public class WeaponNameParserConfiguration + { + public Server.Game Game { get; set; } + public char[] Delimiters { get; set; } + public string WeaponSuffix { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Dtos/AdvancedStatsInfo.cs b/Plugins/Stats/Dtos/AdvancedStatsInfo.cs new file mode 100644 index 00000000..d12f6405 --- /dev/null +++ b/Plugins/Stats/Dtos/AdvancedStatsInfo.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Data.Models.Client; +using Data.Models.Client.Stats; +using SharedLibraryCore.Dtos; + +namespace Stats.Dtos +{ + public class AdvancedStatsInfo + { + public long? ServerId { get; set; } + public string ServerEndpoint { get; set; } + public string ClientName { get; set; } + public int ClientId { get; set; } + public EFClient.Permission Level { get; set; } + public double? Performance { get; set; } + public int? Ranking { get; set; } + public double? ZScore { get; set; } + public double? Rating { get; set; } + public List Servers { get; set; } + public List All { get; set; } + public EFClientHitStatistic Aggregate { get; set; } + public List ByHitLocation { get; set; } + public List ByWeapon { get; set; } + public List ByAttachmentCombo { get; set; } + public List Ratings { get; set; } + public List LegacyStats { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Dtos/StatsInfoRequest.cs b/Plugins/Stats/Dtos/StatsInfoRequest.cs index 5cca4e86..3340a06f 100644 --- a/Plugins/Stats/Dtos/StatsInfoRequest.cs +++ b/Plugins/Stats/Dtos/StatsInfoRequest.cs @@ -6,5 +6,6 @@ /// client identifier /// public int? ClientId { get; set; } + public string ServerEndpoint { get; set; } } } diff --git a/Plugins/Stats/Dtos/TopStatsInfo.cs b/Plugins/Stats/Dtos/TopStatsInfo.cs index 22fa8a8f..fdd357a1 100644 --- a/Plugins/Stats/Dtos/TopStatsInfo.cs +++ b/Plugins/Stats/Dtos/TopStatsInfo.cs @@ -11,12 +11,16 @@ namespace IW4MAdmin.Plugins.Stats.Web.Dtos public string Name { get; set; } public int ClientId { get; set; } public double KDR { get; set; } - public double Performance { get; set; } + public double? Performance { get; set; } public string TimePlayed { get; set; } + public TimeSpan TimePlayedValue { get; set; } public string LastSeen { get; set; } + public TimeSpan LastSeenValue { get; set; } public int Kills { get; set; } public int Deaths { get; set; } public int RatingChange { get; set; } public List PerformanceHistory { get; set; } + public double? ZScore { get; set; } + public long? ServerId { get; set; } } } diff --git a/Plugins/Stats/Extensions.cs b/Plugins/Stats/Extensions.cs new file mode 100644 index 00000000..22acfdc9 --- /dev/null +++ b/Plugins/Stats/Extensions.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Data.Models.Client.Stats; +using Microsoft.EntityFrameworkCore.Internal; +using SharedLibraryCore.Dtos; +using Stats.Dtos; + +namespace IW4MAdmin.Plugins.Stats +{ + public static class Extensions + { + private const int ZScoreRange = 3; + private const int RankIconDivisions = 24; + private const int MaxMessages = 100; + + public class LogParams + { + public double Mean { get; set; } + public double Sigma { get; set; } + } + + public static DateTime FifteenDaysAgo() => DateTime.UtcNow.AddDays(-15); + + public static double? WeightValueByPlaytime(this IEnumerable stats, string propertyName, + int minTimePlayed, Func validation = null) + { + if (!stats.Any()) + { + return null; + } + + validation ??= (item) => item.Performance > 0 && item.TimePlayed >= minTimePlayed; + + var items = stats.Where(validation).ToList(); + var performancePlayTime = items.Sum(s => s.TimePlayed); + + var propInfo = typeof(EFClientStatistics).GetProperty(propertyName); + var weightedValues = items.Sum(item => + (double?) propInfo?.GetValue(item) * (item.TimePlayed / (double) performancePlayTime)); + return weightedValues.Equals(double.NaN) ? 0 : weightedValues ?? 0; + } + + public static LogParams GenerateDistributionParameters(this IEnumerable values) + { + if (!values.Any()) + { + return new LogParams() + { + Mean = 0, + Sigma = 0 + }; + } + + var ti = 0.0; + var ti2 = 0.0; + var n = 0L; + + foreach (var val in values) + { + var logVal = Math.Log(val); + ti += logVal * logVal; + ti2 += logVal; + n++; + if (n % 50 == 0) // this isn't ideal, but we want to reduce the amount of CPU usage that the + // loops takes so people don't complain + { + Thread.Sleep(1); + } + } + + var mean = ti2 / n; + ti2 *= ti2; + var bottom = n == 1 ? 1 : n * (n - 1); + var sigma = Math.Sqrt(((n * ti) - ti2) / bottom); + + return new LogParams() + { + Sigma = sigma, + Mean = mean + }; + } + + public static double? GetRatingForZScore(this double? zScore, double maxZScore) + { + const int ratingScalar = 1000; + + if (!zScore.HasValue) + { + return null; + } + + // we just want everything positive so we can go from 0-max + var adjustedZScore = zScore < -ZScoreRange ? 0 : zScore + ZScoreRange; + return adjustedZScore / (maxZScore + ZScoreRange) * ratingScalar; + } + + public static int RankIconIndexForZScore(this double? zScore) + { + if (zScore == null) + { + return 0; + } + + const double divisionIncrement = (ZScoreRange * 2) / (double) RankIconDivisions; + var rank = 1; + for (var i = rank; i <= RankIconDivisions; i++) + { + var bottom = Math.Round(-ZScoreRange + (i - 1) * divisionIncrement, 5); + var top = Math.Round(-ZScoreRange + i * divisionIncrement, 5); + + if (zScore > bottom && zScore <= top) + { + return rank; + } + + if (i == 1 && zScore < bottom // catch all for really bad players + // catch all for very good players + || i == RankIconDivisions && zScore > top) + { + return i; + } + + rank++; + } + + return 0; + } + + /// + /// todo: lets abstract this out to a generic buildable query + /// this is just a dirty PoC + /// + /// + /// + public static ChatSearchQuery ParseSearchInfo(this string query, int count, int offset) + { + string[] filters = query.Split('|'); + var searchRequest = new ChatSearchQuery + { + Filter = query, + Count = count, + Offset = offset + }; + + // sanity checks + searchRequest.Count = Math.Min(searchRequest.Count, MaxMessages); + searchRequest.Count = Math.Max(searchRequest.Count, 0); + searchRequest.Offset = Math.Max(searchRequest.Offset, 0); + + if (filters.Length > 1) + { + if (filters[0].ToLower() != "chat") + { + throw new ArgumentException("Query is not compatible with chat"); + } + + foreach (string filter in filters.Skip(1)) + { + string[] args = filter.Split(' '); + + if (args.Length > 1) + { + string recombinedArgs = string.Join(' ', args.Skip(1)); + switch (args[0].ToLower()) + { + case "before": + searchRequest.SentBefore = DateTime.Parse(recombinedArgs); + break; + case "after": + searchRequest.SentAfter = DateTime.Parse(recombinedArgs); + break; + case "server": + searchRequest.ServerId = args[1]; + break; + case "client": + searchRequest.ClientId = int.Parse(args[1]); + break; + case "contains": + searchRequest.MessageContains = string.Join(' ', args.Skip(1)); + break; + case "sort": + searchRequest.Direction = Enum.Parse(args[1], ignoreCase: true); + break; + } + } + } + + return searchRequest; + } + + throw new ArgumentException("No filters specified for chat search"); + } + } +} \ No newline at end of file diff --git a/Plugins/Stats/Helpers/AdvancedClientStatsResourceQueryHelper.cs b/Plugins/Stats/Helpers/AdvancedClientStatsResourceQueryHelper.cs new file mode 100644 index 00000000..57165425 --- /dev/null +++ b/Plugins/Stats/Helpers/AdvancedClientStatsResourceQueryHelper.cs @@ -0,0 +1,156 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client; +using Data.Models.Client.Stats; +using IW4MAdmin.Plugins.Stats; +using IW4MAdmin.Plugins.Stats.Config; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using SharedLibraryCore.Dtos; +using SharedLibraryCore.Helpers; +using SharedLibraryCore.Interfaces; +using Stats.Client.Abstractions; +using Stats.Dtos; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Stats.Helpers +{ + public class AdvancedClientStatsResourceQueryHelper : IResourceQueryHelper + { + private readonly IDatabaseContextFactory _contextFactory; + private readonly ILogger _logger; + private readonly IManager _manager; + + public AdvancedClientStatsResourceQueryHelper(ILogger logger, + IDatabaseContextFactory contextFactory, IManager manager) + { + _contextFactory = contextFactory; + _logger = logger; + _manager = manager; + } + + public async Task> QueryResource(StatsInfoRequest query) + { + await using var context = _contextFactory.CreateContext(enableTracking: false); + + long? serverId = null; + + if (!string.IsNullOrEmpty(query.ServerEndpoint)) + { + serverId = (await context.Servers + .Select(server => new {server.EndPoint, server.Id}) + .FirstOrDefaultAsync(server => server.EndPoint == query.ServerEndpoint)) + ?.Id; + } + + var clientInfo = await context.Clients.Select(client => new + { + client.ClientId, + client.CurrentAlias.Name, + client.Level + }).FirstOrDefaultAsync(client => client.ClientId == query.ClientId); + + if (clientInfo == null) + { + return null; + } + + // gets all the hit stats for the client + var hitStats = await context.Set() + .Include(stat => stat.HitLocation) + .Include(stat => stat.MeansOfDeath) + .Include(stat => stat.Weapon) + .Include(stat => stat.WeaponAttachmentCombo) + .ThenInclude(attachment => attachment.Attachment1) + .Include(stat => stat.WeaponAttachmentCombo) + .ThenInclude(attachment => attachment.Attachment2) + .Include(stat => stat.WeaponAttachmentCombo) + .ThenInclude(attachment => attachment.Attachment3) + .Where(stat => stat.ClientId == query.ClientId) + .Where(stat => stat.ServerId == serverId) + .ToListAsync(); + + var ratings = await context.Set() + .Where(r => r.ClientId == clientInfo.ClientId) + .Where(r => r.ServerId == serverId) + .Where(r => r.Ranking != null) + .OrderByDescending(r => r.UpdatedDateTime) + .ToListAsync(); + + var mostRecentRanking = ratings.FirstOrDefault(ranking => ranking.Newest); + var ranking = mostRecentRanking?.Ranking + 1; + + // get stat for server, or all if no serverId + var legacyStats = await context.Set() + .Where(stat => stat.ClientId == query.ClientId) + .Where(stat => serverId == null || stat.ServerId == serverId) + .ToListAsync(); + + if (mostRecentRanking != null && mostRecentRanking.CreatedDateTime < Extensions.FifteenDaysAgo()) + { + ranking = 0; + } + + if (clientInfo.Level == EFClient.Permission.Banned) + { + ranking = null; + } + + var hitInfo = new AdvancedStatsInfo() + { + ServerId = serverId, + Performance = mostRecentRanking?.PerformanceMetric, + ZScore = mostRecentRanking?.ZScore, + ServerEndpoint = query.ServerEndpoint, + ClientName = clientInfo.Name, + ClientId = clientInfo.ClientId, + Level = clientInfo.Level, + Rating = mostRecentRanking?.PerformanceMetric, + All = hitStats, + Servers = _manager.GetServers() + .Select(server => new ServerInfo() + {Name = server.Hostname, IPAddress = server.IP, Port = server.Port}) + .ToList(), + Aggregate = hitStats.FirstOrDefault(hit => + hit.HitLocationId == null && hit.ServerId == serverId && hit.WeaponId == null && + hit.MeansOfDeathId == null), + ByHitLocation = hitStats + .Where(hit => hit.HitLocationId != null) + .Where(hit => hit.WeaponId == null) + .Where(hit => hit.WeaponAttachmentComboId == null) + .ToList(), + ByWeapon = hitStats + .Where(hit => hit.HitLocationId == null) + .Where(hit => hit.WeaponId != null) + .ToList(), + ByAttachmentCombo = hitStats + .Where(hit => hit.HitLocationId == null) + .Where(hit => hit.WeaponId != null) + .Where(hit => hit.WeaponAttachmentComboId != null) + .ToList(), + Ratings = ratings, + LegacyStats = legacyStats, + Ranking = ranking, + }; + + // todo: when nothign found + return new ResourceQueryHelperResult() + { + Results = new[] {hitInfo} + }; + } + + public static Expression> GetRankingFunc(int minPlayTime, double? zScore = null, + long? serverId = null) + { + return (stats) => (serverId == null || stats.ServerId == serverId) && + stats.UpdatedAt >= Extensions.FifteenDaysAgo() && + stats.Client.Level != EFClient.Permission.Banned && + stats.TimePlayed >= minPlayTime + && (zScore == null || stats.ZScore > zScore); + } + } +} \ No newline at end of file diff --git a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs b/Plugins/Stats/Helpers/ChatResourceQueryHelper.cs similarity index 96% rename from Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs rename to Plugins/Stats/Helpers/ChatResourceQueryHelper.cs index c8b484ba..4b871906 100644 --- a/Plugins/Web/StatsWeb/ChatResourceQueryHelper.cs +++ b/Plugins/Stats/Helpers/ChatResourceQueryHelper.cs @@ -1,19 +1,21 @@ -using IW4MAdmin.Plugins.Stats.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client; +using Data.Models.Server; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using Stats.Dtos; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; -namespace StatsWeb +namespace Stats.Helpers { /// /// implementation of IResourceQueryHelper @@ -81,7 +83,7 @@ namespace StatsWeb When = _message.TimeSent, Message = _message.Message, ServerName = query.IsProfileMeta ? "" : _message.Server.HostName, - GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value, + GameName = _message.Server.GameName == null ? Server.Game.IW4 : (Server.Game)_message.Server.GameName.Value, SentIngame = _message.SentIngame }); diff --git a/Plugins/Stats/Helpers/ServerStats.cs b/Plugins/Stats/Helpers/ServerStats.cs index e1c9af66..f9e25d83 100644 --- a/Plugins/Stats/Helpers/ServerStats.cs +++ b/Plugins/Stats/Helpers/ServerStats.cs @@ -1,12 +1,11 @@ -using IW4MAdmin.Plugins.Stats.Cheat; -using IW4MAdmin.Plugins.Stats.Models; -using SharedLibraryCore; -using SharedLibraryCore.Database.Models; +using SharedLibraryCore; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; +using Data.Models.Client; +using Data.Models.Client.Stats; +using Data.Models.Server; namespace IW4MAdmin.Plugins.Stats.Helpers { @@ -39,9 +38,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers .Select(_c => _c.GetAdditionalProperty(StatManager.CLIENT_STATS_KEY)) .Where(_c => _c != null); - if (PlayerStats.Count(p => p.Team == IW4Info.Team.None) / (double)PlayerStats.Count() <= 0.25) + if (PlayerStats.Count(p => p.Team == (int)IW4Info.Team.None) / (double)PlayerStats.Count() <= 0.25) { - return IsTeamBased ? Math.Max(PlayerStats.Count(p => p.Team == teamName), 1) : Math.Max(PlayerStats.Count() - 1, 1); + return IsTeamBased ? Math.Max(PlayerStats.Count(p => p.Team == (int)teamName), 1) : Math.Max(PlayerStats.Count() - 1, 1); } else diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index b9df54b9..312d145e 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -1,10 +1,8 @@ using IW4MAdmin.Plugins.Stats.Cheat; using IW4MAdmin.Plugins.Stats.Config; -using IW4MAdmin.Plugins.Stats.Models; using IW4MAdmin.Plugins.Stats.Web.Dtos; using Microsoft.EntityFrameworkCore; using SharedLibraryCore; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using System; @@ -14,8 +12,18 @@ using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Context; +using Data.Models; +using Data.Models.Client; +using Data.Models.Client.Stats; +using Data.Models.Server; +using Humanizer.Localisation; using Microsoft.Extensions.Logging; +using Stats.Client.Abstractions; +using Stats.Helpers; using static IW4MAdmin.Plugins.Stats.Cheat.Detection; +using EFClient = SharedLibraryCore.Database.Models.EFClient; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace IW4MAdmin.Plugins.Stats.Helpers @@ -30,21 +38,25 @@ namespace IW4MAdmin.Plugins.Stats.Helpers private static List serverModels; public static string CLIENT_STATS_KEY = "ClientStats"; public static string CLIENT_DETECTIONS_KEY = "ClientDetections"; - private readonly SemaphoreSlim _addPlayerWaiter = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim _addPlayerWaiter = new SemaphoreSlim(1, 1); + private readonly IServerDistributionCalculator _serverDistributionCalculator; - public StatManager(ILogger logger, IManager mgr, IDatabaseContextFactory contextFactory, IConfigurationHandler configHandler) + public StatManager(ILogger logger, IManager mgr, IDatabaseContextFactory contextFactory, + IConfigurationHandler configHandler, + IServerDistributionCalculator serverDistributionCalculator) { _servers = new ConcurrentDictionary(); _log = logger; _contextFactory = contextFactory; _configHandler = configHandler; + _serverDistributionCalculator = serverDistributionCalculator; } ~StatManager() { _addPlayerWaiter.Dispose(); } - + private void SetupServerIds() { using var ctx = _contextFactory.CreateContext(enableTracking: false); @@ -55,10 +67,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15); return (r) => r.ServerId == serverId && - r.When > fifteenDaysAgo && - r.RatingHistory.Client.Level != EFClient.Permission.Banned && - r.Newest && - r.ActivityAmount >= _configHandler.Configuration().TopPlayersMinPlayTime; + r.When > fifteenDaysAgo && + r.RatingHistory.Client.Level != EFClient.Permission.Banned && + r.Newest && + r.ActivityAmount >= _configHandler.Configuration().TopPlayersMinPlayTime; } /// @@ -66,13 +78,23 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// /// client id of the player /// - public async Task GetClientOverallRanking(int clientId) + public async Task GetClientOverallRanking(int clientId, long? serverId = null) { await using var context = _contextFactory.CreateContext(enableTracking: false); + + if (_configHandler.Configuration().EnableAdvancedMetrics) + { + var clientRanking = await context.Set() + .Where(r => r.ClientId == clientId) + .Where(r => r.ServerId == serverId) + .Where(r => r.Newest) + .FirstOrDefaultAsync(); + return clientRanking?.Ranking + 1 ?? 0; + } var clientPerformance = await context.Set() .Where(r => r.RatingHistory.ClientId == clientId) - .Where(r => r.ServerId == null) + .Where(r => r.ServerId == serverId) .Where(r => r.Newest) .Select(r => r.Performance) .FirstOrDefaultAsync(); @@ -90,25 +112,115 @@ namespace IW4MAdmin.Plugins.Stats.Helpers return 0; } + public async Task> GetNewTopStats(int start, int count, long? serverId = null) + { + await using var context = _contextFactory.CreateContext(false); + + var clientIdsList = await context.Set() + .Where(ranking => ranking.ServerId == serverId) + .Where(ranking => ranking.Client.Level != Data.Models.Client.EFClient.Permission.Banned) + .Where(ranking => ranking.Client.LastConnection >= Extensions.FifteenDaysAgo()) + .Where(ranking => ranking.ZScore != null) + .Where(ranking => ranking.PerformanceMetric != null) + .Where(ranking => ranking.Newest) + .Where(ranking => + ranking.Client.TotalConnectionTime >= _configHandler.Configuration().TopPlayersMinPlayTime) + .OrderByDescending(ranking => ranking.PerformanceMetric) + .Select(ranking => ranking.ClientId) + .Skip(start) + .Take(count) + .ToListAsync(); + + var rankings = await context.Set() + .Where(ranking => clientIdsList.Contains(ranking.ClientId)) + .Where(ranking => ranking.ServerId == serverId) + .Select(ranking => new + { + ranking.ClientId, + ranking.Client.CurrentAlias.Name, + ranking.Client.LastConnection, + ranking.PerformanceMetric, + ranking.ZScore, + ranking.Ranking, + ranking.CreatedDateTime + }) + .ToListAsync(); + + var rankingsDict = rankings.GroupBy(rank => rank.ClientId) + .ToDictionary(rank => rank.Key, rank => rank.OrderBy(r => r.CreatedDateTime).ToList()); + + var statsInfo = await context.Set() + .Where(stat => clientIdsList.Contains(stat.ClientId)) + .Where(stat => stat.TimePlayed > 0) + .Where(stat => stat.Kills > 0 || stat.Deaths > 0) + .Where(stat => serverId == null || stat.ServerId == serverId) + .GroupBy(stat => stat.ClientId) + .Select(s => new + { + ClientId = s.Key, + Kills = s.Sum(c => c.Kills), + Deaths = s.Sum(c => c.Deaths), + KDR = s.Sum(c => (c.Kills / (double) (c.Deaths == 0 ? 1 : c.Deaths)) * c.TimePlayed) / + s.Sum(c => c.TimePlayed), + TotalTimePlayed = s.Sum(c => c.TimePlayed), + }) + .ToListAsync(); + + var finished = statsInfo + .OrderByDescending(stat => rankingsDict[stat.ClientId].Last().PerformanceMetric) + .Select((s, index) => new TopStatsInfo() + { + ClientId = s.ClientId, + Id = (int?) serverId ?? 0, + Deaths = s.Deaths, + Kills = s.Kills, + KDR = Math.Round(s.KDR, 2), + LastSeen = (DateTime.UtcNow - rankingsDict[s.ClientId].First().LastConnection) + .HumanizeForCurrentCulture(1, TimeUnit.Week, TimeUnit.Second, ",", false), + LastSeenValue = (DateTime.UtcNow - rankingsDict[s.ClientId].First().LastConnection), + Name = rankingsDict[s.ClientId].First().Name, + Performance = Math.Round(rankingsDict[s.ClientId].Last().PerformanceMetric ?? 0, 2), + RatingChange = (rankingsDict[s.ClientId].First().Ranking - + rankingsDict[s.ClientId].Last().Ranking) ?? 0, + PerformanceHistory = rankingsDict[s.ClientId].Select(ranking => ranking.PerformanceMetric ?? 0).ToList(), + TimePlayed = Math.Round(s.TotalTimePlayed / 3600.0, 1).ToString("#,##0"), + TimePlayedValue = TimeSpan.FromSeconds(s.TotalTimePlayed), + Ranking = index + start + 1, + ZScore = rankingsDict[s.ClientId].Last().ZScore, + ServerId = serverId + }) + .OrderBy(r => r.Ranking) + .ToList(); + + return finished; + } + public async Task> GetTopStats(int start, int count, long? serverId = null) { + if (_configHandler.Configuration().EnableAdvancedMetrics) + { + return await GetNewTopStats(start, count, serverId); + } + await using var context = _contextFactory.CreateContext(enableTracking: false); // setup the query for the clients within the given rating range var iqClientRatings = (from rating in context.Set() - .Where(GetRankingFunc(serverId)) - select new - { - rating.RatingHistory.ClientId, - rating.RatingHistory.Client.CurrentAlias.Name, - rating.RatingHistory.Client.LastConnection, - rating.Performance, - }) + .Where(GetRankingFunc(serverId)) + select new + { + rating.RatingHistory.ClientId, + rating.RatingHistory.Client.CurrentAlias.Name, + rating.RatingHistory.Client.LastConnection, + rating.Performance, + }) .OrderByDescending(c => c.Performance) .Skip(start) .Take(count); // materialized list - var clientRatings = await iqClientRatings.ToListAsync(); + var clientRatings = (await iqClientRatings.ToListAsync()) + .GroupBy(rating => rating.ClientId) // prevent duplicate keys + .Select(group => group.FirstOrDefault()); // get all the unique client ids that are in the top stats var clientIds = clientRatings @@ -117,59 +229,67 @@ namespace IW4MAdmin.Plugins.Stats.Helpers .ToList(); var iqRatingInfo = from rating in context.Set() - where clientIds.Contains(rating.RatingHistory.ClientId) - where rating.ServerId == serverId - select new - { - rating.Ranking, - rating.Performance, - rating.RatingHistory.ClientId, - rating.When - }; + where clientIds.Contains(rating.RatingHistory.ClientId) + where rating.ServerId == serverId + select new + { + rating.Ranking, + rating.Performance, + rating.RatingHistory.ClientId, + rating.When + }; var ratingInfo = (await iqRatingInfo.ToListAsync()) .GroupBy(r => r.ClientId) .Select(grp => new { grp.Key, - Ratings = grp.Select(r => new { r.Performance, r.Ranking, r.When }) + Ratings = grp.Select(r => new {r.Performance, r.Ranking, r.When}) }); var iqStatsInfo = (from stat in context.Set() - where clientIds.Contains(stat.ClientId) - where stat.Kills > 0 || stat.Deaths > 0 - where serverId == null ? true : stat.ServerId == serverId - group stat by stat.ClientId into s - select new - { - ClientId = s.Key, - Kills = s.Sum(c => c.Kills), - Deaths = s.Sum(c => c.Deaths), - KDR = s.Sum(c => (c.Kills / (double)(c.Deaths == 0 ? 1 : c.Deaths)) * c.TimePlayed) / s.Sum(c => c.TimePlayed), - TotalTimePlayed = s.Sum(c => c.TimePlayed), - }); + where clientIds.Contains(stat.ClientId) + where stat.Kills > 0 || stat.Deaths > 0 + where serverId == null || stat.ServerId == serverId + group stat by stat.ClientId + into s + select new + { + ClientId = s.Key, + Kills = s.Sum(c => c.Kills), + Deaths = s.Sum(c => c.Deaths), + KDR = s.Sum(c => (c.Kills / (double) (c.Deaths == 0 ? 1 : c.Deaths)) * c.TimePlayed) / + s.Sum(c => c.TimePlayed), + TotalTimePlayed = s.Sum(c => c.TimePlayed), + }); var topPlayers = await iqStatsInfo.ToListAsync(); var clientRatingsDict = clientRatings.ToDictionary(r => r.ClientId); var finished = topPlayers.Select(s => new TopStatsInfo() - { - ClientId = s.ClientId, - Id = (int?)serverId ?? 0, - Deaths = s.Deaths, - Kills = s.Kills, - KDR = Math.Round(s.KDR, 2), - LastSeen = (DateTime.UtcNow - clientRatingsDict[s.ClientId].LastConnection).HumanizeForCurrentCulture(), - Name = clientRatingsDict[s.ClientId].Name, - Performance = Math.Round(clientRatingsDict[s.ClientId].Performance, 2), - RatingChange = ratingInfo.First(r => r.Key == s.ClientId).Ratings.First().Ranking - ratingInfo.First(r => r.Key == s.ClientId).Ratings.Last().Ranking, - PerformanceHistory = ratingInfo.First(r => r.Key == s.ClientId).Ratings.Count() > 1 ? - ratingInfo.First(r => r.Key == s.ClientId).Ratings.OrderBy(r => r.When).Select(r => r.Performance).ToList() : - new List() { clientRatingsDict[s.ClientId].Performance, clientRatingsDict[s.ClientId].Performance }, - TimePlayed = Math.Round(s.TotalTimePlayed / 3600.0, 1).ToString("#,##0"), - }) - .OrderByDescending(r => r.Performance) - .ToList(); + { + ClientId = s.ClientId, + Id = (int?) serverId ?? 0, + Deaths = s.Deaths, + Kills = s.Kills, + KDR = Math.Round(s.KDR, 2), + LastSeen = (DateTime.UtcNow - clientRatingsDict[s.ClientId].LastConnection) + .HumanizeForCurrentCulture(), + LastSeenValue = DateTime.UtcNow - clientRatingsDict[s.ClientId].LastConnection, + Name = clientRatingsDict[s.ClientId].Name, + Performance = Math.Round(clientRatingsDict[s.ClientId].Performance, 2), + RatingChange = ratingInfo.First(r => r.Key == s.ClientId).Ratings.First().Ranking - + ratingInfo.First(r => r.Key == s.ClientId).Ratings.Last().Ranking, + PerformanceHistory = ratingInfo.First(r => r.Key == s.ClientId).Ratings.Count() > 1 + ? ratingInfo.First(r => r.Key == s.ClientId).Ratings.OrderBy(r => r.When) + .Select(r => r.Performance).ToList() + : new List() + {clientRatingsDict[s.ClientId].Performance, clientRatingsDict[s.ClientId].Performance}, + TimePlayed = Math.Round(s.TotalTimePlayed / 3600.0, 1).ToString("#,##0"), + TimePlayedValue = TimeSpan.FromSeconds(s.TotalTimePlayed) + }) + .OrderByDescending(r => r.Performance) + .ToList(); // set the ranking numerically int i = start + 1; @@ -226,7 +346,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers Port = sv.Port, EndPoint = sv.ToString(), ServerId = serverId, - GameName = sv.GameName, + GameName = (Reference.Game?) sv.GameName, HostName = sv.Hostname }; @@ -236,9 +356,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } // we want to set the gamename up if it's never been set, or it changed - else if (!server.GameName.HasValue || server.GameName.HasValue && server.GameName.Value != sv.GameName) + else if (!server.GameName.HasValue || server.GameName.Value != (Reference.Game) sv.GameName) { - server.GameName = sv.GameName; + server.GameName = (Reference.Game) sv.GameName; ctx.Entry(server).Property(_prop => _prop.GameName).IsModified = true; ctx.SaveChanges(); } @@ -265,7 +385,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (Exception e) { - _log.LogError(e, "{message}", Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]); + _log.LogError(e, "{message}", + Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]); } } @@ -277,7 +398,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers public async Task AddPlayer(EFClient pl) { var existingStats = pl.GetAdditionalProperty(CLIENT_STATS_KEY); - + if (existingStats != null) { return existingStats; @@ -322,7 +443,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { Active = true, HitCount = 0, - Location = hl + Location = (int) hl }).ToList() }; @@ -342,7 +463,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { Active = true, HitCount = 0, - Location = hl + Location = (int) hl }) .ToList(); @@ -404,7 +525,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers return; } - long serverId = GetIdForServer(pl.CurrentServer); + var serverId = GetIdForServer(pl.CurrentServer); var serverStats = _servers[serverId].ServerStatistics; // get individual client's stats @@ -414,9 +535,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { clientStats = UpdateStats(clientStats); await SaveClientStats(clientStats); + if (_configHandler.Configuration().EnableAdvancedMetrics) + { + await UpdateHistoricalRanking(pl.ClientId, clientStats, serverId); + } // increment the total play time serverStats.TotalPlayTime += pl.ConnectionLength; + pl.SetAdditionalProperty(CLIENT_STATS_KEY, null); } else @@ -440,8 +566,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers /// Process stats for kill event /// /// - public async Task AddScriptHit(bool isDamage, DateTime time, EFClient attacker, EFClient victim, long serverId, string map, string hitLoc, string type, - string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, + public async Task AddScriptHit(bool isDamage, DateTime time, EFClient attacker, EFClient victim, long serverId, + string map, string hitLoc, string type, + string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, + string isKillstreakKill, string Ads, string fraction, string visibilityPercentage, string snapAngles, string isAlive, string lastAttackTime) { Vector3 vDeathOrigin = null; @@ -478,25 +606,26 @@ namespace IW4MAdmin.Plugins.Stats.Helpers ServerId = serverId, DeathOrigin = vDeathOrigin, KillOrigin = vKillOrigin, - DeathType = ParseEnum.Get(type, typeof(IW4Info.MeansOfDeath)), + DeathType = (int) ParseEnum.Get(type, typeof(IW4Info.MeansOfDeath)), Damage = int.Parse(damage), - HitLoc = ParseEnum.Get(hitLoc, typeof(IW4Info.HitLocation)), - Weapon = ParseEnum.Get(weapon, typeof(IW4Info.WeaponName)), + HitLoc = (int) ParseEnum.Get(hitLoc, typeof(IW4Info.HitLocation)), + Weapon = (int) ParseEnum.Get(weapon, typeof(IW4Info.WeaponName)), ViewAngles = vViewAngles, TimeOffset = long.Parse(offset), When = time, IsKillstreakKill = isKillstreakKill[0] != '0', AdsPercent = float.Parse(Ads, System.Globalization.CultureInfo.InvariantCulture), Fraction = double.Parse(fraction, System.Globalization.CultureInfo.InvariantCulture), - VisibilityPercentage = double.Parse(visibilityPercentage, System.Globalization.CultureInfo.InvariantCulture), + VisibilityPercentage = double.Parse(visibilityPercentage, + System.Globalization.CultureInfo.InvariantCulture), IsKill = !isDamage, AnglesList = snapshotAngles, IsAlive = isAlive == "1", TimeSinceLastAttack = long.Parse(lastAttackTime), - GameName = attacker.CurrentServer.GameName + GameName = (int) attacker.CurrentServer.GameName }; - if (hit.HitLoc == IW4Info.HitLocation.shield) + if (hit.HitLoc == (int) IW4Info.HitLocation.shield) { // we don't care about shield hits return; @@ -509,9 +638,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers await waiter.WaitAsync(Utilities.DefaultCommandTimeout, Plugin.ServerManager.CancellationToken); // increment their hit count - if (hit.DeathType == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET || - hit.DeathType == IW4Info.MeansOfDeath.MOD_RIFLE_BULLET || - hit.DeathType == IW4Info.MeansOfDeath.MOD_HEAD_SHOT) + if (hit.DeathType == (int) IW4Info.MeansOfDeath.MOD_PISTOL_BULLET || + hit.DeathType == (int) IW4Info.MeansOfDeath.MOD_RIFLE_BULLET || + hit.DeathType == (int) IW4Info.MeansOfDeath.MOD_HEAD_SHOT) { clientStats.HitLocations.First(hl => hl.Location == hit.HitLoc).HitCount += 1; } @@ -550,7 +679,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } } - if (Plugin.Config.Configuration().AnticheatConfiguration.Enable && !attacker.IsBot && attacker.ClientId != victim.ClientId) + if (Plugin.Config.Configuration().AnticheatConfiguration.Enable && !attacker.IsBot && + attacker.ClientId != victim.ClientId) { clientDetection.TrackedHits.Add(hit); @@ -573,7 +703,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers await ApplyPenalty(result, attacker); } - if (clientDetection.Tracker.HasChanges && result.ClientPenalty != EFPenalty.PenaltyType.Any) + if (clientDetection.Tracker.HasChanges && + result.ClientPenalty != EFPenalty.PenaltyType.Any) { await SaveTrackedSnapshots(clientDetection); @@ -590,10 +721,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } } - catch (TaskCanceledException) { } + catch (TaskCanceledException) + { + } catch (Exception ex) { - _log.LogError(ex, "Could not save hit or anti-cheat info {@attacker} {@victim} {server}", attacker, victim, serverId); + _log.LogError(ex, "Could not save hit or anti-cheat info {@attacker} {@victim} {server}", attacker, + victim, serverId); } finally @@ -605,16 +739,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } } - private DetectionPenaltyResult DeterminePenaltyResult(IEnumerable results, EFClient client) + private DetectionPenaltyResult DeterminePenaltyResult(IEnumerable results, + EFClient client) { // allow disabling of certain detection types results = results.Where(_result => ShouldUseDetection(client.CurrentServer, _result.Type, client.ClientId)); return results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Ban) ?? - results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Flag) ?? - new DetectionPenaltyResult() - { - ClientPenalty = EFPenalty.PenaltyType.Any, - }; + results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Flag) ?? + new DetectionPenaltyResult() + { + ClientPenalty = EFPenalty.PenaltyType.Any, + }; } public async Task SaveHitCache(long serverId) @@ -647,7 +782,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers catch (KeyNotFoundException) { - } return true; @@ -668,13 +802,16 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { new EFPenalty() { - AutomatedOffense = penalty.Type == Detection.DetectionType.Bone ? - $"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" : - $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}", + AutomatedOffense = penalty.Type == Detection.DetectionType.Bone + ? $"{penalty.Type}-{(int) penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" + : $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}", } }; - await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken); + await attacker + .Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], + penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, + attacker.CurrentServer.Manager.CancellationToken); break; case EFPenalty.PenaltyType.Flag: if (attacker.Level != EFClient.Permission.User) @@ -682,9 +819,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers break; } - string flagReason = penalty.Type == Cheat.Detection.DetectionType.Bone ? - $"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" : - $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}"; + string flagReason = penalty.Type == Cheat.Detection.DetectionType.Bone + ? $"{penalty.Type}-{(int) penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" + : $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}"; penaltyClient.AdministeredPenalties = new List() { @@ -694,7 +831,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } }; - await attacker.Flag(flagReason, penaltyClient, new TimeSpan(168, 0, 0)).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken); + await attacker.Flag(flagReason, penaltyClient, new TimeSpan(168, 0, 0)) + .WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken); break; } } @@ -708,6 +846,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { ctx.Add(change); } + await ctx.SaveChangesAsync(); } @@ -743,9 +882,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers victimStats.LastScore = victim.Score; // show encouragement/discouragement - string streakMessage = (attackerStats.ClientId != victimStats.ClientId) ? - StreakMessage.MessageOnStreak(attackerStats.KillStreak, attackerStats.DeathStreak) : - StreakMessage.MessageOnStreak(-1, -1); + string streakMessage = (attackerStats.ClientId != victimStats.ClientId) + ? StreakMessage.MessageOnStreak(attackerStats.KillStreak, attackerStats.DeathStreak) + : StreakMessage.MessageOnStreak(-1, -1); if (streakMessage != string.Empty) { @@ -768,15 +907,26 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } // update their performance - if ((DateTime.UtcNow - attackerStats.LastStatHistoryUpdate).TotalMinutes >= 2.5) + if ((DateTime.UtcNow - attackerStats.LastStatHistoryUpdate).TotalMinutes >= + (Utilities.IsDevelopment ? 0.5 : _configHandler.Configuration().EnableAdvancedMetrics ? 10.0 : 2.5)) { try { // kill event is not designated as blocking, so we should be able to enter and exit // we need to make this thread safe because we can potentially have kills qualify // for stat history update, but one is already processing that invalidates the original - await attackerStats.ProcessingHit.WaitAsync(Utilities.DefaultCommandTimeout, Plugin.ServerManager.CancellationToken); - await UpdateStatHistory(attacker, attackerStats); + await attackerStats.ProcessingHit.WaitAsync(Utilities.DefaultCommandTimeout, + Plugin.ServerManager.CancellationToken); + if (_configHandler.Configuration().EnableAdvancedMetrics) + { + await UpdateHistoricalRanking(attacker.ClientId, attackerStats, serverId); + } + + else + { + await UpdateStatHistory(attacker, attackerStats); + } + attackerStats.LastStatHistoryUpdate = DateTime.UtcNow; } @@ -796,14 +946,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } /// - /// Update the invidual and average stat history for a client + /// Update the individual and average stat history for a client /// /// client to update /// stats of client that is being updated /// public async Task UpdateStatHistory(EFClient client, EFClientStatistics clientStats) { - int currentSessionTime = (int)(DateTime.UtcNow - client.LastConnection).TotalSeconds; + int currentSessionTime = (int) (DateTime.UtcNow - client.LastConnection).TotalSeconds; // don't update their stat history if they haven't played long if (currentSessionTime < 60) @@ -816,18 +966,18 @@ namespace IW4MAdmin.Plugins.Stats.Helpers await using var ctx = _contextFactory.CreateContext(enableTracking: true); // select the rating history for client var iqHistoryLink = from history in ctx.Set() - .Include(h => h.Ratings) - where history.ClientId == client.ClientId - select history; + .Include(h => h.Ratings) + where history.ClientId == client.ClientId + select history; // get the client ratings var clientHistory = await iqHistoryLink .FirstOrDefaultAsync() ?? new EFClientRatingHistory() - { - Active = true, - ClientId = client.ClientId, - Ratings = new List() - }; + { + Active = true, + ClientId = client.ClientId, + Ratings = new List() + }; // it's the first time they've played if (clientHistory.RatingHistoryId == 0) @@ -836,13 +986,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } #region INDIVIDUAL_SERVER_PERFORMANCE + // get the client ranking for the current server int individualClientRanking = await ctx.Set() - .Where(GetRankingFunc(clientStats.ServerId)) - // ignore themselves in the query - .Where(c => c.RatingHistory.ClientId != client.ClientId) - .Where(c => c.Performance > clientStats.Performance) - .CountAsync() + 1; + .Where(GetRankingFunc(clientStats.ServerId)) + // ignore themselves in the query + .Where(c => c.RatingHistory.ClientId != client.ClientId) + .Where(c => c.Performance > clientStats.Performance) + .CountAsync() + 1; // limit max history per server to 40 if (clientHistory.Ratings.Count(r => r.ServerId == clientStats.ServerId) >= 40) @@ -887,16 +1038,18 @@ namespace IW4MAdmin.Plugins.Stats.Helpers ctx.Add(newServerRating); #endregion + #region OVERALL_RATING + // select all performance & time played for current client var iqClientStats = from stats in ctx.Set() - where stats.ClientId == client.ClientId - where stats.ServerId != clientStats.ServerId - select new - { - stats.Performance, - stats.TimePlayed - }; + where stats.ClientId == client.ClientId + where stats.ServerId != clientStats.ServerId + select new + { + stats.Performance, + stats.TimePlayed + }; var clientStatsList = await iqClientStats.ToListAsync(); @@ -908,7 +1061,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers }); // weight the overall performance based on play time - double performanceAverage = clientStatsList.Sum(p => (p.Performance * p.TimePlayed)) / clientStatsList.Sum(p => p.TimePlayed); + double performanceAverage = clientStatsList.Sum(p => (p.Performance * p.TimePlayed)) / + clientStatsList.Sum(p => p.TimePlayed); // shouldn't happen but just in case the sum of time played is 0 if (double.IsNaN(performanceAverage)) @@ -917,10 +1071,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } int overallClientRanking = await ctx.Set() - .Where(GetRankingFunc()) - .Where(r => r.RatingHistory.ClientId != client.ClientId) - .Where(r => r.Performance > performanceAverage) - .CountAsync() + 1; + .Where(GetRankingFunc()) + .Where(r => r.RatingHistory.ClientId != client.ClientId) + .Where(r => r.Performance > performanceAverage) + .CountAsync() + 1; // limit max average history to 40 if (clientHistory.Ratings.Count(r => r.ServerId == null) >= 40) @@ -962,11 +1116,112 @@ namespace IW4MAdmin.Plugins.Stats.Helpers }; ctx.Add(averageRating); + #endregion await ctx.SaveChangesAsync(); } + public async Task UpdateHistoricalRanking(int clientId, EFClientStatistics clientStats, long serverId) + { + await using var context = _contextFactory.CreateContext(); + + var performances = await context.Set() + .AsNoTracking() + .Where(stat => stat.ClientId == clientId) + .Where(stat => stat.ServerId != serverId) // ignore the one we're currently tracking + .Where(stats => stats.UpdatedAt >= Extensions.FifteenDaysAgo()) + .Where(stats => stats.TimePlayed >= _configHandler.Configuration().TopPlayersMinPlayTime) + .ToListAsync(); + + if (clientStats.TimePlayed >= _configHandler.Configuration().TopPlayersMinPlayTime) + { + clientStats.ZScore = await _serverDistributionCalculator.GetZScoreForServer(serverId, + clientStats.Performance); + + var serverRanking = await context.Set() + .Where(stats => stats.ClientId != clientStats.ClientId) + .Where(AdvancedClientStatsResourceQueryHelper.GetRankingFunc( + _configHandler.Configuration().TopPlayersMinPlayTime, clientStats.ZScore, serverId)) + .CountAsync(); + + var serverRankingSnapshot = new EFClientRankingHistory() + { + ClientId = clientId, + ServerId = serverId, + ZScore = clientStats.ZScore, + Ranking = serverRanking, + PerformanceMetric = clientStats.Performance, + Newest = true + }; + + context.Add(serverRankingSnapshot); + await PruneOldRankings(context, clientId, serverId); + await context.SaveChangesAsync(); + + performances.Add(clientStats); + } + + if (performances.Any(performance => performance.TimePlayed >= _configHandler.Configuration().TopPlayersMinPlayTime)) + { + var aggregateZScore = performances.WeightValueByPlaytime(nameof(EFClientStatistics.ZScore), _configHandler.Configuration().TopPlayersMinPlayTime); + + int? aggregateRanking = await context.Set() + .Where(stat => stat.ClientId != clientId) + .Where(AdvancedClientStatsResourceQueryHelper.GetRankingFunc(_configHandler.Configuration() + .TopPlayersMinPlayTime)) + .GroupBy(stat => stat.ClientId) + .Where(group => + group.Sum(stat => stat.ZScore * stat.TimePlayed) / group.Sum(stat => stat.TimePlayed) > + aggregateZScore) + .Select(c => c.Key) + .CountAsync(); + + var aggregateRankingSnapshot = new EFClientRankingHistory() + { + ClientId = clientId, + ZScore = aggregateZScore, + Ranking = aggregateRanking, + PerformanceMetric = await _serverDistributionCalculator.GetRatingForZScore(aggregateZScore), + Newest = true, + }; + + context.Add(aggregateRankingSnapshot); + + await PruneOldRankings(context, clientId); + await context.SaveChangesAsync(); + } + } + + private async Task PruneOldRankings(DatabaseContext context, int clientId, long? serverId = null) + { + var totalRankingEntries = await context.Set() + .Where(r => r.ClientId == clientId) + .Where(r => r.ServerId == serverId) + .CountAsync(); + + var mostRecent = await context.Set() + .Where(r => r.ClientId == clientId) + .Where(r => r.ServerId == serverId) + .FirstOrDefaultAsync(r => r.Newest); + + if (mostRecent != null) + { + mostRecent.Newest = false; + context.Update(mostRecent); + } + + if (totalRankingEntries > EFClientRankingHistory.MaxRankingCount) + { + var lastRating = await context.Set() + .Where(r => r.ClientId == clientId) + .Where(r => r.ServerId == serverId) + .OrderBy(r => r.CreatedDateTime) + .FirstOrDefaultAsync(); + context.Remove(lastRating); + } + } + /// /// Performs the incrementation of kills and deaths for client statistics /// @@ -994,6 +1249,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers attackerStats = UpdateStats(attackerStats); #region DEPRECATED + /* var validAttackerLobbyRatings = Servers[attackerStats.ServerId].PlayerStats .Where(cs => cs.Value.ClientId != attackerStats.ClientId) .Where(cs => @@ -1017,10 +1273,12 @@ namespace IW4MAdmin.Plugins.Stats.Helpers double victimLobbyRating = validVictimLobbyRatings.Count() > 0 ? validVictimLobbyRatings.Average(cs => cs.Value.EloRating) : victimStats.EloRating;*/ + #endregion // calculate elo - double attackerEloDifference = Math.Log(Math.Max(1, victimStats.EloRating)) - Math.Log(Math.Max(1, attackerStats.EloRating)); + double attackerEloDifference = Math.Log(Math.Max(1, victimStats.EloRating)) - + Math.Log(Math.Max(1, attackerStats.EloRating)); double winPercentage = 1.0 / (1 + Math.Pow(10, attackerEloDifference / Math.E)); // double victimEloDifference = Math.Log(Math.Max(1, attackerStats.EloRating)) - Math.Log(Math.Max(1, victimStats.EloRating)); @@ -1033,8 +1291,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers victimStats.EloRating = Math.Max(0, Math.Round(victimStats.EloRating, 2)); // update after calculation - attackerStats.TimePlayed += (int)(DateTime.UtcNow - attackerStats.LastActive).TotalSeconds; - victimStats.TimePlayed += (int)(DateTime.UtcNow - victimStats.LastActive).TotalSeconds; + attackerStats.TimePlayed += (int) (DateTime.UtcNow - attackerStats.LastActive).TotalSeconds; + victimStats.TimePlayed += (int) (DateTime.UtcNow - victimStats.LastActive).TotalSeconds; attackerStats.LastActive = DateTime.UtcNow; victimStats.LastActive = DateTime.UtcNow; } @@ -1072,7 +1330,12 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } double killSPM = scoreDifference / timeSinceLastCalc; - double spmMultiplier = 2.934 * Math.Pow(_servers[clientStats.ServerId].TeamCount(clientStats.Team == IW4Info.Team.Allies ? IW4Info.Team.Axis : IW4Info.Team.Allies), -0.454); + double spmMultiplier = 2.934 * + Math.Pow( + _servers[clientStats.ServerId] + .TeamCount((IW4Info.Team) clientStats.Team == IW4Info.Team.Allies + ? IW4Info.Team.Axis + : IW4Info.Team.Allies), -0.454); killSPM *= Math.Max(1, spmMultiplier); // update this for ac tracking @@ -1080,15 +1343,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers // calculate how much the KDR should weigh // 1.637 is a Eddie-Generated number that weights the KDR nicely - double currentKDR = clientStats.SessionDeaths == 0 ? clientStats.SessionKills : clientStats.SessionKills / clientStats.SessionDeaths; + double currentKDR = clientStats.SessionDeaths == 0 + ? clientStats.SessionKills + : clientStats.SessionKills / clientStats.SessionDeaths; double alpha = Math.Sqrt(2) / Math.Min(600, Math.Max(clientStats.Kills + clientStats.Deaths, 1)); clientStats.RollingWeightedKDR = (alpha * currentKDR) + (1.0 - alpha) * clientStats.KDR; double KDRWeight = Math.Round(Math.Pow(clientStats.RollingWeightedKDR, 1.637 / Math.E), 3); // calculate the weight of the new play time against last 10 hours of gameplay - int totalPlayTime = (clientStats.TimePlayed == 0) ? - (int)(DateTime.UtcNow - clientStats.LastActive).TotalSeconds : - clientStats.TimePlayed + (int)(DateTime.UtcNow - clientStats.LastActive).TotalSeconds; + int totalPlayTime = (clientStats.TimePlayed == 0) + ? (int) (DateTime.UtcNow - clientStats.LastActive).TotalSeconds + : clientStats.TimePlayed + (int) (DateTime.UtcNow - clientStats.LastActive).TotalSeconds; double SPMAgainstPlayWeight = timeSinceLastCalc / Math.Min(600, (totalPlayTime / 60.0)); @@ -1107,13 +1372,15 @@ namespace IW4MAdmin.Plugins.Stats.Helpers // fixme: how does this happen? if (double.IsNaN(clientStats.SPM) || double.IsNaN(clientStats.Skill)) { - _log.LogWarning("clientStats SPM/Skill NaN {@killInfo}", new {killSPM, KDRWeight, totalPlayTime, SPMAgainstPlayWeight, clientStats, scoreDifference}); + _log.LogWarning("clientStats SPM/Skill NaN {@killInfo}", + new {killSPM, KDRWeight, totalPlayTime, SPMAgainstPlayWeight, clientStats, scoreDifference}); clientStats.SPM = 0; clientStats.Skill = 0; } clientStats.LastStatCalculation = DateTime.UtcNow; //clientStats.LastScore = clientStats.SessionScore; + clientStats.UpdatedAt = DateTime.UtcNow; return clientStats; } @@ -1161,13 +1428,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers public void ResetStats(EFClient client) { var stats = client.GetAdditionalProperty(CLIENT_STATS_KEY); - + // the cached stats have not been loaded yet if (stats == null) { return; } - + stats.Kills = 0; stats.Deaths = 0; stats.SPM = 0; @@ -1253,8 +1520,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers long? serverId; serverId = serverModels.FirstOrDefault(_server => _server.ServerId == server.EndPoint || - _server.EndPoint == server.ToString() || - _server.ServerId == id)?.ServerId; + _server.EndPoint == server.ToString() || + _server.ServerId == id)?.ServerId; if (!serverId.HasValue) { @@ -1264,4 +1531,4 @@ namespace IW4MAdmin.Plugins.Stats.Helpers return serverId.Value; } } -} +} \ No newline at end of file diff --git a/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs b/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs index 219f671e..165f12de 100644 --- a/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs +++ b/Plugins/Stats/Helpers/StatsResourceQueryHelper.cs @@ -1,11 +1,12 @@ -using IW4MAdmin.Plugins.Stats.Models; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using Stats.Dtos; using System; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client.Stats; namespace Stats.Helpers { @@ -48,7 +49,7 @@ namespace Stats.Helpers ServerId = _stats.ServerId, Kills = _stats.Kills, Deaths = _stats.Deaths, - Performance = Math.Round((_stats.EloRating + _stats.Skill) / 2.0, 2), + Performance = Math.Round(_stats.EloRating * 1/3.0 + _stats.Skill * 2/3.0, 2), ScorePerMinute = _stats.SPM, LastPlayed = _stats.Client.LastConnection, TotalSecondsPlayed = _stats.TimePlayed, diff --git a/Plugins/Stats/Helpers/WeaponNameExtensions.cs b/Plugins/Stats/Helpers/WeaponNameExtensions.cs new file mode 100644 index 00000000..76da43b0 --- /dev/null +++ b/Plugins/Stats/Helpers/WeaponNameExtensions.cs @@ -0,0 +1,10 @@ +using Data.Models.Client.Stats; + +namespace Stats.Helpers +{ + public static class WeaponNameExtensions + { + public static string RebuildWeaponName(this EFClientHitStatistic stat) => + $"{stat.Weapon?.Name}{string.Join("_", stat.WeaponAttachmentCombo?.Attachment1?.Name, stat.WeaponAttachmentCombo?.Attachment2?.Name, stat.WeaponAttachmentCombo?.Attachment3?.Name)}"; + } +} \ No newline at end of file diff --git a/Plugins/Stats/Models/ModelConfiguration.cs b/Plugins/Stats/Models/ModelConfiguration.cs deleted file mode 100644 index b2427afc..00000000 --- a/Plugins/Stats/Models/ModelConfiguration.cs +++ /dev/null @@ -1,43 +0,0 @@ -using IW4MAdmin.Plugins.Stats.Models; -using Microsoft.EntityFrameworkCore; -using SharedLibraryCore.Interfaces; - -namespace Stats.Models -{ - public class ModelConfiguration : IModelConfiguration - { - public void Configure(ModelBuilder builder) - { - builder.Entity() - .HasKey(cs => new { cs.ClientId, cs.ServerId }); - - // fix linking from SQLCe - builder.Entity() - .Property(c => c.EFClientStatisticsClientId) - .HasColumnName("EFClientStatisticsClientId"); - - builder.Entity() - .Property(c => c.EFClientStatisticsServerId) - .HasColumnName("EFClientStatisticsServerId"); - - builder.Entity() - .HasIndex(p => new { p.Performance, p.Ranking, p.When }); - - builder.Entity() - .HasIndex(p => new { p.When, p.ServerId, p.Performance, p.ActivityAmount }); - - builder.Entity(message => - { - message.HasIndex(p => p.TimeSent); - }); - - // force pluralization - builder.Entity().ToTable("EFClientKills"); - builder.Entity().ToTable("EFClientMessages"); - builder.Entity().ToTable("EFClientStatistics"); - builder.Entity().ToTable("EFHitLocationCounts"); - builder.Entity().ToTable("EFServers"); - builder.Entity().ToTable("EFServerStatistics"); - } - } -} diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index d21e613a..fe6456f4 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -1,10 +1,7 @@ using IW4MAdmin.Plugins.Stats.Config; using IW4MAdmin.Plugins.Stats.Helpers; -using IW4MAdmin.Plugins.Stats.Models; using Microsoft.EntityFrameworkCore; using SharedLibraryCore; -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; @@ -14,8 +11,16 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client; +using Data.Models.Client.Stats; +using Data.Models.Server; +using Humanizer; using Microsoft.Extensions.Logging; using SharedLibraryCore.Commands; +using IW4MAdmin.Plugins.Stats.Client.Abstractions; +using Stats.Client.Abstractions; +using EFClient = SharedLibraryCore.Database.Models.EFClient; namespace IW4MAdmin.Plugins.Stats { @@ -37,9 +42,12 @@ namespace IW4MAdmin.Plugins.Stats private readonly IResourceQueryHelper _chatQueryHelper; private readonly ILogger _managerLogger; private readonly ILogger _logger; + private readonly List _statCalculators; + private readonly IServerDistributionCalculator _serverDistributionCalculator; public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory databaseContextFactory, - ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper chatQueryHelper, ILogger managerLogger) + ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper chatQueryHelper, ILogger managerLogger, + IEnumerable statCalculators, IServerDistributionCalculator serverDistributionCalculator) { Config = configurationHandlerFactory.GetConfigurationHandler("StatsPluginSettings"); _databaseContextFactory = databaseContextFactory; @@ -48,6 +56,8 @@ namespace IW4MAdmin.Plugins.Stats _chatQueryHelper = chatQueryHelper; _managerLogger = managerLogger; _logger = logger; + _statCalculators = statCalculators.ToList(); + _serverDistributionCalculator = serverDistributionCalculator; } public async Task OnEventAsync(GameEvent E, Server S) @@ -149,6 +159,16 @@ namespace IW4MAdmin.Plugins.Stats } break; } + + if (!Config.Configuration().EnableAdvancedMetrics) + { + return; + } + + foreach (var calculator in _statCalculators) + { + await calculator.CalculateForEvent(E); + } } public async Task OnLoadAsync(IManager manager) @@ -267,20 +287,20 @@ namespace IW4MAdmin.Plugins.Stats if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null) { chestRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => - c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / + c.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_upper).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) - .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); + .Sum(c => c.HitLocations.Where(hl => hl.Location != (int)IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); abdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => - c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount) / - (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); + c.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_lower).HitCount) / + (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != (int)IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); - chestAbdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) / - (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount)) * 100.0, 0); + chestAbdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_upper).HitCount) / + (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_lower).HitCount)) * 100.0, 0); - headRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.head).HitCount) / + headRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.head).HitCount) / (double)clientStats.Where(c => c.HitLocations.Count > 0) - .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); + .Sum(c => c.HitLocations.Where(hl => hl.Location != (int)IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); var validOffsets = clientStats.Where(c => c.HitLocations.Count(hl => hl.HitCount > 0) > 0).SelectMany(hl => hl.HitLocations); hitOffsetAverage = validOffsets.Sum(o => o.HitCount * o.HitOffsetAverage) / (double)validOffsets.Sum(o => o.HitCount); @@ -402,7 +422,7 @@ namespace IW4MAdmin.Plugins.Stats async Task topStats(Server s) { // todo: this needs to needs to be updated when we DI the lookup - return string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s, Utilities.CurrentLocalization.LocalizationIndex, _databaseContextFactory)); + return string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s, Utilities.CurrentLocalization.LocalizationIndex)); } async Task mostPlayed(Server s) @@ -423,8 +443,17 @@ namespace IW4MAdmin.Plugins.Stats manager.GetMessageTokens().Add(new MessageToken("MOSTPLAYED", mostPlayed)); manager.GetMessageTokens().Add(new MessageToken("MOSTKILLS", mostKills)); + if (Config.Configuration().EnableAdvancedMetrics) + { + foreach (var calculator in _statCalculators) + { + await calculator.GatherDependencies(); + } + } + ServerManager = manager; - Manager = new StatManager(_managerLogger, manager, _databaseContextFactory, Config); + Manager = new StatManager(_managerLogger, manager, _databaseContextFactory, Config, _serverDistributionCalculator); + await _serverDistributionCalculator.Initialize(); } public Task OnTickAsync(Server S) diff --git a/Plugins/Stats/Stats.csproj b/Plugins/Stats/Stats.csproj index 79344a62..1dd2a9c9 100644 --- a/Plugins/Stats/Stats.csproj +++ b/Plugins/Stats/Stats.csproj @@ -15,9 +15,9 @@ 8.0 false - + - + diff --git a/Plugins/Web/StatsWeb/Extensions/SearchQueryExtensions.cs b/Plugins/Web/StatsWeb/Extensions/SearchQueryExtensions.cs deleted file mode 100644 index bde74b82..00000000 --- a/Plugins/Web/StatsWeb/Extensions/SearchQueryExtensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -using SharedLibraryCore.Dtos; -using Stats.Dtos; -using System; -using System.Linq; - -namespace StatsWeb.Extensions -{ - public static class SearchQueryExtensions - { - private const int MAX_MESSAGES = 100; - - /// - /// todo: lets abstract this out to a generic buildable query - /// this is just a dirty PoC - /// - /// - /// - public static ChatSearchQuery ParseSearchInfo(this string query, int count, int offset) - { - string[] filters = query.Split('|'); - var searchRequest = new ChatSearchQuery - { - Filter = query, - Count = count, - Offset = offset - }; - - // sanity checks - searchRequest.Count = Math.Min(searchRequest.Count, MAX_MESSAGES); - searchRequest.Count = Math.Max(searchRequest.Count, 0); - searchRequest.Offset = Math.Max(searchRequest.Offset, 0); - - if (filters.Length > 1) - { - if (filters[0].ToLower() != "chat") - { - throw new ArgumentException("Query is not compatible with chat"); - } - - foreach (string filter in filters.Skip(1)) - { - string[] args = filter.Split(' '); - - if (args.Length > 1) - { - string recombinedArgs = string.Join(' ', args.Skip(1)); - switch (args[0].ToLower()) - { - case "before": - searchRequest.SentBefore = DateTime.Parse(recombinedArgs); - break; - case "after": - searchRequest.SentAfter = DateTime.Parse(recombinedArgs); - break; - case "server": - searchRequest.ServerId = args[1]; - break; - case "client": - searchRequest.ClientId = int.Parse(args[1]); - break; - case "contains": - searchRequest.MessageContains = string.Join(' ', args.Skip(1)); - break; - case "sort": - searchRequest.Direction = Enum.Parse(args[1], ignoreCase: true); - break; - } - } - } - - return searchRequest; - } - - throw new ArgumentException("No filters specified for chat search"); - } - } -} diff --git a/Plugins/Web/StatsWeb/StatsWeb.csproj b/Plugins/Web/StatsWeb/StatsWeb.csproj deleted file mode 100644 index 65b5a055..00000000 --- a/Plugins/Web/StatsWeb/StatsWeb.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - netcoreapp3.1 - true - true - false - false - true - Debug;Release;Prerelease - 8.0 - - Library - - Always - - - - - - - - false - - - - - - Never - - - - - - - diff --git a/Plugins/Web/StatsWeb/ViewComponents/TopPlayersViewComponent.cs b/Plugins/Web/StatsWeb/ViewComponents/TopPlayersViewComponent.cs deleted file mode 100644 index d6951bc0..00000000 --- a/Plugins/Web/StatsWeb/ViewComponents/TopPlayersViewComponent.cs +++ /dev/null @@ -1,28 +0,0 @@ -using IW4MAdmin.Plugins.Stats; -using IW4MAdmin.Plugins.Stats.Helpers; -using Microsoft.AspNetCore.Mvc; -using System.Linq; -using System.Threading.Tasks; - -namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers -{ - public class TopPlayersViewComponent : ViewComponent - { - public async Task InvokeAsync(int count, int offset, long? serverId = null) - { - if (serverId == 0) - { - serverId = null; - } - - var server = Plugin.ServerManager.GetServers().FirstOrDefault(_server => _server.EndPoint == serverId); - - if (server != null) - { - serverId = StatManager.GetIdForServer(server); - } - - return View("_List", await Plugin.Manager.GetTopStats(offset, count, serverId)); - } - } -} diff --git a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml b/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml deleted file mode 100644 index b747b6fc..00000000 --- a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml +++ /dev/null @@ -1,91 +0,0 @@ -@model List -@{ - Layout = null; - var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex.Set; - double getDeviation(double deviations) => Math.Pow(Math.E, 5.259 + (deviations * 0.812)); - string rankIcon(double elo) - { - if (elo >= getDeviation(-0.75) && elo < getDeviation(1.25)) - { - return "0_no-place/menu_div_no_place.png"; - } - if (elo >= getDeviation(0.125) && elo < getDeviation(0.625)) - { - return "1_iron/menu_div_iron_sub03.png"; - } - if (elo >= getDeviation(0.625) && elo < getDeviation(1.0)) - { - return "2_bronze/menu_div_bronze_sub03.png"; - } - if (elo >= getDeviation(1.0) && elo < getDeviation(1.25)) - { - return "3_silver/menu_div_silver_sub03.png"; - } - if (elo >= getDeviation(1.25) && elo < getDeviation(1.5)) - { - return "4_gold/menu_div_gold_sub03.png"; - } - if (elo >= getDeviation(1.5) && elo < getDeviation(1.75)) - { - return "5_platinum/menu_div_platinum_sub03.png"; - } - if (elo >= getDeviation(1.75) && elo < getDeviation(2.0)) - { - return "6_semipro/menu_div_semipro_sub03.png"; - } - if (elo >= getDeviation(2.0)) - { - return "7_pro/menu_div_pro_sub03.png"; - } - - return "0_no-place/menu_div_no_place.png"; - } -} - -@if (Model.Count == 0) -{ -
@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_NOQUALIFY"]
-} -@foreach (var stat in Model) -{ -
-
-
-
#@stat.Ranking
- @if (stat.RatingChange > 0) - { -
-
-
@stat.RatingChange
-
- } - @if (stat.RatingChange < 0) - { -
-
@Math.Abs(stat.RatingChange)
-
-
- } - - - - -
- - @stat.Performance @loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"]
- @stat.KDR @loc["PLUGINS_STATS_TEXT_KDR"] - @stat.Kills @loc["PLUGINS_STATS_TEXT_KILLS"] - @stat.Deaths @loc["PLUGINS_STATS_TEXT_DEATHS"]
- @loc["WEBFRONT_PROFILE_PLAYER"] @stat.TimePlayed @loc["GLOBAL_TIME_HOURS"]
- @loc["WEBFRONT_PROFILE_LSEEN"] @stat.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] -
- -
- -
- -
- -
-
-} diff --git a/Plugins/Web/StatsWeb/Views/_ViewImports.cshtml b/Plugins/Web/StatsWeb/Views/_ViewImports.cshtml deleted file mode 100644 index 1ba5217d..00000000 --- a/Plugins/Web/StatsWeb/Views/_ViewImports.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@using SharedLibraryCore -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@addTagHelper *, SharedLibraryCore \ No newline at end of file diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/0_no-place/menu_div_no_place.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/0_no-place/menu_div_no_place.png deleted file mode 100644 index cc9e0e56fbdd121bc52b912e8453991f23510560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12836 zcmXY21ymc)*WHBR7Th5~ky3tmu|f!5plE>t#ogUCcyWpsTC{la;uZ=;3ME+4A}z%V z6nFdbKj+JNyKj@s?#?9h-pt&4H%?1KnV5i{0001DmFEgN7?1qlhKGaM_ronlF%DuU zt1b%w4Jm}T7TB2gFstV}>HrYPi76Ka0N4L3zYPFB0s!#W8~`M90D#8*eTTLb<_jE4 zHDv{i$GooOJHs#z-~G9v7XT2F|8E0LEr;F$fZ!Vy1zBDH#r=@obcVUi)w+W1e4IeQ z5(o0;SL#|~Oz{hqvSMY!7VA3a8k-sumG{=^x{U!dvt`E;Vg35|k$*;KXE}Y}hv?Zj z`MCt_FY7rwvDeK}JB)m;pi7GoXN1DUVFEzlb+OrS>{6>4V2cdU%J?MwBRXHHgyrJ) zU%;{#8XI1uxlM5$1urtw{>{AB?f($^1*_*kIY}zai)G+DGlYF$_&z>OUt_4p2gS0x z{DD3A+6tzqZTa9Q`Qbl6j4k%lde?(suj%_NH1EUK>h=D^DZeGIx)&!j&Co4y0MH`w z&5Zk4<+%6ocmMj|!NW?}4L{K1H_)29d6t~1k2$Nit0A<8@tLYE*5%mpuQwnVi$@8! zBco1ZRf(tT+31f8x1S2e+Y9!dA0l;rydsc#Bfjjp=LH{ihv$P2aPm(<=HjM%)_ytlAyLu~ zOiwe@xEN=@ypdtvyZcw*JZW)j7X5P2^e}iss_NjC#i^ugyKybhhF6Ghev|4}&m}E@ zU$1K#7`6z*nOuC?&nseFDWF2^TTFD*6%XkP#t}LI8(p9+vvpwepbW) z6+avge;}|?LE=iU4%_n7#%-IpvcIXJ$>qd>H5(r9svkTVpCewG-I4Pdw;@Nf!<54M zzDDclY;|b-Bsx|4!h!Gb&RlD1(49inc=NX}JZJ@(rs4GaTBR4h@TK z?X}F;jZvBYsdst+Dk)EFP?Xza{Xlcfdh7WmK0Xeaotumt+4=>8g*}+mS}e5Nxd$rK zM_f?nSsS6zi3POzpRw_ocD+$8jc{z1JU8@Q_?eKTWCcQXV>RDXdjAwflB~54s3q;0 z1?-j&-O>)JRX?dVFfnAhG1)M-`F&7p+8u8!8fz>{14L?fPAiq_NMNlstOuX3Ll6Wg zIZRbur|>gXZDK}4ZY!4^xJbY6o?IsY)G539Uw-imp68DFTybei-4FB%6UqM;C#lpW zh=R@>%&^9h>yOtIE-%LL;=404Ty%zrL)SdOj0p%z#Xp`B&?T$}6YD8@2$2N^SX~cB z2!2r#`zb$$EdkaUVqb-0m|;QcjKUI8k92vdCYSc;c?2ZLd}w@HmpHd7e2=`Mia<}# zVo6k5hNI7e$pDLR$C*C4Khl6tC>KX1L-qy5V-D=4mS5r|n=_Od8IT|ZObslRg4GZU z@XKZ@9@2i9e<~=G9ijdr=e~(91|)~4!IzJ8dHGCsP0C>4gYeC!S$tO;`!U;r|M*)H za;9>Kc=mT2GzgE;OeHOXe{@6W+s3hMEg_J)F(PZ|Td;jcqN<}BA0niqlYY=U*OXN9 zWu$ExmhjnZu_d8&T5St>|Lip3MWIzQ$dk*{tnt$XUT(9+pPBpcIl~;r?yyt8CO|0( zkX0EeQTh$yCIFUvSydORsD=a;p8l!n}-r<2%6?&QWF)oqG z&p2yCUM2ZaeFo+7IXez`)Ppra4u%aBcIn=eC#w)JN&uAFDpyOdsARRfig4YwWuXwL zT*dlh@Kpfu$5q(^0|6$KH!z1~4boDOe9m^rNU0dkLpW?x!D;crPFfQRsc0n7(=XyC zkV;ueaA6#hg+{HlN}=VoDe)qJIiJXomiAggS!l$1)knEC2p;1yOCTSm;CYXhbr=N| z66=w6@xchIf9Q`PK!y@vfDM3Isd?oJOCMQp`2Z-_Fd8Iy4jZC@-0kq((cRGoA9I5w zx-_1-0+-&k-c_fie`Kw)2ZdFmzv$Aa#J^J1j&LDYN&8%06&EU|!I5|a50nuN%nl~8 zN&e?lg`<8XrnhtwQtTa?grnAZ#|I!ZcSm0KL|GMDVIdlH8OaP|R6ttBKN*0AnB~Y{ zdu?etg^3L`))F(5BTk7;pyFNzzdDsU%Q3rxo9^k*0R*&k<5)--Cq=~H&lq?^_unGp zKK=`EB747p`+J4wQkFx;{T`H0jfd{w0X1uv|Hc*w1dU#o^nEm~6FXk^47joZo{0Z` zpHYH?BqDpV5WSba28)Qam!M86xDh=4wnHE#le@If;BG<_m5R{B`WznHZ&B}-YkMfe zI3ehZ3&U}7|D6gO*zMqZF&(wr(GUXAlEn6Tv@`?>&|h?K$q2AQYS-nU*w>87VQzBZ zn?YY^Xl%aSGvC9mC@2bK9EvwBXd%h>Vkp|BQ=kLqkw)QtFP^swO?)vT%Vzkop>y0H|U-3Rm%|o+3D^LuIRcb%=Hs)^}R6FMxynK6tGOO(hP$B4Y zuZ>^w8I$!^6E{ue{lR&;Q&-$?U#Jit0c@~Mg>9u}Um6`J^lZd`w9z~VhsbguhXwns zLvG(mP8l5*FI{R}Rc({}Sty_Ukn&>p+j;?NPeL@{|EK;%{FF8rfs;CF+flomb93l(Wi!1)fD>2Iagmd@rbK^!ELuc%fh!)d=o(neT3-YTEdzA8+G=HMBGA zJfd{g4gqMS3@Mw&t8sn4>$wfkA>UT9leYyq#XD!50hat`6V#axdjoF=8F*zPWC6dFF4s)FSH)p7yjb;(MdMMhyBLg%SyJ$!Q^+_WjjCqN>J`L9IID z3l;pmOnDq#PNi+ArJ$&#urXmJp3w zB?$!sc=EktR3g4fJALNr1!Pn<`lo)=LLPNDi!IVex#=^wbOwT(d6C0zoXBDW9x(7X z>3Y~Nbl4wTSwWcqX<6yt!eCKV>ma)qw)j>i$Q-A8l|D6YY&E4Q{bQ8PYxWzJe*VQ> zQqKpK-Z&wtkzh{jze$p+Uv=EOrgsz5!M(}s;JzYI;hXqBZkm6l+F$aX_qtnxpn9K; z{;P;5(9@Z8Y*7mKvLwqHK&lWy6OdcLoRG4&*mU2>cVCybe8Rbs8XymDEYkdr6at;FE8a4PK}*sG@h=mRV?juHWD&0G^HpqlQrbWmq@IbiWxbDq0E!r* zr=~d;h{G>&LrjY}u1-jS8nk%d$G%a9!KFNqnZfXfjqPx`9;9u;=54lS()qo^r%eww z|M$`G$|0Q9*XgB*G=mAQ_TKEI`njX--*~dG_hL**N`%WD@?2b9z(AHJf2_-E?oYqp z>>=5)P;#NHP!(($!8DM0B_+#sQio4Ey(|B#J=is4VWMUP>opUWk}mjBfrCt^Wv{s0 zC#G`&qU`K*WbO_*=6DS4 zjuZ!%sQ2E{PFEkKXfR8J-QN-dtio)O9m}%@ z5?EMnK0LkZNDsXGyv2DSrp{>5dyz0DezRT5KPhSr7(DBxz6+Gq&fqE!trQe_1}Gf9 z-S-Zt?3(@89PpUqXu&wfjGGSy6B)XDx0PR1V%hCmpLBVI#UOgr+UH-A*lv|hOWVwf z)aq?w&ZpdcF_e-(_=rQ{)W})pub_gg07>e|1yh4l3?J`Y#Dh_$w3+{SS`znsE-9|)#VP{YfQd#`G9MFgzH z%3QMoYbX4n%yXduKAQ;|CBj_o&g--SPm<;d$+Y%3EJ&{T((Ui)T{>w@gDrkbWaqbe zSLC29fch?D(`4d1{jBVxNS1p5uz>?zK|a2KfMrs4;)Hs2(}m@ulJ%*F^c5Rw$1C3- zTX4<1t0b20@V}e36O&bWd4LZ#DI+zU7s$GcMc4#LoNv&;AFu)1x4=zOGt1zim3OMC z%#P&xm;Tt&I~0nRRI5yx1L1Qr`}}pbMph5ekvS}f4v4R)-ye}{KjeO9YG|tH)0FJT z_W)`C9D(k=WLyb8@o|3-BvVZ6P`ESZ9aF~r=#O5PaF@d6`wf@kKNM6_ICG!!vl}vC zM0xGp0_O~9CYc)e=2j5j8mM-Cs-5WmB>C*(&IzXhe@OC5^|EdboWF`xyCmmQyk$Vu(2;(Gwl6YsxKCh8W=~PU}zf*21qh zlGKa;djDjUN>{A1^!oM$jRl0>KCDEgrI|C!*5ya%7!>H4vCw?~y{K`0U&?>Y`~&B# zg74GhrE1fHLXnm@?pgwFKuaXpywrdPhpoJE@1_b4z)uVbkYcOB!sqN>@kdt`8Y?N` z%9d*!>-YK6z6BqijVFuaeYd3Oy1(A_-zgQ~#!P%TSRklGDd|LrLCtCrKH=mFsTO{! z^}X!l9ar^Zw4LB)vV2`i(58dKPXjrTti$Wo9ufeAx3cU{102p989XblH@IXY5%93K z1)#CKRPoVj@fCPre!TpB*-Tw$SJ&T*L361l+~MM=gNMFW%u$~=@Z~nh)q5>|1HF_? zd;xp88q3$s$2D>H=gfpgo@gj0a!3?!sGq6Bory-?4UcAq`7nmLhU-uG<^^dbDVkXR zbri$kKG9O6vL$q+A^H)=I^@ij0b?KFeWPYq^pxBcuDY^}5#QPgc*lRY{B!Xr-I$6` z(_#>}khzK=%r0d^b@2_6%H^^9P*Ot^Dr$i)IUvT}R8Basn3}|zWudxUfQ(Q-c;pMGd}VrI}2nYpbXwzKo^?Stsl#Dsd%li zoty!Gy_&kNVMC#KMs9P8pKAG>5SvT5H}W+3>)4X>OyF9pNf+7_I->OGK(17jmx!_( zV?bOIuGDzsuGTYFdQXLPuan)S1^-c$R9ZrzT{R*sPDItIg05Liz`*U;tLCri z_fip^K9@ED^IZ%8uSwsSM- zo7R+}x;5*4ouUE&+}WemIi5)SFd)k7flqH-f4sHjH7ZsA2P|sM_Kb7pbG%)C0FId3 zO4O)|)|4R>w@(UXk4@sY{bl2)d6+GIgrn$cDD=`lq+ovZ=x8os7ADTE&JLQVRoV+! z5XMU7khn~o0S$?*Stn3e&oet;qeFHqi{+FWm}5%af-nr)HY5%UzScz57FfA21Me0|QcUqy=I%0U$>y{klitWCTiM{ZnmaPgaVwe_C$zUuDr zpmZ_k+$2?PI=wE@qL|#0At{9T&XvnOt~WL%`3L}%YKr==-O);`tu~E2pR&~LdI^x( z3URNjv8yVIo0erUIE83Uq4BuY-Qv=4nR5Tcy5r$jQFu>*^JjYvfd3Hc&niAR&JrYJ z3g8;Cr(%hLi)l+FnAiMsmDjdFc*Q{SR)n4TMKYWsh&um7%;K|z^2)oEUK#dT3IF_* zC6Qu+=kdLj?zntELCrqjz6y;cVYC49NMiS<8}<1wY~<3T+aT-DJD`zfog>tZ z-J2irsK79-v=R}P`g^t&-WI(fJPMko!=pYX?31_(zMliV|G6u912QKGjaD5D-t-cB zX!5KTA_GQf-p3RtO4+;R4l?ANhV8Xqm5ABX!IF!;oL2~vdhNF$Nd4;Q6Q`{LO7UNe z6>8#H=UAwPZ;l(4oqh+$X*@?)(NcBX1TD{&ka)cO{3Twk#BEZ`3fPQj?d8Yd2;Rhy zciV!pP~q%zMTb?^KivfrQRHB<jis zSsfW;HAhp?4SOSJ?pAMSdlN)eouxw#F+{?qgHqZi*+}DX9~Hce7?y=fxaSl5%^`YH zW2+`4iS|Pou8d7n^$fTF`9>Q{ay`#Iby79*$oQP5Go|XN4`lG`@=2`-+wbQlD#hkH z`Skww^T6MCrJ2^5qVU(^TbJFbkcx=xItYE50xF!XVDC*;4rL`8**X>A|GeyC<>KOk z&Ow<1+;(0Ib|7w(etz>$liGtdgVb5^x)=_5M>L$Olv0Efxv1>R58vigazKu3@FrP!8I@S~e-k z)8U{ik{i#q`JPMg9_F38%4~y{;d$Kpia`i}qC**kawKT(lx-M^Bh*O5LVR1Lev?o+KFZ~7z-2tux3 zKtXsV9>|IUe!Llyx7c)zu$v>?$Ie{ZU);qZ=#xH4+(rd4l?>K6A^Pt)s$a=5b?6r~ zC#Q)2glhF(3#|3t8ByE%WllV9|MYDfIR=?ZE{ge4XZH?O`jP_!6&5+ri~Q$m&8b$R z*>tLwmfQ~)cl-cPy3U#LDi4uqf%k z32TFk30e4mViLdyw!W!tWIMg~SoN&#q1w9{UTnQMIQxCm{)R>A&!K=08v$G;1C~(2 zUNYU2{=V28;B2kTp9K$!{hJDJ{|GVHmDICr#kuwk&2GbO63Vw@*P(PmDOOgJy==`Z0bNYfU(@o(9m{*1<{5JYNZ$efRrVEA?} zTngRa`04WC>JpB4hb9;E5070V_+=3B1V#08E%=ptpO=MmpO4A&Mo1rV-44EmE!mAs zo82Enso&ujLzECa?|k`qA$ZOXQC~_n9>}YNDC?4yl1xCNgA`^ks+DDZ7$4z^My8E} z0m;`s-iu5I1K=GB>nS>2w^vwD0%+Uj2TnfefSt+nJKuLuPb`F1{(p}_{urcr$5McF zM1Y946Q_zr*Me3F>S(-bpj`bUe(-}`v5GXSBs1JWudbxHau8gWftUVq;iKPz({dm8 z&O3oVv65-=7v3T*OZ&z8)eTfbMWs(g7{0rA(u|3i;v9m>KZNdy6x(*w1uF>~=3V5v zOVbcuVLP|BH1sqi>oi1RGE*=-CHfZJD5-~EGi=nBTh=FF|5XirV)-FWnn1)q5PwDPUyZhC$_F0@khBSU`AN-G%-1_Gl@22fLI}?8)Lw5Jymb&rer-4d|N6svO zw~2DyoP6t2^a5#un?$P(oB|Jt-jdJCzA=b9Hs`eO;p;ay53`o6#iHA>I42 z-2$)Kh&aAjYneZKw7@t#7p_E!TqgGX+tO7GI*4L5c$uPbD(ytX zsl+9im&5^x#KQk(2i4*}f3tw6y@b5W|4KUe^|-|AYTl;=%{HP_!Pz#M!6&QFda0w9 zs@ImRILCB~n~OnzZ43pijI#b9wrHpc`-EGK{_~b(nqlzy{LJM~WBc00zD8c{O91`- z<70bk#TX0v*Lkg?4-ixVU>|PFpaDV5aN5(C9bGqH)Y5HuUg=4f&~!?7p?g ztayT%#$$n@7bI~)X6WtVZ94CuWrG8|{_bX@|IFb?Bq@NM4kM5qE1Rw8Uf%b9z(p>- zUHZzI@CcOpUS$e$xNKB2yKNI__BeYqyLflKUVZ6@*5MpDaT6c->}o!kqHcG}$SW3X z;9K(+^_Dk9k0I^Re%@mDs==4glbaL{2a(c5US!dw+RnSs3TZkmt3k6GeR(08NWp@$ zz}Xl~SYv3$!DctWpTT1jYlfJ}Go$>2T4?Fg?ri6Q4?kue7%H6o{X2!6IeAARy!rMYyrCXhwG5{im3ON=wH7Qc&9luNIoB$Cac0UPJ}Q_vsjq5XACcwz=DDfEs{-7jYh;F zm&0v9!UhFcHUmZaU)jI6+K*1JA&#msW7@A@Q0Z;=G`p4i43nRE^DfDiFXIzQ&oXPj zt>fVlQ6yBn*WX`S4!v*#&45ntI0a-WOjGD1#QZie*=?G@DZ%NNI7_lZ8f%fLCz;3xvHu`-h=*ean(S) zU&5-aTGj!3AxeAU8I5%egqN&mZ$b}N%6VY_`{f;Ri7;@e;HEMMAF^=hNpXa0@9Vm! zj;lC_S!l7rTR1?Nadi>G+*m3GN<0Dw$F!2^=eh?20vg1?Oj3_Wd0>eV{|DZ?vSOY- zA=^!qLgzF|H>7|TYVff>6W(qtXlD$VN+7R}jSf6c8ZUO_KB^ z^nhA783Kr=A9Ab(v03;W2p#$tjihBvYP6$k_}!s@B)|M|Vo^A@SG`@%d8-^4gAV?- z_Q$#UW6@B!)xPBn!&xt9)NLl35R=QKADY%#SUQJ)ivtQ|LWnoqFiKXhd*5tv>%7xp z>7|A`n&arOS{}!5CtHgQoj8k2E_^)19WFe_M*Dmi^EN5p{S(e9!S}w9IDNFDLFpAG zM;1+C6;BfTbMT*;%Z8{&CpjW-b`A&N{Kq27XtId*gqyF&k>WVG&!?dAkR0;mS1);- z<-)3ML}-)4Ux-qC4t8pdoOQ+Bzj5)t-QF=}V?nym4u06|-Ymend~E+n{Vcz33^wH_|GAS1PAK?GyA5j&5{9~ZNU)GZIwSb;! z)Xd1}OI9!2@a(L9;*s{ICi&I(pzj6rF-J5&jz=@Yl`}_<44}6|u{EN(izBqTbiegJ zESSVXyZArg^>_V~GY|;R3#cU;sB`cCsg5K@p*?Rr@b;WY+*BsIp)K^ido%cqAq=eRxc3)9)G9fZWsGtTz=N$99{cVmNB@3-B$*0VJsFc>nx5iHqf}`* zJp4iOV#J$30y_0bOtPrUOIr3fUIDRMV^ZWJ$z+4jwBmrbM0l7{&g=tWslv^Dg&Qe= zxgS%((ZQwJYTVD5v*0qYExobC^Yci;Z{8T_re0PWhXDmOJ-p~?aB^N~`7l0imypKY z5Gcclct!M5hk(*B+)845|I~ijc%?s;AtGJDJ?+i=vLd@ZIVfcNorteGMgK2oM{U0c zBZeVL%#}#SQb~iwTc)a&a}zKQ^|^~H@MK1;i`Tm_#1~HxurX3KNTIFFi7`b0KGAX1 zEOgvj=rD#aroPBY@;ld|@pcD^EYzG92eVB7EQ;&5&06!_g0&Yf#B|8liJ{w+)bHPl zY{?3;!3hDy9((NNOtLZt>q3P)xgz zbB2iOLSnLWS*&j>?m?*Aqbzhq=XBCCyM1KP_a`wH!89nUDCyj!e&Nkk`% z0JO9sg-&mFGDo&Mpw1AzxbO-iR1j`_goP0W)o(RQP!dD~5Cm=F2&UEJyY?4}g{?_e zo{fu2$Mdpr;V+ihv+5jJ4W7XTIxac|H|&CEB@!nr~vo8v9I@+c(QF9BHw?r09AGD1hp;x^&h!7%67i zqErbVP}}yqu@_rf3t-k!9n_+%_qQZF>-70J?J(S!C|ehK`kvq|t~k0cm7?ey591tY z$U{qysf zQHgJBz=fvE(miuU{_5G1*O1-0Gz-xA)>qp5M|DXWfYACaK&wWJR0Tvo4h~ZMqmA(> zcho(gq$V_*7TGrzIkcd~aUO{&bMT%S2jwPB@CgWW#&acbf8b3blEzvOIk4w`H~HBL zKeq~7Z3PPgvONX*OHki(fU$h+7x1Y ziJ{QkoXl{xR#_i?&J6;h*y8|2zMy%Dhtf^9)!rXnbDy3_Z*1r^oGQ-Jatb6B}PEh z3yua@*~i2Jad=mKtOHki=kEUE{*b|Or?U{Blg9&NiB$9hfcdxM@|RQESTNPZ$qNKs z@Ad;rGa;}>x|tf)x5?sRyD{~Gv#Zp}%b*kv$d+Q_um`y{ zV}l^E*IeS+^&>>_SoTX#_d4J5kVxopEFemjvVrN)Cl@8x_rp8(TdGOq39`aJP;KDiu>ptg;3x)uoLAX;Z#cEj52FicwhD@?oi@uC-~v=g}JD1_yh*A6J)k2;plBx*-BJ_UlA$K8|rJV7@nk0ruZX@}a0ZGr?YgUX4g z->3~?5J&}h!BAce3sw%JxQ-6NFf2bkXH5PLMvB&zrpa9VEH(RQQ(jLn=C4$wOA>to5xhe z+{L|WL6QhPWYyGq6x3RX?mf?kFBp0_6>?w_M*8Esy0@<{03`3j%C{!|wM@>tBK~|u zUbP34G;)(xi&d?D{_o}n_$Qg)zj8xT5k7~#59NJ7s=I+zg!>poyHHrmdgAimgw3|i zgBMKMJp*`aBrD1DOEC5Q|ReUV|oU&9427 znIdDEZdd_-&>P3<(KXoCSw)!n&{_9NPC*?0a3A*9m2{ENPMbM#xZ{YT%c4Mou z6*x%Jw^yis5TNAT1zTiy4l_fth{2*}4qR4)>@@PGHK{fEj@S;!FDWUZn~V9xMvuACx9ebY~b!ZMC$yK0!oSf&X~l{NIj>MlbVLccg2WHB>)3GT0;jLqL7aG4jzewEKEgwvbG}>sNV-%?mx27j6W|2Y#?cf)^ ztq9`o{N9F{4$@3a9kBsh3V*zClrE%c%2}&&!e!ZQSx~(x=z45N`GoKaK||Wjy1L^F zQxozGB)MCL`(TBP{ti5oq}Jdy-+%kmeNC(S$KkErwodCV!>)ZxZpGYgxP_nPJp|K< zaxZclPK85Em9M<%k~f@9uC6j4)bXxB_HK69`HH6yZK!?~?W#C4Dq&r8~~ujtQ^QYxb#glWYM;^&b)RfzJMh>eU88*2G({&{q3zn~{}c z6P-R=`tBz>4G{4e>Nh%=yIprBFYYgrin_UkvgrP7LM2BFNITK!u98AI$Ah=K;i{zR z5OYdw;3Y1vI2$Vw;~8Rz>R)rq>s|rB@9E{)ngwISbUo7;@rLtInS9sVTaZfDM8_&v z9ElZMvq)`JqrdhyPUtLgA)b5by8xZ?w8*D?GeuRE9f zXZK!V;)I;z^Yf&_4U5rUfag8eC{O0CmBfEF(su*vnzv4{_eQ1M@sJ72c)|q23b!AV z`#wc>-Wj7Cu#)n*{i3B^OP}bh-d>ON^FTfANamoODGm%re1D9A$nKva&5%m`3l}5q zd?))>FB_OeuPXqcaEb@p5laB05ZPqk`a`K`*y+796~;}a_VvlD+QMarp<*c-=5C~G z9fQDoGOQ?yPP`Y)!!o{T#*Iu442_1s69V#vR@cdipl3^q&@1R$^**4U7$#}pqGCh-CFj6=T|hu$&{?MNiQ?7Y7}W5BFUyfkG_ zPDjF@9{T>_+R2ui)c3^ z>6*^`RszaHLpQqaza;SU?(OZF+u3o6?@u*l9}Y(=9}cFhTrOl{lA<7TxA0zidMhT3 zNz{8(rH6OsG(7Of#zZ-dl*xA|ri>5I%u!Z@b74*a>=I?Z$ z+tuBvtedW*5${-P8YeZJrGuk_LNefgdCY&_JijjsuYypEnLCE#YMH{DZcn#NZ-2^+ z+jx12x&CZB={^We$uzJ?Oc`%IP!!z^2>uup`neD8I|7VEz##tC)%jMYqOE@|Ur!0j@zA!i8@E@tAzzeKc+t{?VEjLk;i_jLL+3 z0uDVIK*gAd9es`?w}b-Oa996yXYs&kdch>>8dh&P$U=544u+{r1|*EhYYEcVTS&ye z*lP-W&O&G+6BkMa08#&nBLx%_?nt9zRzkuGu(RQ_W4Q2qQB>$aq$<$TAo^y!_r{>j ze|n;h2SB<5ad!_-hJx2#Q2>d9nb;5W3Ag|M&;!OD?>t~-%&ld&)4uNc-vb*eiW&;F Ia^?~L2hdX!r~m)} diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/1_iron/menu_div_iron_sub03.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/1_iron/menu_div_iron_sub03.png deleted file mode 100644 index 9ee5d882d674bc8f8e07899e87373d4a27045267..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18393 zcmaf41y|kN61}(;*WwPv-CZy4?ogn(J6zn|-HH`=cZcHcTHM{`@%@6AHOV9^XRXXk z&Loq)C*g|nl8ErQ@Bjb+Q3@!g{H6W=TVbKUw*3M|V_yo=Tv$#R0H}>ccr$|fIwm#& zD$4-?o|IqXf&hS*|HdBy04_`bz=@|5VB2T4De--sfHszq6#LR&%d=>^@0WtJ z2WmM100?ORtzfeopf>^b{j3V1^JBVa5EC7w0Yfj>ZP0~7-73> z^117_bINU-_34{H;MD(7CP-ZhC%p*@p6ixcQ$CJ%SFGUlZwcf!S}FHyJ&Ovj*N=Q} z(!O-l&wAAw1PJ&#Ko^_&ENB0)+Q(9$X9seTBpJ+cNNWY;%32#svlb|%ote5px^d^V{U zzu@vhuh;Peh@a*1%G=iAJ$v&LYbp}CBx-aN4(sE%+a2ragJAs_$36-m>9;lf^BnYT zDZ8iln(W`_hSQYKGXnNj_WQ?KQKW`{te=+Qpao~Zp}c^%;~U=RH6EJ}C}FhlF%%=A zg{lR!&(`H*m_LAjs{Lv4@~SV@0N{@0KaXr@zn?Zo2puCAr9ha;CvbhXhCS7tp{MVO z09u7Kym^>yEV}&G&HEZWhdjmi+Gy~BTc65M=WJ@bbFxrQE2ELB4^stkNg9^F>2QCW z-7JmN47dHMK$=%aU%0g!iXba5kFTStc}5Pv1VY4uhYrO?3woR_*ValBd03(uI#~Dz z(?EeGwB!9- zkoZ?DO8o4}rGEK(_ePL3_!>os3r0*B4h?U0I)Da8bNVb;PW>1DiresPW-b zD~#{#Rw|Fj&7PLuSSn+8ZA}Ylba7(ALK$=qQ2U#hKq|Hy+kF+xQS&t#Cse(&Isb)+ zfWOzGbeqs|%T_v-8FfW7=BFmo|GLY`YChnEPKrlXYyU*ex$^|>1;Ix{RU zxcGT=EcxiO*h-XRa?$??HgFcYG2G~9D2FZf2i^*Y0y^VwR`9@Y~q zlge0|LCch3JNBl^vtRp}K5Rb1*s49DOSKwS_l)Me06X+ zcl-F||I>pnDrBzC1j3>Ljna?gFbcE|muvb5GCwClK1o;ZvAa8|REUm)w`52*0Wk0y z)Vpi|)_)P$*@IBYjg>I&VD^eHTHqV~3Ex?Bg82OQni@7t`b!&Pv?&Z}C{I7XBVH0t zXs4ijzHE)$#DPsuat=={i3zZ3t3pgo?$#|n6*X5$8Q~PuwI+r*b~M>24U{;J4S%)3 zEi1d=UOdIT+j!t-tCVM=jzKJFJ#3MxKYf-4uyux)h26R~;flTViS@&`DyQFD$IUAy zITlH~)c4Gr`1Wz?&_zb-7_zhfF!X z>hkki0OJYu^{~BQVJ*omtVw?aWo6h#`aM4~f+=p40Z_t+J3kXfgWS$YyV0)+1MV*_ zQx^D5iu|@jTVx=!hf@@e2v=hkLHfhBJ6V_d=II;gV@w%rnb39k159mO;#rpu`Ernr z*&Nt38mrQ_585%M!w*O&!An!|gjP<|dqCv|2r2!K_fPn~$2uaU3!IB!0Pf`dSP!b9 z$3>^i*q2fGxu7eyV38aV5(Ub1!;@YW!W**d7D>QNFOCy7gY$;!+<;Ndfw=v z`+wRpI`{Zou^*aNO?3Jyo$?uhF3@f-4U9qZC_C zI`}%3IYR=KP*`Xmeo>G?5L~$dak$0N`))ZKXh#vl1t@-Ro`e*IhK+O;DZv#(rSmRk z=H|?FHTM!@i+Gjy`}>P8jmVB^Z;**?tOut^VC(Gbv|!G-YE|2pnHd=uJf*sH=U&$* zYQp=qnuVv2hKdrdX8Ck5{DbAESv}|NQJE5n2Xba-phKMp{Z5)AJHcCtsZ@yO142OU zulA|nXz)=8sY5P>8=;6k37y!#_?hHR)@XUv<`p}OUE`U3ooIdt9)<)s=@}V>Ik~z0 z6ai;%;K>uDHK{0NI{UnyVe7pa`+j>QJMv+@zi@HnAX)?e?Bzwxu(dgZjr!ht{Uw-6 zvAcRR3>BD`8Mp@Oe8b>?f7KUs^H>z;JJk0GAFmxXBHoX3%XtMnMgjne0lo9#FvWp@ zEzj#rSvk4H^o&AXI#eP{tLGW_aZykS-?|%0U~|fQHf#$ja|`VG9y9~9`=djS3+>+4 znHIw=FSoxpM0OuV03NE)jo(#5j@Ld#4(I}kkJ^yv@${D99)3Xf8^Pn99u>#@2JQ;VQQ@!q4vqK|r|oi% zhQ@Uybj$R2p$3o>0R{3*NuIBqA+#4iDj~?b#h9q!4&#yIdM*>MUdfaE0!&FZN%Dw| z;D{1UG_*8P>?b9&E+3_~>u2P$9Xmy=g)pnkRV3GD6v=4P&=zc>mlY!x8eQ~X`%`@s zKHpdcWH*{$X4JNx2KG=5;q#w1tmtmL9Q{lZ6BCCelnXlEW}Br5WLa-VzUzaoO_h&3 z#dKV<2&9ibURL*cQDB-8E@Uq|nn5r;gVDt6M#sMzn|y_;5tJIblJ-j(`4D@os&oE* z?M&R=HH<*CDA*go0e+Efl7M4B>(_*G+!WMuT?4=QXe_@)oAIKUtnULj`9%GydcPo z4?p}h$Nk1a|K)*GsgLG(h8dQIjc!_w_>bSh9hVUKtYrVZ1+JVn+G~b>8muT4AY}8- z+IFmtzj|%LtQZOi7G7+@J zKLDDJH89^%HW?YMVJR#2anMC=P}X6HE#VpV9o1aHgncZ)K9sZhmyJP%81He8z4f|v z4XPNtur_!LZ!P~a<69(p4c7EM%jqJS2Oigdu>dfSHZ*ssB z+Z!U(twM1d%J0zIczlaIoVt$my|CJ=Hs}6)Ipw?FO9V*T;qh|%zX}5+hhr54AgsN2(OZNb%%l0lJI;OQm;8|3EY>#yWE7w7?=`*d?JKuJ7I9 zOXmGa{<;vrA&f((A^yx=C}In*gtlzDV_$XEj@6MW35~6_ zn@bq)(9~=st(^Rj6fuIOYsJPL3e1ZsTkZ7=!HOk^xo!s%k->AjA-vE1y-56aoO#}f zQS`b}Oz9GhC^GNOKEDjWxHZ9Ttu6%`6^$@;S-ap=+2)DAd`}@f z7xAWY-jw-@#Sp??W>BV`WV&;BUjF5TWjG>5n$J1nbx!Dzt_Y63z5SB$b_|@5Qj*`? zE)^lyeUjO(&ZwDBW5&UltlaAX!-O*Ro|0*}2njOUk(``2_~;(Wi~!~j^7?u!SdZAf zflaX7py;^MMUcO|fdcxa^FJhM5Zzc`9e(NA)212)@Bj!+fiDIJ^Zh%4(U~EdxY942 zlqEhbWHud8?1-uwrdZ9?tFwPOne!1`gV2K%8)9U(1m>u@(Xw2EyfLr@c3N&kPtWXa znX3&hy+EZa_?bIbz50dtjQ4uGv;;#uyxskI87>bZ=R4jQ{>0=|e0oN)E}h~E9TPKm z@4%keQaD+^)D0Bswe&YJYMZ5p_3>3hc@R&vY1Jy^-ub_E8L#F0mwvjuXq9( zav-8hW^i-h8{Q!L#Xzv`Dos3&Y#gqGG1aMu1W%G`4_UyTzY;uN`7UQX$am?(ubslL zz{DioTwT3xAT$UqBRlsthKiC(Qx^q6T_Pm0!Y*P(@HP*K_G6>xA5;v{2lU^hvJtO_ zH~IE1bY{-P*4GITwpp?5Tkco6k~<>`n|&SB?mw#@o}QlW^QogXdcAiz32+}#AjB~> z48S=qyK&%>wf-Cj;mlg^plSObd8Fz;jIvFD;+wMDa7_E|-@V2p%hbtyZ~j?ggS7 z_e!87#YLbg$7`dx&K(RusO0=8K5c6Woy(AT-MnDs-5Qh-QCBVWi^7N#&-)_t!kZ5X3Kddo;_sy?5E4oyP-=S0v?})fNSR7)r-aZQxT`f#d0WKn`e2Z zZ-JwuofQTtP-p?d@vW@v0-&YKFXKuELz8RlMK&mZwc%urA4MmEhGN6rblTeX2zc!^ zW_sI6{0fc(O{Vr1)ioy=y}}r6v4Gzw(gnB&*Y`aD#R~Es*!+*J-&52dLP9c|nXUu) zch)9*IWmm%?)3sC>ZJ-+?#8(u+l_GaA=2FQG6&1cq?vHUQcPn}7w;~rktY8 z3QqNScFYz>qlw!y4v(qKI{uBjzv|U#q_}^y9=69Btm~GjjwAw$FKEQPIU%pcf1T7& z*{!b_&|sxyWjw@P_AQ*Add1l7-K{8CB=E*nAIn9VK~$E_a)ogT7z)gn~F?N$!*1YY1U`kl?H zu?!D){*%}IFC@r_vG}4G=`Ca}D(w!`#ni|^M@9V!29#K2rB%8bM}El`!O1;{L|xBM z2;6&?>wL%*$Z}c_%2_FAJ#!Zd1!JHl7#3PeZTHZb=L3MwcUp(i)%XN5UPxh6e@gS9 zd;{Lhed;I@+0OL^GC_4kVUB4!tD~p;3Sp||W(F-5?DMf7bJ!t2YA>J8gi>a+5W|$tRUNjug^6vK%axDXU91K)113y=jYb? zH{GdC5an`us6xb4y2>kQ%X%W^idG%X8nelI5*>Di1g8cruV)lh_Y=OQg1+DS31y8Y za^@5k?KnLh^JBhyimBF!@OP<%hYHT4dykf?y)OeP`9(NVsk$>xwZ*!a1g8cds5H~C zvpC%NWyon3H6>t-k=0I4;RGbW-C1ynGX9HmG_nh7&z@6h zSy}TpN?b<92K#0q`W?fv4uFAC+A|Pi2u?HgV={h@|6~= ztLvV2U^=dnt8Zo_18~s#MU0$bcSsyh6~GbJDc9k^zLl1}2(hK${7H$dFvAWTS`B39 z=bu>D#T&giBRc&9#grnid|U$_5Tms;-^c-`i3PbfQmt-x#@fQ<1t;tNZ#*t05zoPNr%M{&xyb|65N>Zft}wq6+ z2yZZX-||jh>OX>=QumBc6T?mlxdQs$alR! zj2JTH1gOf?DIMOe@5Gn(>39AYaqg~_Lavp7OIWx0eV7t1ZXa;J{^8;lJxyIr;@2HM zCj^^~{CTFZyHfqP&0ks=wlxp6iZuC|?!q~E!llX-GxZ{tjhdAF_++bJVXaoKZ06pX z4VB^hG*$XFLDAz_D#RC0juwqyxmacZ`SE^!cP$UQP3@xV&Eq zQ6@p-dL^@};|Y}W17q__ zSCx7->M^#3vka1Oj6#f)i&V?{zi@I-(E^1mr?n5jql>EH^fNx-Hv#=Od^seFZdjWE zt9u&l&XaJz$V=UIr`yqgi9bUyZ;CWuho`g0)~moy->ax~Tlgd=Ns{Ij&x)5A>Bj48 zh{KE=93uv5wnd(^wv}%+Z0#mYscv#XCufLT3Y>V&E`r!R8mKWygSCo(7~qh$(EzZd zIKGBi&5RuvB;B8H@*xt)Fw;_da=YJV#3r07G#o+&fokji^M8*$uZyyG-&k&I?Q?Gi-ts7QB~!93=1gLY)*@Rfr^+dMNM%$)wSmm_2iOL zRpWL&qb`amS~-ojMb&0#7Ob=j?K^901KX#u-(#5o6!u=ZXHn(bPGw|U-02|+I?bXtK@yyI%D=NB&4WF1w4=k zpW#vy9IIqdqJR#YU z;^s&q=OB+@D!LmI4Q|Ym0YLguY%ejq9kI`b4(G%o{TZeS=Bq8lfn;A#EMG*eu2v7K z(AS?l_voz#9dkRp3sratc`8@!AwibED^5#X=<#yJzLH`m`k`f}fCoQPm2 z^Y0{;UJ8z45)M{nrG1Bgry@aBHQ!aNiZXi+e@=u94a753#zbwz!6uX{9c)@GY1Mgx z8)aM+C|f(xk6jwjRP5`6fe17mxqHyAtXlVzX&-=RcEbs!{mB7&AiZO=*1Fk462WX# z|KxYBp7|%PTNxQIkj8u_RnVXJ*UwA+rOdm+NBcM@yGb5-46erm@ku^VaU_67e5M+q z-V0sBDHF;}KKq6XAXKDG>Es@@^)_@F$IZ7G{8sgNy7l>PyGRAd;9NwFB0$73W^r=& z1s|!he;F^hLc&oMtZ}04E3`;xk&m8&S_+2Gi+2Z zQu^WcDl$<=g@z`oWVV%k`FD5bl;=2}{ENS$Xx0~k-_WIQQ|r-<^I{2bE-?4=v@PM{ z5uStV0DfTAYt(0XiIOXpLC_?77M*4wq#kP0r;y}LTT4y4py93Iref7+sq@}JAAZz= zf*nhHS_S!*SbN-x_s;z@k09klOI8#4tj^S>C=-4mMz1@j%$XC46NJ^aou#c-+M+T* zQOq$@EIFRG`oeUGNosvh)qh1vFY@W(ZPmS?nC(D`7DMLn&O3e0w}`A_vs$rT8IWOe^uSH=XZL( z=X<{INX^*4cX5tdSin5M!cNOcD^#T6zFaCO)P(M>37A>7+Jx?h?;?D3wfpuPo5m&k zC!YihVS!?mb0y27E1P<1eIc^>D&#bn5qH#Y&yi1`Z5x>3P=7f?Ns*%;%wp&1fnmYW z&)St(78e|3Fp@}vvU5GoiL^HHuRNYVqh`j97(T>CR`YjATwPs%vEgQMZ8A9i;(^1b zU)yZH57@Le%z*ayi>k5$KDAfZwq=@T=+V!YD3&jkE}qEB;hQtfV4W2i`xABF+AiIG zU8PbTp?m9+;Be_yj5MC19w9e&{RCdSz<+gV>B3-c)Y?@?Wh)VXecq)|2(ZSMfB5bu zM=-__UkH#B#dqV#1XyZ<<;IG%f(!BCVuP^~EiW=q$!D8=I5qMyt%^D>clHn<43#4Yrq+%gPPCgo4 ziwsf5m>%X^;ANC>5u@!jDe%=Ft9p*r$}`VD19zCFja}qMp5>7gX|OcYa{oz8f3E>+ z;qr=~V=dvAXX4?JFqazpNh+MLDsujZ!upH@PU3;5EI>Y6NK2{4(~;!O?DZ|L<58QN z8YDAhvT3I+dYg2+uuo_1S>+I)%Xm<&e)>W&V1@=`VMnvG!{ZkxLUG6nxFgGgX5QZQ ztgUM=z`MT#I<7Jyveo|p`y(o4Hf7Lrr6u;;;bel6I!>ArmKOf{kD~XRzdjb|v~W~Y zGOjc={((lT^Zungx-77UjXHv=0K1AIo-rjpfYU+D#hzSmY1FKK!1&ys2yddME<@ao z1C9p%*jan;$wlN8>xbbx|CSejK4&S2;iXD(qbh+b4$aik6|)ZEHVgDdhrQJiw%2S! zQ5d&IH?GG1?z7DwB&F$KpCzj5Tn=9B^{RImdWz)o6J_7Pq(`^0s@K#1%K`1V%tDFa ziF5-!aikw&FvfdT2;Ws#%dUphGYK}NrB>0ScCa935jqEdXM@QRSu)=Lt==E4K5snU zkJ~l9`xEc3(Ut$3dT;5ra7hx#qf4BQYh=nkHp@PpA`+xhx=MOdDn=@&ro zNfnBQ5#e=T>&-BAJS@&fSyqO0)A$IMy03(k#?4q!+@%ag4N4@hy#h5 zHCBmz0PxvU%y=tfdSCw;bkfAdzLVtlUTEa3ng)7qWP9DlaLtZ?T*7^*5ZAqs*S!z5 zZX0rFoVt4ud$$|huEJVjevZsr?Ef;`dG?LHh*Q8mKX%1muIoy31XV1w)`8X-~>fMX00Ph*oQ+n)zsz&y(P%nsU8pY)pF;8%j zh&P+Z8QAIg>;wJ*FbPGft9wI@mI(X+CC@8nX^TR1Yr<;VWo)N@%{qy(P=$mUMD#b| znO{4PGC~MzP1moYBmMw^w}v=4D2OzyCkPUeUI2YJUEC4!HuA_5Mcf`heGF1?UM^A4 z6JryA1Dyx9(ZdJiR_fM%P+*9~uMO9k zQ2dd$S2*7?6gt7>nt&sK4(xS36%y$AqoVKPV)BJ4n9smz#lz7EU$RyNDPa^LtXw#V z+QrF|19{#vbTGKVJH?CE-(j~Y#mm4!B~>+Br%s306KJLjIa2#*!nLymzi7jM&xNAK z5V|S&zh52oR-%bSY0|k$C?z#iofbs=E{w#3;^FS;Gv;;ptxB_V*H777vlt#Z z=JbsKpVWi+*=bUt8j}Owi_FDM2+$>6q@2qoaDAIjmVOA3_{S18s5Md*K!K%89kEN_ zwS2@B`3451XGOY0g#&;Sj38ploVNV^6sSpm^{TCJYfxTrBb39SNP!A zGy?&blHx=TgB*u1ujI_<)Cpb#J z#2osX8q79aLkI?3{R61^7S-5;2(2IY3nIMPV?GXYbDb?dQspQbYJVs5UfzWpLSk0k zZe{Z~`97+Ik$)%#E>FWcX*|9RB-aG&t{WiI{xO2Gk;Gc z^Had{S5j$A(Q3H{9ib@5-Ogp4S%0x11{kfZpi7k~{vZQWgDG8TLju#>I0I%n4NW&v z$KYe`QtyXtsaEh)R=*vAKZ^t_w?Z1@ZI!PZir$-$9zrod&;AFFkzAAZ`YtwPu7+WbZMr!1f>0vj3P z8mVX~xh?~ppEWB8TH~YDarqyh*egdw5efYaeFUZ#E}=FJn@wuSBZ z2Sba_c$?aoZe-7zwyk6Z{XE--XxD3wUKqXA!YXiQvSq2bEyQHxhK4|=fDct$%$}8&dWShBo3?j!lf-~0k zX4*9@zltr)Wc;&589XD5-z?I%lnkzIeWv(X8oX-{C$7Y#-Bf@*GV&E&Jpzh66r|7} znWlSjEdsbu+=aW3qVr*SL4&fk3&dFA1(zq(5iw{;CMz5uslGZJI`eZwKCFE0CEx>j zeu$UKx@TMUmf@jFImLru-JAN7KHLmpk+zdqg^m*mds5wPOvx;q?zw)aYqE0X9U53h zvt!ZL#qNECMMiZ-aeDZJB(g-oOqX`$5UYWAh-c?+`O-;Cr3G6rOupi;Exbl+gwe|q ziwK2W`ab`ZjlMb^Ab*O5GkGv>cw9P{{EcD6%np}=;62xz%D*hHb2;xcLa?;r@F}Xo z405TFx~QsCF;Y|v@m@AL3@u7DrP2lV5HyDu%yelvGIk6}JKQw0NPFt2V{5>&GgpGn zufI)eJ7W`-@Yk9_TW`a@sm?55PdNN65|(Vi$VBnKAUoABPhyX;lVx;VBfqSP-6Esu zo>CZFLK`gNFVf_z)}C9YQ(vaWEaiOx(xmU@C&o5Z(dk|PP6?LYkuK7I7PMc2T3&As zCOK;R@I7>F)!Pnt<~d&xxj37u-Y?~WOPGn_cX*&1V59#wH^gK^>i@2X`d29FN+_r+ zCaZg|7bD$WM?zj9+KGKlp7+%A3kR=XSufy{Amuzzybg<~T1zT_y)-2sW06p>Kb?VD zqueo>L&w0yde+T}SK5h%l?FAO<7U*elr`(uMtYA@c??gh^YllEG#0y@H)ct@R{Pt> z8T_q2#CEy+gnVmW8$8aou11BChk5fS*!HYcmk}$N$qyeb5b*QtlqW~)y?j)uRQrJy z86-j?At3<^9XNmL!Yq32GC^9u@*#Kgst98&hV%`Un@Ls(Zs!&XNQj{eASS$MYRAs% z=m$}Gh^7qg%4lKfcd3^LTV#CYGZ%ib0vzhOh6M*=2)e^dKa1xaF@C~VXOV2ZI1>sv z4y>^@rN1FS3QcC7T#6JQzIKi6&mwyW%)hsEbHU+Nv$dO|$s&W^$?Exq#YIjg8}x)> zRxVzvYs9sBiHDDq*VrC8^GlH~<+~ikcR`+zy<3&#)r+z3*!t*pB<)NAwc((WG+7WS-s+0 z-ji^hoCqjjf6l}Atotrlp+Di3Pst}tF)79ds z6~)?+2_%jp9g;^^*dBJwFaAtIq!4StpEmjYJbPvAl3)s-@ZVi&=<-PQGvGxvSwO95 zX1Sd3-Myn3kDjdHve_iVNGjMB`-D z=1&dmwxQY`umiz1Bv{F4d{|>mEK8sSA{29WRy&YOmKx_w+KMOwfq9={>_kN*jX;W| zy;#Zs*xLYw_KF!SF=t4TYEGAJOqc!Jh;3zK<37V6Vfrs-gS0q?zp`4=uOuPrApP=M ztBjy5%uy0?;c^55l0?FtyLpFz9f6PS16d(mUHA#^b)NMa9zig%YzwY-L-vae= z`gD#ho0+y*|7tn0zR>o{GaHgeb$r08%pjpeVN`3c1Ktyw{ePeg6`}9E1`P%^chOE^ z%=sLAFxrVw5-XK>Ys(kHz@=aJi(G^aSKQ%k9kE2cYePj!_IQ+(@I3Wtk*I42Rfq+* zX#3|ZWdTi*W4fheDb_v~rr_VnR;6KG*>3|gnQ}B4LqI-x+wwkXhN;BZsV|B^Y4uos z`e?$^Rb>?;w1>6`P0f5P%d$1PYSA6w`VJW^O1#@TfGKfAI;?IZD;{!x{PHNYj5_ zzhB^Y9K%qJRvkPqe)X5$2`Qrl{8p?~59j&ubN~JVSgC`yXC`%BRGq@Zg)~F#Lcgfp-qidC4@`u}ycBEX zka1G#7nJ0*SPGx8i`{LX;+;<(cPVs`W^Xmsj9#6ePn8s_&g>jYfsMB3!AdsM6mr$_?`!w(2%i{Gg6=ZQG7iqw1QUcOCGPsR|;Iw?Pwlr2bi-#rXbNm8uV zdtK|?+D(99@zixr1)&p@lXU`hn>?@ca{_+J3r)k8rXJxXpbPG8?yq(*POZ0Xv`8Xd zs9dxSPl+~%t+$(g?RCT zWwLf<2=0Z^b0^vAZ5P8XSTP~bU}-3k>Dv>AjK)E0+q|9uvk%k6+GQ5Dc=IFn64W*+ z_^~a|906uz$A)Il1To+(ayE=og6s|22lmWZAAr>BQ;~QY`EJG{%>4 zyG2{CAvi)>=YM@vJiX8P4dSi+{gi9PjH!D|OX2Je+9Nr2({eH-P9|uO?p_wlD-Kps zRVV7wTs7?-nTFO7G}^^dx~WEsA3=3AK_Z~e9?veJ0%g;ae3h&;fzf%e~`1MPjDnjyZTsb{eto=?u3 ze1R)A;WOKYuwOR}ww@u*fO^Es|9<{`M!9n6%QR4@kR|!3#^)|0+yHNlvv>t79|uE( zx+<+HLx)pu@}(E$FFsr<4wM4Y1pCJ==O?7?O*mrWvYoM=KTy;2nf`abG7?nw`}N-2 z9c_YBIl2e2bKb>=hP`NQ}_{$j>qTnaBH6M?^+<8Lo1s)AJWjU9G7+sl4%_ z?7;6&1?V`tIXwdnlF7{jtI?!)_-`Y{Cg?r1(y?+^MFieRD}RAG_g|pHS7#n3QB1)a zblWJyV~fvQr(MJ8Fbp3@2CfeSf5OmVJvc8f@7?|V%(8{M9d-hQDtq?6)ooHU$9F-{ z?^6y&pF=3-IV#f7ms<+iTI&1SJ=P}Z=Jv`ebcIX#1 zZ`VjagB#o@ad=J5!T_j1FuJ)O*VHa4VWoAYge$OjrP>6tvInI(+&vB%NN}*P7M#ni z)1fMBjZr%+Ek=wPH#fK^qql)?f&D)SU*8y&*Tz}hJW`GmOQZ;aN~P)m_wxk}_sfmu zKbP}9*TAT}1~=P~ek1TYYsnY2lZ>Gki5>CPn3ux|&8PS?N4c|gSJuut9sx};>q55gQ&^<@rI?Dwcf5g@ z8xwH^7i#+_w^n5pRg_@8#7?Ke$BQ2a*G4D-^Spbn1H5Ru2K$~n6}rzAXg&6uLMqF{ zKH=GFsr2G(n$3n>>O@-w*0^M9S3P+B1^T6Gq+=3anw5oPvKGC>2aajg-WXulrh)#h5Y zhnS(28g4YS&yE1DC&ZYoQn{6Wrx7=?2c+NBuvzQ4tKPrSbPM%G1kGY8F5&{n0LVAA zUZg#UpdgXG?Sa{Hz?wB2_lG>HblL(8j8VPx5oTzZ2 zU(hV}5aYAOv-cAOm~444BlXVh^OX!KQ>We>&iAldwaPlRN>o+Sv?lxM%1X@X6P}cn zo5k-iQrP5avqk6g@q}bOX8cK3aH-;$6e)W}}_KE6gXppA#b}(7LJJ zTZa_uizXsotwuZ6m^qP?S7=y*(v}ZNz=ucsHaemlmq$nDRw4JxvuG=mjlQ3@-WU)1 zBPPF-soSqYtdm}E0hDYRi^=TzGpk=^E{dON;%}%^$HOdV`$uX&i%_|CIa;)sPi;)m z0U!h!Ej$Lr-Esb}-QJQJ<5U-7NAT5cDoRZ5Z&6sc&d%pfCxCFdT#zIRr1*>9`MtO8 zn)Ss%jDq|iX*~5d8S$6^QNVpjlE6zJjc6d8t5^{|?>e@rhMhC&!I{+-m4LI~oC5!t ze4~g({keIKY+`{)!92ct#Rz<YP4Uv9DYE%t$3dF0v39FSd`UM_;5m7=tq90Da52@3cJl*fzpN!V+!Rc8u z-}yO&8+9!Q(U=XWF>b`kltl7TjJRc~F(`RZ$O@_NkO#P(sYMI&ZS>llcXsdJUfRQU zk=R24b&m+on`!G*_JvsRq(Xa5M%yS?R5{)!w*@MRbNcWT`(xPGocC33nv9rjJcXAy z0&Zhko%zB-JHBtjBIF%6xn05ztvcl7*(0lawcpT(SuhsWe_--hzPgxw4^{iZu1!iN zhG+@!w2LH^Wuwho8fpgip=!1I9TkKt^2afTixpTuroYKtPTah1J#p$KFU-Ou(D%qt zXkZqVcPoq8fXNCHug_c3&A9KkGtx8C(=$K_inO?Ikj9pWfyY*@cU$dGd42c@bs$_I ze20zCo9QG!4*UWN4VX}13Ay5=b9lHRo)iN}wuG$X&TaDHV1B}h!^LmW;qE8`;UW9F z>~kYFr(q#YW!ndJszJHEdtij0ef4Z7YE2xA9ie|_U>W&d8=Ar0oUNk-)b9J{{9~@1 ziK)@QK{6p4H63d&M0c^UI%WJDreezEArlSE%D_Lo=~HXsh5h-qSK$3o?i<_-@k9T4 zV{5OHsN-y3q|Arr`WOBva*?zaqZ-Y9INA3>HaR6@b2?FH;>mcj?~L+F)L8EK3q-nl z+S+fZ_TN$G3?zR(T9dZ)Af4M#Uw*%!0&CeW(2K!XB_)BcNRbvlzu8~OhJaB%DNSTO z*{OBN9ZP6#Zf3GEqSSBCp&f+z4gK{$RX%F?&UT_}Mt#y>Oo>Fe7yLCJ>U79}`EtzazfCLFsS>#IME~+( z6x;{%Z%#cxmtKO~uXYXPu{8dGsn7lD+b33o1Fz4i?)}Eg50J*8WCGcU@Ji*sxiZzU z!H}wIh-*=@(vSGSQ12OkE-HL**r%OLM$qlw)}_gJloo3aIX8>By19spWgq-22NWU3 zqXtv8IX1a|Hn|P9iAr7DM)!-*t>)NhA_4c8`1D2IRK~`a0_Hx;ptHs^c4BkQp=}{P z!d3R@6r=Bzy~}xmvqZh~r;u-kXxsfO%|Gm{ugpJAwnU;SHM4y1tf`Y}tkoyjlC+RX7LT&HxE+h9vmxcPu?MyEbU1q$N~ z5<~}#1JjB}tKTzy9}2#Hdo^IsJop{>M!zj8W-OVU8MH1)54kNG=3hJq-q1QAPmD6X z1v<1bcrnbl>ve8mT$e0TCh?-z0SK^s6HN$o)KpujF~Y$?oInZXd4tX)Jj;C_w6dD+ud9|FFkF1p60q|BLFPPv!5gmu&n632@ zJ!Tt6SaAjxetv!y2XAd$LTQ%Io%NUQPvq_w6PuE229fqD?p%%R+h)}DTNBZ)$gEsw zFlP}Iqwn9qR3d&uqEd_#`rgG$5{>OU>a19;AO_(>8VP4j;*W;C!~Zpn{j~thaxCHv zHCS@df7-8RbvRMde~JA}5trlyq~T0m&6~{0$~88}L_Rj7^J7&pT>nMZKb#HSutMy5 zq4iBHm7Kh)+?dk)c7`xx z=MB7F$32!)><1fu5bHLd_OuTg8#Qav>57lvxj@beig9^bu1io}4u@yuQjUb-|7GhF0g~zd zm0NAKK^@R{FA(D4K=I*Y&*IWtJ{t+Fp~zju7Dkku!Ck1L%lk$C*Wgw16W%WsbgH41 z)w#WYHj%|Wb}V=e2_n)3-SVYwVx$k+UR$^=eqIgQ-K@G9++37Wqr`?6jyqC>?j`b} zslKXy(;TzISVWo3WDi=h?LVFa6QfYi`e@xXLNHp}Dx==?3C)FuX+hPLpF;(@v2W0b zyjJpdw|i`J`?xJFVJE0KDynx(6l#NVjo4;z*>`7*=EI~bDb4n5ol6z$Zxn&~_Zv5H@bj z8I%%j0&qPyQNXvWYprB5c^E{Q7+QXhi)oD-N?2tyJxX)8$!>EOY?H-zFHl;~arR4J z<-`NWnZ0lx5JXVQU-w?-)Z=IQQ-AeuF#pa4kL9~CHa@|?V1n(fJoS1zuhAudcr;F> zT3Ki`jW=i`e+^**Z_xIQG@X7HopyWGB|awjqzM4pV#pmB7xC`Ebj^%_pN3%=N<0=n zpzUZ~1OP(LH+P$)(`iDX5VdWgoR!vdod52(Ieqr$_}c&ccge4=vYxw+yEgTg{-?jg zvtRl1{KsGWm;C6ZZ+E@m*tk#{SC$s(DYJ*)=XcAuuT`p*^QKLfZUR{A=~LC|r`x}e zRm;B>{45Ya>n6=c$VC|uV+flzQe)TH4oUKX!Dzfs+pSCZTDVOL1Z~SUTb1o{Yh*Cq ziX_rhwzt6_0Dpkl3+H_+*OvKnf9-FOJUEJJ8~pYE?Vl4HPVsmD`!7?>Z`khhV~Ip7 zbL6y6R*bxgd!B@!VD6Hjp z`h~AD{peZd-g$#x{fB?cxhl{C$Q+*}9PZ=#>a{gp*L^tQZhy=6IF8z|5zP4_Xj(oGn>Y; z-q>kmj!hm6hx@3MOFn=?KF7J2zD;568s}d6&)&mgi36>vQ#0s|Mmc+B;r04XeOXbI zA%qU%5rFIOzrL}NtJJDL!Cj6mh@e257(Nl@?snnRLI5uE6@*gQ5A^REM!jVj1MygV z2!vADK>&u{++7Ly10U*oBfGwKU5^hA#Yc~hhYKCbT_NADDmMMdSrWq|t?ZSBkJeYO zzYct0+NPo?N`@W+h)3gS4Xv=TwRI5@qt_6K{|LbWww>Gl%+7xJbPzzNyfhIx2SEfe zlp4E+9FpXCB&;fyjcvDV$?y01{C;1dq3a)+wwX6=(==`Kdbv_8t4c6*bo^*c4#};J z;zldrSAalk^5nxU+qO!JAG~*=v{n3xX`9zg+q8j%*o^y1!2e z)6n$~8oK^_2mh$JXf&>_uC6xv!hM5Bryl5AxIA~|`bSw2jO<*2j%2{qrK~)s>E9Eu| zZy;Q}AdtT0e3tnXAs;?{1OV+|$#sN2AS0rSrChP_lT38t*;qV5VY|AGV9P}W7tjz@ zv@?j*b$|uk)O%UA8;*6?+lPRfIxw^gu(Y^v86oQ>gwnU-d~Vb0CHfSA|K4x$iGc33 zb;N8Ht;Gk~tBbEW=eS|L9j7fLX7xL?O}0)bBeeNN#G3m&?J}#^01BIhYr0{~ArS7i zE!x4HPaS-kbO0Azzku!>yRm{{1fpfV(TG*br4`_H+UA(S{!XMGzdd38rsErCFGi1q>v_u8LnSMROh)2IY?f=!!UyR2D4C~t7{f=LZTM9#;p*>|nu za~EM<Gz>h$-i>&))n|JC;pGtfGGx!Ylh5rwOdBSDe SdCNKg0000`WcGX$Ey1Gy8Ue(og zP!Wpq5(u!kumAu6K}u3o`CIz`SD+!k>plU)v2Oux{!{KJ08kqT_ihOBeNJpFsVoNo zcv6113kCpQ|7(8?0Jty#0H+2308csqfMuWEs>Jtw0n$iDLiAgHA1@+pe%}JdUQ*Ku z0DwdNuYk;M_`U-Gk`Pj&KULjVFFL&J@iaWQ-@tGIc-E-k&~;Mb=oI1TKcwp|M(Z%F z-j|ik&OIvkOsG^?UGA3UE6S@VmRa*dWi59`NNJ3@JuO}W9% zXpW?1R5A{sOzzu|;8THZd_|XSs*Ky&zp%H0HvX?+uj9!p4Rrmt^939; zGc!L}civj;7GtRA58txSFKZ4f0a+&(?ZBqk~^rq2{-s$J(=k4cbu7s?c$yd1B zzQ$$u;iIdj&bN@_C#Y7DqJ#uPv(G-eE&r{TN z*h#*Z`&Y}HUylr97x*|8#$JTA|!#1%CZS zg%YoeF>CjD3QtDX7sSd6d;re__%w4tTN4q$3$pTH6LQ`5_d|Ej>jalsp?oXrjOfXL zvYG6gY3gyC%I0xOEcpBp$pb|-$i*d4Pqa)FLm}9NEJOL9(jx{rKfpS;{5EVo=$kR{ zPMM)Fpii_7!`PD&)PHFHss#)rd)6ni+i~t|^38ia{_?r~H(R5GBgdxxJv0etD{nOX zef^uxN)dRELA*8T=iDa;H>@`-_P3_T9}Ox5JZ#Lxk5AHqeMgTrb7uid0AQ(zBbHjh#@L9)s%=@i5`3|6Xc$kHbtHHk;yfi_F~j?X_PY zP6m%C>_?qF2+96Pld|$Y_Vz~SDkW12`L-%J#}&2rU~w^vL_~*YTcE_KGLiDwWiGvf zuMuSUn+|D+wu$+5-nr1f7eOw8Q1{+wJtJ*K~ACx-loP6*g?*9HR?;zJ@R76C3&tWQjZ}Y#vP?qg4XW25c z#k)(`vYRBnjwP}0-5=gVxE=Te(8~#~;2jJ%c?jW|xxJ`#o#5OhQJ7lg4tibAKH7w{ zR=H;JmhZP zOh1z#3*p4Oh#-LiuW|+ME{(my{t&GeI~v}?-VBhJH{M(WaDLFlnP!k z5;bE`r;jwkO$S~Cx`gTIW7o7d$m@74+wlDNwaPrRXQaWCCx%)An^hkaYHe4LlSQBHPG+&nf;n z{*tOOM}5+uuk@dx z>hK}Fw0MZ}gL_b-VPb6tj2i zxQIo(MOY8(=)z0JEF@9Wu<%!bNxI9Gb424l1mSqyh*rL6wPJrjP_L)lp#?+|L{|GAM1`xI~r-{4!^RtplYsi0>}?74iT2Xh4lsO*Ppp6mT@_>=%$B)g{hP`imhLDM^M|21gIe-?*CN= zi6h?u^Csl1ZI}1eHGjIcO-)NHQ_QcL2s#N?mXdhvE>|zFJj44&c5bGwWTnX#%cy7! zi$)9!%yz!`XrH6MXHztNy_SSTD6XwEB`bMS*1^VZ`}Aku&np7`-DnQA+po-NbPW7XKcWST9rJ!We)?sTf^fx8sn>%f(gy+ZCqr=CY7_fNSV?B|YVFq#F z6}$v(-L`^Yv1Xk#;_8MCHAoJ8+o0G%!d)KW4bNVTfpFP;8=GW%jM|%F}`n2I42L&OO#w&>fnIsr9G(as;l;?Z_aw}7SauBfjw{cP zlre489-Ee6mHFRaqYUx*sPdJ@qP!F^qmb#v!E{~@JQU<3Dj$e(pdf3wR8rFQ$Dm&xqf>` zz~5Fv=~1`m-Cv}2ef;8JwtkSk;gEHsC8fr^8i%NRQBDC{&ifUa-$Vx355C7(R?5SBAh>rN$MD#Q3h(8PMiHT9y9(LKzyUd#)nPGRVw3+f8HXrB}ur zs7$u!ksYs->S1C=iFKM|`+**H{{(q*g^;+$G-8vUj#2)UWr{YcxXx7ZkOBfUGE$dy z4r+a^)Gvv!MHj`(q2xel-ar*YbMEj@Z~Bp-IfqRF#(<;4GOz$ImKIhZLt2y&uxGqOqIn2cH{RiqB_It7z~16)xANX%!eWRjJBcWvO6TL2GGY!W zhb*ri_ryL;#yM@jQ>|_U8CYWqF*-q9I$ic1K`+|zRQk82T-Lw+$e`!#`FF?j<72_I za?1>54!&ru+4P>rHgD|?dC_i}@s%WTgQsz4zO97o{++}KE=qP{oS9PgT=yxgsA@+E zxx4zqm@F6KyBp*CBT_=hKi`X))Yz*Y4V`F_FuRp#7UONnIy-?)MjJ>pbDSM-uDgXM z>SDbYq9Xjec$0SN3syTq6DY+84RS+1ysr`Tban1zW@Ndw3HejE(Ba$P3e1O|5Uwl< zKR8I{$+`$3!LmC1Zjxgg4Sn9leI%A*vm}<)>ss}yvCbG$#s_Dvp5Aayu_DVqtdOpa zS{|)u*eYC7BTc0Til1E3T# zvDWHvkX^J8=aj_?R1>->3L$;eUhoJNXAlTr@}ZLD(8_)g*Q+vUe88#Yoo zQJ3M;v`XLz)hc{xZ)brt{n1AbXy_8GM>23wTCN19nM+d50l?eZrs3El87iapdgPg3 zk61hx@GV2Dep%j0GUAwyF1FlaTCcLnozER&65b^cuz&Sm$HqTw@+8eH^BGlS8^BGf zETC0-Wzt8>ZK*uP@Ol?0IO`4}LW4+dN*B69Wwi3iuwq zGx5=Z@cA8|L@@g=Pk={7IfOpNFnM`|=HZh2(5iJPFKwnn@3A2L&Q zEr4m}fAsZnVaQ-lasbDy^E&D6>%F}xOnCee$@Tmr=b=emUV?-ot{dyr&xD`5E0xgI zOwJ}v!M5E!@xuRxBs@DLy?)k=ibS9iYUI#0_(p}p*rAnj<*2oFDWePt%V#Z8V@)l@ zxdWA1AtoXDc1@Hkwz1u1IuQu-2e+h(m01iv zM3_;d%WfWu(?!^HEs&1g{Sli2xmE@v5RE&VXSKu;wji>;*poXfg2UEBCW1t= z`2)YjElQ|&o4Tl<2VkeM^lHr3SJ2qe|9zv785@@E#@ z9I$opYd^`+;TG8$_;&_?m{EneV8B1H@N$pXbG<7rcK0E7Gx+Q9i14F`k}3W9xM!tX zU&gN{xI|*Eqjle6w7fj_>|fG0c^G;uZMdrP8x;3t9j?pjxnAT^d*Qf3S!xt_1wd|9#&?B-dDNO4hk91RwLzb$_zjA4%7iVCt3v z$L8ek`0^7i$Eg6Nx2!z~Hv;8A}n4k~1j-KH6m^g3cUIX)Y;ZVUl3T7aYHx|0bO)E zu0%Df@DBtvoEe(0>Sk%|Y8rGY*jroJHOI~}TpOs$y8Dy)L4`3>cul!QbQ@q#ts28s z5kDOa{(dz+!NW%i=%%mLr``sbK@kN5Tw~7hpU=l*sDTL~G`mSRF@(X%Cbm zIIK6jwT_y{#ZIuKy1$?GM^)=zEBYGtWF3_<(t=;2+H=$QsF`}CSxYnbs5lpsVsrJD zFwY;+S46wL11+Jh(u8HBF!DJ$w#1-vOXU=7N(g<$$MD$SvgZ`~Ao6-caZW66sy`Nn_`T@dtv zu`~g<^x6RA79-=214m=8kIli5YP}*3F~0-L;Nb=?jJbW_)P<=5ad?|t7sk&Mbh5Y@W+$nC`3XaV&tsfjFhcIm!Ll^EKGz!~k{D$V+jlRxpLU%B%($T^ z&^M~7Fx&r%D2N2S0sgZ2zdL>cLpSdIJh>xgcSL}7PRWZ_&@N4*@Y-g}GJ-zAY5va> z#jjbOl^!0i`%fV`0{jGqo;-o)i8$EMEKL6zUe?|_q}zILcn~r4qm_u@F*7nq+Rf94 z$Ke62KvrjnkS}6vc!AX6p+N6o@at&Yb6lC?xzZkn#1mDpTXP1v1gRnz=ZLr%*(o-@ z_l`RhY0j*RwL_GRW5^UR5K8gB`{Fw9vuAQD%91MD8pr2r5JW!q(SDV}by{iyfwLw8 z8<&^@cJs5F(PnL{;p`St=*6YWE~}g*B6){Pkr||fEau`8E0)(4g%~C#WO7_NpgpVD zk0t9-4qv-672>;$k03SSaK^#ojZKB!L(+r_Ail>7#Wr<92F|<%cjT7kJCm<1#Oj4 zjFE-SYrks6@<@PqpXe#{aesu9tS>bxrR+C{fRe}Et7{a(^R~UPWqhF%iy>VPCVF36 zhSB#1h|Z70HiVsA7eQ_{HNx-H_d$)$;W5v5rddN zGKCMzc7A@|HY}Z-qN2CE(#nyh9BBN(Df)|bQYZGi1!iZ$(qitxzd=$|e+~x1`+Jqo z?O7*o(Ms~`x%P>Y`*D-JPUf(?9~mtU$-%%#a{Os2fPaCeA>1{sZqaCgVWnu+d4hHO+5`1BS&k*#T_BZeu(_LgJCAew;((whgap4dmM@yM4i0M41$ zmE_J-ABX@N;=`qp2$d_Xl)kQ6O@2q=xNe4Rv&U(LRO6&eD#L4VGhxZw@3wx*Va(BFpQw|1O z$a`QN_nK$KM(S^uM_D2+9;m%-!Um?qnmW}8$14@U_WN5I`~zxBMKM|ni!kk$ z^u~}|h?z0Dab5F;68qjlpI0^X&>!^w6s{+KoOgCL*?I@Ng>cpT1#@ww>{L>1}(YZVTTmMM~YV7To^u*uB?j%=y& zI2=P-U$XjB}5`jU`Bx`uch zvPy70>ieZ7P$ABDYNRSPg$Qv;M$TjmLn_KL4Bd5Wv1Mt4hW8sebzf-=`3BGno4c+4WiD zmqr_<>8;1v**ded)wY62v|8t@NI{?VQavck`}}KM;+&8%y~~ko;HCU_s$eLWW3d)8zoo{@mMw zL_SAceY{WtSe7cd`x25i=gn2eZy!&a=CtlleZONnT*`0ub;aFp1i1a3@ldj8p=~_d z6^a;D;p!!|&rrh}E58W{+7D;Rhi%io-Cbf+9^E%pE`8V43cir3Phihuutlguf9q(bN) zpQ_h7ZSv#XvtW!NUp{a)w!-v;yqRXmO`XZCOi~cobm~L$VXRmXg7@o{$HQQh43fDko z8BM8iDW$b}wR~e*R=5Wd<+e`{nC&9KM=01M?VGGi2?UHr_GjmfcDn!)Wm!VC`dg9V zbT$x^@{X=4P6YW?cH5gVG2CVHiA#lhL}DLsr?!xT**isVRI zGPN^Xao()9;X#LZ{k6MWH#{Mjqw2wyA+ux5>&&T+$YeS>h%Rg{vS>7*M1{g*?uj7& zwM^-#4xi-*5NA@Fc$cXPE1@4^&W+RCRxPjWJ}s}Twat<>c{~;d{-%xD+-zm@)Dj3Y z+9Ah@$h(BM^OR4(K-V-pHLE0iSwrT!6y9zRFsxc42=iyXk;QCb(jzu>15oXPeG|l?~Gy`Iu*tTTltlxW!b*Z=j#sGA$ zj-kp8Hx>6F6N=b|(szc@VqW|5eGJVG_e3%0f~y*WM^vkC4zeDxEHE8n$Xe@bJrIQY zHf#us(^#Ty;kq@MM;qR?QsCBI_s3upL`?)*%Jqe;DQja^i&52d+K^)d>L1R8m%q5X zk+P%q9}wtSa*5V9Ia75e5@w=M{T0->-EPs7^T)Oj@r)+AroeS}3#HFISvxsK+HXDg z5VDfH&0uEgbA?)z$&edFKt#-#GY*H*j17kO*?RIl+e|v$JYxg(de6#hZB`Z}{ayVn zO@2)1xFzOkp&16X3G1Xsuo6h2o~l7V(EMd&pKL*oF$=Uk^_SanI=Z4ag$OY9W`Sxo zk*70D=wPXXFV-XvlHI>$+bKbGy6kfbUTZh?hl`pibJpvE*Ab34UF>y$Pne;H!gf`# z{zYXAniNi#ta-Mo>d4N??!wAZq^0Fosy{9}fF)M1FnvXqf`M;jG|yOF)Tn-0AG1p^ z)+gMbnFDWEq5o9kc;E5E3@cG>e~bZU#l`$%Zv#$Sn<-%+6G*%KcKr}ZzI0SmiV{<5dyc~mO6Ch9CG z@}kcphM?Wm;ufSP%ATub=t{D*DbA@`_nY4<_X&^3cQLm@ZGQk+`BbQ2dp|%(qj0{_ z`=K6K(mKy^Fsh4>?O`BZ(qwWEbgqw0TNycZ6XU}Rdwq>+X7TD`6=+WD<5x68lw*Um3iu)D+Z%t%BE zCu)fCns&(!n{Ct|A#MNq&0c3Xalhi|C?MV>>;qOp$R)NaULI}shwgalWOk$C;2=)d zW5{nR#q)lM(zYg3;!3j`WQ6Wq`2GZN0@XkzkIuN3HXgBC6;P(>Sio{X>N4muQs8~p z_Cd0sWrMG_#C=hFZtaM#Gm8*k{xvL=lQ{>13WJT2Q6e>hnCjH=CNUx_{1yE})DVMX z^%Pgq2g2lBkO1!bDKWReR(?4PB0bj$WxFodWJgfIp9eX7LV*(4P(?7uLNt}FEy^k6 z(5A#k=$NX8Y~Ld@6~i)J$kLR)|00zBk|kAKnbEE|Ey0%~l4?4sqt{J`6C5be+W}(2 zO-hGI7QL^oxMt}DqpaeUrG3_!wXn9%--u*f1(6#v5dgNep_<6IcQ$xVA7 zMSvMVlK31m%~ z-4bm3IIOq&PfQW_>khnhYpqhNZyKkq;{``Z1ZRur*hqz{T&+C zOG9fJ5D}k){*^7UMm@uzy;Yb7t#t%UbzEO1RdeG4Ng%2v%w!!JF#Z7wJ%OJ$)F7^q zn^rOu%z|e>daEkyVMvqODu5wVo0ud)*Cp6F`DYIpWknD#v8}2_VUH)ei?E_B^Ll=d zpjJcWIiT$BqPnA=O!C7^%IRCEP7Dag#N5sV{;ajKXi+=UWN*h$(g?PM2b~n?%x#G6 zu62akC(GnuQ_WA-t}UX+1{(gE(&CZrMYC}SW+uEV7QjJ9XGbq9&g*u}%<@hIv6UD_m8 z1Y>nsfqLRga-hDP8P*XjlovL(MlcQv>yez$uHmjJX=wO-j-{)F^h@DP6PcHjRa%{( z5=j{r4O7M~rR*IeNVBug9nx`+m6nY#OGN?KMen^=OX>B`)ErN@dpnjUK3bP7+uaAt-D80J>+z4SCu** z?bMB9Pnean{JgW_IujJxh(`|2P7Wk1n^Y0;!1{rO*$SRqe#daX*Q_qs?hNCSaK?F^ zeV}@t1;&eYN9Foumf8N2NLR|w^Xw3Je|!D#>ra@^-3czRMI9lQtoG`YRiayzN;sjV zhc8at7#n~B68yay!T#fMoM>ToTMEhFVf^DpN}5~G2QZ)q!Q3u)BzWdZx?G`xL*cKi ztLIe=Z-Eelja17Zh4X`2q6+#He15LMmWmj&^i!+k1ih7r>a5|q;10<_`nDgKk3T*GwxC55%mbjM!^&yyXy_rCZ^Alv?9Ct6Up)z#Gy z9|WD%=9HB9+r(Mg6w@;SP1dMO&ef)O^=%un=a&@I3{HKk)U~_FI^C7fr2o=-U)E7K z>Y`lzcsDjcwCI5U8r00LBRcpV(57Zus_>eC;y^@VN5fF-&hIP%IIiQ{5$ZZPn?9ig z-Qha4zS8X!3LOS2vz36Mvz{G$16;~ZM4Sy=51R{?V#94$Zu^$(V^5qCG_BJl$!2nV zE(;q6Ru<>Ak#-^YIq^f}2C&Ifkv<72mkwU>S;@IUjQYndQ94v^cel!6Q(AReU- z6TwtO2dh;NDtq%fMlEN``?bkVkM^Noo*i@_+cGfp)23DH$<$OIbRppfl@oXn_}}KF zbbFBiN*0!Uy8V?n0>xLDq9bb^KL$Z>Qk*TUzo_#+Z7f0qc5R&QT_Jv0;;t0*IJ*V~ zZ18eBTfj@S^*)3^MA!9*uMpc|TidzJ9R}((1YLI8THF{Azl*%(67Fpu{pndc7^23- z7Awq@R$Fpe_CS#)zUJ(Z*bw0zvkL$$$fQbeN%() zE5(@To<`sS^@V)89K5JTZsLokuM5L0!jN*D-lW{Ky!n?rX3SHTnh^B%Qro8xPm|*D z5p+jab9i#5cGEVHLzbqt5l}^;#;J{Be!C&IQVxQ*L3lR z)6#X3mlCLrSR2tY6ujb{2!Id9`*T1+uy1-2&okrK5YhafC(SH@Bk5;v+idv=YnrGn7UL{V zBIG5Eu~93_ z+#B2UxM}+IBxYX>#D^f4r7jzBi18w_?5n-Alz}QjN7`5Ieipt*fUo^Aeacp3Q^TLl z1!1Qg(XSm{e4)9Zf_Dduu)DvaRl=861z2z?>(>y!trF&}Aj+)!zxEPC#i5N&Uc(2{ z^-W&W^{aO)s+jknpM)uu2f`2aLX)u84`nnN2USop>#YxAA-6O|_{d=N zL%GG7Eu;JC70gl7>B3I6VRvfKWDm%xU4(pmi1=DsjJ$vNaU9yj@j3vPd1_bQIf;VN z!WGo1RP5H4Ypo^n==mN03D^0v7v4a~1axf5TOPbh(4C~Y4f;vc+}{3q$Xr}4j=hFv zb`|geP}}#?VJWA9oT+t-MVT_A1^XbqByGihliAn~40)zFdon}2CCUV23u~q$-34E) zvZ5CfOC@)*W*Rr5yL`Rc;u{6#^7Kz{k|>{OY42uAt#woDzu#kVJw7t~zQuip&TR0e zyL&%XH+0hPLE4b+P;ws1ZQ!BXk#=&=I zz>gZ)?}7#(9ahSjSC6I{?Qp(d2D=UY^q3lSA%NP%;;#eFZ$#pYiPBc<%K3MT5ybjC zS3iE(^KJ|h@-1xD1zJK6`L#RZ$~#Qs>zEyYC>zZ> zvxO~`7|r?murXOot~jtp+tSi5?kphXEHKz@K*SsRs+76=j3Gu$W_)3(SBKd`H$D(P z$w)fJ4rIZ;PpEHnlhO8i=V+Q*VcV&3=cqyF@j1jdmsfDS9)an6jq{8BCR5CyV{rN| zww?<0of(n7Xovs7OB%)8`{7ftJILlCwT%yY@@+ZRm?R(pz1(4XEJ?eQEX}v2*tgAn zjQd(zX()r#HJ0#8retSVa11P%WX;X}+Z#e;zs=!kob8Y!L9x;%sIb1CmJzu1Uz!k5 z&Tr_&SV@xKiKsKBnDAhQsMQJEjKy6nTqIoVo5Yn)o?R zIh)<=nsnuRq}%uq;{I~LczZjhp9gHpErY`XD0+EaH#DJMyCG|a-ww`vX-fTNiM99B z9nEqqnk{z!tr|Qbpe+S;PsBAZON{L(2x!+nwXG~{2I`A+z-LRA*d2t z89Y;8@;!Pp4<~mVX2_5vl^{b?dn5&WBp_X5{6#h$1t=*^Io_M0Ki{Bqv@vqY!DteO_BoV@itL+^4^;$jMmFJkP&=P?gQ5N zeBkLcvrSC3-*%zoN4lCBdsR!Y>}N#W(N~nK*C>KyW(3ZPQKQC_t+SQ6o}lZovXv6FFI_38@H20(MjFHCeU} z0m>Cov*Huz*Nu`~fWAtDbc{fd41#a(ACDJ;fA1?~nM)4BoJk*>gQmJfsV+%pv4b!7 z7{%BH|F*{QW<%IFHTTmO#($2qJx`r)nE8Y$U~eIXXT9@k^1feetUx0aX@$AOH|c>& zQvD0{6Qq#Qgn{K4V=4tXP&?AfIwBqrfKIM{I5=PN2@F!`S~5p%rJCa}pgktaGSIM0 zHS;Mpmv|W`uc@Rh0Kky*owEt*$Du{x|1J*Gce{4et5y9=Od#CGJh?R@w+{RdCf1)+T#{xT`F48LP)$SjhF)MUcXttR>DR>m zO}%?LeqN1k52M!zmW+;!X-n#8owXP`!ZU{JGlu72uA#*hxZTG>MYivgHnwRwIFpA% z{>}NFDM?MHB%U9g z#ZtChRZrGdTou~a)=1kKTeo)M3f|T_9femDA={}#qF;@yza{hySDuy4LkM7CLH#t1 z*Ye6z-$B`#yLLyt=f-woH^t2ACM*L?4e6fk&2~IrvV%dgoDMyM4g-|9)O|^l7-?<6 z+=bI#qINUN*iHg|y)>#9kI!HBoI5e33PdDel#+9wkZbF5gE_p0wm+EuC+?rfp4_ja zE%G$^9miHc&<8JM3x`jPUFU~e3WuhvwMvk4eZ%a`Vq~ESF*km&rN8mbbnQJn>n(V{)T{czZ6>fGJan~%@D z${;6BREUwIowcb`oF${Ou4RAJjQ-u~>y#6~^>}#JPZo3bAima4e%nhVID;o->A=E9 zy*}b}7xi3eGU+=0XG!CZb(o&ea8MJ?LaeaRZzUc<(Ru)J}Y zf?;a`6DO7IV1B+*c3p4m3^U|oG)f20z)fKd=ll_xr!Yl^R3T&_qF-3oPAh>dY~Ew( zGmp0!Ii@zx<4zfC_iuRA@DM^^xOE=RCF-LK=RQ9j7s{WXyskz5#FY!f!p;r<{yYh? zJ9KZIAo+u7b?AlF^bKWVaL?^L6_(RvF00m^C#+q2Y7=;FEdEX!ibFY8=Dt2hxozQF z(Pn>Y(qv0NMgSllsxSUhFvrF{H@DRbA9R@m;R@Da)aX9xXBunPMGgHOs8XQAQ8Ai5 zwAX)-T5kGOZF{>4>0uMp?-;9%$McDa^tJ%NvNO%-#Hk`B+HPU|;v>+d8QSvBk+~wW zve$jQ!Z#|6uK@(VHS(g{(H0-LDSq!NNmg&=;Z<5i?+r3c<|w*;j6kBKs*xuW+5gfl z7?&ovy@-f{It0W;0)*TP7fY22!NRL+jx-cMT!*y~Fu*hopjc1k{-%Jk=b;&{vemJT@RpZox)1#3+TQqc_{cO* zWM`^`w9+>Dc&jCAa?%#kE$((c|A@(i(eLxhH)lb$F5m6d4G~0@r=1>gVC_^9?B_S> zx?M3PEv2?V>Z&Sd7YH%+xP$%CvZRtpUG3Oh339hzKxpFI(s(~++Q0CII2Lg-O4Y0(5ziBm;v+hoN>};#y}BLY z+FrrNF>y8K<_`^Kv^fVfb$)8~JqVT5%&t`>HmCe;(x%vU;ke+a&x@vIpRuL#7~;{w#F3eH`^B-<7N}S>H4ETF`6A z(rds=({=?oKZ8|Po2@Xx&->?=opDObJ${H?u0OP)HDy{$O8((M_;w;v$sc{n)Z^_w3V6L%JM;Ik5b!C8xVfk60!|?_Up|;0QN7xH0Zyc zpY#Mj=0yXMe#x5Gt*%|QH*FTW(so!jp`OEX+e3qfGl(8r*ntt(B};-8`S0G@CQCn~ zLxh2GRF>|&jA4zCr@f5mzq9jry{5NO7YEgB=om3)fIwMm@H#Y%JilK=$6isUO#mA+ zyU0L-Ut2vc2aYVBB0{h|_13?5{am6|G)RXR_a~=6gS;=z^$kz&p}ao?KQL)W4j}iN zw0+|-Tg19t$xuPo+xm7mvH*lxTtZ=j-G6rYzh}>kc6-Bv1woJRy;EZmU%yHG7D)X~ z`;Qe!WIH7SpW`wC*8f`kb5cOl#u`A@TirdhwBK$Ev z=Fls9!b?#m8ji!8sgR&t@5Wv*R~sAG%vZkd5q>XFcF1ih7{Pl9FY8mCy(+mr8C`Ec z!R_a*&#BP2H%~RKN|U5cj-o`#5@ioL89>0sj{RC=XM7ZTyp)4+ z>46jb**G|lyIycS*|HaA7p}^x0N1|y&^=o{ND4-r+ z4Axffi3jt4ED{kMOgz=>I*v5!u*4B~{$cdJ(4StN8L|7i>Kaz2i#!KULtAZU$v5D{ z4yglLtF~%u(^Rx9EQB1GfHVIt{Cqb5^Sf%>o<|pT1B6Ii=}7;p?dy7TeEpnPd?mdh zz6(@G4BT~p*=Y1*PaJ?4jQ#H^z*T7v^(^AR^h4XO;{y8Ok%?L0@~)viUbZA7GeZt^ z32q>9{`AH@$R@H$kxq%)LSD*ot{9v;3lb0WchN5M=35r$^ZV2nYM9^`%Sk`#H{fp2 zum0qieaEz1ZO_CT8$-D54Hyyeou8gPE{Ci??w;HVxQ^Qdzxh z>GwmsuSuxYR#!rl2{fSZQPrCU%K9CdNM}qo5jecwVeX(*1!!4MAHC;8V5{`;8>DUlHCgp7nuvV3dU@%d*wj32$U@Cx|*$3!0>z@!GY z+bKcj(J8-ACNwBZIJx`cBF(SEuTPa&g~>(vW|PkQv98f$w6NzvqEE!665OV67`KQK zQXi4|z0`5Xe{zN#3DL!OtLP1tIsi1Zw;@OXC8NBqQ2*76iV_D3-CTOz6gf!__;$CS?R z7wT*jk>xAyb{Ao4~@UHSJHZRJj5oq9#*;;1!gOXj4NQ#bqB_wKduZEqv) zmV{sOtF&%t(0}#CxI7oP8DNkJncs<_^KfJFD^W_{Rewnd$o*Tq+$B+peIGt-{4$A z=zQ5Er|$@=zegVra z&#H0%ey2{TcQ=8y0QvYlm5N!B98f76w8?JrrV(FEtt?nbk6Xx1S;dR6;ZxT4MJ)nI zBgA9ruD$n&;RhiC?gTDG%2FS-`2>Snd|Nv(Vx0##G_if)(?CbovIb1ERQ(3U-$&6X z5=+!g@EbZW{lY(Gc;X>k+8jj~YH=tY- z35P%b6Fj+RM-}0**b>X}niJ{Jp@V$xYrn?y*;7@PZ$nU3>FQP~tfp(o2XKhjcl+9z zUX0J^hH-)#@|O@M@G>>uNYVOEn=3qgcFc!>A2tC%jSJZwVCS)<6IN>(-7F-JRXEcv@J?Sy8-+B~JeBH#v0pX@2#ezd~$riCAo@8j$j<|NIrc z^re^iz5n$4ymz#5|D%z8W3(y?sar`Zh34GA4*G%tas_>9t)QRO4I@G$0W39rQ_lKM z`};mpE&p!tqd)+aJCrg)BzO>W3|`$ZB;7Dp-7PIWYM`@qJ+Dbl9N48)(aXhRzCu~A z_*&hS_MRPNv#Y|KbGkTn>WpLd#xh^}rC&qc){jvx@z4IvZ_&~pGA!RvQ?VD@rMdO z3IuQ`s31gxTvti}>9sY-_O9-sjuyAHR+m+yM7aXOYj}Mrb`^(fZFGDhpcmHB#mu84 z8IO@%igDznFEMuTFjHqw@H_wZ*Q^>`V!C$s2wrb1@mO?8-zYi)zV;Si zS7uvRcj@@m=}W-(5v<;J;YO+D==-4~`gZW6P5@975q72v6~R*Tg^gnSU{_~%v1CXa zhA_|S2w;6}UAv?gN(*{ny%63#vd!ylCA*RqyPw5l96S03$)y_{JNn2Q z=!HTia&6{)y`U|~a!Z%DrNviI06wowUogOA^kyut>)*#-jxC5FNsSmDddBXfgpUgW z*vOX=N?{w&Rw!=djiS-9tGBzWSTfi!3`&$M?X3zxX>DDLg6pbYC`1yAH}ycUE6^Vv z@+Rw)yJWmJ)jRgYVS?SgmB_W3>xspi?*msT8?r37gqsPVtD~J%ZY?>NN}WS2j?oZ^ zzmDJlt5&r?vZEh99t2P?FAap>z>Oe=bXM0rEpBI^+t(_WD&?|U@<>i_I3c;5)2uA8 zvQai5*y48e%Py&-#qC0JNv7)el`9U)XQGSeffES1pG5>|+Mc{eK6Cd`z{i0A>cK>K z$~vg&1X^-UYYle=2DD-cvw}0&rcfxBa_PKw5@CaT0V$lZNwL{!&Pu;avk7pp*raV?CmI$^fm2_T9FRo<2i?H!c z1lylS1ZZY?+M^B zwSeEh0r2jn>5B+iFCmn^sP(%Fch1T8qX>7~^zKI$bgLu~qg9j&S0=B{9tVi0()N~S z>sDDnjOw%0OtyN+Ahh{e#G3m!!ea*l;Y`j)ZfG0&6awLPS+U9w&7c1;@Nv=sY_RuHL)B$59EahcY#GZL?;HTFR6=B}}q6#d2_W_Ptj3yMeGSVu+c&2VR%= zqW~Xw0EfovODkIFW$*Ofk&_WmdE32X`fAA6{`$J6H>2LJ#707*qo IM6N<$f|Y%5?f?J) diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/3_silver/menu_div_silver_sub03.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/3_silver/menu_div_silver_sub03.png deleted file mode 100644 index 8eb75894c48a612552f6c81783f10e9760c59efb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17540 zcmZr%V{|1=6Ta~#8{4+Eu{L(HNjA1^+t}DnHcmFSZQHhO-tWHuzk9l;@0{s#x@u~s z>glRyA{6B%5a4j(0001jl%%Kz4+ALBIkAzX zk{kfwNeP-43;?|SH~$0xaA5`j&h!BQo-_ae%RZ~^7a!;Xw4scIC};%zUPapdKm)A3 zq=pj!@E!HP4mP*x`vCxmoJfiORB>Os?DX>1T6Q^phq~PX>xB`DLl%llB33G-nN5&V zHkFi7ozP4nm8i5TA!xSX;VfV;n~y1JmCMYuIA%*+Z)m+D=R|8Rn}7Icd(PuZs7h#Q zJnm>NV<7Gk07NA<*nI%b{1Hrg` zHN5Tom^o>x^W@8gAES5aEtQaDcJ;a7_p!jiJtg~e9btU2{TG{+RFEABy0D z$6?*WcEvRP^|LL#x;2L>N^jq-%HgZ=%CGYLeyUl8$1pk?0Ur3sNeHQ{F_gLp=5nGA z^^wGdWh?eb5A%ESJj3r%Irn4XlRwN$m)ra0hT2|!P71w_ubCQ7(Pcb2OxVA85>}(msHElGfH#Idq zw)@&Gdu~GkpT3MB0wSEqa=yO4^uYIp?6~N$xXTI7H?L4GRqR9cxq|zT{x&zejY?GL z)bp4L#!sBzRsHlArG56U6!(&uo~Ej4B7XjuH=90OOo#6|dgmyBqNgZo>j{yXP^H_I z0#Z$w)?>9`m0n(4bS&>WFW8-}7?)R8ErN|8pI=@URaeJuZEX?mee9V^x;w!G2zNYo zww95e0QS>E9DuCfh?``;WBz@8`AWP?tnq@qZJ%5dc&}GN{Y%Dkc6HT#1ncza^o}#A zs$uf@xXJ6c?y_^bYE?b2Zre+??9AC1CQ*-Q&Y{?ZyWG7sjxM z35k&BW1QjHrtA4Jh@UH49<qx|!f)59?hO5*q@sV@P0O{jT8UI+@RZ(Cqm^apkjPA_#cC4M@t=*p&;J)B1 zsg910r3dFM&=i=kehppMeL4=j9Ov#%uT%x}^%4uYo=^Q$&_mjSWg^HX7$XUZwEm{K zfov-dP7VgE(FA@KRE^KIvO3#Zv}RDy43tw{;wr1GGPSgnzNDaHk|mW8{mua>Iy8MK z6E!`-$}D-dF9xTadRMG~7U{Rmz{SJnrh>+LM2L=R35&-vK3isIc2t$@JIm1ID$yc4aGvzwx`AMmeCd<6omqGi~alT%P> z;*4^%^$Q6=p|RK5DdLPlW+qXpr#wBfiXtu{9xg_9I);pK@n|fb zT42lRC>wq;i*oBlk2}bgz#)Sg6550=W;7FRGMk7TG@NYR9%zx+ zBy>dz5_d-FH-m(r%>TuAJow6}#@}!2(2_6B`d}A4m&QwE;y7b9I$MKYEcFlxJo~ZB;G7o)JaU zbv7Ph$&_19wq zLoUIuY9iP6)u$ay4!g6z$2BKUeZ9!0IeEKQJE6HK2#!R8!tXxSv=>y zk3HBp(AW^hwt=v=;xNSLy~p!RPG9zVe&p}L@$vClzdXFN}CZU);n)_XJQPg2~kra7*!{lh_t9ybyAe^C;+|1VFXuNNB6&(3BK0D)}e{dLGOy)V;>f zoM`T08xE})7e#(u3uRclCRO7!61&pUzs?a?!{*F}?DT|dI22^!G)^1p#=@)_TetlT zDHHdTr#3RJ7+OWy=eP>n=t7>T^@0^i~e+DfFtvQa968KEx$kD_{gUJ~v zi)Z6xoF6mz`n2Ywj2qP#QtUXiSTZZs$HYcEs%rvPXfMy2`mY9dOQ%}Rw3awwJ|b;M z31hKhhs%+3^5#X@D{cNk;-9|hdRBDGZqPz2(oWTWRjKm#)K6cSipYFl{IO`cU8QOs zLTqeL8z=H%O+WaJShI`vE7gDQOr}2VCrKB1I_M4;_6-V1NF|6$q3ONaO&U^%prBKZ zgcfc5lLimDd3C3v{3ffLox=2WB9^hlQR{lC*;&@I(919&$L6m>KR91xAu{f%W-X9! zp}jw6-D+2Fx*hv$KJ(L|EM!mVdt#zN!zd(XqA1sn#GDkn-HMR8XXwlWe32>JnhLx` z5rhpKeljLK<}brqbk#+0Lt7&PqtyR2kQJETJYOVfHlo8Ew)!;l%9 z85>@G!W14FB4NqDvoEUf2eHNXg{u*B_Tuf$fKin{@dqM*i{F6&N7xzcQxdz5#HWO2Z)Ap$42zR6HdE@hcOPQxfQCx-xL2Mb}G zXZ!iK#Ip{Ew+Yi$TUj&P(UtxQT)<>On&UGs0BAZ=|2jxa4}Z?{*{i{4z0GA8v|x(=a@-a#{h!mJ@-6N>*XqYhLKm z^_s53pTs4PZbT0j4oc>N0$D^vhU7JjJ8|O4C?_ zk`;>tH#Q-hLUI5VbRqv9nS zQxeqC7WG&{l;Z{)YppNkJLHy!DJ3#|IJ7o=Qb&q>T(dfq)&wtE-MDzH1F_@az@L4+ zWm+n7G6kPGPvu_%o~~&&NSDR~mq#zR`wdM^;1yj}nR*b-fnci5O-(jX<~BCUu-jW( z@<2R8UetIjorYSQ{oi(HnKurdiWjheyz%AjYY9@6qk{YE7cBwdUfEQ%Z}g^JWisQ} zL&T|Iq)zb^%@P~7;?sz910{`(E_BWQu(nHh-)dZz%?R~6RnD<6XqY_WNx?!l$>7`B z;NtB1N>H~scl(b^^$op+`3YOliIKlCkNhPT_9QN34p1RKWDXFP6hj@U%W~={Y=QKj zsb~S23LJ9538Wf+-*`OTnJY1}Py%@<4tbjCx7_K-=~M?w6W$a)Bi$^E>An9z#@V@f zd%Xt=MA{#@GuM#80m-%7hReL{2SQZO#j5EGO`nhZ;bw5V?o@ci(|@i%Li$KLty~B; z-=FtO9hJJ9(y{z*@E_$6qO$J(8JY@^Ms@)MDjTfP5m6+fBj0{JCZ(io#SXrqa0k+iyZzERFYGSKeUiI; zcs9w8T;t_g`kZHLZ?;FhCq9kQm6$;63wEf8AP-p&{9 z4?Edn8%3NPllQmF+zehbdDGnAvu?sX#q;CXTyJ$+f3B#4YZSosPa-us>C;Yi=1$rg z8F~kvWmsx*G|X&n%81GnYe<8A3p2fek5+82!@XXCtZMt6(aCfPAygf-wzf8zXFmcS zytC%ScJIK}-&1*hZK<*8XYK#gu63hx!?v4id`LSBG#kDGgU==`w6I}gIL`p9QCkDG zne)fyM(UH#!(K6>1t)c8J28_GP21&nAxcJ8qAeDpMmjNBeb9Eu;cAoNfe26k^X;)b zpmKxQw)nexXI@b>s!#m#O%WJ#bpT?OdaeE6CF{g+F7TX9Blv3O``C=M>}6fFE?sM0bZ*4r9p`tAZ@ z9l}-xykcu+uI+K4$H4_v5?C9M1xxaZ3ixYbbDwW?O$7^J=41EP+GZk({d$|C*dFIS zGMe|fwA6v%D#y>_@(4sY=iI3Ibs|pgkGZ0|Ju_o}C=EHiilXfj?Jge1eRezJ(OqLh z2c246{OH{6id?obQ4o6}6f>?qCS!M?V+T7iXo`rxlKYw_%rI+?9@HyDj+*zrXxnym z-DiPC>NYD|s0A-$V(UE|lg;~brsqchkZ2?TfxGF_upE)ki?;3@fEV9*$7Y``UT>4>0;OP}N9~4xf(+)O$ z!kjZ}@I$@d$#r&o)&(eW>U&A7_gPNm+KrfE-)*{{zWr!M&oX)}6hhxH!n zV4C7%&+juqQw>n%iIwvpiVISq3Z`x4b93__I@ima!5S}zvX0LC&OmT;jEOvECkkwh zi;YwL+BUx6Tx5Aw{LJBBT(pv&-`7flh38)k&fQOM2z*z5OrSrWF%1th;OWIAc7b$wTj(dis~8+MXw{Oa(R4%!l8$Nb%VTmTCX zC7c*LK$`Z@clGz-oqQCXIBznGNKTvuH;VgNxhXm!-ovAos@BEGN*Cd{$(}~xnl0V& zlGu?xp#Mt$975;fv)Kpqh*+GOhs~CHc3Z0Pi`cS+Oc^t>;9p%9d-!}mF$bshKY!9= z$^^szz3BEY`TF@k^eUe#kWC`#Nt@Vzs?wZXQ(`CZI7vZg!>w3sMa1VESN$=lhWS~= zc@i;{kNp7s0Nr_ZwP^KtlK6J+8LC@Ol@ea|3=uw*e}drIplPs@Fo&3VaqV$eoojr) zgh!YVc`XxGcI|ya^7OSX@PQ^!XQmOAMUYq36%+rERNtEjv7#Ez4b_AZ!`rWHKsT=M zf9ML9iH~Sj5A1_P44X;7*sIoQ$Ml!dGez{T>-;oYPkl|ZG8*^MIuV$ej3MB){W9f@ zsMKn9^xk=qLleZ~70h{M1O_8{MSr8&2G04OEr&DL#n+S3-p)taQ`J~-Pir7Ts3fH% zZS9u+W4wR&q1FMECSqdqFj$|vn*H$2Me3e@u0j^X+x~iLetl~0{;U!(q8X`^rN%cr zU#jGLT~^roKuGoPgG`i>t@xD&AhvfvU5DcZX~3E|x)6Q>UG;tW0-RjxQ7@U-%8KYF z%AGxh6;JaaD$8MC^ODq?JF2x$-fr4fTDC~EFa7Tri~uD(-d97A*xYIL7qo|_b0DOq zPKqFjUU_a%$`YpMyXWd-nGSsPH_E7?{QPeD{Gp9n0Bm%cbS}9RX|j42ge12h#TG>^ zavorJP=;RAu_Jl=?Wp->a@aRM@Y+J-^kOad#fd_Wf@x+QUN4%`N-**^`{=*7-$6M9?Z3T9>*-N#nKlJSeW+isrV; zjE$b_+gIOu<_x(o+rQvxmwDXIA+)%C54g05R;2Y=?`ZyRKe*pC z6SuHNN9{@BP=}%n=`ztW&_m#}@7!*~hgL@*UFvF>NZ22?>nMoWWfO^HG}oRF?zdIe z5)@)hpJ2G{aID+Yj| zQWQJ;kJ{&9FU(C)s>Wir)|;_g<3yuk)y_ws4y4mqYS#w^=!w_eS>kf(dQ;OYIsYm@ zW*keE9uH+~mRWn+;SkT!<+Ct$cMlHbJ>zoN3zz;F*`R;4!nM$yh6tj9L1*;AOOwJP zB28C;OoJxnkxIbz2W~V}wG#Fi)N|{UYf}iZ=-V%F!J*LjumhejaMm9Sx5HE+x^90p zGG)e#*%xivmR#nT3hyE-P3=6tg&H=4EBIbYkp~TIN9qUg67`4l_8w$+~ zc`p!|v8ACSUg8q@sgw}kg`6)s%n;KaU#S=YQ7xNfJ=AO6q&$HfYY(aJijIT87&31amrLCJUS6A0}t2((R*V9jo?`!Jxp{ilh zAJ1?gI2nm*;W^(02-_t2mK)-%M2DcL-acmnDAhTw0}nP8af@l$goF4CA@1Mpar@3R z(@^En-fud7D)`UJsf2wv5vQ?Nkh>Q;0|#Gy0sva>_%K!P$ZH#D;M;g~wY5eV04`Uh zsjR8(DKY@FOH7KfFXQ(H^_bQXyyc)gf+qde;k?=|@c!=X>`I?5wdge!v}s_buMhCz z=?%u8tkk2Z>g7Gkb1nLw>t_hsqii945HROU`lIaFg>Dh@(Mf3Q*|%!bCBtTo0oR<* z*ei7(ioQl8@GatEZPuG={eZrR9U0d;Ud`Epts`zt8{g_ShnxA#e{6Fn4FlvR&rdHd z4)DBva!+R6~@bTPWyO|aPG67KM4Nf$~)K5)A5~vJt1V{ zuv#L_9pnF~`qv{S7@uAP){{LoCx##0e@e_pbJY0Q?GR|r<7X#UgfJaZVBKc-y+{== z=1jA3TB&9PJxeWb`Jwwb*AKx?kCeiQIb1qg++-0;NLzePCQkZbh0?g;pN&xYBI)U! z^`qm{ z`%2>|EjnxWp$@DKv(PSx3yShgH9|c|m0}+5KC}zrW(Lh9jZdsi(`y zI4l^+94?j%NAJO$R`Whu_S{ZI1Np|&9;lDmNh}y1I1Z>#ugAxh?|Sd!)yP_LvshbM zOvLG;M< zR_>*=s!Z3BHoI&kcvSnRJ*|DOkLgWG&o9VmHPZa>YGWh_I%HXWuox)Dw{mC&;dOq3 z@*7V~mVka5^w^@Kew#L?{i%%x3ytE_L!)1jJ0(s_5g8Y=I0 zPhSbFC=QqmD_9#`p5Ikd5d1`!hz;kChTb&H?CtV-2PJceszNE-^u{MFTC!1htWJ&M zTXB-XwrUTtGC@&HJV-eJEqsvt-v~Wz-kfG8ABha()2&UqcxRq zZER^q7|>6ubQ@ZW{`SNvqt?=GI8ASk+~IG(KFy!NkuPpnGt9t>$ONQ#aoX(C0YB-I z)M;5Vq*po)!TwApXYu%Ex%0`>rVA%FV+&bn(Iu;XPc0TcY4CK`6#qR73PA{h9}<b6Ppp@=b^mTCVQeOciWFJRFyWt3^1 zZd1^K)AjuBPA4~g%Dy{YfgNNpExppmI5++k3Fn?y7y9?73_eE-A`KIK)hm@;mc0j0LHG|lm9p-w` zqxwsDx;KYHxeY0sFu#$4bH}L6;-DF|*FQFt7Z+e|jqZ@TtB<_oU(^w(ctYx%o4e#S z;H6Qix?#2%)T@7EBZQM1h7v3otDbHh>Kr(F!6;+^&R{4C2!tI&mPNMT7q6b>Y}%Tq zJ&g3bPD@=&ZUpT&xKH=CFX6_*@?_0tSCtnq8k(E$2mCyQH?RHbb4LPCfO!C&(#wXv7}SL$MgA@gd60@T0EZ!^@*&2CcU`Buz(6eN_xPCHkJMGw05j?n zEMx6el3r?ujqC$>pzcHf?}FRh2YD-zcAnq4y(Q^w9u9#|CL9E70}8qy5xB?9&YtGK zgv;GBdu8NsdkuY* zNUQk1OY8PKo7b;8iWIxtY;+r&(sg^@=zk$NG2XSaabipZp05e$7r;iM$4 z#%Hv)_V&{&OsCJ}3ZiE4?Ci|fyOKCBQ%`7F3p< z)$}rPmC0Kpy58o4_oP@!6{|x*J!s>Gp$&XL+P2eJj5orywXiAhut9@CB2bCww%znB zdW6_%>!*Mz2@Lb^?=9QO+fk{B&C~}36(*`S*;u~^4HNl&+ye+Qc^}@NB3@75eY=oi zd6!v_a>rc6)$hE)UNMM^*g{K}737t)82Yk0&;-uZ7WXod(d4oh8(;1cIY(N5TQ?sU z>*QvQO%C|TB|p$YTAG{polg>c1|Rn=EG_*jPcV+OE}0)axuKqVcz&VuPP^Yym^v4} z!(rcUO}u_{S>#zrUIMxNpW7(2FF9Z9C0$MrlV8^(b$r1yhbix^LTegc422h?EliamNZFlT>C$qiELFNCCQfS&9xc_mPcd>Y zlpV5BUKZCYqWX8JTemD6F4n~**UU;_>>TWW9=-gV+Bs)F*9^3)G_}iB9UodsaNaRa}Hmgxp}N~pG)s*BI_)a z7ZVec4}H9#@OZjhAO5}#B#{uqDylg4{$2U%i7lkVa(WV90IG7=7!4!3@--O!lJ)hH z;LT%)pk~UcB+usZ0JqURf=A4O)E{6=Q6~8sl|n3;ANQj2wmjE^Yy3f1n?{a{i@RXN zsK!urANT?qBw~?f)b%7pbodcm3L2VCXsbIb5#~(wOv16@VaoKfVOv%E)~8V+v)oJgK}gh(Z5r9mKck%S(lrL3q4eO#V--c1 z!~ccMcV9-?#RT$MSB3UINH_$$G%)mqW*h5rh+5xlL#%BO_TUxlx+h@MIv{)R&$yPg zGmGfR+co%s)8N)OJeFbkV;Yo39?v22RmiqnoTqv-94ClY^C=egHhI@9)nb?$H3dhm z)Z?c*7ua&Brq=ycXw(X+d?tPhO@FBRdkq$Dqb0i#I9UM7Kq@G<9q{pe^FG#mZlQ!2 zao~o{;^wh`2w$~!O`kl%7_;l_>~!v~tNvT>ghr5^d3v$YAW8Fw((w_=Cg*-A&V<%h zcR8wwd6|fCQs$1{3@W+nWe+JmBiq2IR#eJ!mqLnlw?@r~MJt{h%`*s-o6^W_Wj5A| zrN{}5>yo3k66G~g?o`D^vlG@SBw5N2P`MRcHsU{jN{;-^kd{@S8FwM$`xK;wt#$F? z)kMv*QqH*RWPk9tw(U5^2+MMUX01yfRz zm6TM4K{_1eM}<4999s6o3cTTcTsE^Q$!pxs8#I?ivKU)UBDRyozJM<|KgokMK-FtS z@~^B56j~EbtGo@mK{oCGb=Z^35wuR=TF9E7aEfYLVwRqsLxL%D!2FYy2K^y0usp0% z@O{Eo9v*%t_inz<8R9$mRXF~uz|Gm?oO5dqJQj1*H#%J3T?wX{*>nvsEra0w;n+Kv z-0i{JeTiBPo0SR<(t8w8L#1()rq5A~)GZm*I3LhBFKnPE<01GRBQ^lzet_1UhpO`m zwCyz=U)jW<1bLHU{9B;>wU(ypKi^c{Y6?u5Qi}L1@Ptw7QDc=#s-i8BKsSR_UvX#_ z>(U&zT3Vc}H%owTd);6ke4q0!$KTrsJyiT_u($#=HBu_;=!XxXUhCX8WXvfqR$gzz zB1Twq9GJ@gsaep{(WXaEIGi15eO#1ymHw+V)p26Oj12ky<$#%Ar>6kfiqKkwa_6E=#@)nAGfD|T}C`A=0Bu61iBq4*S zwZ>WLtr~lyT(jm$A?mUW=VxbS4eDIJg}H+7-Ce=&69689iYh0A${NML^ToKJs}-d? z$$A|FJ-1+X)+A3u9ejSGDJBR~sO0GsqZkR=PGZsL27p0zmGGJZ^8nP~#1m^`?3Ov7 z8ZWu~HPf~xXAt3l9e`O66}c+x&NDH~`Tn{Z`>gm|XVORKc^{8xx&gDDKur#zn6#EW zN7W4Z93q1O8y?#EHCrX6Ub1AKL;|fv0qNH-4Ok(MRw#`W7OjcCKPlnm@KB1iq@9{> z)KNtnfmK2Z%-Ds+#i6gS9`K(0l!+0NqVyZav_Bx2*?2`vOelKCe?lw3s@)iMf2I+8 zVj4zpjT#r9I77=)qCs~Cj3j@nb&n!dM!`tl>L)P9F{!zMw238;M6wXpx|e}o5!BQSK5<&JdH7FxnQG4C3aL1 zw+0*Oed~7IWUZr0v4ahoTI3s&Hk^KWLj?N09nxNcP8tKIaB6=Vg8}>+9c0kYz+PhI zUK$Xo$h?@_sZzO6pN3&_@hJJW9e>iNTQuigp&WxJYSg$dG&=ni=Z9){{@mDD1HtY| zysxXzTVgO({~6ENs(R~~*rhbqX0_YAk0e4P5wY8+kf42F)cbRWIwQmcF<(|pMICs{ zMn_Y6?|jfj&gx{9!ew9MT=Hi=EgPuB$oDAN4dxw0^>q-ty42`irPCD4A8$6uZthgM z42p6sO%b~wqD3*52D{dT3@fJa=$A*S2pLZAUX!9B=JzQi)Xx;P^@eN~j-Go`M zcL!aryVjU^Rf)DN!Rcyl@*?F@dMCP1dHh%4xOlr@ObOcD#xSz72}rR#p0m9Mako-B ze$QZa>gm>5gxvfm?Rl>aC{FD+G&HiWptpN~X2;wAliUwk`rIi2`oJb1@7Hm?!uKAqwx%xWm7Y@`qLzyl zr0FZh~JAQ&JmE| zB$zV?yIAYuOmKYi2!nciCN82R@#8tdM%9d63`6t7*Jwqf4DPchgZm9g?|(#Y9(KK9>Gkf8U{_9<;Dp=^MC^Y&3=$QCCxS(@wvypa zk5TIWj$SmBYyGD~j)^+r;1Q6iE%0U91_%JphF)1&SZS#&s|8bnCFpsGl5|Z9kHn=- zAP?MSE|KpVEChmARvNBy>3II_K9&&t+g+WiAn-MuHXah5jR75*-tM-1-`7&$zCVsyA%P*3v%@wdIcyxfO7kzqFjygZ0`P7mh9PM&GdM1>=U6M~i|NQxraCmqKdPPi~ogapc z4T0Or(9}e@u38{?adxh@crx>C^tY;}^iS5oWcGkRFEGNMHC7+^T2b2Q-doy$Qucr`UO z^;pG@G+i;`+L=q^P%{}Hhk&~q{<2u+r=%2qJ}UG`A*}l@Wttw5%AVK{Q+VMc!&Zy-|F;JAIYu_vOE%2WWFb ztnmX)eM8E?a~kjffLl`|v4rtnEf>WRs(g-nq>q>1SXZZD|8@7@CUbweXIsO;f0Sp- zjWxjccJ8}10q2B5)*cX2eJwHT8Xu(ZESOO&waxq^r&3syH@{oh_K&9txcF%#5ku&K z@ZyI8oePDDv}i{LLB6k<;D9#Tl4I;`IdQ(IodqWk;vFrf{gFu=N>V({^EW=D|6R1A;Y=kPXBD|3Ax{h*Z-ma450fw1*8{%d$P@ZRDobn= zGma0K;J^};<7L#QtegAX7{F^1O#7VEO#~MQpK9h9$@LRt@o@Jbbv?^Uo5isswg)Bb zp-TUeq5gqQEsaH>cxq3+wB0K3TT?Y-4S4otL{>n?L~`^Vf^53&VJnQ(;sHJ4j{Y4* zV~`OlsQ0vs^R2W-)f~k4pvPrbQB`rYI77vBN;kE2Rqb3+SLy4i1v@%AqNbtA6Dlzx zvC+wdlXX11p>yWHYj4TmK+b8Ce7O@7I)ORY;*A(nTe&ab*KTu;XtY{(JX@e4{2VAy zQB_sa(1?&P?^ib$t)Bnhch2?>_rTNHR=o^I^Y<&KN)rM1Bhgpe#mas6)yxCbK^#Oj zqI4>J^s$!my!1Pa-xb!Drk_WQ9cIuTudjY1Wfga0(%@KB%A}3uBFeUv6R$cjD$8xu z4E2hdroF$_QgLwzT5mp{bNwzIPaHY>hKNMNzv#Ys0llUGv+NN5JCX>@mjdTGIoX*% zwwqrCoIsEjmt8X9SHY~1loSmGMUkX9S`00WQy)!2k}QQeyE!`L3>ZY1UawMZ;L;?L z5B3mul{SnuXhju#&A0JNuQ?q=7frH(&J}H8c#MNd%BMpDm7v@$o`Z? zqpNEFmUiuLVy8dI-hIE=tm!VCKgWU~!Lhjc?L{dBdL#sId6RyxaDD7!aV^eg@7q`F zZua!`C8PV7+eQzmXv@-5=9svx&@j>z=W84Yi7d5A-;dFwZBI93)ATEQD|qFG1*2@sU^0Ke*GqfGnC-M*F>1=eWb<#+`c9ntkVn2UKl08yS~2`rta z2Jxcw*}v&nnT9^^?{U_<7A;N0l5e1|WT>*dkJ9}N4vdG~m3J-kt6G!ac(t&(fAoA2 zT}^qY$+S{{tdjnq@aG#zXW^2Ekq8LS$dtuQ$zoziB)fd^`T?_R3x;E2z`~Fzbty*o zAq{i7=dQP%$Lh35z|g6g&_$eKQ5=I%6_5}REE#pP7Mi!`Ey`V&6fY}&+Ra$Z_&3%i z>@1*vuZ6M(g~w_5A#FOHHDlVcS#x%JdSl8)LXS&~F&ny;<1d)9D%V{?bW{E39l)(h zmf)LUcWI8+WsS0mN+D~2ZaG#zzfj3?yzIMOauV|&%&1zYxDd( z0|t3B1Y%Qy=vXh0D=#3c=fldZNRO1LpCD|O2(@>8xUXQZT+@eJ5E#1oNFiB>Y^oxh ztaisq?8WOXQk4p?mF(ga?mS$HNC6lvEv-W?PJTrNJRo)%4bm{hF%m^o{Wk|$RF_YJ z;tna%<`=VSrie*k9$N{w*V3ej1uQX+Gdc#wFJx-Fr@A@o;8sE z>dm(ls~h-F#V~*pvbCmiWIuk;onG>LzvAfu*UpcJrarYYUgj;JTf)shmBUH48Av|b zCjoHiG|U0WMkmf~P&-P%Odph7yFSJ9O+@t7Fw)PiEhsDOoeS+EcyCSw%iW&Qp zsF%LUTePs*9ssi29ZBM8dH$_CA7E0h|!8Pdr^RHb1kx-P|T2Ip^~+ED_WVlaEve?&6wZYLy5;* zS@%!1zanaX_ot$t?@p?i6g5?+68+wA7+*Rhq5jhO=aWV_YEeMpCP3jT9b!7sqGx3g z5)nNUXK^%bzfEq_&S98;{}Ux{`42xX>OOrMNE8OW#q*SbpS)?Yrw2Vn49;uX@@M=r zs1JZE%84w8MSw%&VB+0J2iytUo?lR@F040Fws43aI2e?ImWPM*cdDbeicXj{=g5q% zqes&T$Haz1z>bU>QDdFuQuZYZ^X&?Y{k*!KeXZ3a?|6E*LJXI2NaY^>fb;p1Dx}frQR))FSWjld`O#HFAIaQGB6`1G~_FB^YDf8$} zpwFtsjG2m@Y|_A^Bb{E#;%s_CFYNsukO2D3t=7(ZwY0LVDzCZQ?JoA~A=a0hllK`@ zxc#{Z7+XA@D=s2qXLjS{iNN=nTnCaJFXUGM9RW$2|t1P8AYtA zb!Dl6fZT$un7*WFPMpMvr;%df>igz^tGTxFJ~8he#@dw-=J#ok^EF(~RQ1|V^btIL z_14hFbV^S6xq-$G5U5Xv0W;gs-5-}zw$FWi8`{776Vf1=W{e^GGP@Db z`PoT@eCs7WlGF!@H7d92rWN7Do0FHegHBmPDm+y_2OOSH1{h*nfT?Cq9;q(VE}z+R zRZQyIbF*gRkr%r|)cnmG$e_6Lao!PT6l2NE)7->j)p?AAphHhOnvT z-$lZD$ft>Bu zGHY+8Qf)AZFd?9z6^Algtn|Is{UXrJ`2f7n-3iQ~u|4gp7$ZDbtFT+)l#r2Z=;_+= z>|)TJ2?sEzLmdbv4Jsp3p>3;zvlqugG;nUtItwZmQ_4%4boDA3lHf+}-J3w=5B+CB zSdaxBkRF_NhJpEC4IpVqXt9L?tooq|KeHq$p7*u|2WM(!gR2%z3mQg(JBZ8AQE1`y zX&d!vS=j6wuBmbM=zQMD1Ht~FpdzrQC=ce{=j^yr2dD)Za%G5xcWDGiu!Wb_P^U8% zpwCQ9P8NaaNOV8U(H*K;{qd7oPT*B|%Oe;?#q1?mW8N!$0}};!1fQs%SRt<1%mDVe z+(GXPIFBZ-0(Z=re)n!TJWJEtz*r`hWQH~>~i6^uX`Wnp9~ig_yjgiam)SW` z%OC;FwU=e%M+X*)0BrH6S=4{Q5mvGoN$YpN$FJJw;zxUpnD~G9*k(`sl0SUk`pp2; zbQfe6I-{kCAdUyyHDVsxcevcx*l6ggF&8`h^Dn=3wFVP`nu0Kv>JW+>Lt#i+Jdwqu zmIqcrq5S?)J{Nx>i=VUi7CZP;r!X#c2iwNMF;V9D&n<71hB{|J(6&1K8o9}{kk z$5gDrTTs&@vl0$pSv21;J!qgUeCxa_BmIbf{H|@O;wUVY|MY= zy(JL&);*(K5kQQ2nA7%KM*Gn^o@6DejllfiC9sREO{c0 zoOC8>kyJcfaIwho-e`+pPSo)J=!-iw9|o(`Ti@bi`DCcD$l2b)U{aM3xO3UiqgzqJ zsOXH(n~LAf-2&dNu{U2%6qS@=GF*{mfiXQBChja2CdET&pK*K{m&e{qrX5%(2%|-P zn^U3pXx?yow*6lKSp%m0;Df*b*+?LqOJ!tqf=KXku&AcGrgnaQo>(kaQ0=T{W_D&~ zc6PQ8F$OmRq*AHN!OOu5^Yio6RM$9bs%wZPlA4yzcIG3I%flxJ`y+DX4RTGfbCM*L zIqZ&FS(c$dn=)Ihct+iBS)Ts|LeYcF4Bg8JY4E-l{R%!v43Ir4P#~rEHS_cHMK#qm z71J}*1*N5>%*@W5o}Hcj5rP4VNHYO2KR-V|Ix#UZUt}yQU)^*^(eTN^v*YJH2Z59E zWLyd9xP(yT&PtM0YcX5ylw}#S)s_l}g2BlP6Td)=@e>HKKZ=Od4f7sY^llWlYHr}| zf)ZRZomGl~Gr?exV0o~j+F6~Qi**7)$RMx=;dfAGUL0|sbzk;+ycXarqU9>M1PmdD zatS3HYTC;e^o+WD5hh*`M8BN=AL0W+o<#KZT7=T)P5+W8DPToDp=`x9Et)iqjJ#ei5Fo6GpPnk}1C0)i4t@;?5AzL;=2yNbtm~-z( zSnNO$oWX&C^YVOT5J7OITqfhp`M}|Wqys2W>;iInJKMc{g#rw7b2H|-*;y~pLsA`% z#aOzPN@R$C8quO>vwklE?uyLKtqM%~Unk?XRU&-?>GMBOqF=!WnE@0iLoE|vqJa6i z+1Y8J2k>SwfPw`?>sGoFKZ2M;dB+tL0pZBpoEaerGzg+A3^2t9wDrRWlL4}!*w*8S zzFM2MxQ~$JEJ8US;wx0 z~f|m(%+L83t1%0XK2)_XYkvF+hS${~kez z`0W1wMxf{c+VuStDKmGI_kG{sy^aaI)zBk|r9()9I2oq6QRuSn37NT%|1R+FjR6V} s#8!xPtH$Qpy3z-7y#FCS#FF^`0d1`4X^3W&Q2+n{07*qoM6N<$g3dvASpWb4 diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/4_gold/menu_div_gold_sub03.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/4_gold/menu_div_gold_sub03.png deleted file mode 100644 index f44ef1645ae7c5f16216ac30c95db6014ac22fc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19996 zcmaHS19v4&*Y*h~oH#kLamThN&cvSBHYfJPwr$(C?c~I^oj1?-1HN9hYj>}%)pcFP zUA3!2YY;c(yp005$-goxs|_Whs0K!3;m{QBeH3er?aMhF0?jfQ{Mhx&ddGL%r1 z0RY@7zS9K)0I&Z`e+&RPGXemodH?`-3IKp*m(ixc`~3piKw4bnTYq0KzuJAi6|9|v zh9dv~kNQ6Wo7?n$2LNPzB}Igk-PSHTy|lEJov%JJxmfzKp~YAbB7lA|;t@g;FbKlJ zeQ^iK*Vnf121+mCxdXN*0jA{KH{66Q7hfp)^x4Zm0o{vWvI~^CD%eK{>k876I zh=glq#nD@ z=SM*A^TB1ZvBuls)(?TZZCP?zsyBBMY)y3`4vyjF*DmyBu{Ih$hJ*Jyb=sg`l+f6C zc(0Jxr_UuEE~(9i^`l%2Fwltuk;?yeptH2VHsCX$WJ^yhMwN7Rbv1N#qn|RWsowlO z3-NR?b(R%&X*#d|SW9p$NGA#wT5V%)7fWT_apZGX z1*taJ*gQX9d4I+euD;#&sy%gW*u!zsjXN+f=24A}7-wy2xN2q|oe=WMC>IZ(I2AES z{B5P%AH#5ubgH~+SMAXz?QxH~uRGe}1Gti=xbLD~RRXAe*L}yd3C+tkUScC%zphs~ zK*w(FPcZL!V93SoA9h#M-cNVg?;`@dpDUZ!Ko8x^oU6{<-cAPB2n57vJjkj4!fxpq z!6%IQI%(cirs5C)pI-}5kfz`OgiK&TTU(ifogEb}05b;xLZ)Y|QWK}iW_?5bW~5lN zyzxl)Z+?1IvxiU7z)9EEY0KKemW7Zif_3K+xtTHpK6Y>eNwHs+|^atMWC7pi!os@&0dUw#wMx?s%^7#=QH z9UoIXd|8KdJekG^1Q5Pj$PpJFH-I-C_joS`0?uQ6HE%3nn-26=iQogc0Jx2Uk_J8ft_pjO;(P9^x}l4d?5iQRz1x9?&r`h8LsB;i4;vE;9K;Q0=M*(d6dVh=%@S z(0iJqYk6@s6S~)kC@_B{EPv!RbZPQo{b{4V++g}L6F>#eSjePXXxajH*dGbj12f>; zybd~dZ+G^n2MCozEQf`Oa$IfA_FdxB(aG_CYOifQGV`KpImvyO3IF1s#5cLoxI30Q zLE#jvq-{81lR4e#U(~69$~*7&58oI-r#R1bW_QD9 zGx{Fe&DViAA-LXCX5)ERJ$v)D23>u-t={O@QO1)|_LJ_d=Wx=5Yuz-%Ti1Dq*6zDv z+V*!$aKcVdbzot89oVRm9 z_cpHF=MkAF!xcyndiAYyoyYS6Zeh7MRDN8uOlx5koM`zcxw`qcv~u_-g?H~@039Dn zK|g-UAer3?4mi^``!(8oM93JiH#-fPdn8DzjB}`*FQdS)Ri)?v zi40o2k2Ao(_ZI{h-s#gnS+Q$K59~}yJ0mhF(HbmU#xMrt{8{T>tcW>v0!Vbg{tF5% z2Cj3Fqc8)ER^Zkaf%$q-1iJFBP;9eNN*D$`S!ZnVXX^#PV5Ji;S4+2RQ8@B3iMEd6F05|BP#ld6_FnUI#dq_u5`BC zBza1j^fpz@^*^-de#s2X2T%6Udci&c$|*2UNB^C|APP@?1=qrt*LyBsfs7t=l+9{} zjGn@*=n0W|@e5B2`ra71jOZycV7g?%w3i>SOAlR_Q7W2a!Y`lH3PjX40wIniJywyod+#Gxh$~l^4q^M`SJO#57+^_p0-Y5J0lXLS(**n^xa>YycCn@&gZ85}O?kiX z<{dQR%+}Mx1T+_CaBN}b6Ue1P$)yG*Z(;VYHp_-6qeiCY$W zFEA09(~ld07F8%gHu!a9@SoE$CkJT{3rn_<3BM$Bl0*Q2C<{H}2a_)+q5J~gX^Il6 zmb_2a!z4g{*9nX}A;ce5VP;LlG5$D8HUm$O8@ZrlWa|1q2BeSAuQRAEa1-Ayw>U06 z0^-=}RGTD7&H%xKR5cw-Bva7L@^ZW*LdisPsaLib4+odI$FNVpDhi$JPOA^SpRRF? zEqziFU=2lm;Whcy=aDOh6pVE)CEM$=?!aZ%mAz6b+v8uy3VxGxlDOpypt_+^ccRMj zA?dG;AlwEO0G)iQ1=Um}l%;%ttK;fm>W)fEN_xt8n`ge?QQ%B(JL5Ma5S(uX|EIqY z6nfArGuo&f5TuSw{?pVXPA^7&ml5Na88x&$LBub`IGDi!1zRRGiPR9_goq5qz9%Uh zveZfJU1Yc;-n5JZSxkIFtAuPEF{P;AjAsIsUOX|0q#ip;NcoYNCK~aHK zE-xV*gRG*`rC{jzvsmZIU*^yjVUnsGk?o#d@3!{#7(^jKS@V;b+&x37jDD#MuEwch z6@V7UCKaG=l7#;urF$WAa~SiC9_)r#kIbk<1aM^z{)+p}eM90;!e7cnU&~4eMayS!-sJT=%gaBgvZQBFd#ruHu#K)fxAbnx&5_qrB+ z^e=^zWXv7ez8U=<8xbTaY(<@jS#N=MKb;2PI+6jrr?)=<&#Ef#vB@3Kwso=-3-T!` z_+arlR6O%I`K?X5NecjM*Nj$Kr{hKf@c((NG-;^6w7pHyw{bAi1@q(FC0FQa^u<{ijv3nEkPxN` zLu_1KEaa7EDl=v~U@YRrCjW{iM zVhN={MaA3>5wXw^LpS!{GO&U`QLqGhu-@zw;jfwl>uhr<+KM4 z89`t52c`p+#Uy(|jJ$EB5oONC=PwT?UGIzkm?wVp5ew|ZWUqLptat)!XhwwUuaCRp;VZ&egjb`X^a9XIG~gnwZ;V;q(Kh9=I!`@a~=(jcCl zKffnmO;t!!1vh!ZYLbl#lco$kv(hmMG9QM1E+?20$BwzX{#Ji%Tmrpq)Fb?)v(ZoL zD8%5C&T?7>)7Un!(V6UEl|qu>Ln-wAMyr8_Wq1Bk>H{yP*Fj{OR@fTmGcc2!|MKMg$5X)^u`2| zbos54ccoJvzM$0|Gn3`ZXz4QkOJap7oNCO)UJf>q2xG6qaJwXY+T~-(>RL7q4s(`$ z-Fh;NCuS_y<6y9}2p5+}$FA4$cY~2cT@G+W={WLSU`ReuZe?Uc%js(jyB5vGdNw6% zn;Lv3gR4HjGFpzpv|>-cRC>C)$K&4U#&u%`Dr3q@=%8)V!q&JyZLY68m8ImA*_ISn zH%E85M(ew(!^qMt{n505{ME77x-5(}I75ft+O|6RO$4cQ;z#duAgW;81<65Z0mtf0 zx>ZU92^dhu<+qr$?A!<$Pwk3DsX6*j&gqZ6Em2U{7YB~p^>X!86tbd7>kxy{^Fg|@ zSy`R#jYi}P;O)`1PBWvr3p=768=&6#c4^H6Z~=8jc5U$!LHGwPa1s4EOk!gPbaY80 znG0j(hYx+>{GARxs!OeoC0n0Ow+3EZvVM<|K$%oXJys2ec-nzZ1s8+3OoV#`owyga zvmmEYXd#J7TeHtOG$$OG219n3h9xBApGQlRG}wpr9^&IaZNOn{f>B!xpQb9yzgugI z?~PxnC1JgV;jQx=V)S;{Ecl#({1Fp) zDY6KJ1yyys(d`FlqSzjeA4~EHW>PC(XrW{Uf^lSdv%uMulAa#gHD&I`=ENNvGhby? zQ53jDT1}?3yVzSii6Mhtc}dx)_P8wsMH@moT+C1C5JtC(?9Q)OR7_{cxvwoCAp333 z#^Tfx06fO+F~Kl=S4lKpXc0f*yBww$;-tN;7$A<7Le0WzlOdzuAO*L#!%R!*$dT_} zlWm;;4LSh;(JKxk*u1VYVo-fLhJvm#u*mUPn@XUY6mcy(@)H19RmpxFYfzk)XBNv~ z_k?Fh@!b!Sp9e1i_lQPA?^0x>U?gR3<=X!tZwa89P+JDmz47A7AZN*G)xkgSn+7&z zPkPq3$}@tzW5U-Dr~D0x7HYK7BR@TpE%#SlJZZ)ud=xuWqPI57C^p9gBh0bT(BrVL}34 zqaW^0#mG@*19F@Cgug;Kvk@pAqms)RBQ0!c#$PI#bdxH%CVtFC$VvOr z4xK%O^Oa&U6Xv*hVQ0Tjnpi9!dAsH?EMHh!SGMrmS)9hbAWc)kh+_q`c{?`|Ft#7N zKh>h7ol?(D{CLh6a5KZN`49uTkpienZ(EiZmlpqgw@ROi>@Gi)Q%i?TVPi+J_Nq#G z&97GJGid3?*YmH%B?cSwx{Oq%nG~e`26yD&%X7k~W*!zOcR~`rgkLq`{}WT6Yg*8A zzwLFTz&rHx=k{vGo5fPH_O=%SgUuhCKRMMid#}XL1 z7NvImPx(I?I`C$ou2PHiO2H+>E|4fI^Wao_^X>H4*5r05O4+h<%~SD@S~?m?)Da5o zD~+HF83L_EWA*4~U@AJ-T&p zrFa)2qDv&5c*l`Q3155<7xro!pU%jo=*s~QcVP7sy2>Jk^wx&Q?+IIurNmiBtMfDg z%+MiuW#by}UnVQYW6k=k>r4mh^tvN|g_xcg-3%i5p6IOy@3S6uzHLbS3u|jY!{vsghbHdR`AQ4Uiv1); z*<54%nLr*B zJ|s+)NE})IvT4U%JvM{n5c!Acrn9EqvNf1qyX*$Yt0my_S1PmF#4@lO-CWRYRaMSZ zoN!qf9AR^YKGkQ4yhb!H#! zs86RnoK{#}rg{=HCf{}TBkjwEqGFHsi9YDl#^uVa%_e`Q5uztY0+^uP&VO1OHdu`C zZROg5b`2H?cT-KD>c^DEYo7wB?6Jw|_vjghJlr8Q{eGV{H8wOO>Q6Rrrw5pgiIBt+ z`RU*(#e`6X43LWKDWKj!9{;AY$SxfqE^=h%hZ|2`uJim$r!Xo?o7kBqE>y9MA~{Dn z2aD`Iv-)4+gka2kTul-f2?zghQC8F6wn13FByj0O&2ezG9D-cGnIc+ehqYHx zxiGm7be)B$bcNX)%n^v_ci4p2pqHFoA#XT0TGEn~+HtU?+V^A<06B815k3!ryq@Mj zD$Kw51{vtE}f1|_SXs#upQT=}_YY4{xkfQqfnwHiZR z4+e(Lt#}j9VV-~!++b)ZKv@|}(c01lVna7M94p3D$n7{{v|jDXl^czk4&9xs4&^Uf)&or9^qbJYye9WL!5k+3(Y{9X zUU1G7LnxFbpQ_ZlrAv(p?FU}v!sexwTK-;})WnB{SLaSi!t6j;YB>BW z1fq4V5q2!tO^5rqM3Fq-5CaMnxfm&tSVcHRsZn2|LO~J$tSA{GOq&_^$9}5mG2hO? zUiY0O|HF^&P=6$ZFbPQFOHvf100M&>jkq>4_rF|QfU%C>RKiXFv-oyZ&`K|2nxqjYd7R)X&M>^+)MN+^ri!!YziwvZ;MkHd|G<$%{MPhip$1Lh26N?J{38Qj;PxWBEaXs!`Ks-{3Zs~!<4B9GvbIq1*ACADB;p06e-assnLTY$xb4Ml6g0fP!teSypp`B z;7$XJM2cr;8x_@#XzA0xk^@B)!8?Q0t+I@$qt%_VUd+H@`CgUdlu2Z%QHJ&8k(NQ6Z@01kotbQ^?UY#|S~k_hR?ZxIk<5i9rc>zBnBu zNvNwCp7(3HWiWh8^#qgz{Hpk7{5e*Yby_jlGn!Q}w;UT;%TLdzYGQHMD>qKF>hXD$>P zpa=Hfc^Jp*i?L(hOR;)utoJlZ__jCMI8;Ns*>umGk0-Am^Q}qu2M^k4K>X@MRR<|g z*XA#qU``fU&32=wMhs=-Z;|~eENGglK_#ycnU5+ALzSV71jl*})w(ZVPP{+O2|@L9 zlOO{GJlgQYjRqTOolh^XwzgDAo!=U(hrNO>3Y+v#o+XQegTa6VI7MY*D^S7EfmQM< zCt8Rb&W)f}Oh5%RFdas|X+w6oHlnt;wlp^Da!@S%?P?WTQ1|HpV%uWG3^kZMem2CY zA&(=J47)M~0d>~R{~Hk_7IEIdoTNgY`H&^L0*OchjGrEnX(|w!1_;M6{{B&Ye#GPR za_^i>x=t|%qB)(oPyK3|jA>if&|n zZ06xub_Mbm8RbW zACJZJrLI807Fhzz*8(l3bsl{pQS3~4{tZxSLqf4};=~y>RC!1ueiISWACBkpT3+eg z_)D|DVWEwPsw&mDfY>s&a5lthYH_aE1S9XxPnvl{C*#bF8jDuX1#d1Y)VFe*6L85a zP^r1W`xcDECD*58Hqjwa{v%{CukQ#YMltk$jBJMoCN?Foy)V>tU^>0}d`}5UU;qtg z{$FQHn5cKKY}8C!eIgyA&Ep1LQEWNQc+IMIkl@EMVd2k^$48GNKQlQ{4<4h(dBPR1 z;Bc;={`S?}e6Oo@^?Kvplsn^!V`6Ztplr!NTG@o>SI=nu0^5>9g=wuxn|1hg@);pc z{|VLppJS^X)iYp!5t|oN05~?~_JD{VL(8ssI5PlWFd+2j zBaN<4+VW4lb(J&w!+SzRO9#!sgrHBqT$C|(*12X#K$8uo<@twFE)6&lrW`=5>Yw+k z0~SLGz-{M%-in#`mC79X-r03_ZB6)0ym@AA&EMQFowGEkD+F86$;Amp#+agNO~-<= zOe(_bZEdx)JyG1pwHDm7o{E$75U=KBt1MRLC-8^=3aVCFm?Z3?ydWLa%SR#D{sx} zO&y%m8-luAnl>rs8@TrHX^*tMjqpPm&et$O)l39AcbQ;+*cY!e$+r&hA03vxFwVW$ zEd6Pzam+wWy&R&8v)|>K`?Tp-pZU?%9pF^$Ps~|t#&r$;mgUiJ8HG)!Tk>a5hskM7 zZbrZy94N3-j0wmz{L7_;mfvvh<{M!9grY#AZoT`<1w)bT7VzcS5bh72T7V-$Tr^+& z>q-iml$!_ztLp`oi1&zIKw-abbOmlq@1fjNwk}7oiBmh)3kQPegX@(H zQxQmdCjSDRuwTN-f^mY9z*rg7&sD0ZgP+iCZ7rsBW?3n-Zs5{F#5=7T&_Dj2@Pm4u zBL>`})$3E_!7Z@p@99^qB0Q+^oVqzYyDn;;uKYTUf)Zzg{a$*gAKaX-%0E1wy4HNU z%H~2HUv`(6**tW!6D>V%A3*Dq3aEcVg{ZEpVO z-&`jaAiZ+6ZRU0F)G;ne;O|CfV{K!?sW#IbPdJ0?%p#}Rl9vuBnZMS8kromw zdld`*Pg^6@*2r!4PPQFNE+}9pw)D>07U={1m?C+ZtG~w}(4!WgliO*m+u$3X=j&&Y z=4-T{4@u0O!>~hauDtv^$fB9)^uYl7(&9fupQDmLBS8}rAquO4ZE`^fzyY>S_XK(6 z+R}k|E9;w@#=-u=5hKPzO8?)`@z>O2dG#NyU138|3aUJ9SP*}zm*am^#FB-o|CXRC z7cFA^nzJ!ACz=?JiA0s6%?*wcN(8{CR0j8HgmHU_o3~a*Ol{55BE$U0=zWQf*nCy+ zbkUSyn&ARJMFRiLA(N0GbuOh_*!Uf4o5YT3{l9yIrB?W30`7xiFCV$OCRuery^wrI z2Q3{e>rJ*ywX@FJo!ZoE*=)^qnp3DLnNdJiKxRMQdByL5oYEoKY18hjxk(E*)(#2q ziL5cInyS-7QB=XXq{edba`JwsZ@{@s`D9OzZeah3!ALL;E-G9Mjui|zciLmFyJvU)1u*=8Bi+cXcilWwkq6pPo z2NyZ>GQph{00oophj?u6c#LeD(_gJ>pqXkZG73Z0s&uT+c^dygUEEq?G2ZxFP z-D>&|cNCp87S&8PCTE5=g@i_rwM-}pK_Nm64HjQ7#DF<1q!3jP5WgxyOHB*O4cma? z&xM38dMNk?kZBH+a;&zu2VGz|mFlZu^khKzZ>X{{UKZJF5|ic=PkqBChKFt|&nN(- zXRMdWK!?Uqi&jAYXR0mqP!>VO@3s=o0TV}d$yP2~8U{&`FWF!tnIMoRMKlikoxPZf z5Mx>dFj9{#VAN>92r^zW&mw4IL>(9|nft(wHI4sBl5T8-jT%Y?$KDYDu@Xjeos}iR zo)RZp9@Hdj`*p2;?X}G}5W`q<>xKYS`-`{C-T3!`@W@w31br;Wz0$|csI2?qBG+3k zh_S3?Ea>?u5)M|cetk}%TVy2JGCIw^^xFW%dP>X`|8OFhOtB+;>1!(goNA&=O=_?( zHgUtrfHQPeU)jpwDWYdRuEim%fDRS@RrT|F#FY8&7GGP3t^4~V#Gfi=?`=h81(Q)O zXb2&|xv21MRP>8oV(WLfPFOYbpq%uS>3~Av^}+&*Ub_=G9D%bUL!yxSv+Vole1sC> zpZ-XgOEfk=v`mG8_Fp+?*OKL;gz3u*Yl&!SS0p!n%KX>nX#K1P;Xh1ZQA3K-|V1A5eGS zecAflsoln+${h^nVP&Kx2dk(H zW$H@>p9;$-^D`ET5v>I8ONOnR`MWTkl<$pmHpr3Ap?p1p)r7+TL0~=1jBjNwioKpT zw%Vq^$j14DG(VRW*+?T|r*04Ed4ZJ1HN!TP{!bkHuMhPmRN#XB8)vc% zUHifq5mYXk2(n2n*T8-+91-?pJznD=@j*7(K+cSV# zN2@={ftrN|O)SYkED8IY+qpr{S6Jg2h^z+WDi^FzT+=k_C^qs33%WIiBmNg(3M&v$ zELK`ozUbJ{3?yEiE;Ijqa3q?bNqG=R*P5vl`hc}L&=7N7)v|0Y`qfTgBSP3W-t$UDlCZA95Zy@9xl&(gs z_mYOv^-y*q&OMnJ)3S_Bw17}nYh4MjxMfSZi3|b~qCIWaO$c4pmPfDsv6^N019#P+ z(}~?-(TJ~uHD@w|ThP)G_YGJH%^Q%JztUu3!Cb=hMQgBRD|y&|unav^M=%$RLW4J+ zStPVLq293pYb0Vi&P^P(i2?tr5l)qZRijxTIE83%1ci!%1Qf#E;%mRa3k!@nK7Ym{8=G!OR4|899wb0jPmyiZskhu$UTB|17}fCbH91 zfGXAxhDYELQP4M$|8636xgQ1J{5B9}8OVXv)eN<{da(-;w;A48YD%1`yyi41iVYp`72_JI8XR0 zmK#XiVb{?;E-3vCxn3G_)@6g%r$z!x3XqZ02lSyqP8(aP=29Aidijx*AL;ie?}uqL!A)b&-?UEQ(jdT-o+&6 zDtXglhSnWm8o-H=!aXLIN&g}9AOAV`J5HT8tlywlKlYd~6~ZWE3Gx%3_uHO}-xc^e(ubtF-N*A@dg~nYlvT zMxuTWfXl+bd}m>LXQ_3%k15558fH!%#b(N&WoTmL#xCkmhxC!i7a;3;C=|Hb&y|B2 zoKheIc6PQ#Kxi964i(oVbHlt+)FvNN2jZqXChI=AX8VJ5I_^Ebi=*p>1K$acfH>uV z;*rv4R#wFC_8?WiU|e70zQaeX_uGCIK+E+Z^L0$c{)!O(k^m@fXRBVz(VT21{}4~w z60%w^a!6>&YUiiE?aXh4BhNbd?0O!SV{-5gyL|cp6r79#qN zjnutl@yMMCg@&1>aR2~0K87VCkwf$*j^x7lr_GIb-uE9K&s!kcs5iCt-e1=7DMoN6 zsU3|;AbYoy%ImsR0d|xkx5np9mi^&_n(b_b>*@WU;f>0>fXK@J; zc5Z2txv<%X!qv8j05$8j?Eg2yTIpy(v@HgfqhLJ$$8-u|f~NZ6cFaSPc^Z zSObkIx2ZNXHlvq8O)UDd4NG^oeMJ=!$(AOvx)5hT`?)~c1!6X{M*eh)w9m1OxR^9P zQ6&Us`)>)Qu`k~-fI@Uh=T_j4eHC@SizcEU3xr4_l^-@$dCm8RozeXWwLIUTYVhzcH>tr{ z0=1Qw(BJa^*8DdxMe$nCXw<|1XTd#It7BfkxMJHDg z_`QFRrgIn#=;pa#4Z`AZ%yg|4kVC_cY^Sf*JSFRC_Kww{+nf6r@l6r~u}L_1h$BZ$ z1GOir$+8Dq7mK92GG@49IM|2~6^^Dv6-Y7Y&;yM5*X<9$^K_Ixq=~7+*~RvHp5s>2 z;;$=Mfh);a-}?NKAko9;p>Dy^MLEJcE@&_u=xn2VUar88lON+T3paw>szVi zhry+c#wWzO>($Qi8}}TMn_fVC6bo@%lu=P0JbuuGEbK@BY0a)yCnse1m(}5C%o>J9 z^1;v5ChLcqhes)4mexDGcK+Bm{-)yWbz5|`IE>M=lAGXC~<=FrnXa^?hb zkJ1#KA^^_hR|a2pd-k^w{ws$J=pZ7nV-85WcskGhp!~}C>~sl&N-llg^GG)Z)8-`+i=~2 z;GNJXEnVOP?-8TCrdnNehQoi;DJkxNneFT%fphYhzOUzns!I=VwS=^EzW9u!#8+r; z&kjRrQF(IgG|`EWXK>FpYe;}c?gEa6hrMNT(G8rqq~CL{?gwc4ulgXQ=vx&Bq} ze242Jc%`d#QB`i(-%JtHWdLk_W+}{XQ6l?UX<7o|YWRBZUtHZcFZdPe^HN)N+z7W) zImkOmITW3U_YT~JQ%^D6SA_!!1}|-hzy#RCcdXXNikJn@z`6&vi7Z@V7bbrldcmeN z3FEJm`SO2SS#{HS`DgzNiANzGx9p9l(-JSTrX+=r$-cm&w1@X*E;9?fBep%^|m#KQ;Tsf zNB#k{FESDvpBvZ9+@>AkHC>xw55@cNN6p^)tzX8KGd+<(HW5L|t3I5uY>2d6rJZ-O zuSj?~F70*@)s+}hs$U*?=S#N^-{xMR7>jpA5{c$3FX}W^N^OPwMOB%FRCyWDTUR@{ zajKDuhRyYS>|LVNxl(f*ytxAIuLg$DW8MTzWM@Ycz1PP`F66I(|2eTKRTc@}!32En zL0yP~UfOIyFRepsMPeMAd^%lE(HBG=t?Q_zB9BHQj5OM@RTzM)c>C>TivoD6*Tbi^ zv}Tv=-P&mz@SH2J*=p6T-Mm{&`!lq!dsKD^-usbX*G$)0_j4Vyfu^1RcAkQ7DxUP} z4w(f|rlD#R6yNkZ(NI6X4;djZR85<$eq71eo4SCBi8CFvI{;!P-%Gej{;MqOQz4I_ z%h$#>m7eCt8g?IcNX;G_({+dwpTT6ioLZpa3FEKzU!*jmAFqSI=s;aiSHIU>%pMqNF$qxWx%9_>98As!K^Slp{t0T1xY6QV)o~Ja+uumShvh0tWy+H%D<`^b))X2d3N`ds3 zPKL|E;!dP*Mv0BB&?#v=E=8$Xi2enqJ!v7~?}Mn}5E2QM<;7N+Arxyb!E%fQC1sD- zFAQFBU4{YD%wOw1jnP{yLTSo{Jn%651A&=Hx!Kwnch#5x_#-oM6mM`WKQjAU--P)h zxsC4pFt4|N2uSZ+NH4d^E^~8Q<0%aB$)zFw`F*_{pVJ&}ucO6(cW)@4;{}4MKTb%k zzCzSN>};{PT0%{9=$-JGj!{kZXG#Zno=g&d3&9Tvt}WJkUS1A$oxe{|l@~tD3gp&z zrkjn(u|k7k2#kgjOIhN^RBZoQme5=HclF!%+aYc4j`TFE7jV&iIHY8Y1&Trt7Rfc4 z2U5v_wf0C*!QW!>W~F;+(g5C`@V6V2e==@3`d+lV)OZyGPhaWXZn6mTYecBr%T-%B z?FPp8K$db~ZFG^wqo;|gQP~+H>>~PCMZ z@$`EhwOiw@IZ;1sUcEQ{+}1NSF;~)cB}DSx5h8f+3wZAbeFRqfJlG2Ya{u;9(R{6H zp;ag(TS_%)GFYRWUtNPUgI=;hd-9fOn*43Cua)rpdS;U^s~#=USyhJj1YP%KhiN>_ zOD#d4&$UoHR+Uh#vPC$1PgguWQJd>8r@B7j-*oJ@6F*Ko(m0ITdcSVEpJts0r0>L< zk2O)b4xS+RV2UiYd)c7EJ7U#)^#{xGB?oL_B}vfFSNWkB|y8d2orY3b&9u1o#D&nhLW z&4XN*bWLOLVD9zy6RWGksY;tun`uZLyQCEW@JcPYSz4ODK}!U}7FLi(k)8+*-t(=J zEpLP29Cy2z0dZ!T>;G|CLen)KzPwnmdc-@lTyS0(-;--99va5bz8e~px>?f<#|EaQ z2{yc+6{R=Y@0a34AD{iipFG!@s~Zh?x~BrYkDIQpDfSzFU4WgYV~Wphea4zJ`4pr= z*gD-*R`X9acayjIB~{w|S<>Mj{>&|`%!L0oe?h%EuRl!;up4X|4zvUaQvWQxzJV~W z%B)8j4YqsiEt;yeJ4nRYl)1(?In~_!j!M)_zS1d2iWkG?#Cqq zi!wX}1R0^Br>nM;AuzodG{HWrMoNJ9#m`l{^Jh-4;UE!el}wt)W+X<>U3>nww`_y6 z%+&vueN(E6FAijN{=OhXnAWKhW@G1cF7!cYGOJe4-9|{@b7J&augot_oJhH%e*?k6jzwq9cvptZDQV)wlmEQzj;CzqlDbHpox5r zA{bV&D$eJ~hfKl>(O(~tWbnD46KYegue9=2)4|`q=83+GYz0<9Ky@ ze6ue7bo9=2Oob|56gFUIVbM@J=+jV4DQj&^C>2cD&S0Ld9(lY0G;CcSUTY4QYSN&S zB0>T#F;qK_etF)Vf%cdProg~@Xc!3dzWKRqyh#GMbx?U+5h8+LhU7XH5;WD@=Y;jV zYb{m2-h?v9{ck=t`xn?l=}VeM`$JqEWWNhp}P1GOl)oRD2vh4(4 zPT)R7ut%8de+YccBdT&IGP+DFXLzWW+2KnSf$q)gNKRafJm%CqCfisI$S{+-p zMHaRAyCyRa)v7ZRwliR&7q%W3mvHUHr9}gb_WDr=m`jafk8EC)ju@0HAQjfO% zY{aIrOxH7UnM(TGnv#+1EuQh9VNaVH6q^eZQ_TgGutea~5C(xjL>6}!%o!%^5JklV z@vKu~gIeIVt~}!a#%pv|p35)tDGbq+U-Jve>9b&kst|1D%qi8C%u2fP1+`*Q#fapv zX&VI}X6H0XN+5Y5-76TctE|BoN)%Paz(n-V6UZe0-xvg*u5q^fJbf$5Lw9TSE_{iW zxT_6b9P?O1*gSl`>z)2f(P4ryVW|7x{WXoy^GhYRSfzDBE>?oY$6Dn-T%7UvA0TY5 zyU8npb5Yu`_Rr@x4io^Ocpdb(_P{jg^z^6+FC`5}?#rtpY)+IC9x{f_<(NhIxow(| zR5{>yHpU9*0~5Hyw;4XP`yctm(oa?Z01lB6JH?cl5$Twb{6U=-x({pbJDx&}*cK3& zr1Wvcy6}jeIgg`i#3^CmP|~$ASyyFgR3YKQht?X;Z;`q`X%NOT4QgAs@kADThkHOQ ze;&8(8X0&-IA})S$(BWqDzL+pBs$@Gz9gIO@QjMRfe9gk~>+WW`sgjb!C2{y3}E?>*eXk z^yl@<(-zLQ*?aMoe13`_Nc^$bL;P=Zoy7z$}-P@{NhCbE9ofAtszrg8Q(DvWE<9 z88_q%@!13wAp#mU*znj{-imFOhgbZd^1w>n*wBPNijqB|u?^wq*B9*Dg>#KJ`~vO2 zG)>Xl3W#VF8|U6idV^c;gm6808Ktwp8~?->ICA&tX+sy<{xnKMc5KFUgbo4J!|ca5 zU}}V4FOeea)G1pdRhzL@#}~YM^59Fa?iY4$4;gfTpPOe?doz7;b9ubL+fuaRC5cA! zOH(2c?e05p!cU@O9LAb1#G5WCwbb#}T5D>T&DhBCT^IUraXZ)?8V{gW0}K*v194{{ zZ14cs)4RMPPPOnyLq(>aAFHGlv8YKc1WtLNOmitU#d&@wXg=u_5@+@2)KC^J)e76(JCC|=Cy%xOYmyF_ObSlzruRmB-&c#FG~4XxCGfAw-dLNR7FC9I@A8ajtfuiIvr%dPJ#7b6z&;wBEa#5 z8-~Y?15Weiq!yLLwXj$#ZQb$9B+qziR`|`BfvFQ8PUR(O3bY`T zfx&zkIPuRmgV+@RfeLpY6mFt@EbXPS1I*74X9fWeSG<|p&Y~3f`dK_ci{MGduhMd=+ar)i z<5O$0$GV@;Hm_t6is6?e2FyD(01(J#kraWJ_Y;_!1vklicaBn+*D=ym)*;cvbL(tr zIW`N1MPd4%J*IxMM$I~H&Myv*>^Thept&SO@T*WmNJ`3JH$Xl(cC!{~H0WQ?uxvmPE0x|hY*<-Fq@wb`jkPc0|| z0=yqLG{ad0V(Fuc+mcFj0uR=6r-G<%B=%{dKR#AJs-3e%D=u$hVQ)FZ)K3c^-j*xh z&7D}te8v6*8-&mk|E^Nny}5LSb}|)vAJXPw=LX|Vr0LOHN~CpV;@UBEFu-eW&p`bb z0+T+YYH%N3L{!2aefQA|6EnV9S!X%pRX%jqe&cR zm)S>q#;U*(;*e~J^2~|<3tA1O@=SIi83~})@r7f8@wR)wwj1J;tf}#^rpCihpKoLM zOlF4Dv%ZP#pZIl(mY34@qo+CY`m3PN$oz^GR?5ZFE@f&eJooW?Yh@)gr_-2Uxu%we zy0uigGwZv){FU#X+W%VjTfi~I+P-mwch3cc6u5|xvNzQ7e;xqPNJl0dDP+0?D=>O? z#2HRF+vhl`AYIWo})`au=E~QX-;7KKD}pR85sLCg+>XI&@gAd4xjq#FK(y zr`|tCz(2vSf9_!%%Uui|6Ro!Y*!v6)4s+jq>U_PaL;%40>*8n}Rlik`1%Oe~4b1o{ z!FZDjlDIG=efHCj^1}0N7}N+Np7l-a`i+O_Kk_y|`kQYv?H6+#8UQL*SXt#NWR=IJ zbiVEN0>+lx-31x|Hg0XjQ(a434ePf5jjrkc{OPZ}IdtOuiz@SHQ~*qV(t zxD49r-bthqj0>Zmx&2KAN!r(!%|en z@xFJ7W8m4JzRs!P0q*<61DV{!jgY)mO)f~dl8n71TQCuYBD3+6Evp(giEJ~dknVdOwcG9av<9;O? zcmD3@KAxY_Tl9uJ3k~aCw6(p(7ryitZ*{#h^hP|&kjngN-~?ipHN+BA?jJM&=*a8= z6-DU9nv}SBa`>F`H&6V#?pDuAcJFGj-r~yRly`!*_G5nF^z5u6SqshPvK2P-?5si} zn$XL65;}A!(L@?rQ@-Xp2(w{!fnpa0I=!C?4Zgg4KadOW4xKZB5-KR4!U z%=vlK!fzN6BZFd~M*Y14*tC0B%f>`BJl)pbH-YE}L5v_8@88p~8o)c`&jGFXZ0>>( zC9bgNGY?Z$-^AV@e2FvsOJu53I#G2*fZ?c$^Wh-oS9rcckoe%btiOL1gaNnMm3V;{(cJ?9s_cX0i1HlBj zA^U!z%=txpLvt$CK;S@FW>%=jb801k7)IKG)nzMejm;a}tAoCv6qwD-2$~!<4EAK0 ztf+hYRMj`J=Q9s8cH|{qc>cNc^_Fc7y!5kuOJ?+*-Mi^Ll<^g~?-Tb?`>_WZINHUt zPd=XWet@cV4M^c!zXSKJu4LCy?~Ka)_Ym6qyIHqrO34HQ80W~eepnF0=NHYKUnH3j z8klC5D?_N|T3n)8^>+=zYExFV+PP`lhO!me+t0`56FR-Yf@H7|Q~V5P1yryWTKKPD z7mVBc{l^*V?LxNM0Qmm*zt4U5-G>6~eeO9v|EW&_nJA`OtMB~DQ?&2T_$kUVI30E@ zW_3zA8BU96S4knESn~YAcf98j#+&m9tKEcJrsar$Td3vJx`%1R*nZ)56+d_SWdZ<1 z2Wvq9pb!CqI2r%8LZDjxKS1;DJ1Rc{Eb~pM7Q6Y3VZ|sr2}Qz;jb%B?#1-~@_7SQY zni=ZtV*m61lD>4`efN=wM%nvZMnbsjMPCo_?30f(a5Q81aV~e_C{&|-siPH3o> zPMl!qy^KrHp8M}-+kg2i14p}f@_&7WNnb|NIF~zdE_afOMbgX%Fd2jZsB)L^);p&M z=ahIS8Rnly41p)e*hZpiIVaV0V>?#dAYJe7;Xe<`7Kw9Yx`DB*GzuJhY5%}6*Yc%T zABSc|7f@E_q^vA6lQ-1c#djVNV*dNz|Nf%q_S}CzdmeazXPKmO{EPf6(Jay#303ybn`mBE{>LNUG2K4 zM3b?f9UOdnE*c+F*W*PHt@{F*7`@tV)eFn`OQl~009=kzh^|4-N-+TMSWwqk=eyoRtj?VvnKt2$AejGi zHRRkV{i*{1GK#7;JaVFn)8MR9*tE`B5{|^Aa74^IWdY#g?To zHs=$Zp3(vMePgumeGdQmGqmr`1a+`EmZxg!8&D#VfcNC!!P$$Evksf3IA1ndvjN~N zvQS&;WZ$7vW0S$~VKU3HClK!169{9@4bRy9Jn4f10FC+D`s)IqAULbcDHoMx&9{{o zha)kE+zy*14FHY#{^_v)K;K9YVu4H;@RQ^;nFyWmE8P0wg8_i-{xXhG zT#X1YOpQ+~CbPwCU$xR9D+ygPmC{Kf?1augIyHAX9*_It$#^`TjGqexCIc4Pn77)q z+Gff#r6wjPQU<*Y7*f@Bx22NF#MIF7_qwL0ClAMy@pEyp($i65Gnd;74a+QM37fSb zq1Q{v!U8$@ulwGAmn5AenIcJ$BxlH2@^1Rf-Oq!5l|}(qqBufx9znD&t%aRvKjb}; zePd&Fdco#7gpmb+L?Ur==;Tn_(8-}A4u^v+o44Rt?xbZ$E5P*NvHq^mY^VdFz-crB zj8tUBJaU)WXn)5$1au;tGf|HLHIKivas9Q@2SEa8lsziYNLGLAf*~cpah}=i7TB-T)Cjcm4p&k5(vf~M|k0$#lQs&%(^}9dAG+s|C84S zjv*FgNC;q!AhiA&e!&wtH-kQi000331;N}4>6GI5-kn@pxQQ7Go^kN@X(4KaK!S#!RaxAGmEYFn7zqDc_qU)6=$IG9Z}c119=4 z`XB>9BWjrI6^--ss4ZAhQyj>ZUoWt4eEPlSlo*B#EGcS zv>}{UqKHYJi|RAK)Y-fnr4J$ivMEVMTx+6PBIELVxqwO9rdT?zEWT&6j`L*v$U|Hq z9Q&_2eb51*(QH=oW&Q6;bS=!&-gkja$h;3ceGqkk%Tbg}Yo1nr-^l7&9i(@cHjx3C zCJDHKcmGPzeSB8GsK7luzj0k2K$QXMx zP+Tt=vfc@qwU7TH=sy|&^ay5a%(_`)^K4z|13BLRkUpd(>Hh;t5#+M~6E%+j0000< KMNUMnLSTZtwjwS7 diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/5_platinum/menu_div_platinum_sub03.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/5_platinum/menu_div_platinum_sub03.png deleted file mode 100644 index 5738a84ab3df787badae40f5df4f89b39280e8c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20952 zcmaG{19v6Q)4s7b*x0tUv2AB#+qP}n$;P&A+sVfE#!mkC_kMtPPIcG0bNigBs_yBk zeyS!yK~5YV78@1-0KiL1h$sQM|9=e{64(#&8B78hxS61=AOKJw2lrtB0sKv9B%ve= z0C?Jgu z0021T{~E}`mhT4upvWUBBB)DWGv*WVKZpJqUaE2_xL%y;ti+ytkCT+FnotRzoO}!L2lE~8GAPzX-E%;*94><(``%?Uo;SZ4wwgXRN&(j*jE_^6W|E##0ZO}``Bg_K?-QEWJr^^d@;>j) zgA4?`2p@(Zgrld{KGlzc~gf;UL*55idIcvnvQ&B=f{@`AYzo|xpOuKbgroo1~41%1(R=`lr+fT z>NBcA`VD5!qR?Tt)06dlRn1V_X%IKq-lC1Ti_ewZ)z855;J#Uqw(*UG*`*1oO9N;) zuW96~^SZgN-Kjr8aJ|{e0T+loB=Zkq=o;$J!?U%sx|j!vIp1!OEygB<@xLvgy~wIz#;N}aq53J z|DA1)25ImY-JMp`^*oy9e){WhPs7kXa9ojtiqZKS_wU_pcayibo$_)bqd z$9_7{INo=;J7X`lrd)#(eFm+@-m&xqBtw7Fx-AN~({D8rtFZEd8VgL!XgjwX?$s_S zoO)@^uKAr$k*;j6Xs)eZs^WMFDqFoDZ+bJm%DtXr;EQXVUes~sTB0#-GMdz!5``f9 z3aooy&-c_MD*`4J#BWYvk1M;soe+H-mYrO;I%w{(?c9oHczq+TP;x45-HPxEZCl-% z=C|iZ9M5?iA}&lmOi##KxYc9uzwXkQ`O<8pV*Elwy>Ypm&6n@JjfA7$g9}_vi(L`A zmwZ*$j}+V;RGsON2|*;b%!FL^>x_eL#$GbMbe{fDA8P2`5lS+XFGqXTMHPY>RJEfE zDH~Klpd(vwDW#fpczM~Urh?8byP_tI51p=2Rx{xL>8L@7S{8f15Wkg&tmnpc?s82Y zUJvK^a>v+sg!%u|J`t_>^=LaN&3Cw#LXFRJ>{=HGt)~8a_=7xu7ycc z?xAm3E}a%#)mS$k>}-`WZ`I4rcsC-s2u9tu-Q?R0+iCoS2i&WL!rQr?6zAU>1gct= z@uTk^k4Ld2(2ZX3hW0+oJ^of8fFdjlC_PIY&bHE+*$>-gGDO$BD{@vea#pgTj_SGW zziNI)U;sXO%ej+#_d0c(@mb#;jwm>x1zFj*q#Y;*$fV6Zh2tk}_x6jFpd_U ztkcg$B7ftX8?RD^S4b5qq!fstPhSU{O>eo8?jn|LUXFb4G*@|)1Idw6JFw`EEudA4 zY7B66B0Hd8gVgcZguV!g{E#NBv3gJLe~@L|-2b@!h!Pi1c8k5!JH{6H=PT)d4**(} zyZ2iwj+?-H*I@AuY%53y3n*pkq%H>@^w;f@^pBU%N?WkCJDVYt^4b5STc>Q{xm5~U z6m-2_lXS6hsdye$n!4d$AH6-uVcl7w<;y!Cj9_YJGLw5&+EkT2vEd0h z`vVyPd~Cri2+}Yr>a_8Pv4vogx=3Empc1hhExIr>X1objj&7K4sTmjZ^uhwNm=XR6 zE{kS0e)Vq#u}^72aTC{@&Zu|a`_=i=hirbofFvI?`@By7!FKep#`L?1i?*W{)0KAZ zDyR0gy%8}>OFLsWToYGvDQgFq9No$NeI71Z^r)!&{P}njMnZ-mfkMIBWx`43M53r- z_aBDwbP-qTtRsoKgDV{uFtai!xfx;z)B6?ML&LW)teIpZf%k{$(|?x~B5A|sE@Grf z4dcUaDg5q=e?G5W8U!0%{a~EA+a2&KvZ@F5k5;(L><>z|b)Mha9DNBU*b$NPYzy0Rc5~gscRj$lpZEC_ zb&aA^sXJ-RYUZ7KBpt`}`)@6kOYadH+W1vpdLC#g$-x?l4KK~ij>9DVLw?vkrn(bvRfyENX=gLjH4pPm zHVXq0grtN&L?z;Wu{Ve{n(j!8^p89MDFX#e6D>NC)WllcjQJBleK1Kw9S{VNd1VI4 zXZBl--H3K_yY6U?_j@T&_SoUuhVtwM5bAoCZ>|6Ro8A2JZgjOpBVbQ;EX_$?gj-Aj z)kj$D*(}JMprGBHNcuBIj0sCNJ^A1hgnxz@W7>_C0wkX+lIJA2iHR1DO~WQ5s78S@ z-T12@h=0<%r@=80qm=PT9URHu-H^zGLCk0ZCYe5GDVHFI7D|{*xErie%758>l&-U( zVj?R0Q}`y2{UH-XK}BB`icr<opm%KiKi}1}s<^n(-Rxal}WO^RiI&=@29X ziw3S&e??!9JxP-ycB`UsBM2ER(MGf&2CFlEq@@nWlCB3Ex6Ey=1QfCF_fYzitXI9z z%Nej|F@npcPmv4tBLPgKGV~cG3JT+g(;7a6`PI#2nI6b?EB1o?UHh zs&lI}o?gb}flR9+B1~FfM!s)xtx7HJk_VJ>87tGRTOESAKIO1KwfcGS-;O{DV}K#n zwsNXT6AHG?sOCcOxUQtt#W~TnzCv`#6@+UEIT$MHM$-G#E5wvG>T#-Za`=pB(k6Jn zF}e(EhD~%VY^~wJlbDp0)KK%M@1X?vxUrBC(w_}OIZ0$?T}!Qr8C)o7^8U6CJYwzn zF0Hcof<2DK6S_PkMct(C#5r?r4YB^Em6a)wml8aGU`)*GU)zf+@=0%2hm}FV~ zl)rbtz6PXGt3m%&i zPfd%=S-6mz4%F3!bDz`ei*s9F5NMyAw|` zv2G0(NCI|4#&mtTX5vBvwk<~Nn@q=2SakJ-N$T-$__qVyQ= z*S17R=^(t9T|N|IjS1sXNk~zD$YPD>glMG<9e#SSMaI%1M@7+2FvH!$(N2lm=eaaC z*CR+W5S@{U&9*0yf(@Y)wT#WBM|*7`c%EKg4b}I+dQg|G`)t-YJ}mG(ET}>SsCf2{ z0C1kKWJND0D$g;`Z%kjJF<-;zORSG_o60n=;NihbnX5A-4i|XEw@$Ebl{$LTb2_od znbo1igQ-jvA6l0!2ThyFXIYM5eXN!bG>r?74!p{$knlUUl}7;upV^eAq8Qf|8O5!p(U?xt0L)YD;WOie5@st z`r}xunoXwNaLAT9Yp6xkV#4kCuL=!4a>*LYj!&vt&%5XT2z1xcY1`K)| z5vI;-Cs$`2M-i)5iLuQyP|RkK%~Q@9S;A?mOkaKG!I`nFyVu#rlC*|-$FPC0m^Z)8tRQ;SUds!v6mRn%6Bc3X;aTatE=WFna{{A>2kz@0Bs zTCn(;Y$uoDK?9=yN7}$!#|P}L>Qv$T<=L;@!Aa-dc6X_n@kSFwL0#3P+OnsRNji4C ziQppNLW_*-BAe%SiN*P0dEhVrP#+rBTAdWEf1DC7 z3T_C+;ZMVwt`sfN?6|tk?+Ui|vZ{*wwzA-U7O-?!*t$cFx|1l7;$LbUMly*YN$b&a z3?gl$l9*&L4+H;ZCqRQh8Ws}w@xM3NIk&dbUV}9qKFUUAMG%ymH2}4h%0F!FI?6$l zslFJBNn(y#xHF@uT)3LaYi%u(P%WXP`D7HJtT{FB~y3jJZbYQir5FD8;?6!*htTuK< z2O`IC(UenatsoQBG{3benQ@4ion8|fc_`-e9CVH<-mloWOSGfRr4Utg8pV$Mexs+$ zz}_!>61T6E4kE$Ar--QTD2`bRHX(Q2RHn-_Tzj2(Xj z-Efy%#L8fPp=cn*Zfp1FK)tg=N0yrAqT*B&q|WMHHf9-cC8eo$0KZHlke>+ae>Wi& z3JF|(m~Dq4g^C4SDkY_UY8tBjM`Olp6ao4&Mtnt>epJWLdFQ3yOXpw>|D40GQFxcO z6ed@{k1Ch82)!TCr6UzxHqXm9fA{Wd|1u|?badRbY$V6h({MQx!S-J%6xuJFf->*2 zct_XASQS|P0}5MNQ@OFw)IAUS=ed$v|Cf}R@5pnb8p2B%Vf=~l7z;InjDH_DT3@c+ zsBLEx3e^@vUP`m$_fr=3nr{+jawvUd|7IgUPrQSSJC}qz*HF;+D+@5pP8v3p0tFf- z_EY{^9@M~NNa2^ADmIT(=0pWGb!7$S=?w+7IJ0N3RJFKQ9R_EjQoe(ivhHK*Ih{}G zTa6}sml*&R4XylS&6RceDw#B^v1@!0UORI$=%e$;CdL*{BJY%IB3>-k)3Q z+s|cf@DT}(xtc))Q6Mzf%~s!({B$=WXl?bkpRHIg<2z!-1L>-%f=rWQKp`66rvf4F@{R6A)n zVa2R$LsQ%=jX)AH5nqZOorRS-IGLutwm4%&O*5fEc8rBtsRaf-1spL4Vc)?y{47T! zJXlnc!P;dj(fn$(!(P*7yrsSgGY9h6G>{aX*s!H;;ZP#{pG>#}sSs<21ZxL$!_>ZY zMS0@BNH#jq$nTz7k|S$4^#|%5 zn>)p2c}(CYA7eAr)Avb}T`?zyHYp<4Z3C0wYK8yp9|g5Qk8)1vGYA+!B1*)A!TpS5 zMNm>wl9_F1wR54%sz+9xrl1_qGO#RunK(b@MHV)gFtq~}f1(ykMa)7(+$ad70TzP+ zmdZ|xxSsiugw@!Fi^BQ^Y=Ct?F4$4cdw3F|7}JIPrY+J^NoRR7*+s&8I7r%YKs zKZW4SSPEjhd`S<|bFX`hOOoFI!oql|&i7Y>^o?{+$8>_|T3+QlbcUb0;7ZGeoL``E z^>mP%)Uxlm(p1;t5xJuo>?}zmlN_Y!dXgP@i5CC@c5W!R2qXgqa^py`2r^)PX239^ zc#jnOIVc zbUb|Bu%N<{WhmI9y(prwC?ZLM*0gC?#{cxs)Q~7Y3dSeu+Voh1Ou*KZ@b@E;cj0w( z3nRglc}IHmFr~p{qdr4Z?dhu{<zmVZ(yLMljNdt@kIwBdG`H$NcH$J|*1L{a|AM{_!t6f`OKi;V1I6y+@;~&?{Mb zVZ{U$2vqNUz*>8^Z{^!wz2BO=MLG1OCyx-QGfhRGhElYh%37`4-|deY`W_#%&rYsu z`;8x(mB^os8aAM)u1r195TL=Jm6bTlJNU4#FuF3ur4b^_5@O00rd&hOhL)O_2ve^J zv`>{zgEwo-&g-AzI~)TDqVO-N#aS*nr=?$^$-TP~esUqzIIXHS5ZlVSTV4=-v3Q#o z6><0|o@S#@TpQb{KXx3PjF7>pV`yOFJ8#U7Q`8vv88>=6->x-bc`V~}EMX55`}A0wyi{0=D7{@hCPbG!bkzh9XI%fA}C zxa=Y;hV&-Ek6ek8EZWK`P1+bJcEj^76qK z*kt;7&!D3wvzdjLoSI77uh3KjzEg&=Qn7QX#`J_`W|Tr~KLZ+GYSuIPZ5^7{NG z#!`s!0StDxTNLBc{yD!yvYRz)hM?AMs`(Ql!%zg&X*SWhGsP!^6Z-%B@dg9=8C)7f zb$qf;KlxFx$jkG!8dt5~G0TA6H=~ucR$oa)1z{Q}I8cD3+lo`m?POdVsP9esi@*M2 zXhJ}B)Bz-N#75Plc=$ivOD=& zjs2>l5pMJfx{5PyJ&1hT5L&ydX8V*yYyl+(; z7b`~%W;<7`S1%l5(e2}^$+6+K2RIK z;7;%1BFGGfkeMDJd2b=$kG0`KLPWEl-6i57G{MZ_X-Cr16G{^>j?;6Lzh-BcxzjA~ z;S3HTIM;DQ5TtZ)n2rzY3=SY0ig}n&lx*M{k&-OD9vQzsdwGTqRiJ^W#$Ro@+-afl z4ezQITp;0pe9q1_ef~aN$K1rWEqWia5*c7V)`khfcimnPAVea=%`Pdw6)UQ;*0r%Q zawQKOP8V(=$`a8QuUQ`{nUIZ+n{~XK;?4}kq5c(BpFVPhwMt7%>Il}q9@O5x;A~q{ zl#|olWw+Z69(3LIo|}V1H1$Q$wBYUZtHuQ(_jS*pqH^+-`&Y8Vzuo*g$ch$~ML+7r z>eqj1Jrc^wg$tX%zvhDUUWgINZxoKld%c*A{1#<}G@E*tr+Y5wd2QF)oiKW+=7Zkl zBi%cO4Yd*~d$D1jYfvhc{+KmS?Kp2ZT+qK%PTla`ufLbob~b6gXMNvX1@=iYfPknd#AoT-DSrwK!2jt9VT0d=ACdn<^xV!|+u{1FmS1pnvvPIa!mkqN zOWm6P`||!jr2zkFqq?e=P!pmfRkgdl^AQd37j?f;k&G{%ovNa*%d)R>*w6bnzq&b$ zbQ>K(P>MFv)Z>_byydm#b+WB`Q{SS?b0eJR7e4s@RCiL-eYw?2agg4VwAIw}<_UQq z2p;?<_cZU;5EmKg__8jARIar9&TlKryyMhA>qFPMwyfeZn(*}13pRJg0TF!QFyN1& zC_@b@1NPHLF`yar#ZOZ+a}tC)ijuyziY-k?Ee8&BVsfJKr)W4U;1Nd|t3G#cu?atJ zZj~FhA>7kT2sA{gCgnKpm(%Vj6wr5%-8&FFIWn8s*{hTKx8UE+Syl?m|JT%MnrNxFFZ8|s<=AK}hR zsa?36mo0Q@BAml%i0ee_QbTP)?6E1+oNG#Zyra&s9e;BzdKm~hfcVo~e zFAIrs2NN)Ph>r*Q#mNb2Zeg*#xv&t;(`nt~Av04(rmmUVAjmsdT3$nSl5tZbQdV*B z?%C;3MK!=*@A=ls^^B1JnDYC)6)vZz(St%doFOMtNSir!T)}q)^sP z8|SySraut{jFeIEuC6L`Z>XL2sI`6(SAaCoR9M0T&{UgUuU~&8@-;o~Mv1Ee@}WZg z{oaE3-GL71xZCZjLhd}S;i7`+jD5-DCxOE&3P6!mhZ7Y|eUcP?$=j7o$f)cVj)t%Pm zTW6FT>(QMa4*258G#4`K#OkyosoBW>DxEFy$5;G->AbNve9n>Wx^v{__dX`9u66mx zuJ=j|To+1u7afMhqa!6(m7w_t(+5qL_H&+XDaX8)>U@nzVVU79YdgZCs&uuuS2$cR z`}2c+{9wWr;FzFaXS@9?jVYo$D!LlozUKLH1p$28AyhxlwDlytHAEAa(-DP0n_Atp z+2nK;kBflwg8#WFp0vaJv_nu>-5w+U_4IQibMw@j+r`JjARtE;9t%0&wK1x6u_mK< z)x>%lJ zR?)iEu{Q${6_p)FR%ikjqZmTZ+ShC!`;yh^XsOUSjuTi|&jUXq=J)aB$H{Sys+HEx zWoh?p5;obRhlDw4OnY5$#<*f+E9=7iqP#s@INh21Phuw?RAST&!OB%+HD3b*zDPe^ zaPO+$5x0^VpWi1qZKa2YT_A?LU-LBT4Rk=tD9%gU$Mq?U3B!LezN3-O1yfU`rlk=- z7`wM1)M5Mno{I`A+g8en#2+~T7ZSYujRV0(Q|jeacU+@u&n2E%r^zC`65Bj1seGSd z=9h{4do+d0OsOVyn)(B6 zlD@k}H6=s3#A7!GJ-va|Jm1u`?bANfRw61@-X&Pvt5M~}=`?BZ@p!5Clm@jt?s8^5 zvXs{+lVK8oOk%L4$16Ei(kr}62B$Zkog1+U&2y&BP&!?#osUhiNvp1s6=l|L$S|QPYgPk|VVWP9&2K_w5~MSmoV(BiAA^leBO_NkHMu3DKK6=#~0l z*hfN=k(R;;TO!9wS;mPA4@-tUbEugs&ZX|EWa_`OCb6asdZ1y|6?VpA@^@p1YK#qS;wYNi?zR29BT>~Rx2F$5{5WHK&UnPDS%u%jbx zt4*q8?x@ILszFJ0sdNdes_~`B7Q!yr@K1)`7 z13VUC8#10BjdEbwz8|Lt5W$%E_~f_6v*qSnicps^wAm<-)V)yP*?@)$2nA2$t_zkth$?J91CBHr+*4#8~{(dx`P^#&ccHuQDK-91E|cDosDw)SX3r@fFv<@o|+w(Xm8JFLCVXbkglYVUT92K7phz~Y&rZx5%m|Bg{vAQXT^Uw zIjE~`Y#&*j)-*fh)x8Vkn3#FhMqN6Z_K-6p^rCXT%>uV&fQ;@3y>{Vw|zbS)<8Rx;1N4;>Lkm0_mYS%b&N9 zbUgOorE49e>yNv;NdmM=dsG0o8FkSaqari$%)JUQ?*(N%~Bb8H9VHb z=8Q%kY@F7`wYHqS#qMlA76HF+LRD2XR&71mtCdOl1I-v2QW41u5)!<~h z>U4NII+}zNO2>VIXGI+~@r$T1Xo$2JFfmZnT6t0ayca<&y-~?oDuHE0qLAB@pEOA! zXt`$KK`Kb6Na!H2(08avFL^I=INX_TDyg>i64cNtuuwr*0QH#L$qa_0%=l=-{E}3w z#v_foabx8npYXnL=V?4< zS5&}OR8a5Y-+KIlE4Vo@wcv94)HVwd@D$!9^!Ze98475BF{~m7bj@hf4N_+q{h4Dy&c1q8aT+!V0 zk<*2`oekRS9nSCH`k@hlJT30A^(T5Xtn<0>K<34SDaT=_68Q@*+4q7nuB*hPQ?mCU? z@s;^`FedwIhdM^Q5}@S?Duq*4G$ z%25{6X|#x`F)<5s50hVmMm3vd>u(cQjnJ7IkVDL5wcq)Zpj2uDglCKrTryl>iE?4n zmiX)af&g!(T(da0lxM1X2@P)(R5~mNyq1G%BZK-22!S}1z*(x-9 zM+%Gr#`H3B2^o}%atLqs)-`jWA<$HO75{7$_Dlr!u9Q4GRXE&#GND6LLSw6bVPJ6J zt)O)aY2X!>6eK(cEqKX{JfpM7nV{Bw`R$h{ORl*K)2U`vCOTcdsg-xKcoL=PEV|#z zSz3u)7L>L|JUwi&U_cn*Mrzc)EXZ8@}A@Q4V^@ktzoyc^q})OyA5Pd$Oz4 zb1p`!(nLd!d;+j5mo+2H$gdT@ppd$>T_iIm$%1KX9F-!v#|$tP7LpbxvsP@aid?l| z0mV3z8aLD=jC-TTOhyxpeGqmVaLBQwjmu){83|S`8_<;V0?IWW!*IVc=*9<5MWwLa z8BzBmN^?u<3&gZtxDr7E=OdtfO>_c|$n|d<(go!0*q?pgwv8baQYzTg9CvpR7yLZ^ z^(mWcPvpPZG#re7F&}BhI}Y!IU$M;IzD?a5F|%yT8co#M!b6alL{ zS=>9~`WJmzYb1*SK&{%?+E(0p7rXHlNGvLEZ*@Qb`ty7CtX!~o!(WnqFbX_#Tcv+u zfaN6X?}8G6T5eJ4ttZ+OVK=?I!zpI{$!0{%C?m!#q*)#R3WqIaLHDE%wMWKcQFxuR zPbK*jmyfBhKbvK^w{D&X(dRD^-FsU1Gn;=sF0B}w-mF!zRgoFmZ}`0}4AZ7AI>MAN z>rJ4!z<|iGu%y$XHyp!HQDXh4%QhTeWXkg%?+q{qqnJ&WhM+6^suZ*naLt!ZCZ~;~ z-3kB~?k_A*7@IUXl>*EKGlZH|p~W-DfkpRJ7!Hk#X7mOm;nsAyGbY{LZI{eWNyLm()zaARp{M#%l# zV`06r9m%vB)Hocvc~)%NOL`#>5;=tUkr)x)?2i z4i}BLZ66K}&D~B>&f2ml{te~XnIv6a#s~Ht9Cy4W z*CFrBa*b1Z9m+N0bAU+(R`WRAHXFAuRrw=TPBdgvAYQBohJWT4LgWeuFtb0%esr)c zzcX5>_nLLc)cgp)v}9M<(gVV2GhI+F$)8;HAeTx*WhhLNd)SAr1aX%+TlK3jMsEqPVj0=6M(b9TOAd?CdDc3fB~GuLb1idf@MeSN}6))4&CO3_s5v=)nWo@)+I zj&YBdIcBdWhI>p>UvON{w#rAxBU-}64bFY>m(>u*GVgxzqXd-fV{^2&`W8fvoR5zW zmapFlHq?O?ZZ_ZYU?abG==20J8mERB5LB8ai-V)|4JeoNbL@P_Q_L&vX-Qp)MR@w# z5JW^KJ7wLlt9{VNzE|4W8h6zSopY&p?V$Y=c#Pe88Szo4WqXrzj@s^B$uRDbRkTuS z0a0t07`L~f7Vjj*tW8whQ!hluaX$-5J9V!Nij7THq2Jn766|XR6)0|4fVYTRC7c6p z@`493F-uEJbDNveva;|wH$|3Ut1G{Q#G)#zaG(Dn)!Z>#TPeTMGAagZz|_5@q_j9k zWeBbC?ho_s%i16oCCabX(iD`<#V#6{c{2-arNW{!&AC-DWI%&ZQ7Nb?PbbQC#Vz_6 z_8NFBJbV=Owj*ao}EtsK;n(xq#3HJjH>2rceB(CFFQf~ag(6B3%BLMmiHX1>2wbGD5mgN zM_@g-ujfKPL9}a_y9V*SEu=d=>3__BFx7)sD92n+PhciX$%)$zG-V=#g@rM|UAE7@H?(b_( zlNq`hhWHd4!g#jZq2!Vy;YK23UXE3?Mh^p!!sUU~b4M|TSY_Sgf%g`S%0ZFEnWpjV zx2baU>+va6XJNTxK)v~5gE103_=$-%tio|}{b>C)Jx@^35Xn#P!a`>%<$t(Ofx%`X z5^D>ONAYtrUJUNg)1e4=^eZTyt;l_N2_(H&h_BxrtfenF0Pyt0_#*ViFMr0YtbER<}@~FJK_JuG~>l4HCaw0;;4B;mVfM zQx|KGw?zwyLX+D@=jyWF{chYmUJ`mGa!A7xvx0<$+bBM8d1#%zL^Gm9ZA#YL@}uX` zQ^-uy!m>elCUBz?`awSM8Td@dTN;ak-)uTxwiks1Uj+zpIWW=@c!oQ(G5+ON1dASy z^|sH#&wy>};Ls%Mj5iB@w7q{IEwlv#^9GgF%ZndL#NKC=brfFTmZ+Hs$X%2o*25!@ zDz>!6Wv2^gN^u`YdjHbC>3-#GUOX!5WEpPEWf(kd=VVVt@+0+GPh1Avij+j)X3Ax# zQUm@DUPlj2I+}ELO$|TcrO_{{DeB7ou8BzHo&NEo9ShghXsljAyUUR=E9D0}T+ZPW zbUa|o{h_7X%52d-O-nT;h2>GsC$Izy|K!)fKFsBM2aD1ibbkGWUT4rrrO$zrl#4gmw$zSVCLN^ zXR8%C9AeaSv_CtQDJNI!joSI$ z*|OPE3hM%dTSESJfi}dD&z&pVV9Clv&o6HYkH0;dKWhA4QXkE@x4pE2yPcIo$<7{8 z?TDC(B?%4!Ar}&CD8~KMAfu9c8}|+aQJRsHGuUoQcY$kV-ccSQYm&vWzB;?^^eNFU zri~-rUR<7FP@C7ITq;T1Kg#DqAUe~W!CsWcoGF(k%Tq$c%r2ihEG8HL->o|v?3ZZH zD)q3B>a<97Tq4}{c)vWQEP{4y(4@Z^8(-))F^me7*&EwwK?kKNl$kej6 z9r60ghU_yOA2b{{GIhm%-X+``jh+9vMYn8SMoG^!+?}!jRZhZmoNoHNBBPu$ci`EL zAGIF1ZYW0&?V=$ybar`ZY*Vj46#7U;j0BFlaev0=017|X)QttdiwK#Xks-%6PPnJ3 zC*@-U&sLctYk~uCf7;1AiXpM9v+a(j4S{fF(^DJYZU0H`Z3Orzo&DNFvt!`aq75t; z9Q+vIX`H7FdGcnXAv*!{fx(s`E4|jP;}-(2c1VnJ4=`E;$sKc;3*ER{Z=2bRb-zkh)hjV-w_%;N^@ZMm1&G z`+TPJHr6w-`Javj9O?CU*l0iXyyI+l(_beBLP*{e3+c*=DJbaKU?%KT#HD1kk%nRY z1_LcH9;#GZJB36=cC}6NxQ`hlizNkiHI(8LYzkgMfbT{5t5KHS z63dH;uHi(NV$`(Mg{KuJu2?dPMCZ}8{j+*Ef;nO84=+*AS^zYO(pa{I4ZM9la8kbl z_z+~oUzTdW(TB;3opG%u+XU`MwJ_nM9sg0x4#@BB@q4iX5v1v08fetHveiVbq= zB2d2neEuHTMoJHH-m}h;yTry4vm1f%fTIAF8yJPix7tbrLDoDs_y)hZZBMv8(H#L2t zo$b@GB@Hp{X1(r834+oaPFC}$Ta6SX30^XE{`mk&%SHnqG94U5bodJG!;AOu2+ggz zAgx|SrE0`LU!or~)`oYA*T;KqbhFJJJ|!-Q_@w~Qqa1sSAqy5d7;`K+kXR_4($u4D zGt@AXqyRVDw5sNL!iYo0eOBCTi{gJd=mpm=yPErf6y~!U zuxzG4mo@d64*ghcKjJ?IZp=XU0xaAZX*O`T09H9wf?#6H z5N&Mj2;cMO1$gldUNC&8kK%iT^SPFqK)Ja- zBlTdCdNWB#W@4F1PI735(;^{IP0mmX)YaCr)K#q*2>VQI>FD{LWrFu8#7`znxTkzA z5`2?2$8?^aaR|+7)fy=QZj{LP@LyjAU6?N{1@ZXjLi9T-V7Ha)$E>I@2n35_bas)C z#{Zs#vF^N#imyAZ`XsACceC-)BQyW~qCK1i=`gdh&W;1jCsN?hu z=@G)xt|R3ooB816FH$u>e;4VQTHG-wEZ$4$2TFLZ-|~ZRH8$I2T_p_mR}reh*}vIb zgBR;xUe_InYO1E&I-8YY>kgy%u7B&pS~d}#iXM^TzRuDtwm+$-J8$|lm14gQJ!1%O z19M(~dt(TzqaUOh^A(|2;N!U()oVnEDNpIefTB>PsMeME+t1D3(*N9%NCVx{*;-m& zouAJ;qo~t>Ak3N221~gO)8m@T?e=mfrGtg}4;Tgt8?AMyT&3SrI2TaZ7oZ1TQIieh z1>wnVx_czaKv%HLuA*YIU7ggBhMZ8w2LwG^>ip*k4OlT5u^X`Nb@a<>Q97N#L@y@h zaH3D)#b}lAm5r2TVq|YG5qpGp>Rm~z@pn8BulW7&X8#eg6d;Atf;AQ(QM}9lX+7G{ zLU6bfVgEYAD%od>wt_wLzMx}EQA;4paDRFoRG(r4EkM%j#;?|$-8YQ>lL&eTci;Yc zoF!?FBJ$^FlZGa`QPkAT3^K)xw>7>_OYG|!Pa+Y<_Y$i~R_i`~)}Q-J&Y2DdLaRra zDKRSTi^Hi16zvCj`+0uBnM4Fm*2%*c((iw2e$$ORZ|K_v2Bdx5tWy@xlt)=v;bTY% z{l*gd6XPSvNz-NTKN!AFy`)d*-B~$3d4G?G^A%9Q%}1_Q4QlJlR?+B)JM&FwJg@sf z$?2lJ*I)rGRC?-h^*~2_bhAatUPhD+w6tnMcCFKcc6<{1Ga)s7-<_~d_&%#CPS39O zpKBu?E)y2J-Q}Jcojc+R7JYu$)s$E}{o=}kd2X2co4`^j-G6>g-BnFRQ+{?#e%|tX zKCeZ_$|Ga0S=izgwnSUnalLhVIb-kYL3IWc#h18$3f7dDg6r(+Ql=)35~K#3iQZwE zmC?H+t@QiR0eBz_W0~Q887#%(SQeH@{WV-UrRd#Tk-$)Dl?Kr4h8!bsMcllzc|E#V zO+K9$s96t$g!e=qA3zWjW~*1v?i<1kh+v|&Y9af%_AUp7a-jQQUbgN+alyXI%*)yD ztPkoRmE;>L|6DMe3jIm}^GZ?A2|LbaOkrojh1BO{o7|)PsiGE@-Dgnzura9Tn=b!- zT$;eTk72j&3m5VvG$-Ke%XegQWIl(K3uDA+Y&6LLU`1WKE8kEO{Vw<2cE5s0*5JCd zfFbnMsX%<}UhaqEe=}H6RPho9OC4x#v&1gj`GgTdG3xStp+MzaRn%gb7=nLrw!dsv z!{i`Kw7hK3n4G2~Q<`$Ca!_jU)fwR3=i7M`vts{;60G_p4F%|HH+Zh2qiHc;YqD^v z;avSA43-H&Mzs(h(^V%RL)CDbl9#BaAd=8X3gbU^2u=~#72RwP|Eu$w6dUuv zFw=qqCzI?jkN7YT6rNUu_z(@ck*+r1KWTKQpPzHsC+`atxb>P`JpTF^vHOISWskz( z^I{Sy=w_sXxVyhkf)~h25jJ)W9S(tzX*U(y!e>*nJ1(!~A6_~{%{sSCd^XfO&{xbY zy{Sgf^z#OMmtkml=(-pHtGOVxf5A8TK4&@i-YFYPfaaH0=3w}}*nlRXj9Xzp3zQ+EV8D4o>Nx0s=UiJ4A;P5_fUy^vl0QDD<5hpe!{y9nfGpl2lU{PjT zPQJEstzpJ|S{{fHo4V3R>P`@?8VV;#m`5l6Y{s*A=X^_#CZh;zJeeUU3p{aVsP7}? z2IhR~s7S8n4mmulldI-2u=56dzG(N#0UPePS?huCGW3`Wn^Uyn5EXHOdB2`Nrl-GiL$&a@haDaTwM_waD}5{74#z`FR1^;yaEeB z>eTP%M$&+U>3u?~BOc4d%{!TH2ks##wjgc2;R$vdoT}6N#cj^`ulxITXNZ}_vmQyH zcyf3>X_WJ0Ab?D=c9jEHPKKO?JPE5%j981IfF7H$nl8GtX0t2VhKZrux9V{yeDssp zutyJR?q{!iOqC$uFL)F_ucE^SK_b9 z-{`Y51IcWg>ZP=Am^m1^JTVRVg_#S>ZWZk1pg{DjG1=~Cg^7qFUBoN6Fqn{cn%YVt znPgjq6%Yd(_NfS4F=Huh$hx}(NCyZ2I=5=-8Q|nE(EAcnA*|g}hIsLx)i<-MbNU>D z^Z5N4ze`XFwcCBCP14<}i$vWaRZVb3Gh)tN5#>frNmkxQ$Sdi30j&D0$Cmy}9lqo! zGr#0aNg4qWz+@LTe5QxX{{r3+A@9*AEp)$j2%E!6{cZb*PKUUdHuY?CT@5>LYi2qW z;^aHs*eo_~+KrA6TQ(m5h zygUo~Y$1~h9fiE{+8dlYc@i|R^Y&&uZZ~I7zmsG>!0!7Wz~(5T^@mT>{o2bJbFWIu zs*vX*O8})MrJ5XLPIA2(M_~~rQ!eH_p^6;q*5lez6MgCMf$o!i-K~f){1{?#r^h4qBg#11}@q1q&e~ptNC7JZx`Lj%iLhQV)8LQ1k_+p5B zdp;Kf7s)I6afu&r@sL3(rXzX@7IXOAx zO1YR!xu|NuYeX-;43ta;j&c1^v?l7YO!2NzPUuDw!MOvjvhyan=3W0UN zO}jtw>m{H5_J2R-R6>NzDM_c# z4V>0YPEBOh*EKqv&Jvu?63|K-G+?tA61q4=wlStMe{s)kb-LJML^Bmgn?0L|ar~7- zwzQ}oM{ zR+<_&1IVrICuf^)u8|@$OB#UUvT7{(4$3R81E9Ws2R@&N=b!uja9>a78$d52raz9z z?wKT&=n>}{d;SLjfaE(RRgM%=D!~GbPEAcj4!w9_&RJAqaym;)w!(E909$?`?xFr9 z0FJ+NHgIFzrp2ah4&!7XLScc4sXzo03P5_h2~PO9_jCUhdr=94?+A%<>U2LtLuZpx zAj_b~Y_Z@h7K1@``k4v>6#!~k`1-~h$x$M4kXp9(p@$#h@XLo$=SWo6HPG_F=jiQd z^9g z#r^;K*z2APo);A6Pb&bJK=l48gvs~5F#dxEfJ&+q7)6LN^m_d~FxmZ1N5nVob=2Rm z%Ve_`YE%gjof8AR;q&96HOe#9%O>SxOL|4r0l(v9V(FiV5@2 zKlePJ_~a)T9u}F#l3t?afzQ$OvAa3=ttV;y>5npw*K76EZgo;qT}16x=hDA^|E(#1 zV0s*|RadUhwK}$FEcp(qwg~_jwK4Yp>tkmR{p|ZkfL?harkXh;N}E#O-3LJ*1OS$k zOiEWR#A302CwzW%QB5c5ukBKbFN z+n7B*HN8~0#Cb-=v#p5!E+GvLzj%lX9uIfl za}RpG9=%?VE!RxZnj%I$qsUR2NK7WK)w1>a>(LwZ#A2xc{^vjUdA|M6-$c^tk+gd1 zZn}m0KKCW8wtW7_7w>0c^c;Gv6}?tMua#Kmv{Jm$l-OMDT-vgA?b3;p-szWK?Q%oR z4>8A{efQ*`OK1%elopxLCqg{(=pVjuvak0wc_B8aF#jTO1`%Zqvr5SQ!v+8~QE@?O zdQwti&O3HNKJfgHG$m`-(YUS2V#vzIKRH2Pf3F`nH$E|~bFRrV*4306$0w%AHR`l3 zml)B9Li5BFmEiY!Y5mCo?*6?$;+DJaWzy$m%IC#>?i^ox{BbHOE7??8nRGO*Endsm z*ceONrHpw8u~>{lFC5~|+wbJ;V9GI7bz>9ve&Jzy+Fs||kNu~^KD7|5BMwl@{k)@;+QU0XuuiH`BV_>2A*~?Ce}qM9~@}&NWIg$pTBFc55+T`m+Nbpih=%FJd4E zP}gunV<|xAiH;sb{+{X;Q$a96X34$}lzveXVEJ#(Dc{c_lBP63*gJM%%s)BNhRARC zE8ok2eCU;v(!SkWZF=pZHWU(xcQ#u#*#(>MdsCjpSRzJ$R|k_mFZX`-i&zayoK^Db z&khdKf4ZOIwZ+LSVpZpNyxqZw}9KrN62uIHh z?;?};{iI(60G3l+Y4eCdqE`7IL+HN{Lied=j~UTV0>i-~NIXVC*8pO=A-RzC52pXZi6cQJN;n6Z&z`UlVQ^wUpMw4sbO8_F~Q$>KhvAJJG>2`%@}l&&OM^OEF*givyhq&)pa)oj#68*vv)5N+9JqRRcP|6#8XIfOJwFM>7bCFoWm~ z0mKViATjvCo?lU3xMC}rS;$e_I~0X_I|ttGy(vs|3&LhGHrWjiIbvrV$lnuK2t>-joH*~DW?0BckIw>{l^f#`mtp#{h7kb zbE?nxfsXR8M866ESh`G0AXI_@F(5Zi&C0r|usjXgHMeZrloJX~>!t!TNgW-D&LtfA zx+TdFThi#3mU8n-352GTa|@3gKB$?P3UK%D{t;_S*0C6m^UznmN=f+^KKGg5V9a|V z5rd@|EalqmOE)$YVYBJU(#m9MW%SxiwYjx&-Q2=LV)38;t@Ta4mcdwp0GWC|gy{Y1 zN`uRv@s~=!3IMnqEg@8clx$itQ0hN7p}BW=ZTY74`MOXzN+>MU=we*6WXTm``PHN6 z&Y)qYuC~rL7o8&-jiT40@sC}g_4yxh-yeO6+8dhaIo{4!|NKwVe-qcHN}MI@IQI6* zG1oeq##Lg?4uvxTP`S~;owsgX{Jn?2eG)M{cOsTZx^O)R=6|4$oNJ|DbpSw0MF`tZ zivuB2XAiv6YyR|}t)eof214OzIsoSSho(+OqtTJM=v=gNQ{~zmV-C}yK$3y2&;JPT z=qN8gpAz|2yM3vuwhlQO4fglG(}tE2*E(B)%_3RS0Z_ToLCfvc{MFZ9^p1=M-a?s< z9ZN8QFkvSU&YWwG*nN=nVF7?z-&R6P7GgA=3(U?=&*n8ZRTQX4W*L%Ie-`_PraZuz zXf*1+FnU2Quou|YZK^c-$5Mkk?`Uefc3Ttq1qDm)vjgYGM=!Jir_qYUUe`KX1^}As zT^#Fj`=9w~R~JI>M*x2;!8wEkP=gk~vb`VP=d|z-h}0f52aFRV8v$G+Fny@aonN)7 z*wR#2THu?CP+&+tQ&5h{>5i2*`v&{`WlL2JRSivLfhj+OXZn!zk_Mo?a6dwa187ZVLoAMNskFonG2#tdONl4ov8Rpb z|7B7PF?#kOdY9V6&OH9DwlnDmHr6I{>QsgR5Rb>t4xZ^dJb0$>xV^x^_8rYQ);MY2 zy$|4GUvGCuXeNA=6!TGj&(p9qvs&jjf6z7vv?G|0@;|8D<1fvwf3NgmPys5XTLmgf z%4f~!_;k*vKen}C#5b)iDazx(;ghGm6Vv~WaKhvuBnCh+L@4K6myA&>Ks{)J`Ehbz07j`KL=iar@S-WBzFxwv;Y)p7aEM`ty@NN7(prQbie6 zNf6^hLLUYdkWOlH$#h!F1ILr8$rh=9zHa(ql_19D7mmt*pz9Fya6OpYTMdm0g(8Bva( zacywTyEeGy|NMWw(2JOmp+f-6gBbNsvurVj4+DJ|0RT#b5W(EZWLx6&Up@A;S|(ks zuRf==5k#*(!Ri&Xf{4-lAYx$WL+Eo54CgCfJ8<6T5BDJ$uC|Lx`_Sn9bowxj0aQ}$ zcv;z2V+Do4oL;XtocByvM?4cApe+`Qse{EuR_~<}DdwL>04FtnTuTmc{mAIlh9e#Q zuajU*+2bY!f*C$!qF<#CGXPXl?Q9cZ((Con5zoXl&<1$Y0HD%5qIaw2p%1~#{$<|_ z5&#H|c&Dtuc@m=77%2cu@geQ~@ZlQ-LZ)LyUFmEI5oXoMvK&K<56&vz>&T3=tM<7E z(ew4nb*5R_i?zgvD(4(VWG*cr0z7ldIlt6s-nG()5di6wASJF<(X2zbisAAFlcEUb zX}GfZo=N*ZPihUNFxN0I?^l67>;O<{Caw9>zPl2=7v`zgnsoVJ16k{rYr=r^rW0UDk!d&^l8_G)ZEAa5cD4n09pjIRc5_kwt4zk=|gGne?%YA bs`P&W*wbwj^1JM#00000NkvXXu0mjff+ar_ diff --git a/Plugins/Web/StatsWeb/wwwroot/images/icons/6_semipro/menu_div_semipro_sub03.png b/Plugins/Web/StatsWeb/wwwroot/images/icons/6_semipro/menu_div_semipro_sub03.png deleted file mode 100644 index 284818b74435baf440af91ae7bc1b9f3f7b9b81d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21663 zcmaG{gLh=j)1H_cXX8w4CmU~UI~&`!ZQI(|8*FSF8{4+6Z{FV@@XdL;>&%&ZPT#6q zQ@6V6=?Dcm@o(_B@Bjedo1}z@5=i?0H(;Sbb3dQKI7mR63Caor0CjN)?*>qy??grt zO0oceCk5!bU;yCtzw3_y02d|z;8Y&~;7$hsu718jD~_ZOu==9UhK1g}`%GI+^3NWDP35MfOgoA`cg_JaB z3db27Ft4&{t87=(%F5L;yCJstx+ zNMr(Ahy~6798m@vnqqxoo%QZxFB6CupN_qD+QnP5^w4(Idi3d$Gwt%nDaYxLQ!my% zl#ig^zyDwGXRG*?!&s?gGD7wDrj)^c71Qo8N*S=>#tac4Li>Gd`C5-#@(r{?6G+Oj zka_;=H{v9RILSEjg{L1fV?Hm-#}GH_cgg+ycXqx8FD)!(#OebU$QdV>6$qk z#rw&PdkNoe2kty2SdXzLWHxwg_O$4tkQH(5Zg;L{N4(nmBq6XE0@>scz#Cb1y` zrI!A0h}-$+|titMjuDzpZD<^?l@`VW93mxYh2V^?9T&LjqUOHZL~MPl54!MNwa*hoa&Q z8>jCfhaJL7PCnGz<1%qv<#&7!mxm2R0PE2`f?L|m>Nb4)Ty3mex?Hm|yXp!OkHx>d za(!%n^cwblLlxjejFxMC1Xg0H-T?Wx0%y#NI;x_zz79>1oLvp+>7J8Vwi#t{T>$PbdGE%1EjWvlT$ z03jZLRROt(`!@!!k|yeGX}t>`U{s;FuyC;b&tQ1;55w?GP;6I_0Kzr^KbLvTYHZSO ze`03NwMSH{UQks{7hd2fAV@;lvsT|;Dvh%-EbA4D=HZ3e_%xtAP2R(s34gbW?chan zb%65uhY)yjYMSG9kDzfkJ~YVs^#|o2TG5H#jJ1GTaCKGH)MSkB`&bwl6XVo$BjQp) z8`T8oo=1RoEgshq;oC3pRX%D6MirQ4rxkO^Je;L&sX#@IkOZ-!-0$`*k_TwV#Pgw=spRL<@_RG&D77F}xASqCpA#*kOhvd-%SX(&^pBOk~pzoBF za&Ao;T3)S{9o{2^>p9GMvKZNxaYY4PtL5ZHrCEo|Q$jBGom;c(IlxuKoru}T-$Blq z7!dD|vF%=@;9-HfrfXxc;L@}#`6GoKq@~9>^-Q1BAuN422e^Oztr9mfKIHacO$`Ol zLi#m|M}>$&Nyp$k<3FivWLX}s(~lBfc{RS0+*01H21$NkG4*l!A1rht69H+eE>cg6>H+>BFu|tNN_eB$MQ| z+8$73IZ9Va+z0E4HwBlR1)MkY{QLQa|LxlYXAXmB4g<>}_K03QPu;^xD*A2wIszHQ zE9fuzVj;t-%qOrUC@#Mw2*c$x0capNj<)tfmt!wEyNM28w43A@j>SsTGLng#Jr0kP z7vjsqr&T;0?E>ua@$=P0Pt%@`AEhJ=8xM&OCkzjK9v{0$zvLaS=<4--*LSzao{oo^ zjt}#(ajmeD0xU0?Qj+$k+xyry5jSluZbr?WkWdcG*v4jL4w@|U+v|Vz%%F3TUkPQn z5u*tR64k(f1?CF7icilLn+zri{^Qw>@mt4-C~^K7ONa#ki5wVw07i-ymvc|=aX90U z`&BsdmBhQ}^fgt#(PnU3c;qj2KN0ZgtZP{`^e$8!$(krI;tFLEa)Il6GB{?6;Y=kA zNU=_0L2!35v^;*^L9{ex9@5WqMWEzqId{a5owT(JV$%NbwF`rhpE9w70(O4yIGu9p z)>|je|1)F{Pl6{u>Q3)`>`nHG5ZE?^skm^I3^a03C~P>4gdgNh`m%~f!XJ@7>p4MhnM<5LnQTAtWS#fRX6`z9vGMQ+04 z6O$x4EEOzzFYsXK5p!`7rl+S2yU3%=nl5*Ggcg_=guqgH`2kz)&Z1B|@4K`0 z+lMT};mwuCFjd-`{Ps5{0C#oj{5+enhFGGKLLhv-o|u%J;A0$VoP2z8wg?k88QW;Z zF~Lou#S|F_KeG7K%<>J~7bI>>S*ik)h@&G*fImP;NeK;%+&2z`8i$-oP<=_8AC6CV%YJeVCuc*%lg0aOi9K zn!=%w=h&L=&0b@KT*va*n$5`r!GAZ|QoDU^`x5%?qN@Fg<}Yj>j=38^0kpmd8B}R& z^ImKY-tCSVhv^(kVq$41J9AIs?^b^Wo(Nq405h8O)YPMlDJp`P{%`YC6ou4>A1ozO zEpi@`@Q|ZS$HXYcFAv{3?zh%P8o$rZtw~aA`fVex zb&kI!(x6z5^8^F-!!jpWGb@;atSEq6GE6cNn-G1hf-Y)rn)i)&h3mVel@)+#V)W?H zt~$T1EB2B!?D>K*uh(ZxT#vs+{>8i&&L8LmB>CHtZlFOy1XE|4W#1|vM6%j#r#+Nu zm)|g;IqUGdJy=Ba8hx&m8Vr7HtO^S7#)IAu5qUSks#|+nl2u+^S?r=t+vw7`eiziP z@pjR8bkForg>g@f#!bD+4N=d(sQ2~(thr%)O$2C8CT9NSqs;G13?`N=lol$KCK1hK zAb4yTdU(Dh)o})%6x99>zxvY|HvDyk4rsW-n5f!bSd56X+gOk~`=h2vou(?!Q}c&GSMn7D z&Sxw`w#y7{MY+69jQ7YIaGgUq%t3f%DD)|S2nk3m>NlPzm92kaESK%jGY~`#ffAY! z$3d<&y}+%ovRZkX%Eih1i3th7JP5g_2H&1L1{YxJ2I!ApWtxB0zGX93fh^Hvi(K8V z>2Y70wY;@CwQ5&W{914M*vYXmNr3(VTSrxVJmr2R&?B!Q3T2X}HV~VkWVYya_4=s; z;DkYcd-!N~-9DC$wwn6YX*$hx;x)b#k9u%Kg-&ye40K@3!a~?ULX)2G5MjI#UbyS^3 z^Z#tJY!}gu?`Z>kGLg+uECa%m#0rEpCoJs^juM za#MSlIsoCJjQU$IYS@$#&3=}?fw8f(8#ZcMSX+w#Pxd~fyc>Rae90JFnfELbHGEOs z6=I~Y9|=Jv%qTgx+tuWpijqV1+&XoQY8=l21O)d(0PZ`;?dYG@c2~uAi8efoucZnf zDK7JR8ZbnfeBh8zn|_RdZ|d^EKQD5_gVp#ryHG*B=_J^Q6fBk-t2`DK7JO&J>mElr z>mFv_WjG3f&nZL!k}`3Zd2q0bL(Oa)%7%>;Ou&*e{AwPz!N)gf-ntL3b#V^b(kZ%}=ph0sMh6pRF9uV{ zp-#z`w+u@6ck!JiE%Aq6?eWk0lXXHbRxy{6+v|X?tb7z8B;^_9KU8llUu^txtOm`- znbGdX83tEWKNeD~pGSk{Rn&;Qc-I>rkveR#64?v9!MJ1e8|cQLQ&571A%l7$55xM1 zg?3N~<6z>3gUDI&q)nkyWk^9-IgI{AooxptDo2GYWDbj}0v`MiC7Q~En9UqE0$zov z>^Xt#_<~?N%kND#*W>l+{sGx(8hO!aiGM4|>R-?>sj`v>T;dD{E#t?bMPh?w-R?24 zw6PF*yw6h2@65{?=o|<>2=zi1l61`HOQmf;`flG#euwo7p?J0Y{n-hi&w`nzt&OH^ za*+dba_U%r`idJF=?F02Xbfuiy9PA6JlsS@?lH`yn$F-B(wni+cb5cwXKV7-r`?id0ogJZ>nYGd>J|Md(@NGL3np?SPLf7} z2}p{E;sIV1mKMH7t94X&qMZ?!JGowV`NstwbxyI)1o^dP@qq<_P(7kY;|-(Ef`E|` zCS6@ehX~ByMRd$Pb!AkP6i|=nt6)7F{O6CRV*Q(6<}6f{D3r}?sL67jsDZqu1-nn=1FJGCEbqDE+A%yythboZ zdpKybSo)5EDMIeQkZsZN{?3I}de;OYQLfaGM?H~Y#*p;WXBqi&m}MBzGGm>qV75A= zxS_F`$Sd?F?!|ELrRH-o$9P}0b}vWge7Q4gXOmCY{nO*~QHz7s&wy`n-MS6Q7sZQJ zRw2eW6}GBOqaGX6SBWg%1V}@K9jyPWVM^b0DvXyw z^YY_qb9fA|OXeYw+_|Y)d_{VGuVSVGP7ab7AKWDS_pW$ssG&Le7(-=IS3aR%Pu%no zx&!j4Ayr$qPj@&1;9oV@0&+C+Ip zK|Ve^j$D8FgB!%zz4O8G=BZCL02m+9&b6gY*J)3&z0E-ftI<4u*9IJmQVDHS-~eCOe(cYo3jIX`<6}VbAbm! zKuBJL9H>^c1Rin$!(IB3U{$w!j^*<{Ya-O@bsX@9HdU_ImJD;*&Odbjv)!~QOkB&) zxqE;1_HWmGMyMa)=Wr>qc(KMD4rUA^G2r3dS&E{}cco%0!Uapy<@+cKIU5eeMqzNhk@`9j4a4)D1J^#NgNQl<8^@ z*NU6=BLjsJqa_j}5S1AcjfE0rmQSteG!}bW!1v$<(gm1c;UP<5@ zp$+;H3kDJk2?^!m=!@}1YK3WJh~;SYbm;K#to34rsBO~NfsyWF^HbZ%kgzm@WCQz& z2kL9J40OGQ4NQzyx>di9()6#+W7ja*C~);wdWGYx#S-a$DWQ+QdR-YT?}4!Md_x#5 z23M%qci~#A?@ONeT^quuh%C$g+dU{bhA}w^K?o?2@0*sV0aF826Ngcba3hBs4i1;L z2^{3wiTreteh%lX*FCn+eOBt37W!ty5ZDb;hOl*S$}EtxdX2O5-Ck?xU0QDlBo;}B z6Q|3x6_F)6b302)vTmMPKW$w98^Vd>=&Fz5S=vN>>-=cEpzC(!8n4N*9ka8xE^=5~ z3^sxeGC$C*IZnNG3c=v??GyCONd0sE2kmJ{6`RV z*LZ58Cq6gGP2|2Y^gi1H%g(Df!G@L7gz&kptmkk^l;h@_qSx3eH)RNCDsR-DEv1Bo zj#}fXZYdi9s`ME!HSq3r)tv^qrQWeK^}*O5or?p9!|c=UzVk2!8CgLlwn!g737%{N zLApl=8t9K}B%wvw+IN(v(0p(Jcq!>4^5x%!Xg%4Oai%dW-A66)(07LiN^T+8M$=?a zL`dNNp;oxdU%kF+y4{JOMMiV1(2c+fm58?UTK!^K{7&bqM=|0*%s#&Ms8DVo=JkGV ztYSUr@!sq+dhCws4aMdm+|e>dt&tSaZ|T==KRgbS3CPzd)H{)WA6W0;Cjg*XPbQ`o z8|3`i-tVzrPB(yUzI4>rsz-xEFf{_(GeTMyX2JP8*%D^#>4l`Iswfevxa+m`;bp7s zLP}Np2<(bWw(K*GPQ&Z2$JGk@rjZ~yQxabwYcO{hWBuA3w){G)wpjH-@x72-4cD6X zx-t+kZj`9^I$eedL+ZHS1r$k1sPTjKVY|_KI1Zz5?A{F&z0vtVAQDMr2*>_`)Lk5;0iF+1OQ)U-J_U&KU8eWj zY&_0X**}d5PIz4#SvP3P3 zyxM=dc2sFcQ+dY9Pd6!dmPL2Iaj&%3u(CHI_3#e6;~ZI_bJ_unk20!#IvMIqAwBtC z|I+imvZ7w9sE~mRA-Oz|W#8S~4PieZ|aN$Av8#-s8GC>CUmIY8>2p!mx&rYkK55Bv`Y;&+rb}9 zi2fe24gq8*Q}{dF5I($shB6WpgU}U)3(kE79J4dkp%u>sm!%AZ&nLoFjaLvj_cF$bqjUNS zg?V|f^PMDct19+%ptrlUGyoL~9X!%OAo2}-7EFa3V{tU*;bos-o&MQB1hf;8O08YH zP<-%rdD@ix`p1-UX#MKdK9X(I!!kVv<^`007bo?4(ZKIPOu>In#f8`gEd2?^d(L|JzTV@j|3RTo%NLZR=O zT3voWU?flGjAv%ZD=<@ePli$?wy9KVC>o?K_T!2H9B)TN z2}hP;X{iLYwO@4t<>$xNz?*q5z6ZzBHW984yl@bqlvK61OJj^^6hncHJWQ*{3a1y0 z`_l(BL1*-5XivOZ{awID85EOu- z(1AVPR41JWOCpPZiw=xBm3RES3*Dz8JDcbbk#rLbx&PAl^gCWc184!rJ&c@`U2xXh z@PzKyvjgwtRv3*~vJfWRQ3=(Z^NYfp!Ro4)Ma$e5n+})tcMgufpJ1qEsH$U$4Y)Iz z4Sm!_8T;uDNRKRpD4%v~_2g{btuf!8?0z3SaE9NPAmZX$ufIQJncLdt@2n0WYVRp0 z@-8%xF zBvy{R%`QSq2Cc}s*&zOONRqb=eCgN_C@c;1L~+D%$J#dqWLdxE1q`Sj)a_BMT$_TT zyOCQAYQCc>&2(Y+F_luX7(o0uy@I7g^DaTelQPU^l#F3Vl~Oi`Nd=~W+#e`2x21*bbQySrj%xz;K!1ULEpG>5H zu6D6wAZ<-6w=3QET3iD@f$`i_$iugfJu-4~IijEFvX@VVTQ)L3@9>AsSt@s-fH4qcsHHQ=GC?6V25~;deExn6@FOC@J~A_VXv)8<*1^`qY)%gLg)Ak!`ZsCLbzImx9wtK}vwU3gC%jm_BHF~ZAV{YB= zDOL+#O-U1Y20Ijugp6i=)Wm%v?C2+4o2w?J&X!ON$%2ngAH-IlvISglbYC+1-?9HxnF93f&W-d+9;%>)FAJ{Ja!o@p9iTcYFg&!X_px*S7v0yn?sB%g=0kDbvhQ^0a)kOGO&J_P`N zME=B+;db*uA3n^a&qJ!?9w!HBznq3~$s~7&@NCJ}=+Fe&Y~m2X8vW5~relNrio6xc zUk16HozM4<>ky^J2kzE`bbd*z8H}>cI`OjXe^NQ9#3xqdG2woDmV+_(+xo=A$R$DJ zhrKb-r(uFgI6Y{5^m!}=M3C%wxhk<_DI~GQW6m^H?{78?@K>I_Zs<((+FoQzxj?!a&Waihtqt6bQ&Z@{GH&YJ z?E1i;oSWK)u+Im+%}vy}$^Vo}O-;qV1G~3~fXi}jbI&7y9dY;36*B{Xo~4AGoT2%; z@YgE}$EH20ysV>Pwbs*y`x!rki}QJ5L4oJc*K2mz$W+7~39E2k?bVID1HMxiv`Bw8 z0!fD))V(DnNkKBah^+S&Pb}veL0A~faY@BmJoPG(6Ildidw?R-BUD%Yu5+Ec>` zKag9t_)K1ab`PiT!w^?jP~idF`ewW>jaw@zL|`l=fRTxRtox7O;%9 zDp=w8NEGVebkT4!q3nD2A>)R&70*37i}MCFco??R+Jd9dn&so;W1^x=A`~Qa*f0x= zS5TiRikhB%X1*iKVI|C4Q?PO_U#%Ptrk~8ph0MZbq+W;MBFXZiV$%eY;($-|=+JnjL=7cBuIaB&4z}+30YB>(D6AB< z1QyzuWDN_dPbNW8S)$)0CTib5>-xz~5}At3P~oFd6^eJVV7IeinRwZUc2CJCq-1vn z({hhiF=>yvW`fX^ekpYa`+eT<-$m*1_I6wUns(~`_%@8cQ6z;sG~6*U#T1`iB`6A; zqZTApNQ`LyKtmA-cAA!I@Az-(@oF0W8mv|S$|fp7z%XmGiKT@_(}v;{EZfm1@HZ7L>wY5 zi3ylXq2!|yk;a*iNLJlG9IDb4EA?D_w5{B?*_1$^=+jl)(;AukL!1~>846ahLaJ94 z)-GnOE=8=@1`!_r3rmB5PNPYJ^*Rbdm|x8@6PFqq&586Ne%YQxhp)HM+#T_B5hDTj z`R_6XXX@BO*3vZ#FZE^k4$>}S5NC~HyKqEL(U+T~n6d8;QqLcs>*N>%1yNLRoA)p> zV7qQoo)Y|bJMc`%V2As8#u*?(E^H}<2s_7D)ELvG1{P=zyYRTwq+HL$ho1=#{-i&x zk%4@@&&aNb6S1*X{~}qDsxq98TwB%@3Ioi}4P}4_2mCEY1Ys*3L0xYhXxHuuMQ>+) z6#K)imY${P{UB9Osktgv$L_*#NsCn;VyX1h2xfc;1~bRL6_D;4Lf zvb;L~&~b*FgTE;Qb18DM(NU7VokXmFJ1Zu7!h1dFr?K%tQbI;vk2f{TB+b~n&sBs6 zjMZYb$rmB>`})%AP}d^+;wJj^>Wu@@zfyQf{ib9CkOoba>b0MrE>+!r1Z%pRLlt;x zH{1TwxYL(uCR}l7hm(u(7DvOy@mJQGB=my%DgRw;k*he6`_(Nf|oCIe#$l^IRBC zkSP%&jcH_$MadH0oGrND@;(#;v4m_Ek(x}J8#G7fs0mabH1H0^rt%lej;uSr$XBw zXKz7JA-<66H&uLQZtwE3xq9%*N5YUNHYap6%Jd0#A#3aMJ8aapWbiBs{V#+n$&!@_ z64x&;2Q7i=n~XO~3pMTa(xQPkPM;#Yf2C6C^kOnNo*+ag*nFs}Q>>faB_aRaeT8o7 zo}FlGe46R_nCOD`r~hgUdHi@okL8MMFDs9053pHU+CI+YvpKKJt1d14m?+FRypWyO zH7q=M7?H`7#VgB7JS*ErBi@;vRc0!ZPItNo;rJW(eW*Kao;Iaf!6sq8S!3rK<{B>R zE{?S3P}QP~ZF{NJ9Q(F7 zd9L7bU3yl^%< z?1UG4BrxJcvI7t`vv9`T(V1H()@&Jl&ahMp90g6k0s|YE=P`EM`rDVLx}_@sbBUw& zWi)K%y{Pu^hn-zPMG>1IF7NZ)!})TGxolNcMIOJ%U~&nc)n3UrP*x4L z_TypsPr2DiO2kK}o5)bS@1sjJMbNfP^z>wN_Kl~J7&Kusp7>J!alS_=8$>8uKQCYC z6ghv7_L{28Rvp6#BP6`GaA&gW!Q6UB5MMK?0Zzk5m}hMZ`dl5QC^`)a5e7UOtOYD8 z2?{*w^{B*O7f4dBhj@WPXi0GCSi+YExHvOTS4Jl_+&#j&t$R)M@fw|}LqGX~atofd zW)6of{u-mBwU}gW?Sbu4LTqFbjo?xSN=gV}Q`@!`>xC+tZ_#ojk6MW1AbU!Ra`_ zl1IPi2O53eTBZFp456xxy;#d~-*H>}<)duqZ73%P-O42-!mVvvb%dxsgaJUIGX8^n7aq@QH@8_E#QXN3yp7?uwtMs^s9N?80@zIhpIL+ENl6t+NjI1>WgigZ~>5G=7-2NshPLYeyoDs;sKdwJmz zg7Yf}G!yORr_(25o7ddE#PN7GZG|%%taFCD=(ZL{((IH@Q{Fw zZGMkI-r0SG7^st^o%kxDP|9^1aJVjlym!6qjtBraLK3~I5WLR+l|R&WTjF*VxkaYe z$3cvy_VxZbljKF9(&BemV35aYuY$>=TVdd z?LB(C+;~zU;_jHywzY4^$^(R)LSIyUBD?HCBMi=e9u{0w z%k9?S>arD`L(cj z43h$1NS#8qk(^AUOs1f;f2DxUMx$W004Z$1W{KIWkgg!1QZ~#JNc}TM$cl?Y+Y4bK z#pSn>L;r)HZ2!WyG8LLw!k>}5>P+ePh>srW@emW4DHFG<98CY*5(B!D5M!bT(vjm+ zbH&>Da0>ZYGGj`-Bbby1vMUUUt`Ubdc29XC~=^1^NxNKnIu>+4>Kd_I9p}Idcmo~ zeUhyd=|*yBzeD1sEoG^k2eo$kc;9YFHes4k6JU}o00lls6Cz(B-5;$lokr1Xg`|Rk zVK|vVrX9C>SxtSBd5Hy?Yd47TmqJe<6awd_U$`-K#C|dv$g?B$^7lG@=(=~HX(}pl z2+l;I+{H!p_*B8m8gbc1LA0MV2r{c5?gs#9>Ih6fdQ&F;M@D|M=&|`dLTqv;Io!d6 zR_oU-dHu$r!B0_9ll`fjxWDrEYZ^Ew`%{gPCI+hi_8bc#_mtL-lqKXAnb^p>XlcOc zoLE{4n$Y5wgx`2_@Gmg{W4SzdLClHlb{aU8v9a6FBPU>w0K3shZ#qX%CM<9~Hv$omf)yDW)hqF2HXiF&w#iD))>Xn5-Z_7_9ni3;+5HJl=ke82EvN2;GZq zn) zFlXF8e;u)~NA_T~Jd+w3VcW*Fubef*3r{5luB@!Qb89#qDk$j+x~S6U0GozweP{Y! z(r3+#Vv6t+l}rsJCdoP4L-)xbs1u5}8#HIMpn|~IxCt~Rg_4qk3r3s?Vj=XsRigf? z-_L02EswhBy|LVV-=9O*=x5RZQdrq8;_xpX!40J&U;oYH{m$CGIFG?<*GrDr8aE6; z5epKl6f9QDSE^KypYkq^gF(IshF?h$&HDTX`Gq_c^V7{Xt$N(}esa zPs0NITeklK&<8hAUKIBSrMz)o=4?*Wwq9a3I&gz&-zz{K0fBXNc#!aeGAn1Y=I`GZ zm&2*){-$&8v9SsPC`)hVL#;c6(QF;T#dG)76#-6vxk6z$8Y)4k7%^E+3=(|!{6%x7 z60@1t;Vm!)ZI$tLE{fIFUHbDLFPQT7HU?;LVNQPqTvOQrKNy$*`J7CAt@c9<4 zrs?D^iJD(y>dp-4jKW?r#*(t8H~9{=YMGd<02~T@2yBQ@u&{xt{V)ijz!+uc0bt* zQD2=CV-ux?v1Brx0+bkFH&NW^LV1-Pok>OUV~=()*1 zHp2U(g=zE|dq_|up=tRYOHo-_##T-Y5%7@amsB zue$h0f{XV@4lgRYdM1#wC|}mO3f+rfZ^1Z&0TWyPY(qg1@s^JabOxjQBhg#V(=|-6 zV*FMM@rp&R&~o$cNlVoU<#I!s`a}gcz|^>7fwSzVd%LB_jyBbGf3?uHvm8ja7;LMB z)<}rQjPTzYZ8?v{OtA!a8SzI`5JBQsO&6fTi0V|wfU&%=@Pu(=Quoo8mB zmDP=n?H@Lld(7P*5eF)`)riF3#MdhYe+Poxy`C6uv|_`d$qp+2KRbRb$}<8xucB7fxZQz0)8txsaHQ6T_D zR2KV}brUxHgT<)(&pk{3M|Pf)6=*3&S_&SH%_AhF7V3_c=)rO83HB_H&vHtO^+zu{ zr@PvTN#RmCHcU{|KNPse2-v2^SfD~5EB__ASk7ELUEFzRB6H$YHcuC30!(UF1zR`klE6$a@eHb^2lI%Lo#${^~xqsG8 z+s;or4-d+gI+8V&1PT&zk+kKdAEc1Ndyv9Ht>2!-(Jq^xI$fLIcfV>6u)ad~jtv<8 z=uTWbRh70BL<++^7AnRhSTOHgJ}GEh6#GmYH1Rbe#Cge>&^N_rkSF)lG4q4$!UKDw z7JS1HY|K{^Qp9L{p`Rco9Rs9d(?W~_W2rZ-{8<_-{%_`DzyAqI`KDNjrc0$y;0mQT zK2$k~!8B_UWS5tr$*q!_nzSLC?ox-fD;!*$e9KuDJDLl~fNlGZ;0_r`xxq-UW9*Xq zR`(7{sQ$w#N?O{eswz5Ym@v+2iEL-2L4oVVO8Q^7yNj(<0J&WI+uOfd3G%~Wzgo+p zlZ%v-Q&bgQ>+IV&H+-<~zZd*8a#X@a2a~UY6xs_GDm5bK9Gz`B*^zxeRqqC!Rbgrh zO{sdBdZPN(fbA~~BeEVSMh?ibV6M9;|L)pNeUD>R=WZsc6auC+mw0l8=aYi6<}Vm5 z!e`g^&ty+b5nB}DaO70KUwAHtru(xQt0iVZ#k)LsXXm8r=EqhSUY8HY#ha$bp_|t7 z*XKsn%a9G60N`5IS(xeO72|OGIK%dL9S{Sv`B+*ge|^dH$h*ujfr(QThd(7d=xubg zqK^yP?GyW6ZJv8CnU!4At-1chAOU%#$&$P&bU?;j5yZn5ze0m+E{M*PNo|FG9ql&>kuA z?b6m4EM}v0>kEbSL{?fd33FA71NR;nC9W(PxChcbH?IgK#}m@S3i>t-dns@bc-Wa z`pIpx{wUinCoc1#X>9*5?-KhnIi5IM_mt6jp9x_b%?{t8FoOM~!S?vnQoNPd4s42} zeOyU+3hqKWC-|Vn7gN}_TC0u1dKRbJ$=2BrMqrH?6rHYv@IvHDhK0E*O(Q(^T_l#e zP<$#4GdqP-OM6~go^J-@ma8y6za?{*&uwXz`%A`_)0xj#G(0xvOn*-VA(AT)GnY3d zay=W-xDiBTfPoIm)h&&xQ}*p3#HkTi5uri5G(ZL+SRYYP1Ta0I%io-u_|c^n3R(9}u30O{x$auMy)6S#Wx4 z3SCNbwmv*5yS+RqgGKOYbyZ|dr?mOj*Lnr)_%Rc*BO}ivI>%GP@(!ynu0ZwSh*V{1 zTjCI@4AGZuq2(tFdV;l$dq=OQTRa*B`qqd`wc)yOEQU1+z3%7b zAK(0jSAjlZr?jTISFUILTk;-fwn!a+5z?&mcwy@=P(;(TMkbl(&YX9g+y0Fd{5Y7v zsxCVV4-yu~$H0=2*U)n=$5B3p0z8wi>F?V8D$7;Gx8kqc;f-R%%3f$#AZAjzlT3rdUW1l zlRV!A9?vBLDnM^6WiKt{%Bnk4vtN#^N($u?vUwqBu*}~b^rK}n;Tr6Y_~Z!rM-xrP z2d;FyI9HqkA^g0v0?>bIJKfQ%XzPlb@B3uSxm6h-PWPQS8!#Q?5Ii{CUSsRVMc<{v z95EwT=o_Cpi@+BZ!6$T-jtX8l(i%o;XBVIWf-%z5Ku0Tn>)V^A=92zoXrsVsl4}(= ztlr`|FMKLOpRP@Nd^-QX0G1PJ?0AMpY5Bw9*txY=l#o|mPwkh#%%Q#e_`6JB`o2p72i5)(=7gM44Z?q?p5pT*0lsYuf?*8_=OBipCCpE=j2pROLYDHEsr0F?5>;tqaty+s#t;Kc1#mmqBo-eP? zLlqupUuzfAtW?~6E?QpLO6}zqF1!41Fz79e4h8Aj?_kUedBy^o{?I|5v4DU1(T}+1 zs%y}yX0dR=Ma(vaFwIWKG&`M^#y=vVWo&4SxjD1Q$-5XOtVXR?P!t8fUjdZ{RBBME z(Whu|pHfIkNy0sFidiNrp59~3&(EdmvP+nspG&^E5^K&ytog>@VXM1_H(!6BKRn+~ zj=6vxZ*((uN}+sl4Oy04N)}zgvKy{p>l06~gOdh`Xwe<`+-DtJi zSXr2xO0pV~)iB>`!4uF0vU2By7G7Eydi~W8oO^a2{Jo+mt%{=TQxs(!F@NJP2!J@5 z5n0CEM?P{gJmmEjmgMHmo1d))6|=L90O-?_Ri0Cm!d}$y^6x}OuDN*`xCY|m=ABJ@ znPbVKx~?`d=u$E6ALfK}fV;nY8#jGrIYdIBtk!(2)_jf~5zdp6@OjWwYXI%Q-c83V{0h2CNI>F6t$< z3+Op9!0z4Rxus>7QF(a{*WJ7tOI|Mj^p#ua>p2lS|KdyY7;t)c`tg=%1B#I)$A~tp zV3}u$+5W4RT@o^7q_Jgl<9it@RzrU~-2HuIS}dF%8^hh#!|bft6qXipYVZ{KdBwE6v70Ub`3x;@?&b>HrPM90 zpy$K@Jv{@M(zChl=GE+PZDZqI_r;u809AFh1japdygO;`WJoYR%^;DTW5Q%iBYS=} zsm4?mRxHGR@Pu>guXpVLb^=|BqKp9c2mnqKxBC4>0WdLX8+AXbfP?)(n1{jRNeqHJY(Gv`_H44UXEQW#3dJvTvgZURdwR*4mq&N^2mGIh z#DdbRZ@ZfhIu2sB=Hqbm(9*J-#WnK*_{FAY$(l18f?+D_8W~stzxZo`oBiT777M55@Ge{USj8O^T zZ~S%RM|d*Scj{KQ6vjtM{&7L*b2L1j%D`Ezpc4)o$3=*8VTCF)WY_1}wO zYf$l!mI5^uCHP1BkcU0wTC9xq2<5V-rjGm8#gjg4d#;1E-@cVyZ+B2uSi$OR%yjLE zuaj7{NQ@F1pKkv$# zqUC=g%imP`GW=iayWs`B#9CQGhaZ^<=d$u&b#nhL;dvEb_K zXSOkw^mK_2I{O*%%3QW+A$j>(wC=W(m!E~-FZzsuem5QOccDZggjTGy@!jvO;o?#= zN4tACdPKC+hLx)*D;NF0Yrx5fSD0oy_I5IG(#61lhk?E!vMs`25e~`JU14MC6*g4B z(L(}&3kt0?Tw}wKY3AsW9*%a4`)iXV^5@TC_YUDU-u+fPyWSSl#_O&u<7D43yWX|~ zge-H7Dy>S1F~6X!jJb2?0#H_2f!UJHFE&4OyzzyduK*taJ%p6e2=h-6xBQ(sAMSb5 zd9OBo9`{T`%qX4*3qQZN6JPM#O8YNZj zQV|Q^y4#KvG4)kcinJ&<-@GaY003j^aIA%1y}XVcJGXQ5*YBdNyoSyLZ8W|bH{EvZ z?Tjgr6;zdOH%i zqsY`i=AUl9xbmv2=R{9@?!UGmyZZscyWeq)11h6YirH3c zmzJ=9Ut;o!haSEsw%_z>3mxx95<{+7%EO!Qr}LnT=YI1TW#u*8{Pnx&^El|(+sT1_ zk+f><-BeVSP+nC^MO6uwOe+sHIjFd#c3Ji1cd!4B1)z23J{(7c)o<&wEiM4PB$)wx zV>0?wiSmoh!rlB{#2OdTV%9t$T(-|VmY8(up1&74|6X{llhTD|{{9~yq-KeYwmmJh z{jmjtP*ZE8rq)JVYYR_2dOwE_yIFOu@IO59pNT7){?*@onTo}QJpFhR9q)F>`g(J= zp0Y|a`#4k0~PXzo#0yJ)2yDD3sY}5i&*9u41Z-4oGSIhRcJqQth0vJGu zdRJsS{%JFPDue!9BmwEbe4+q=IcUkRy`sA6?)BfPY~8sJX_n~Te)5AYoq!94%k-&I zItUO*T1jo0tEciZGwtuW=yS!DI%}zgvI-%}n_m->K$c}n3eA)*6eiShB}mN@8+WZs zoZI)qCd#balI9&ZXKb1(0$IvpDeX5y5-_1}LFz`N*{pkO_`%+`7C8l`)$D>al*w@<84n%_*Paw2?7edkVaREcTbD=*c z06>61jbOeRC`XGHAr-E>d;NE^9Y?w}k=FlVq=M%H<>qW-x^GM-C=1I$6a@C;GLD1s ze1Vb?9)3(P_l?(D*!E&vBCNi)jPXh92i>)9BZLL>qog6ow%6h@mbMkOEU8~Y?Ul7` zdT4wg#c)x4ahVnv#QIX;u>QY5%C~3!FsDAtC?(F8$8;Zp{P1eBb~gj0*(w zdx0JVLH3IG7JB3l6hEf(TA>?{c6N3$=PQOE|$^{G<1K2=Kh4#^2qjjZJstfkqs z{I^gfqiKO2erzKR*V_2)BlocJ-{Xqk%7(4@4KMYM!e#5#C$fgGT^U}65^QLhj0NK8t`zG3|XHoA`lcC1gE2FM##iDJqW%gSS6*eK-ezM*OA8PFFi}@n|A38- zjy|6LRm6Cu$YBtRU750t^que=mVNRc5eA!H;1D8WcMKunW=C!nO}{h3blb_Fjs6l6 zU@`>}V`LS=is(Xwo%a#XZ8Ld}_}KXA3H^eFxmo^+025+;pcnvl?r>06K98Gks>9_P z!8JI7lmyQ_wS|1Em0P~G28%hF)^~(&|3r_I!`*R5&C2U-{NRC&%(q&3@Q3U9)s`(p zhZ!|XDp>v3*YNvick+5u+~rG1i7{UulLtNSvA2mcKia4F5sjgQQ;62@jBKOF|0494 z1^@^KP9Vm*UW5)Xxl$7PK&@7L+CLG<%E>buA|ObRVx9ILT&@vrzNrqg*+}wzIF?aqeA2>A=voi zyD^(HSpUGLiGkh$8KDS>;ipy`XMTrS&mAfBmhGsvMJ4wf+0;BZQtkEgAn~7B!GiB0N?`s^?$C) z{VdbuxrrcJR1#vk`l;dJF|{e%l&MM9&Qd}lbQ)DCS<;4+C9Qg7WXv88DuGZ?84V~( z%Km)^$NPJFrGNORuXFO)04I+RpoB!8-M_hIHA}u!#m^uAweQV0-cc04(x>>92_-~m zR+@g)m}yE2h6$&nq@Yo2!n0=03Lkg4_D)O$+7RRS=)C+ML;?+k&p7kp^8tX#6kXUN zh1inI`22EUmcgjcpO6EDlwjCA$Ar%(_xXJC4z-FtAV;lYRIS3`c8w@4O?$ZOzHe&H z*_m{H(8Z%aThGA25RX3ci_-%GLm=$&(d~!HQc`}F*_0kRrZS}K@s9Wo4Y@q~5yQD? zO7^H7e~iy?zdxBiPXLJI%tnpSs-x3sf)jFpWGP8+FzPeM$KrFey0H2~L(X373DAzhz8 zF%iI!u2%s=N4uTvh^1Imh;jZA1PDg>l%jS19Q1ht00;m~7ON=;-M~HS@y*K0Hf5&i zQ&NDa1b8(JcC`wpS_Q!{2CX`_8nwT(ql?#@cLoOrhJ1)tJE16w6Jfo3D^j{ACIV$y zW>Zp!YCswjA2GlF@j)d zEJQ7V`H@Upgs~Hkx-}6Q;<;TOhiBN^PMrDu2y<>UMEi3`pH~2Y0KrLweE@_MaP{@L z-iFRAXE@(Wm=A$KB*Ph~I057WCkXRL1ONt!Ge1Udm&eidp(E_~bIg4B{OJG? zw_QYaf#~p1kMJIjj*a*{h?u(fncgS+h=*T+m}K!sL;y-J@zv6zlmeLCgB}q5z9(}0 zFaiVvBm&?wYxJ3kK92yHOi?Ra)IhI_96Jo`MKF5|0hXvOAv!!8M=&r7hCbpcR-#3P zkdhkWzWM;7YjH)c8K3kXpDX6W=er94;b4ibZ3H3|eKL(QGgAVQGMTAoqo@ZDB2(Wc zmCv-P_v7gE4uB{{8FUg6IC8FZKE|3T0EQ3}BRY%qbIW}A{C5G6=+B4-mqY7ZyCH?;vf|+riw}xl{0000|pPp9M)q7eKjiXKr({qvb4UNjbRrj-z zRrmc7YJ~&t>EFggxTB* zXPgSzi*a@<6w0*j?OZVHpobePe{+Y6SCAgiXW3Qn znzUQ$YR>oW|GUq3^NwgUJjjAn8t*LgR7hL#ycac*sm}uG^uH3xDlduI%6h>ZeRq0% z32r!#b#;Xmdm*ix55Z?7N)E4!yK})peGC#BhER%7doiRAzmT_j-OBKN4-hVUV|(cFeCNxyRabf3~s&98?AFEY2f~YDpbuZHE|G zJv3dN0{DYWr0Nf*R~aSO)g0j#VWw!AdTI@cH4$ouSZIdKv4rmuFfaeV0GDbGG=LnhHKXg3+K@Vo`jp z?ssHk_<#}EA{K&(M5ppVgZO1mi0R-Wo zMjZ5)rXL-3ejNP(2>xhAFjjia-^(!cvne@N2I}m38>91*;v?lkR}yM*eq7dcUR4qj zB|sKIh8yJ6{EGXn~G z1{RYaBp}d%3JYl#h~j3Mdz*k5Bpxw%V-$SF+05y>va^{78Kel;>1zsj_2}hn^L)%d z2(Ir_{B;J7^F>_C3QrcZ!bis4_A`@GGX8Kfhu5t=8nS=O=T(_ zN>(TCM6ajOgxR$@nCm!EE-|Eko+yY)Bp~zkbJX)_>*jptS@V9S zu*2@^BQ8PkZA?O`lB4%n`B7tgyCA)Gpt5X|ZfWbZ)x2O~PuI483E`>Gs0=XO&-y`6XZ z*?^*R)KHdGzbMd%?H*;9c8aFf|4?%+T|`)llyRU!6;{;Tu;BZ^tt5wfbc zBH#t>vGJmHgY__Tf4@79KS$Im1x@4636vH6Vp}d)IR#lTH{7$ z@*nDvqP5Wo%LWSn^0F8QprCg@=&@^AVsL`i$M77|*m@C7^rE?WadBn#S(Yy39jc6F zICGNbK!ccwLdcN>R`Idh`J`!7Eo!@qPD$nHMtNmbI%_m!YmfJe`tnwGM6qDN!0_2a zXh9&`*7m%-;*Z%cBe&3fOp1NF8AVn7{l8kDchb?%prqy3dsy`SFVM$JvOxr)Pg&50 zSLdfXtIxV+Wjz%X&4V{)A>kb(J^;h@W;nTc<)3~B!um-1^oaDjWh&Sw!u;9%+{B2c zDa@gRMJsFeEuascoaxmIkDp?N%4=Y!ma_i|Nf*s71vlnu9++Y7cReSWeWE>ri=Ly8+VAy;zj1o!)coZmus1D8!$%>#DrE^s z@&M%V7!r^fQquiB-@1oV>Qgm8?;Jlu`agnIe!*qVXNtITA$RElhR|{8TOYhjThC|B z{nbL$cJ{`Ix&ez^%L^-8Ii|uvcEK^cto-buoz?8qcY*?Y%8A!^oI@~BZX@TP8}{6Q z(z3EfVVRMve8fbfU2VNpM48LQ>} z0f9^$L^j7A=kzfJ&N=}9i6YO972i&u>|K^zS5Lovyo3VJI&ic#`49lvN!;ItnIH25 zh2+!+$82PM#~=%b6&k<|eSd`vc&S&x>2uK3*I4zA{UBEiXg;>gW}2Ohd#zML%IbdE z{u%KTyvp_%aW@=$snGDi(BTJU8eT!6I0f8YLXw;PuUJA`haP)G_h2(=%;9w@=W(Cv z+Y`2}`D3>0LCAuiy~<6e1Zv9IBANo_?tkQ8vn z73$gB!eiI@6{04zA+snd@cnaKncVjngv^ImfNz=qYD+ID#0)S{{ce*LF^9oYOl9b2 zRq4cx4HzrwIK02J5nX-Qpj&kr)db)vmv&zzF?NM{pI!ihYT#*uqK7ShKgX>s66~jl zflU$zpXA4ApdzcK+f+nVb*@)@RvwEW8fF`wW@$J85W}ZPjj52gZ6AddBMCu8tCnib zDJh70Y&t}r`}^r_u=36;0)fn%}z7O!C&Tb!gfTF z%*svrX-rbl$3|yGa`duk?e)e;aAGw0Pr(~6KP zYPw1na3VO{->)SAI1$Ose?6Z9`cNP>mIXD~ORCJvw`NWc6{$?&PI~LU>%TnFiR2R+ z0$PMxh0Z;Fw~3QPj!}kiIC%baA_O&`FE@B>!FuibHeIdDyvB4|?=)vH(%8kvR&(Xa zGFGYrPFA-RCp)+&gh<2VfA1_E^m?TpjlkwV-5)TJd!>6_=U;z?=+bh-!u!>V1;{^~ zR>+@$BH^sHEd+_e<-tK0!})|!m6Qe$_sa z1P2PHKXl0optE4~ALuMvZ$)PgIGiExM zjg45)-Ut2d4YWo-GV;srOXK_w^+bwH4zsJ@O&c?6Q`fk*pvZ}{N76Ht96fn@>gTH8 z-DD7FK|XjWD?ERshLH8S44R=6nH!)t>+jV9J)|b%{s`VBh;YZnTMCLo+I#rgZt`SP zGx2E-EI{a6klLQrOcJhqE0n3$tfEB`AJb%vYKvya8lcXKn*OrL#R+=${S=`2jr5#B z7MRg+JIqwAJvAuu!u|QM@HsvkW%h5QJAGu_Ug(-?)CQUtFe*~$#U(+YT{hgOnfr&qc88~Cl`P0!p)`>pVClHWV>!GY^ zsJQi7BWL{UdiH#4Ge4d9r8stn#EMiQ2*vh#b;#cGyp!Sp3HF}50`0inF2;=UXI zv5>R9CIvrZss7v=yq<_Zk2}ir-M!oG5DS^5`Z+V&=gCHe*~5iAV?gstTVqKO4Z)#o zc}GqDS%*($&8fwxnvLEFc$2I?<$#Sh(?34;YkL(3i|xGb3P^uheQqyyXS;s2H_Obw zGxNl@;ZB&$nJ4pW4yio1wQ1{#lJfqWM*+b)@ArO2B<%X0%@xygn^C}XG@dNR{&PDv zIaY=UO(FSvJadBU@k|hguH$yJd1!qUTdX7%8`p@vH6f;?bPzj-0#iPD5_BwP!SnfR z;)O>5h(*NmnBz0Jh#sGYV>JGusPao?WzqLE-q6(F{e6ENLS%VWtIIDm4?One9 zqLfjUocxyjSDgbtmVQnLGm1Lud$Jd0e1Bqz{f((0mz;NFqu!nDAC$*O&=gCcEO?ur zPpo?So)R;XC>&*NCCp^(`7{^H2mV$6T(YDaHKiqtF#%2vo3e2TyCBLWXKGNc+AAW< zuoBS7OGdScDV#D{&BQ9#w{2?cG_UeG(2-G@iGq~!ITEz^wj$@howB%Q%$IqNvukEQ1dl^Yze7sx{Xbfo8xmcUF zlxw~d=02J)*@@^J7}WaQqv&}-L#saoUQN8b!x_C&zIy&R&Uf5Yis25KWgs38NIyM2 zO%1E}n;YKwM!RIFC$&(C+kxsf>-9~JPuZC!HanpP7rjmZqrQTnmLB5>}gEQXbW79zE z7PrPIC0;UU%_W;aMfC7--4 z?d){{MhHCobEn^{E4(k|3a9%#)S{P#kI})^ZKn8RF=~ooX{OwALWrwnF!(ekBQ6`c zHp^+*NT3nLiWU8fzOmdk`JRZ!gwd(4^_?Idi6~98TfGZLYdnP_8`Swb0=7tKNe-7E!pXzY)KR6CuuSRt`!ZBF zp%^rkrpYdmQ(vSlk!&f0D=V2Qy5ny+sA3c1m3QflZ{~eaF9R{S3X5pf#rpv)!mre1 zZ$o*U)!O5i$1N$+BQn$nnbcUx<^$H8zbX-v%^}vJX@H8n_~gXM=m|)^5g#+R=17`y zs6udtG(bb~jnN-Gg3qE@<>&*f% z`kZ-AX2g_1bL}xPnRD0BUvE3UIRE`F(h9MwqX|`4=i+>*k)^uB4lvg-Ty*k3AQU|l z*_2XvX9s_2YrkfMY!6Z_B6&v3c#(m?6CtzRl{a zu(Qv9^n3igFz`Fxcx*WS-NYef)%Jj_6Ew?!1?>_ayJR}uZ~$fBe!x=R-V%&7_pv4L zyvK88ao@qMSu1xAl{Mi&3$K4@0~jj8U~;WFX2PX)xJrUp7w(XN`>B3fp%2Bh&pf{* z9mF-6lYg=`#`uNOPrDR4dBJKn0sm&j6O^5|3kj#+nOo&k|oI?RBy z7)Cq@JFl3#boZeB`Dh}?w$l+MR1_~1x&%_1zmEroZRo{p5$5{C_DM1$8o5ZgnmBA@J_F#df>;LFWv7J zBumd!O>HBc%t_6b=_38h<)1X#!MCz@?*l0Y2A#3Fo6n;pS$jh5t;6gg^4S{@!W8cZr&4V(4=K3u*6tg?6vo*+yO zxI)faoec=)kx%&Kx2>YIpMinHOP=oh{4Z-0 zzV}+sT@em>e>IN2k$Kb6Ln3VUlRw!%t3=!%4VHR+o{~VBXvXOdL#fx^qUD_}mp=gj zCv2Sh7KNwOp7)(lOp8fZ)5*xcT!dV(nM^~bHkQIK3uLpPmjG;u!m&d|hsT2Po^;^V zU`kHFoC+8J)hAwY`xIQEpXGdZ%XD?mGxxt|n-PaiH=>A+P6RvW=)G%BOV<|?4K45T zs;b|$wVz#}bIZdLT&T*BU#(S934srnXQP21PF$1_kI^T8&H#a13u_u%u64eKM^*ur z^O_hd9%2A5Tj+fb-(Ckrd{0~|`O_v;14MInqp}vgR;N$2z>#;6H-Z{UtuNLbYJ@}T zH>PPZULfm@TT|WXhVB})~9P5#ACl6JF3QW)ee^sfb;I zcA_X6g`pJZSXe6O5DYyrzWOZkxya=zOG<5vsu9+#TK{vYrfOW-^^?^T@Ahz7jl1AB zLOP6?5De3L`kU|ktIO0ntdo$`v<&&CU2FFJNyopAo8K8cTXK($-%FY8pU0%y9`k|q zt{Z^>r^k$52~cJ8qW(tE3L`TAo)fwbu5D&$LCE%{a+o zO4F{=B6%_|e#GVnMmpcsO|UocqCzpjGvr;!2K`W*_1K)wDN8V4WEy7Qm+!Ix%Md{QjiuC%a9FCRM@5Fj;Zw1w#RL67hiU3JK0( z&X5_*5PtO7ioX3I>C?|=gys^0HtU@E3Z#GrA|KJz;Kor)bf(lB^}B?A#&&J8_eN_qA)uu>4X zfA`E1h!wQV^#@PzVYiA!(LmQq-sf8h7wLqS^F)qLU zcEy=bm;p50RRc;(Q0*K>dc-=0!=3@W~P_MJ%QCg}griawoYX09Ng zlfNY;8#4{Cyz0edKem*EB*(Fyzx~Kj-MHH(i=+9zK;5UGtwfng!$F&ZP^{7<&%l~- z*?sK#&+o@ZSFeFIB!JlO4+jl|XyoU*-NKbs4fO1|<}SG)4xqg9PgUTH%g)9jfV|bg ze?!Sf;88>ARVoSyjp9)?+-JYKJC=gdKwZqE*8}AnEVKlGq|jcTMI4)=r%lz7XtKtq zAsjh%QtqiEmcz_G%Zbbb71QrBIUO)LrLc+)1Vz^J=txr|4;}0epBL=Q$QyHFAizjh zA~u-!C0QMQz>yXGwqV{fPIO|G){iR<56&c%Qjuw{!=w?+LH7yo|IS$<6GNTZB!a%b zW6o|e!|DM>Atxp$l4!DoSOg19d+Zryo54^)Xqn_SlLwVt(Sz7#;&&A)`nfi18IEYg zdq&Mdat=RJ__fm#ui%({n6GRk8Zul|__s*8u$cJv&!~gDQDSNVQNAfv)wh8R(JnFq zKnt0m%N2flW=1PFY7*bw+1q1zO}?ercAFdZ_LAg6EYmjaW*?kaqqV?((8>x=X|4Oo zKvq3K@*vES4|h8MK;*VoX_ujP@R*E3kZOJ!(>At^kfuiA`R?<;Rvo$k^2RIGi&9d* z3eB98P_28*K3z>=W#+;|;K5J8qZ9BB0)Biw7p`vSu5MpzEP9DqMFD7X@<6b?hFtBaB|{uO1U5 zH2(t2_ho&e1_jO_!)Z5zTE5z&;+c>w&RS{D=p-}4iS$wjJePcws^ue93k~LPMU~6W zUqiln;$DkC+L6$0T3C45+NzNQRJ(;!p3~$)9gI(gl%t>F9!T1%ksJ&IiHZ-3@!o`z z#x(bf8jDs&i%g0dO|rF`N;5^shB;z|5ZnVSScH|5;EU%X=d6cJlhmeG7#bgqV$E~n zw!No@T~Ce65`Xf;hr_YtLlxoel-psyqLGk!1-Bvr8knjYm_+C%Z`rPH#E3PP$i<8& z5nGSPE>-uF=%Kc{c|qpf_G_Y7Nrtq=GGI$x6Tg_ntfs-6g?feJXD3`ZkIFgMZ_&afo&Joeh z3-{klczQ$#35<{T5|t7dqPU@yHB*sB2{V*39puovCKePT`>&j zVgh+d;u*hO@9P@@;czNo6ctcr)0&bHj+$T!_pcxwYL$FI4GJGnM!t$5Rrf zH6yFn{N#&*!x$>uM`H@T6&-^MZz9P2uONYx4Thu)H9YCn`7mXUO3?Po11&M?XwdRk z0ye+lbkVEAuf*ArsIdwA0{)0Q*R$TQD7HsaFBVI84+iyNx0Up)?k2v0f?ytq7$kk> z`}XFUZu1URXH&G2&LW%#!%h6a7&B$7z3nx(yJ0K}4vGd`Ks2Ixy?^1F!gG3W0vKwsJBe6~bP`2Xi zC-E@*vR#D_JOw-bx7BoAz5=(9XMNRKHyam29y9T-*jV!UW{P%03x1{7vd*u>bgzbe zYuP0su7>Oh!iQxyn^jDiIm!n>1o1bnyqv5S@K91fu?DPu zlt+e5rb5=-%KD)F8`h|gd^>CU<2xA9s?QCo;uPtNKBDC}D%dHeD|M>(&g1Ssl{u@i z8BjYN5J=6lbDaOHFPQZ4`I8flt)ik}`?cB7aZ>;=ul-J`_OyV~waV$*04G`)+EjhYw*afpybl-@xT|4_y*ijLYd z8-(^RI&Q~pbH>ZK9omLsxL6~*E_1k9*P;7X%qzF0J%h~VW(kj6T1|=S+;pnT4r`lP zZn+s{`}*CCl1V>(FTb}NNg|C+hP^>Bfu2W9KM%_-Yfm|PMzVgUInGvNRCR8kgPL_x z+x5?wB|)-rib7^o2!EbNy$pAzSRBQqB_%9JG-iM0Gaok1&pG;;g2n9!Ocf_=cq%<$ zj+y=Y^%q*Gq8~|~#(-q!E+|7{2}MCJQrXD~XIz}595Zl!!^(vJ>vi^>&Mmzyqn>gY zNE9mOF*7>Aq8_F>}mF(*Dv%Xd?fCn>mPF7e6+0K$ZCe*{;@taqL4!%__egm z2ZLdY(~r-5yk1l=`*6I;e3ko-S8VM|X2JSbE4jGooaM&%_NrQjU6NbKD(jA(teO>p zQ=e`uASH9gya+<%Cml!W-wP!nF{131`x6Y-5{OF@{65VSW2aw^aMxJI%A>C!K)29V zTg;YD@O#qfvs?-EPchoEvKwr^Q+}tOn^KAIF})TYuX2x0D`l6|q;aMV+C#^=gn{Q9 z%MBM$}T7TazC#EwalSv z9kFIeNB}^Q);zK#%N|1+Cc+p?xnMbX>=ZHAdt22$Q~8o15%QrA;*g9Pzr3$ykDjFe z+Wray3~D{+-TXN^aM7=o_UTLnIj_ z!@2o>+aCS*>|v&(v-SrdhRFwjl0x14!feL=3!RTnbho{S;A&i@4xWvJk3>=hhfq(K z0EPbPn`~u6-I}Rby1Be$KfGEzuKe7V1U0M7H0Iv56MwbW1W9Z>YGe84a8CwZ{iNc+ zLWy`r2kwT|1VQYq*x|EUIFs zZQHFE9v4QvoxjEy_l$VuJ#))(x4|Ay2_F@6**QWQU*%_fZFi()cEl|``1i#cqHDC# zN+)Xy2y8B7>!rg-JR7H4vFU2*e-0K`A<&dBo}(N=c6Zv)G>`&+aks|pSH%GeAQ(d&*3G2VfN&B9FR6`ip@;N z`~Vl>_s>h>>FMfu<2l6~Tw7H+E+Xo5G5u8k8~Y;WbJ_1lagM?`KT`}YdjQw!8V5qc znZtgfRv(JSOer_~rvP{x2YoxhLI3G4#g(y9Ei+KqZc;mIP~@`M-Jb~Spa*+FOgdyF z9Yi8x8FTpNK#;uK2SY8okb6etzh$ubnXvP_rX{}TLpa~-NXA3Bm&%STPlg{osM^q< z2GjWRS#=7S2ni4{JXK&L`(?2N2Bq+kRSh4O=bwB~JuHLCd2!GsSh>iXwmR74Fs-Kw zNchgrCr+NNyHM=9P(#L$W*fJxFuo+ij4id~X<*^g(bCd0F@2p%a$SmwQjt*+*Y~_| zk;QA{JtU#nQ5pMZAIq_=#$?o;HJ}P7m4J+eSVgZAMlIt4a#b<=LOTvFu*5YiSqYIt z#VHig&_K^Dexz0Qmh9MK9!!1RPlTHmIM~=7Ctio%Ze@L!R;{iF(?rUYh-5nr5INmJ zaRhtI-ne5a3KgZ)>eNwg9I~!wP*XMp%_!7VZ6xf^4XL&sYnd+>t5F#Fn``5Vo}t8z zQN%F_jkyU$1FK`?#Z)2M%$k_>I#ZJ1l$o^be!kjnN2et8?yLF7@SBq*u11{6bgLO_ z763|fO;$dxa7061^(zKVyqOs39s!oWfp1c^CNdvpH2Y*T$|L~+9||nIQp8yE5ra(Z zSzF+~)Ay)5NJq*u1UQT|`gjPdW{1j}nv;&3cH|}|SmHjDzGI=&;l@>0hb+w{-|vl| zE4B7>XP@w`c9U^&$ORK$+w5D+AB&zTBOd?#u=9r=}&6L{-Gd zkKX;lIO^Mkrer|UjDiwtE*%t!iBY3I9?D)!ZZl6_8d|UIpzrCxT&C#5=RQAK_IdlY zy8YQ$dK4r>5b&73blwh{5zubZ*6s^e^d&z(43?4Yj6))Z zso2@HhnVXSNEZ(Q`(|c_kBq)t6lDMWY)sB3EZibz#vO#lo7VpZa6J*nRDvmjm!SBWh^k2* z7;Iqik9Cu8d20ozCeH%^(NexUuw zaw<7$O(!guILnJOnxY2tw&2iS`gcvC%-^ex+a!nQ+`LTjtT+t#8T4!w_~~+WgN3om z9PY-Z!n8&zLs(Q#s_|#erfta{W?3fT!Le2Pnc)>{^fDxb~m_L&&4mKYtP+?D&rmY*(ba8PAEiD@xpQgx)oMrd!Ux9?IulGl3^m1QlNI`&;5Bi$4je&`y6RYY?luei-}K@ z3!~`b;5`*8j!YsDZMR41!bD5C$9nTUH~YMX>+ZgX4;IUS^a&sKBJSvc^+cfELQMKq6hAC(x5Cre(zbB`&QO$=-*|@eXawRjZ z(Xl#s-0LIq`4;kevdI!2+Jd&3zkb!zDe}#fdm}Z^$oSZ*_etW+7f7+EBLEgvFpbb1 zXCiVCtEGFZ4%{8jNq8kO3d9G#swp+RSI|9=*OHon&-aBkgBLXN1BBOn@@vHt9^z)q zv}){Z_o50!GG7e4`oaP?%aq1Z;){xgA$mVEN`?dA3wME?o6Ezukc-}^U!YuG&|(;r zoMl>6%6mJZv_`mngX8Kb&GM}b8TBN7nX68oIBWUflic3!27VHPxxh!@j>u?iQCvML zGqn(U=Fpx~spvIOqz#ScZKcUhEbF2-FuO0;TyA-@$g||?Y0oD{^Maot@o6? z4P9bM8y9}60VYOAkxc|^b(n^-%M?71>l7oQ^cS)|m1H53#WW$E^r%pF0Nv#31^3T> zw;(wqEve;CW}ecr+z)56nSuW%6UcTwFY%OFB*)O5ECe*{E^(2Oi>I;55&{N<^cyqr z`_Ic!6PK(#Tx?$>w5?RCw)H`8^jCF{w5zhB1lNvJqxcM|}OP zzOVvtKt;FuQUNTx0*e)bAh<~J4$V0B?+=kBD%v%yH_-xK4F$PYW2jS+4z*VK+&d9$S86I?|gO zsMXu6F#f!JCl+u??0p{bw+}p%33%)CbY|&+U8CI&Ub0krX1J>tPC}1OsQQASK_jv= zQw{r;ON_)OaYBw&Ol31`jb!yS>Ytj*qW))DKUYFR5g9sF+C0{tA%A*T4nU593{y7Y zBDlo7(&}G$xem*uD;oM^;vX5_G4~Na0WrR)Oo?y5HF*%bP*m|OgLwJ0%a{ExxUI&m ztC2+VtL}v+&ig_g1!MuQjGLcSD#4RPnb26;t}vQdtC3R049AJdNf1qzASvzMXDZWP z^W6NEM=|U8yDTcrf+swTV7E#~5zif85oVs+BAC^71pqy6zH3*@P%P;oV~#@Rl%+iG zO%@@$y2*ae)hiksH|}mv?N&tbVu-$WRPL30$eeL-D8pe(+z5_60(=Axuwd zcYszv>YS?zag2m?mTwf%W3uhCwc1JfPeG>=E3?m}Z*)>hXbk$MG;?yyBzBPL}+WTK;UGxw7g zi;}@Y)GHMe@t#j9w7C{%j+B(WMZ_F(+|1}v)1hK<%&F;Jh6#Ft$0gv_h&lbwP9~wF zY))v@0zo6K_SfxK1_Skx7v|Qo7MKx8z`sD56Z{4tp%Fb-2YiT>;ba#LB8{;14*nLK z{ebt<9Pizn$9k=tqmC*fXWrb3y_k}upq+%`a%r!-Bi<^vI(4lmn}RYyha?B<%CaVE z67gO~PXVyBYVL1e5@}E^#AkIRsf!qb6Q3O%5yqZzZ&hbY;e-JD4+w4l1>NQ9?x+Tk z%S$Q~02w6;4}Vq@c}{EQ?iGsg8>J2c3O~RN-S2O4L7%S=H4LOb0fYhM5XVnmW|s%q zexvtIhcOt5RLe|bW?i@W$Q1z=bZmwFb8_vCmayfVbyaew^wNbri<~$wrgWULU&pej z#6knkk>TrOdMrow+Mg8D-@&2a?St(pVwd-9)|F-bM^%0C;DN4t;<akcXHbe($zIwO0po1;UAtL7mmPb4e!Y>QUl^{09eYCz~1E zUl?2$X(9#{&J`T|?)6N|XKA)!jM5+cIcg~!wD%83i~`6hRAmhAn!gmK zq{sL&W5drP4IA|=m-GP98Bsi0cQm`+?tB~yF=(oKdQ+*WvS_FqL%EDh#UzBEB{Uy;+v1#zF)hxRaAI(aXC&)%r!rmSc|m{h znJ{C%Y-)q3t5NALhhvnHX&19Z)31z8?K3APRDbmPV>Of{k41&71r6H{nQ~#qR2oZ{ z>c;o~9H+^$e&{);H|l^kiw_a>C6yef&ZdZ(qu0&lg*78aKDA^& zGG>>lzy-bXEiWjn$O)XDuPT^0%M1j1FjYvV{T)#Coc}RhkazdGSdmrn`Gs0m#%zCz>E=m^7C=3x=xnVapeilk(_rE!$U!gQnJ)X95=+=xQUOd%5CxyZfW zltu$mv(RZSn^2AGC;m?GO-;?H*8hUGDkMSPbz6miqNQ3Tfq^b71t?o$SK8UGJwZ6X zhpKcb#h8^buv zd+z>X19p@}-fNo|9!DU4LWms3*lE|hxZh51|M#23Zp71O-Ym zL|ny&LE`ss{Gc1PQ9dr-L`X6BC2>p2IZk*^Kqhq}sIPhn{R?xg@u1Yz?&_Z5O9#Iy z`53gQb1+G)DS;=j$c2rZFm{y$6YKxTpn+( z!h@%*8l%AEltEKA#JMiQ`S&7<#ay)};)az0Vfh-UA zzKRr`i4cJho3Jai7;NQ@wDQ#mInoA2bTN@y5i{i|f}J{99FjVjJg1_nwzRD&b$?!! zRWzzGad@fupLYNeT>{#!?wc?nQF@}?G(-r*68dO~f+dQ%902gRuPeKGm`g%ZSX&hm zCRce36SQD5dRmvlnpr1+2!Mj!1qy%Qsjrk&Wzc6EkYfSjR#s999L-)^JV@VFbm=M` zbro#xRl&fVQ+nzy69WZtrdZU7+Tls@P*jS1^Xwh+gnjG?Kbm4^T<|t2f6FJ?fEwj( zrMjBZ|A$3TCi5IN9@T$5mp9N(4+<=L^?&KT852Ohs?aXtHRd3 z9=CsJaKG?N!oA857Ir{v{#=6#P1c`+_LzA}DK1x;pz}ho%U6}^K(mGpwhk+X$coT9PnCvmQ7{fY+x6CNZ zr;LEPibPY&iV8{M>Wx5nyLLvVJ2Mw!*{Um>>jTk` zt;)Ju2`mR$W#8BoQC{)+nTsmyWglLh4%bzYOa-4OBa)iS4Kr}VaDZ%djLlrQkKHW^ zg=*i*j**-+N55)%1L%zsDn_Gi9?eeAa60akIX*$hNgm79=`rD(3Jvz z(8lHoTL8v@t>8T@=H4EQ0y0!HO5;uO>kABFv_<{37SGTNMRSFhEh;hK&z%PX#x z)!IXgAnA}MajpF^!WHwylc)aK?er&lCW6`3?|EhwNc4z%+DuE-4$n`JWhv)1jsw(D zY$C+hCaxW0X$sJ#gS;2qdv4kJvUzs*aKaML;yl69_!5)U>Bpfuy&bK2qX91mi(hEK z8JexPy*W&_6)B+;I)@9+$T-`YlY%`8Sy|bb%H=D`&$+syuvr~4k=Ku%xs?SOgKr$T z#T1N472=afPpxGiaTTW(Vwi#%)ZR=7=`)lAy^78RRnbNW0MQ|&zc!yS&yh(cef+Ge zT9;t;?E11hEGzo_MDOGSr0nJo+L4hH-{PF$;Nm8K>#CL@bH2j0Q*4k>+E>D=jHDcs zeT`y7uyT_DJ(mD?m*AH4c!$(GGC2&#t1_eXp*2%}l?itsJ5Ll&^elMVLqFeV0D?@| zk)<#+3j7RU#<6i@i1Osre)N@67VMleDYKW1V%q6 zCdtts8#f*qPt~*HARp9iWFm%FROrgu=JduI`1wl$zzo$<+V)PK*5@wDww`%*dS#|C@ODJ6$SULdGI>`X*GhZ zFwNYCm(Ib>|I;4t;|8-e2W%Bt@ChPsW zxk&3vBL~9~RA$^4)T+3Sd6(RFZb%M9ffk|ZZz6A`Xz$m)sn}%^p-bmHjr-xH*dU0X zvZ;0Ka@rWO=S`T!zxpJ_g5xA`zCvPAkorG~{Wri=K>NkFK-!5J+c4_fXK$}c!PQ&) zrYrlhs!#MZi!|(2q|EGme(|5qaW_!9L>>A^R_u?m<1ne@E-C4N)@7zYYXDX^A8API z&UzFeB^nmi+GDa6%aGcJ=<5~f@W#%!X_P;kO(q<6Jkf1Ek-5yxxtbiP(>}*>!zY*j z_Q$G7?rh{Lyg6jc)xTC9I)0pI*mQE`ZF2IB)-BYt2qe>!PH}7GRC_Gf$VuJM6KoF& zb$Z@57Kp??COQRqr?2cWp&S4CVgKvQf3l*z2BNdNmZh2%Yb<~?f-+#E*Ov~?ZGWYk7@Q8>L-Z~xx{C^G1mtPo0JUt+HLO*$;EA4>*QFx3S*E#3U z3jiRJo&rytuS*XuXxuuvtBf=7ol@zRimYn^z{mCF+PN{TkjjRqMuVt$CAa zOM`!4kr^1?v-!~;mVG#lOng@IsZ2+kqP#AoySNa)B|tD!-pdLH5YbdWv?5$^$2zp& z`24Rk1^TVd(q+_l2LzQN~iP7VWkPE5mGWC2y%ts$KmN4A}P-?>H2!I#B-m0j%t z?y5*L^`hn+&B9SuoqA+4l9b!9t>j4e<+8=J(v3n_$IjJV0>&F$xOJ^60&6^USN>Qn z@nevmRp5e&X;R!qs4E$ki_VP{={3Q52*B*d$|s71#)mVi$OkpxX`qrw^BtX>l^_vZ z>Yu#->F9_D7h|UG>6Rq+4PO{;dXJwk{H{6&P&R$!7^{954mZTDdBbKUHTc8v? z?io7J#5F>#i4`XCo$hA!r`z#>5ymuT49S@h)u{*&#BR;qu1*gV%+KX}S50^%3Ds^g zW8)PFena~*Gc5t;)+Xo4I3nw5eA5TPoIELfv{&n$t^8=8?DM+X8f|P(9K5}p>jiMk zIuaTId=X??&_Pv3ysF6uqMP|wu~7Jw(VYCk(Rw*#QU|7_+XAbjC!gMlab#T~9aCxC z@`?{v*f1skb#p+|4uv=dZcd(@ns|_0HyqZ^cWZi-prvJSD>sQoPH0vk?TCuBZs{mE zN=fvtE^5dw<){Xu?hujtX zZ-KFFVQS}LLF#1frld_vru6vt`(5vPSnk2E`;q&9f!=fv19#Z9pVBP80iT^EEUY$l zzt+^ZrMR%{d(yTV4{D==r-K5*P{P zI|D>oeJDs+2rR*qP(l70;kpg#(AR3gd^w!msBsj&74X6{((S_jha-D zk+25f&{ekjp@_=HH8Zs4Jo7T5qqzgfzUXN!!`gWwScJC!04Xgrz0e}VLXG@{d@II6 zcDo0+BTcp`(aX$WnuKTODF}qyOGscJ{{@4uWj(*cUea-IWn;?iFrw0EERY!7{;D+n zqF=&g(oWztZ#*Enr`9205yb##6?_+pqg2s?{;|(m$lD z{sQ5_5lgag{hUbV3&ojMO;Laahhw^MS)blhrxGi<*6XX|` z?c<3CZ`XI_p@uN3H4MSlog0EPqHHxx(Z|uxzXWUs=X@6yyZ2Ogo>4lXdU|lHYR4n4 z3Jek!YZxPJ%#!tnRh;Y<&Nro zK|q((==B4_I9tafn{BNUoWI|{8372dH#(7$$L9C32Kn>2bDib~T-1MS!yg%q?tsqH z;#Ko*#0o%Y)lk^vVRW-6F_?q7y@dV1F*&<;9j}DLD{cLTz)A52g%oTTlp`2Z#kjHT zpbdqdg_zAQHw5?AQ*GxnD!Eq8+|wpxHfI%-;CB?W`P^JPzxH+LsUOd1|GK1(mD{LR z1J4~>rBU#rI*Sw!BAM(n$VpC0eys;xZ&iucY>rlKUYa-egETWG2`jfjMeWdZ1F0xt zee*Q2u0LNG5(-k8MEAR5_vkbtvv94q0a4PpO3zDD6DnBq_J;=^{VLEsaGqikR%?V3 zuar-$x&=|GOI1(ab|?5@rqJX{4qk32=z$Lb&+|z?+FMJmqmdr24$2BD*i~)Ik$C8o ziBn%|=P$GqE-psqomuM!%AOOy^swz@*{d>7p%Z;pL53r|#oO}Zh}cY=;!PniAUiC7 z7#|syx+;#N_EqyzmnkeQLGhnWF~4P9 z8}Dmeo??FI?smTah0kZbtb&39{OA11fnx)PqM{;0iL*HSWyV$9mDS`I6p~+1$b$04 z$)REInP+!AxqB)YXh+!i{Rq)NgRu9%WkvAq0zgy)0Ei3}12E-1d3;I@haF8TS{=?p z@t{^Y#{dQq{gaoE)s}~Qftye`WB@2ADaGz6WI7<6B7CAgswX(^G!KKw042MIho%8bY2!%r!%;E*Mv++ZW6s81Ka-dMf~G_TGzKyyS$d+p#W{G(ghXg13)It^(LxwoJUGV zGSz`jFRMRzBZZ|UJoLBsb8dWsmNhGB(L{dBx;B)+1P_1nJ~}n2Fc$y|OBa%B%{3Gi z6_J~pOP-vE&6bDD<;G^q$5HHN>2)g!O`SW}{mPE6{$cMMK&SR@&j8-Hi}^Z}-Y(Ks zxkpA+qR?9jqVnhsZJTc||Hv&Ls|DzJQ&_)(Q(?ofYg)T~0C6IT z1j;-mVqG=|u?*+Y^Uv?(@fTjEW3Px@zULcX!8r>pw`fTzU%!u@eeH~#9U-W#43;@{ zbCtL-$I}3FSJvX67)>r;o^~EBsB}dh|IH((df)6m1-y(f@#?w#!@v|m$|jj7*Y8T{ z?T`RE={FQ3omiTwogVQXJ8JNs^O+m2Tj45Qu#nOP3o%HN0Spv43z?ccha+Ds+3K70 z5srk(wd7)xZH!Ee;LLL(NirQf+bOT|(6YV_vjl6_w15Hj?d@Pq%k|V&ElyoDPm++d zurW2EA{!(m14sstjUX9~7yzruBqEHGNo-~rr!^0oSkCoYDKwlSJvXLtf90-7@-=Lw=h0F z!tb{~e!Tb1?w1h@LZ3qT_D>-E{L_eWKh9P5{67Q$bTVj+*Hvr1YuSNe|2bdyg%_Wh zS>P(Ol`dFlD=2Xp41mK~$k2)7m<6vAzDZxwRp>IDn>v?L+5({f1$jaX@7USS$O$ih z{`pT)xu{%-G6Q_~fBuYt6Q@#AKrmTCmSj;KB&ntVpx>=zG^T)Hx7u;ad04bKGaUe5 z{_?#%|NKtw`TP6W`pG*eUnI&YAKLXY_ug?QBid4UL%tK(ZFcf=^O>HRMzTn_N?fY< zq*w8HJQf`QHP^M`uB@fHVlkx)%IP`OaqiJyKlswn@X6n6%%9Q#FplW`69||5+rs!i zGyrtcrNA&+(PBxGW`VPZdOO48zB8_d##OcgXQ4qzfJtVi&jBQRPxMZ?3SGuzJSl~h zFflcTO}3FMr|a^Mobd9i?d>e8ENAta7IERI%C?<*_~B1~MQzn$8kR0j?JpT6q_~ou zDVcG%lF>+RPF~i-JpKGmwru$rgM%m7xN$w3KlzE&ZykI0^Dke^u2zyrMpMiOSXj1@ z-ow44K-}Z;j#g$u=B}1z#%27=$^DwTALud;Pcx`e+U4~ zC57}@6;)L=rmCuM^Z9iv6zz6Gt(qVQc_aF%*;&8ch)zgs;YeJ`dekQ#gwq-N(oOz zVM3Oa#JBIiXJ2pMq1{SU8PJ%24mgSkybU5m{@dE?|JVR9Acldc)+EyXZf0zBMA`oA zlepdGG&Z%^?Pd!;zmMMj-X6f8n`3iWa&mHFnmIX{h#Ml|5XCMx6`rL`oSC3<$zq1Q zCoy2)!ymqt^*66!$&y9vYTw6Wzk7ybC%oLIdF}F~i@QHUs*n#~{NfkczI{8lZvFsw zeep}QX*CEtckkohe(@N4cZ)K1mRu{oF)tR2m2hYhH7<^~<=U`VEDRhQI1C&CY%5o+ zEV=Hw>kV%ALb|&<$G`i)HxGnD;U0u`KcameM<{+%2potvGG6u8RDOTyFBDF6WY&yG>yS;{rbu4Uh@Jt+|E zd%YVB2G+N&X33I8glA{jzO$Vl|MU@RsysB-F1_f@{`)h}aO5E!99Zq~_eM6B*qzj?IojTZgaAtJujJ5lX z&hYlKg4Z8~-p*;@JFfVmXc+ALbVTGCZ4CP@$` z!2}7WNnlVDsv1$k6c!fe<>uM);xj>GW*xsHN8X^gVj)J0ihpvPcqC4aTtpyj<>mc- z+_>gC>S~wLa{Ubqo|tCui;wZzk)yn?0nrgRgkmw{s6~9_(UhV1P(u40lxp{;3Ii559=SEMYQ`YWa3YA}=p5*+0;KSXI@% z2r&B)k}r(t?GvO6IGxeQmE{Wv1Ox2cy@#Lv;+HJ(EM~C3 zkH5U*qX2yCf$wwchBlg4ihz~Q*LoP}J<8zGLk#wbl(&*Hah;AALnSaE0PxR0c@%)r6W$c_0qljg6!Ssk8tPP5<{=OYjCfCacOc^P zK`{SK(o;FzXA(pJ;ZMSNo&J;(K&Q;S1HFi$4uTv6K=J`1GvScaUf|9zEXfa@6E%v} zjMwKMAETtWgmBQ0t)Lj2y$GvTlW1sooPDnz;(ZOZRCyM&#IqO!P*LtqF(2S)Z$HmG zC4BUqul3+Nbu{Z{-`Ja7n^>0s`F1BcIdZ6Ppzk%rDlB1yG&_mto1+?eX10(*R zTK=WzodAI3oR(R(FNQGQTM@&BGBI&B-(6Tz9#0zLp;;wvl}#o!se&GOnv%O5YJLKYRE|Ce8*xRhSHj=$^pjD3ktCoGv%s z!`&$15Ryq-hd^`d<`+0{I2;55fq}8Hu{RKk-8rr43f{a$8s7=@P6j{{(PLBu^Yu2N z%qqFo9BYZAz>%w}GbS~jKnDTw1OdMfcZCOQu8nh3<6scU-U0+dWS{c~Ie4ItvC#?k z?ny6GH>pJ>2PQ{TKo~nY$fQpT7B!es%md{4aB$~M@;LEBS4TT?%#3r zP6hx75a@OTE9v22CJ+qR+%ESbMG2WyE%e-MGNDGrOlox4i=1mqU^W>d;i(J|6lGmt zY;+>)yAqnnVt(N4*vzDFG^xKUYfd_3Og5Ww6qk^p^+yony>8Sw$7N*b{we954ge4m zK(`x62;)&0I5#~rT~Oq3xTC6y!DtlCl#?`BL_2=+*yw@<75T{o%uG*_OvEtQ@>qDy za%88I;nRJ@b0kz_BGpb0yb>QDA4%8??1`zVVB&cH(NSA&UO`D=NkWOL38Tp<5|s@? z@tZgo=$)82dl(U=qavnvqX-~eRk+q4gWe4QFd$y6gpdYi#H=7M7LA2+EEb17&sI3A z_54IatnX(rTSf!Hz}VE}M55T`wgcqa@);XG3BbAW)9m>54>>(>h_+AML%=tJx3>e- za56VH7ypExfxi9@66)bxSuV(xt@enbVA5>8PEn#|$~$zjAK0ti>nOtWIfhUI;XMFc zHR;nth4hLhsqNFDa9&BFvoObEvCc+gqSUGgD+>jJf!|7!<>hlJ!lru z+ad@9OF0k@hQb~4RJhn?v$+*DESd9c_$Pc(Af_nFKEOCKgzuu^=1@D6R#rgxPGuYO~KOYK*Z7e;2};6GhDT1EiyN z-jP$j`RLsMfJ{mvOsIM~lpW2V;5+N<^4L7LW$ZhIU<`=f&WOmkoz;GuOD_+d99)FZ z+<%a9EC{frB29f~eTNWJzH#k-rZU>QhWYUB13&_yx9HBIVL(p{8ugv^b(K|kR$k!P zmk~yqh1&N@t?6Jmg;3^>kj?xQISY&Mp9_qK!(pBIX!kKh+SdP$9`onYyA1%D6hugX zR61`s9PZM*h86w^-+W9wg;0*<6-hIHigzKs8v&rZ zki!V(+kgUu$u;hu@a+!-CU1y|z!4upV$5fW)92|DVpy2r{FOB%MI{Ub0*c}r8TSn# z6w65j(=(O6x168%r=)iy0CduG4^C!ma{$AAz1_p4^@Iz#yd&Bw%+*MNIKuy+=R4|o4e$Ei5ATei(6^0lzx{SO9*gH@Y??7! z%+V*Gdh#t>=eFFoMM6w90Wg_NF*17p)6YEpt}^`0rT-5e<~X7rb0#7H0000Latest - - - - + + + + diff --git a/SharedLibraryCore/BaseController.cs b/SharedLibraryCore/BaseController.cs index d03dfac7..c9107042 100644 --- a/SharedLibraryCore/BaseController.cs +++ b/SharedLibraryCore/BaseController.cs @@ -1,9 +1,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; @@ -12,6 +10,8 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using Data.Context; +using Data.Models; namespace SharedLibraryCore { @@ -25,7 +25,7 @@ namespace SharedLibraryCore public IManager Manager { get; private set; } protected readonly DatabaseContext Context; protected bool Authorized { get; set; } - protected SharedLibraryCore.Localization.TranslationLookup Localization { get; private set; } + protected Localization.TranslationLookup Localization { get; private set; } protected EFClient Client { get; private set; } private static readonly byte[] LocalHost = { 127, 0, 0, 1 }; private static string SocialLink; diff --git a/SharedLibraryCore/Commands/AddClientTagCommand.cs b/SharedLibraryCore/Commands/AddClientTagCommand.cs index c696f5ad..9cd7c408 100644 --- a/SharedLibraryCore/Commands/AddClientTagCommand.cs +++ b/SharedLibraryCore/Commands/AddClientTagCommand.cs @@ -2,6 +2,7 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System.Threading.Tasks; +using Data.Models; namespace SharedLibraryCore.Commands { diff --git a/SharedLibraryCore/Commands/ListClientTags.cs b/SharedLibraryCore/Commands/ListClientTags.cs index ef1f23f1..7ce5588c 100644 --- a/SharedLibraryCore/Commands/ListClientTags.cs +++ b/SharedLibraryCore/Commands/ListClientTags.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Models; namespace SharedLibraryCore.Commands { diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index abd659b6..eb403798 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -1,6 +1,5 @@ using Microsoft.EntityFrameworkCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; @@ -12,9 +11,11 @@ using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; using Microsoft.Extensions.Logging; using Serilog.Context; -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; namespace SharedLibraryCore.Commands { @@ -1474,6 +1475,7 @@ namespace SharedLibraryCore.Commands inactiveUsers = await context.Clients .Where(c => c.Level > Permission.Flagged && c.Level <= Permission.Moderator) .Where(c => c.LastConnection < lastActive) + .Select(c => c.ToPartialClient()) .ToListAsync(); inactiveUsers.ForEach(c => c.SetLevel(Permission.User, E.Origin)); await context.SaveChangesAsync(); diff --git a/SharedLibraryCore/Commands/RemoveClientTagCommand.cs b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs index 10c52910..95e7e16b 100644 --- a/SharedLibraryCore/Commands/RemoveClientTagCommand.cs +++ b/SharedLibraryCore/Commands/RemoveClientTagCommand.cs @@ -2,6 +2,7 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System.Threading.Tasks; +using Data.Models; namespace SharedLibraryCore.Commands { diff --git a/SharedLibraryCore/Commands/SetClientTagCommand.cs b/SharedLibraryCore/Commands/SetClientTagCommand.cs index c0952c8a..52e3628c 100644 --- a/SharedLibraryCore/Commands/SetClientTagCommand.cs +++ b/SharedLibraryCore/Commands/SetClientTagCommand.cs @@ -3,6 +3,7 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System.Linq; using System.Threading.Tasks; +using Data.Models; namespace SharedLibraryCore.Commands { diff --git a/SharedLibraryCore/Commands/UnsetClientTagCommand.cs b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs index 4dbd2a1c..96737acc 100644 --- a/SharedLibraryCore/Commands/UnsetClientTagCommand.cs +++ b/SharedLibraryCore/Commands/UnsetClientTagCommand.cs @@ -3,6 +3,7 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System.Linq; using System.Threading.Tasks; +using Data.Models; namespace SharedLibraryCore.Commands { diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 3ec1ad80..630f0da3 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; namespace SharedLibraryCore.Configuration { diff --git a/SharedLibraryCore/Configuration/CommandProperties.cs b/SharedLibraryCore/Configuration/CommandProperties.cs index 88e52914..3643c8c5 100644 --- a/SharedLibraryCore/Configuration/CommandProperties.cs +++ b/SharedLibraryCore/Configuration/CommandProperties.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; using static SharedLibraryCore.Server; namespace SharedLibraryCore.Configuration diff --git a/SharedLibraryCore/Configuration/DefaultConfiguration.cs b/SharedLibraryCore/Configuration/DefaultSettings.cs similarity index 80% rename from SharedLibraryCore/Configuration/DefaultConfiguration.cs rename to SharedLibraryCore/Configuration/DefaultSettings.cs index d6f56090..d9ebd0a6 100644 --- a/SharedLibraryCore/Configuration/DefaultConfiguration.cs +++ b/SharedLibraryCore/Configuration/DefaultSettings.cs @@ -2,13 +2,14 @@ namespace SharedLibraryCore.Configuration { - public class DefaultConfiguration : IBaseConfiguration + public class DefaultSettings : IBaseConfiguration { public string[] AutoMessages { get; set; } public string[] GlobalRules { get; set; } public MapConfiguration[] Maps { get; set; } public QuickMessageConfiguration[] QuickMessages {get; set;} public string[] DisallowedClientNames { get; set; } + public GameStringConfiguration GameStrings { get; set; } public IBaseConfiguration Generate() => this; diff --git a/SharedLibraryCore/Configuration/GameStringConfiguration.cs b/SharedLibraryCore/Configuration/GameStringConfiguration.cs new file mode 100644 index 00000000..9f465b2a --- /dev/null +++ b/SharedLibraryCore/Configuration/GameStringConfiguration.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using Humanizer; + +namespace SharedLibraryCore.Configuration +{ + public class GameStringConfiguration : Dictionary> + { + public string GetStringForGame(string key, Server.Game game = Server.Game.IW4) + { + if (key == null) + { + return null; + } + + if (!ContainsKey(game)) + { + return key.Transform(To.TitleCase); + } + + var strings = this[game]; + return !strings.ContainsKey(key) ? key.Transform(To.TitleCase) : strings[key]; + } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs deleted file mode 100644 index c7e7a920..00000000 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ /dev/null @@ -1,196 +0,0 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Console; -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Interfaces; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; - -namespace SharedLibraryCore.Database -{ - public abstract class DatabaseContext : DbContext - { - public DbSet Clients { get; set; } - public DbSet Aliases { get; set; } - public DbSet AliasLinks { get; set; } - public DbSet Penalties { get; set; } - public DbSet EFMeta { get; set; } - public DbSet EFChangeHistory { get; set; } - - private void SetAuditColumns() - { - return; - var entries = ChangeTracker - .Entries() - .Where(e => e.Entity is SharedEntity && ( - e.State == EntityState.Added - || e.State == EntityState.Modified)).ToList(); - - foreach (var entityEntry in entries) - { - if (entityEntry.State == EntityState.Added) - { - //((SharedEntity)entityEntry.Entity).CreatedDateTime = DateTime.UtcNow; - } - - else - { - //((SharedEntity)entityEntry.Entity).UpdatedDateTime = DateTime.UtcNow; - } - } - } - - public DatabaseContext() - { - if (!Utilities.IsMigration) - { - throw new InvalidOperationException(); - } - } - - public DatabaseContext(DbContextOptions options) : base(options) - { - - } - - protected DatabaseContext(DbContextOptions options) : base(options) - { - - } - - public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) - { - SetAuditColumns(); - return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - } - - public override int SaveChanges() - { - SetAuditColumns(); - return base.SaveChanges(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - // make network id unique - modelBuilder.Entity(entity => - { - entity.HasIndex(e => e.NetworkId).IsUnique(); - }); - - modelBuilder.Entity(entity => - { - entity.HasOne(p => p.Offender) - .WithMany(c => c.ReceivedPenalties) - .HasForeignKey(c => c.OffenderId) - .OnDelete(DeleteBehavior.Restrict); - - entity.HasOne(p => p.Punisher) - .WithMany(p => p.AdministeredPenalties) - .HasForeignKey(c => c.PunisherId) - .OnDelete(DeleteBehavior.Restrict); - - entity.Property(p => p.Expires) - .IsRequired(false); - }); - - modelBuilder.Entity(entity => - { - entity.HasMany(e => e.Children) - .WithOne(a => a.Link) - .HasForeignKey(k => k.LinkId) - .OnDelete(DeleteBehavior.Restrict); - }); - - modelBuilder.Entity(ent => - { - ent.Property(a => a.IPAddress).IsRequired(false); - ent.HasIndex(a => a.IPAddress); - ent.Property(a => a.Name).HasMaxLength(24); - ent.HasIndex(a => a.Name); - ent.Property(_alias => _alias.SearchableName).HasMaxLength(24); - ent.HasIndex(_alias => _alias.SearchableName); - ent.HasIndex(_alias => new { _alias.Name, _alias.IPAddress }).IsUnique(); - }); - - modelBuilder.Entity(ent => - { - ent.HasIndex(_meta => _meta.Key); - ent.HasIndex(_meta => _meta.LinkedMetaId); - ent.HasOne(_meta => _meta.LinkedMeta) - .WithMany() - .OnDelete(DeleteBehavior.SetNull); - }); - - // force full name for database conversion - modelBuilder.Entity().ToTable("EFClients"); - modelBuilder.Entity().ToTable("EFAlias"); - modelBuilder.Entity().ToTable("EFAliasLinks"); - modelBuilder.Entity().ToTable("EFPenalties"); - - // adapted from - // https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/ - - string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins"); - - if (Utilities.IsDevelopment) - { - pluginDir = Path.Join(Utilities.OperatingDirectory, "..", "..", "..", "..", "BUILD", "Plugins"); - } - - IEnumerable directoryFiles = Enumerable.Empty(); - - try - { - directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll")); - } - - catch (DirectoryNotFoundException) - { - // this is just an ugly thing for unit testing - directoryFiles = Directory.GetFiles(@"X:\IW4MAdmin\Tests\ApplicationTests\bin\Debug\netcoreapp3.1").Where(f => f.EndsWith("dll")); - } - - foreach (string dllPath in directoryFiles) - { - Assembly library; - try - { - library = Assembly.LoadFrom(dllPath); - } - - // not a valid assembly, ie plugin support files - catch (Exception) - { - continue; - } - - var configurations = library.ExportedTypes.Where(c => c.GetInterfaces().FirstOrDefault(i => typeof(IModelConfiguration).IsAssignableFrom(i)) != null) - .Select(c => (IModelConfiguration)Activator.CreateInstance(c)); - - foreach (var configurable in configurations) - { - configurable.Configure(modelBuilder); - } - - foreach (var type in library.ExportedTypes) - { - if (type.IsClass && type.IsSubclassOf(typeof(SharedEntity))) - { - var method = modelBuilder.GetType().GetMethod("Entity", new[] { typeof(Type) }); - method.Invoke(modelBuilder, new[] { type }); - } - } - } - - base.OnModelCreating(modelBuilder); - } - } -} diff --git a/SharedLibraryCore/Dtos/Meta/Responses/ReceivedPenaltyResponse.cs b/SharedLibraryCore/Dtos/Meta/Responses/ReceivedPenaltyResponse.cs index 6911ab7f..9a796f01 100644 --- a/SharedLibraryCore/Dtos/Meta/Responses/ReceivedPenaltyResponse.cs +++ b/SharedLibraryCore/Dtos/Meta/Responses/ReceivedPenaltyResponse.cs @@ -1,5 +1,5 @@ using System; -using static SharedLibraryCore.Database.Models.EFPenalty; +using Data.Models; namespace SharedLibraryCore.Dtos.Meta.Responses { @@ -10,7 +10,7 @@ namespace SharedLibraryCore.Dtos.Meta.Responses public string OffenderName { get; set; } public string PunisherName { get; set; } public int PunisherClientId { get; set; } - public PenaltyType PenaltyType { get; set; } + public EFPenalty.PenaltyType PenaltyType { get; set; } public string Offense { get; set; } public string AutomatedOffense { get; set; } public DateTime? ExpirationDate { get; set; } diff --git a/SharedLibraryCore/Dtos/PenaltyInfo.cs b/SharedLibraryCore/Dtos/PenaltyInfo.cs index e8f4c887..f325227c 100644 --- a/SharedLibraryCore/Dtos/PenaltyInfo.cs +++ b/SharedLibraryCore/Dtos/PenaltyInfo.cs @@ -1,6 +1,6 @@ using System; -using static SharedLibraryCore.Database.Models.EFClient; -using static SharedLibraryCore.Database.Models.EFPenalty; +using Data.Models; +using static Data.Models.Client.EFClient; namespace SharedLibraryCore.Dtos { @@ -18,14 +18,14 @@ namespace SharedLibraryCore.Dtos public string PunisherLevelText => PunisherLevel.ToLocalizedLevelName(); public string Offense { get; set; } public string AutomatedOffense { get; set; } - public PenaltyType PenaltyType { get; set; } + public EFPenalty.PenaltyType PenaltyType { get; set; } public string PenaltyTypeText => PenaltyType.ToString(); public DateTime TimePunished { get; set; } public string TimePunishedString => TimePunished.HumanizeForCurrentCulture(); public string TimeRemaining => DateTime.UtcNow > Expires ? "" : $"{((Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? TimePunishedString : ((Expires ?? DateTime.MaxValue) - DateTime.UtcNow).HumanizeForCurrentCulture())}"; public bool Expired => Expires.HasValue && Expires <= DateTime.UtcNow; public DateTime? Expires { get; set; } - public override bool Sensitive => PenaltyType == PenaltyType.Flag || PenaltyType == PenaltyType.Unflag; + public override bool Sensitive => PenaltyType == EFPenalty.PenaltyType.Flag || PenaltyType == EFPenalty.PenaltyType.Unflag; public bool IsEvade { get; set; } public string AdditionalPenaltyInformation => $"{(!string.IsNullOrEmpty(AutomatedOffense) ? $" ({AutomatedOffense})" : "")}{(IsEvade ? $" ({Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PENALTY_EVADE"]})" : "")}"; } diff --git a/SharedLibraryCore/Dtos/PlayerInfo.cs b/SharedLibraryCore/Dtos/PlayerInfo.cs index eecaa615..d5aed2c7 100644 --- a/SharedLibraryCore/Dtos/PlayerInfo.cs +++ b/SharedLibraryCore/Dtos/PlayerInfo.cs @@ -1,8 +1,8 @@ -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Dtos.Meta.Responses; +using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; +using Data.Models; namespace SharedLibraryCore.Dtos { diff --git a/SharedLibraryCore/Dtos/ServerInfo.cs b/SharedLibraryCore/Dtos/ServerInfo.cs index ca54da2a..f1bc891a 100644 --- a/SharedLibraryCore/Dtos/ServerInfo.cs +++ b/SharedLibraryCore/Dtos/ServerInfo.cs @@ -22,5 +22,6 @@ namespace SharedLibraryCore.Dtos public string ConnectProtocolUrl { get; set; } public string IPAddress { get; set; } public bool IsPasswordProtected { get; set; } + public string Endpoint => $"{IPAddress}:{Port}"; } } diff --git a/SharedLibraryCore/Interfaces/IAuditFields.cs b/SharedLibraryCore/Interfaces/IAuditFields.cs new file mode 100644 index 00000000..6a70977e --- /dev/null +++ b/SharedLibraryCore/Interfaces/IAuditFields.cs @@ -0,0 +1,9 @@ +using System; + +namespace SharedLibraryCore.Interfaces +{ + public interface IAuditFields + { + DateTime CreatedDateTime { get; set; } + } +} \ No newline at end of file diff --git a/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs b/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs index 503daf89..b7af3ea7 100644 --- a/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs +++ b/SharedLibraryCore/Interfaces/IClientNoticeMessageFormatter.cs @@ -1,4 +1,4 @@ -using SharedLibraryCore.Database.Models; +using Data.Models; namespace SharedLibraryCore.Interfaces { diff --git a/SharedLibraryCore/Interfaces/IGameServer.cs b/SharedLibraryCore/Interfaces/IGameServer.cs index 614b0b46..0b5df51c 100644 --- a/SharedLibraryCore/Interfaces/IGameServer.cs +++ b/SharedLibraryCore/Interfaces/IGameServer.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Data.Models; using SharedLibraryCore.Database.Models; namespace SharedLibraryCore.Interfaces diff --git a/SharedLibraryCore/Interfaces/IManagerCommand.cs b/SharedLibraryCore/Interfaces/IManagerCommand.cs index d9222bda..2999cac5 100644 --- a/SharedLibraryCore/Interfaces/IManagerCommand.cs +++ b/SharedLibraryCore/Interfaces/IManagerCommand.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; using static SharedLibraryCore.Server; namespace SharedLibraryCore.Interfaces diff --git a/SharedLibraryCore/Interfaces/IMetaService.cs b/SharedLibraryCore/Interfaces/IMetaService.cs index 42c06c8b..8c124f94 100644 --- a/SharedLibraryCore/Interfaces/IMetaService.cs +++ b/SharedLibraryCore/Interfaces/IMetaService.cs @@ -1,4 +1,5 @@ -using SharedLibraryCore.Database.Models; +using Data.Models; +using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using SharedLibraryCore.QueryHelper; using System; diff --git a/SharedLibraryCore/Interfaces/IPluginImporter.cs b/SharedLibraryCore/Interfaces/IPluginImporter.cs index 32173efa..4748506b 100644 --- a/SharedLibraryCore/Interfaces/IPluginImporter.cs +++ b/SharedLibraryCore/Interfaces/IPluginImporter.cs @@ -12,7 +12,7 @@ namespace SharedLibraryCore.Interfaces /// discovers C# assembly plugin and command types ///
/// tuple of IPlugin implementation type definitions, and IManagerCommand type definitions - (IEnumerable, IEnumerable) DiscoverAssemblyPluginImplementations(); + (IEnumerable, IEnumerable, IEnumerable) DiscoverAssemblyPluginImplementations(); /// /// discovers the script plugins diff --git a/SharedLibraryCore/Localization/Permission.cs b/SharedLibraryCore/Localization/Permission.cs index fe12686b..0fca389c 100644 --- a/SharedLibraryCore/Localization/Permission.cs +++ b/SharedLibraryCore/Localization/Permission.cs @@ -1,4 +1,4 @@ -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; namespace SharedLibraryCore.Localization { diff --git a/SharedLibraryCore/PartialEntities/EFAlias.cs b/SharedLibraryCore/PartialEntities/EFAlias.cs deleted file mode 100644 index a7aeba98..00000000 --- a/SharedLibraryCore/PartialEntities/EFAlias.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace SharedLibraryCore.Database.Models -{ - public partial class EFAlias : SharedEntity - { - - } -} diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index b0789462..cba16f07 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -1,19 +1,18 @@ -using Newtonsoft.Json.Converters; -using SharedLibraryCore.Localization; +using SharedLibraryCore.Localization; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Serilog.Context; +using Data.Models; namespace SharedLibraryCore.Database.Models { - public partial class EFClient + public class EFClient : Data.Models.Client.EFClient { public enum ClientState { @@ -40,50 +39,6 @@ namespace SharedLibraryCore.Database.Models Disconnecting } - public enum Permission - { - /// - /// client has been banned - /// - Banned = -1, - /// - /// default client state upon first connect - /// - User = 0, - /// - /// client has been flagged - /// - Flagged = 1, - /// - /// client is trusted - /// - Trusted = 2, - /// - /// client is a moderator - /// - Moderator = 3, - /// - /// client is an administrator - /// - Administrator = 4, - /// - /// client is a senior administrator - /// - SeniorAdmin = 5, - /// - /// client is a owner - /// - Owner = 6, - /// - /// not used - /// - Creator = 7, - /// - /// reserved for default account - /// - Console = 8 - } - public EFClient() { ConnectionTime = DateTime.UtcNow; diff --git a/SharedLibraryCore/PartialEntities/EFPenalty.cs b/SharedLibraryCore/PartialEntities/EFPenalty.cs deleted file mode 100644 index 8663d6b9..00000000 --- a/SharedLibraryCore/PartialEntities/EFPenalty.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using SharedLibraryCore; - -namespace SharedLibraryCore.Database.Models -{ - public partial class EFPenalty - { - public enum PenaltyType - { - Report, - Warning, - Flag, - Kick, - TempBan, - Ban, - Unban, - Any, - Unflag, - Other = 100 - } - } -} diff --git a/SharedLibraryCore/Repositories/AuditInformationRepository.cs b/SharedLibraryCore/Repositories/AuditInformationRepository.cs index d712ad2f..6a654806 100644 --- a/SharedLibraryCore/Repositories/AuditInformationRepository.cs +++ b/SharedLibraryCore/Repositories/AuditInformationRepository.cs @@ -4,6 +4,7 @@ using SharedLibraryCore.Interfaces; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; namespace SharedLibraryCore.Repositories { @@ -24,7 +25,7 @@ namespace SharedLibraryCore.Repositories { await using var ctx = _contextFactory.CreateContext(enableTracking: false); var iqItems = (from change in ctx.EFChangeHistory - where change.TypeOfChange != Database.Models.EFChangeHistory.ChangeType.Ban + where change.TypeOfChange != Data.Models.EFChangeHistory.ChangeType.Ban orderby change.TimeChanged descending join originClient in ctx.Clients on (change.ImpersonationEntityId ?? change.OriginEntityId) equals originClient.ClientId diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index f13e1239..9622be95 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -11,6 +11,7 @@ using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Database.Models; using ILogger = Microsoft.Extensions.Logging.ILogger; +using Data.Models; namespace SharedLibraryCore { diff --git a/SharedLibraryCore/Services/ChangeHistoryService.cs b/SharedLibraryCore/Services/ChangeHistoryService.cs index 24e00f8f..4aa4a3f6 100644 --- a/SharedLibraryCore/Services/ChangeHistoryService.cs +++ b/SharedLibraryCore/Services/ChangeHistoryService.cs @@ -1,10 +1,9 @@ -using SharedLibraryCore.Database; -using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Interfaces; +using SharedLibraryCore.Database.Models; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index 2397e890..9de5bc08 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using SharedLibraryCore.Helpers; @@ -9,10 +8,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Context; using Microsoft.Extensions.Logging; using Serilog.Context; -using static SharedLibraryCore.Database.Models.EFClient; +using static Data.Models.Client.EFClient; using ILogger = Microsoft.Extensions.Logging.ILogger; +using Data.Models; namespace SharedLibraryCore.Services { @@ -118,9 +120,8 @@ namespace SharedLibraryCore.Services } } - private async Task UpdateAlias(string originalName, int? ip, EFClient entity, DatabaseContext context) + private async Task UpdateAlias(string originalName, int? ip, Data.Models.Client.EFClient entity, DatabaseContext context) { - using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) { string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH); @@ -276,7 +277,7 @@ namespace SharedLibraryCore.Services entity.Level = newPermission; await ctx.SaveChangesAsync(); - using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString())) + using (LogContext.PushProperty("Server", temporalClient?.CurrentServer?.ToString())) { _logger.LogInformation("Updated {clientId} to {newPermission}", temporalClient.ClientId, newPermission); @@ -413,15 +414,13 @@ namespace SharedLibraryCore.Services public async Task UpdateAlias(EFClient temporalClient) { - await using var context = _contextFactory.CreateContext(); + await using var context = _contextFactory.CreateContext(enableTracking:true); var entity = context.Clients .Include(c => c.AliasLink) .Include(c => c.CurrentAlias) .First(e => e.ClientId == temporalClient.ClientId); - entity.CurrentServer = temporalClient.CurrentServer; - await UpdateAlias(temporalClient.Name, temporalClient.IPAddress, entity, context); temporalClient.CurrentAlias = entity.CurrentAlias; @@ -474,7 +473,7 @@ namespace SharedLibraryCore.Services // update in database await context.SaveChangesAsync(); - return entity; + return entity.ToPartialClient(); } #region ServiceSpecific @@ -483,6 +482,7 @@ namespace SharedLibraryCore.Services await using var context = _contextFactory.CreateContext(false); return await context.Clients .Where(c => c.Level == Permission.Owner) + .Select(c => c.ToPartialClient()) .ToListAsync(); } @@ -704,7 +704,7 @@ namespace SharedLibraryCore.Services client.AliasLinkId = newLink.AliasLinkId; client.Level = Permission.User; - await ctx.Aliases.Where(_alias => _alias.IPAddress == client.IPAddress) + await ctx.Aliases.Where(_alias => _alias.IPAddress == client.CurrentAlias.IPAddress && _alias.IPAddress != null) .ForEachAsync(_alias => _alias.LinkId = newLink.AliasLinkId); await ctx.SaveChangesAsync(); @@ -725,12 +725,16 @@ namespace SharedLibraryCore.Services if (!string.IsNullOrEmpty(query.Xuid)) { long networkId = query.Xuid.ConvertGuidToLong(System.Globalization.NumberStyles.HexNumber); - iqClients = context.Clients.Where(_client => _client.NetworkId == networkId); + iqClients = context.Clients. + Where(_client => _client.NetworkId == networkId) + .Select(client => client.ToPartialClient()); } else if (!string.IsNullOrEmpty(query.Name)) { - iqClients = context.Clients.Where(_client => EF.Functions.Like(_client.CurrentAlias.Name.ToLower(), $"%{query.Name.ToLower()}%")); + iqClients = context.Clients + .Where(_client => EF.Functions.Like(_client.CurrentAlias.Name.ToLower(), $"%{query.Name.ToLower()}%")) + .Select(client => client.ToPartialClient()); } if (query.Direction == SortDirection.Ascending) diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index 1270699e..28e3b1da 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -7,11 +7,13 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models; using SharedLibraryCore.Interfaces; namespace SharedLibraryCore.Services { - public class PenaltyService : Interfaces.IEntityService + public class PenaltyService : IEntityService { private readonly IDatabaseContextFactory _contextFactory; diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj index 8bbcf55b..39eed5ae 100644 --- a/SharedLibraryCore/SharedLibraryCore.csproj +++ b/SharedLibraryCore/SharedLibraryCore.csproj @@ -4,7 +4,7 @@ Library netcoreapp3.1 RaidMax.IW4MAdmin.SharedLibraryCore - 2020.12.20.1 + 2021.3.5.1 RaidMax Forever None Debug;Release;Prerelease @@ -13,13 +13,13 @@ IW4MAdmin https://github.com/RaidMax/IW4M-Admin/ https://www.raidmax.org/IW4MAdmin/ - 2020 + 2021 true true true MIT Shared Library for IW4MAdmin - 2020.12.20.1 + 2021.3.19.1 @@ -37,10 +37,6 @@ - - all - runtime; build; native; contentfiles - @@ -48,23 +44,11 @@ - - - + - - - - - - - - - - diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 4d727247..03d28f6a 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -3,7 +3,6 @@ using Humanizer; using Humanizer.Localisation; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos.Meta; -using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; @@ -19,10 +18,11 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using SharedLibraryCore.Configuration; -using static SharedLibraryCore.Database.Models.EFClient; -using static SharedLibraryCore.Database.Models.EFPenalty; using static SharedLibraryCore.Server; using ILogger = Microsoft.Extensions.Logging.ILogger; +using static Data.Models.Client.EFClient; +using Data.Models; +using static Data.Models.EFPenalty; namespace SharedLibraryCore { @@ -965,9 +965,6 @@ namespace SharedLibraryCore /// public static bool IsDevelopment => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; - public static bool IsMigration => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Migration"; - - /// /// replaces any directory separator chars with the platform specific character /// @@ -987,7 +984,7 @@ namespace SharedLibraryCore /// wrapper method for humanizee that uses current current culture /// public static string HumanizeForCurrentCulture(this TimeSpan timeSpan, int precision = 1, TimeUnit maxUnit = TimeUnit.Week, - TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false) + TimeUnit minUnit = TimeUnit.Second, string collectionSeparator = ", ", bool toWords = false) { return timeSpan.Humanize(precision, CurrentLocalization.Culture, maxUnit, minUnit, collectionSeparator, toWords); } @@ -1005,6 +1002,51 @@ namespace SharedLibraryCore return CurrentLocalization.LocalizationIndex[$"META_TYPE_{metaType.ToString().ToUpper()}_NAME"]; } + public static EFClient ToPartialClient(this Data.Models.Client.EFClient client) + { + return new EFClient() + { + ClientId = client.ClientId, + NetworkId = client.NetworkId, + Connections = client.Connections, + TotalConnectionTime = client.TotalConnectionTime, + FirstConnection = client.FirstConnection, + LastConnection = client.LastConnection, + Masked = client.Masked, + AliasLinkId = client.AliasLinkId, + AliasLink = client.AliasLink, + Level = client.Level, + CurrentAliasId = client.CurrentAliasId, + CurrentAlias = client.CurrentAlias, + Password = client.Password, + PasswordSalt = client.PasswordSalt, + Meta = client.Meta, + ReceivedPenalties = client.ReceivedPenalties, + AdministeredPenalties = client.AdministeredPenalties, + Active = client.Active + }; + } + + public static string ToNumericalString(this int? value) + { + return value?.ToNumericalString(); + } + + public static string ToNumericalString(this int value) + { + return value.ToString("#,##0", CurrentLocalization.Culture); + } + + public static string ToNumericalString(this double value, int precision = 0) + { + return value.ToString("#,##0" + $"{(precision > 0 ? "." : "")}" + new string(Enumerable.Repeat('0', precision).ToArray()), CurrentLocalization.Culture); + } + + public static string ToNumericalString(this double? value, int precision = 0) + { + return value?.ToNumericalString(precision); + } + public static string FindRuleForReason(this string reason, ApplicationConfiguration appConfig, Server server) { // allow for penalty presets diff --git a/Tests/ApplicationTests/StatsWebTests.cs b/Tests/ApplicationTests/StatsWebTests.cs deleted file mode 100644 index c4b95e99..00000000 --- a/Tests/ApplicationTests/StatsWebTests.cs +++ /dev/null @@ -1,269 +0,0 @@ -using ApplicationTests.Fixtures; -using IW4MAdmin.Plugins.Stats.Models; -using Microsoft.Extensions.DependencyInjection; -using NUnit.Framework; -using SharedLibraryCore.Database; -using SharedLibraryCore.Dtos; -using SharedLibraryCore.Interfaces; -using StatsWeb; -using StatsWeb.Extensions; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace ApplicationTests -{ - [TestFixture] - public class StatsWebTests - { - private IServiceProvider serviceProvider; - private DatabaseContext dbContext; - private ChatResourceQueryHelper queryHelper; - - ~StatsWebTests() - { - dbContext.Dispose(); - } - - [SetUp] - public void Setup() - { - serviceProvider = new ServiceCollection() - .AddSingleton() - .BuildBase() - .BuildServiceProvider(); - - SetupDatabase(); - - queryHelper = serviceProvider.GetRequiredService(); - } - - private void SetupDatabase() - { - var contextFactory = serviceProvider.GetRequiredService(); - dbContext = contextFactory.CreateContext(); - } - - #region PARSE_SEARCH_INFO - [Test] - public void Test_ParseSearchInfo_SanityChecks() - { - var query = "chat|".ParseSearchInfo(-1, -1); - - Assert.AreEqual(0, query.Count); - Assert.AreEqual(0, query.Offset); - - query = "chat|".ParseSearchInfo(int.MaxValue, int.MaxValue); - - Assert.Greater(int.MaxValue, query.Count); - } - - [Test] - public void Test_ParseSearchInfo_BeforeFilter_Happy() - { - var now = DateTime.Now; - var date = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); - var query = $"chat|before {date.ToString()}".ParseSearchInfo(0, 0); - - Assert.AreEqual(date, query.SentBefore); - } - - [Test] - public void Test_ParseSearchInfo_AfterFilter_Happy() - { - var now = DateTime.Now; - var date = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); - var query = $"chat|after {date.ToString()}".ParseSearchInfo(0, 0); - - Assert.AreEqual(date, query.SentAfter); - } - - [Test] - public void Test_ParseSearchInfo_ServerFilter_Happy() - { - string serverId = "127.0.0.1:28960"; - var query = $"chat|server {serverId}".ParseSearchInfo(0, 0); - - Assert.AreEqual(serverId, query.ServerId); - } - - [Test] - public void Test_ParseSearchInfo_ClientFilter_Happy() - { - int clientId = 123; - var query = $"chat|client {clientId.ToString()}".ParseSearchInfo(0, 0); - - Assert.AreEqual(clientId, query.ClientId); - } - - [Test] - public void Test_ParseSearchInfo_ContainsFilter_Happy() - { - string content = "test"; - var query = $"chat|contains {content}".ParseSearchInfo(0, 0); - - Assert.AreEqual(content, query.MessageContains); - } - - [Test] - public void Test_ParseSearchInfo_SortFilter_Happy() - { - var direction = SortDirection.Ascending; - var query = $"chat|sort {direction.ToString().ToLower()}".ParseSearchInfo(0, 0); - - Assert.AreEqual(direction, query.Direction); - - direction = SortDirection.Descending; - query = $"chat|sort {direction.ToString().ToLower()}".ParseSearchInfo(0, 0); - - Assert.AreEqual(direction, query.Direction); - } - - [Test] - public void Test_ParseSearchInfo_InvalidQueryType() - { - Assert.Throws(() => "player|test".ParseSearchInfo(0, 0)); - } - - [Test] - public void Test_ParseSearchInfo_NoQueryType() - { - Assert.Throws(() => "".ParseSearchInfo(0, 0)); - } - #endregion] - - #region CHAT_RESOURCE_QUERY_HELPER - [Test] - public void Test_ChatResourceQueryHelper_Invalid() - { - var helper = serviceProvider.GetRequiredService(); - - Assert.ThrowsAsync(() => helper.QueryResource(null)); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_SentAfter() - { - var oneHourAhead = DateTime.Now.AddHours(1); - var msg = MessageGenerators.GenerateMessage(sent: oneHourAhead); - - dbContext.Set() - .Add(msg); - await dbContext.SaveChangesAsync(); - - var query = $"chat|after {DateTime.Now.ToString()}".ParseSearchInfo(1, 0); - var result = await queryHelper.QueryResource(query); - - Assert.AreEqual(oneHourAhead, result.Results.First().When); - - dbContext.Remove(msg); - await dbContext.SaveChangesAsync(); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_SentBefore() - { - var oneHourAgo = DateTime.Now.AddHours(-1); - var msg = MessageGenerators.GenerateMessage(sent: oneHourAgo); - - dbContext.Set() - .Add(msg); - await dbContext.SaveChangesAsync(); - - var query = $"chat|before {DateTime.Now.ToString()}".ParseSearchInfo(1, 0); - var result = await queryHelper.QueryResource(query); - - Assert.AreEqual(oneHourAgo, result.Results.First().When); - - dbContext.Remove(msg); - await dbContext.SaveChangesAsync(); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_Server() - { - var msg = MessageGenerators.GenerateMessage(sent: DateTime.Now); - - dbContext.Set() - .Add(msg); - await dbContext.SaveChangesAsync(); - - string serverId = msg.Server.EndPoint; - var query = $"chat|server {serverId}".ParseSearchInfo(1, 0); - var result = await queryHelper.QueryResource(query); - - Assert.IsNotEmpty(result.Results); - - dbContext.Remove(msg); - await dbContext.SaveChangesAsync(); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_Client() - { - var msg = MessageGenerators.GenerateMessage(sent: DateTime.Now); - - dbContext.Set() - .Add(msg); - await dbContext.SaveChangesAsync(); - - int clientId = msg.Client.ClientId; - var query = $"chat|client {clientId}".ParseSearchInfo(1, 0); - var result = await queryHelper.QueryResource(query); - - Assert.AreEqual(clientId, result.Results.First().ClientId); - - dbContext.Remove(msg); - await dbContext.SaveChangesAsync(); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_Contains() - { - var msg = MessageGenerators.GenerateMessage(sent: DateTime.Now); - msg.Message = "this is a test"; - - dbContext.Set() - .Add(msg); - await dbContext.SaveChangesAsync(); - - var query = $"chat|contains {msg.Message}".ParseSearchInfo(1, 0); - var result = await queryHelper.QueryResource(query); - - Assert.AreEqual(msg.Message, result.Results.First().Message); - - dbContext.Remove(msg); - await dbContext.SaveChangesAsync(); - } - - [Test] - public async Task Test_ChatResourceQueryHelper_Sort() - { - var firstMessage = MessageGenerators.GenerateMessage(sent: DateTime.Now.AddHours(-1)); - var secondMessage = MessageGenerators.GenerateMessage(sent: DateTime.Now); - - dbContext.Set() - .Add(firstMessage); - dbContext.Set() - .Add(secondMessage); - await dbContext.SaveChangesAsync(); - - var query = $"chat|sort {SortDirection.Ascending}".ParseSearchInfo(2, 0); - var result = await queryHelper.QueryResource(query); - - Assert.AreEqual(firstMessage.TimeSent, result.Results.First().When); - Assert.AreEqual(secondMessage.TimeSent, result.Results.Last().When); - - query = $"chat|sort {SortDirection.Descending}".ParseSearchInfo(2, 0); - result = await queryHelper.QueryResource(query); - - Assert.AreEqual(firstMessage.TimeSent, result.Results.Last().When); - Assert.AreEqual(secondMessage.TimeSent, result.Results.First().When); - - dbContext.Remove(firstMessage); - dbContext.Remove(secondMessage); - await dbContext.SaveChangesAsync(); - } - #endregion - } -} diff --git a/Plugins/Web/StatsWeb/API/StatsController.cs b/WebfrontCore/Controllers/API/StatsController.cs similarity index 100% rename from Plugins/Web/StatsWeb/API/StatsController.cs rename to WebfrontCore/Controllers/API/StatsController.cs diff --git a/WebfrontCore/Controllers/API/Validation/FindClientRequestValidator.cs b/WebfrontCore/Controllers/API/Validation/FindClientRequestValidator.cs index c9d3fc86..968c653d 100644 --- a/WebfrontCore/Controllers/API/Validation/FindClientRequestValidator.cs +++ b/WebfrontCore/Controllers/API/Validation/FindClientRequestValidator.cs @@ -1,5 +1,5 @@ -using FluentValidation; -using SharedLibraryCore.Database.Models; +using Data.Models; +using FluentValidation; using SharedLibraryCore.Dtos; namespace WebfrontCore.Controllers.API.Validation diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index 774c1a3e..32e83c36 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; +using Data.Models.Client; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SharedLibraryCore; @@ -10,7 +11,6 @@ using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; using WebfrontCore.ViewModels; -using static SharedLibraryCore.Database.Models.EFClient; namespace WebfrontCore.Controllers { @@ -215,10 +215,10 @@ namespace WebfrontCore.Controllers Name = "level", Label = Localization["WEBFRONT_PROFILE_LEVEL"], Type = "select", - Values = Enum.GetValues(typeof(Permission)).OfType() + Values = Enum.GetValues(typeof(EFClient.Permission)).OfType() .Where(p => p <= Client.Level) - .Where(p => p != Permission.Banned) - .Where(p => p != Permission.Flagged) + .Where(p => p != EFClient.Permission.Banned) + .Where(p => p != EFClient.Permission.Flagged) .ToDictionary(p => p.ToString(), p => p.ToLocalizedLevelName()) }, }, diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/Client/ClientController.cs similarity index 86% rename from WebfrontCore/Controllers/ClientController.cs rename to WebfrontCore/Controllers/Client/ClientController.cs index 86a7e353..dc7f0760 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/Client/ClientController.cs @@ -5,24 +5,26 @@ using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Interfaces; using SharedLibraryCore.QueryHelper; -using SharedLibraryCore.Services; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Data.Models; +using IW4MAdmin.Plugins.Stats.Config; using WebfrontCore.ViewComponents; -using static SharedLibraryCore.Database.Models.EFClient; -using static SharedLibraryCore.Database.Models.EFPenalty; namespace WebfrontCore.Controllers { public class ClientController : BaseController { private readonly IMetaService _metaService; + private readonly IConfigurationHandler _configurationHandler; - public ClientController(IManager manager, IMetaService metaService) : base(manager) + public ClientController(IManager manager, IMetaService metaService, + IConfigurationHandler configurationHandler) : base(manager) { _metaService = metaService; + _configurationHandler = configurationHandler; } public async Task ProfileAsync(int id, MetaType? metaFilterType) @@ -42,13 +44,13 @@ namespace WebfrontCore.Controllers client.SetAdditionalProperty(EFMeta.ClientTag, tag.LinkedMeta.Value); } - int displayLevelInt = (int)client.Level; - string displayLevel = client.Level.ToLocalizedLevelName(); + var displayLevelInt = (int)client.Level; + var displayLevel = client.Level.ToLocalizedLevelName(); if (!Authorized && client.Level.ShouldHideLevel()) { - displayLevelInt = (int)Permission.User; - displayLevel = Permission.User.ToLocalizedLevelName(); + displayLevelInt = (int)Data.Models.Client.EFClient.Permission.User; + displayLevel = Data.Models.Client.EFClient.Permission.User.ToLocalizedLevelName(); } displayLevel = string.IsNullOrEmpty(client.Tag) ? displayLevel : $"{displayLevel} ({client.Tag})"; @@ -77,7 +79,7 @@ namespace WebfrontCore.Controllers .Prepend(client.CurrentAlias.IPAddress.ConvertIPtoString()) .Distinct() .ToList(), - HasActivePenalty = activePenalties.Any(_penalty => _penalty.Type != PenaltyType.Flag), + HasActivePenalty = activePenalties.Any(_penalty => _penalty.Type != EFPenalty.PenaltyType.Flag), Online = Manager.GetActiveClients().FirstOrDefault(c => c.ClientId == client.ClientId) != null, TimeOnline = (DateTime.UtcNow - client.LastConnection).HumanizeForCurrentCulture(), LinkedAccounts = client.LinkedAccounts, @@ -111,6 +113,7 @@ namespace WebfrontCore.Controllers ViewBag.Title += " " + Localization["WEBFRONT_CLIENT_PROFILE_TITLE"]; ViewBag.Description = $"Client information for {strippedName}"; ViewBag.Keywords = $"IW4MAdmin, client, profile, {strippedName}"; + ViewBag.UseNewStats = _configurationHandler.Configuration().EnableAdvancedMetrics; return View("Profile/Index", clientDto); } @@ -155,10 +158,10 @@ namespace WebfrontCore.Controllers foreach (var client in clientsDto) { - if (!Authorized && ((Permission)client.LevelInt).ShouldHideLevel()) + if (!Authorized && ((Data.Models.Client.EFClient.Permission)client.LevelInt).ShouldHideLevel()) { - client.LevelInt = (int)Permission.User; - client.Level = Permission.User.ToLocalizedLevelName(); + client.LevelInt = (int)Data.Models.Client.EFClient.Permission.User; + client.Level = Data.Models.Client.EFClient.Permission.User.ToLocalizedLevelName(); } } diff --git a/WebfrontCore/Controllers/Client/ClientStatisticsController.cs b/WebfrontCore/Controllers/Client/ClientStatisticsController.cs new file mode 100644 index 00000000..829c01f4 --- /dev/null +++ b/WebfrontCore/Controllers/Client/ClientStatisticsController.cs @@ -0,0 +1,38 @@ +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using SharedLibraryCore; +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Interfaces; +using Stats.Dtos; + +namespace WebfrontCore.Controllers +{ + [Route("clientstatistics")] + public class ClientStatisticsController : BaseController + { + private IResourceQueryHelper _queryHelper; + private readonly DefaultSettings _defaultConfig; + + public ClientStatisticsController(IManager manager, + IResourceQueryHelper queryHelper, + IConfigurationHandler configurationHandler) : base(manager) + { + _queryHelper = queryHelper; + _defaultConfig = configurationHandler.Configuration(); + } + + [HttpGet("{id:int}/advanced")] + public async Task Advanced(int id, [FromQuery] string serverId) + { + ViewBag.Config = _defaultConfig.GameStrings; + var hitInfo = await _queryHelper.QueryResource(new StatsInfoRequest + { + ClientId = id, + ServerEndpoint = serverId + }); + + return View("~/Views/Client/Statistics/Advanced.cshtml", hitInfo.Results.First()); + } + } +} \ No newline at end of file diff --git a/Plugins/Web/StatsWeb/Controllers/StatsController.cs b/WebfrontCore/Controllers/Client/Legacy/StatsController.cs similarity index 78% rename from Plugins/Web/StatsWeb/Controllers/StatsController.cs rename to WebfrontCore/Controllers/Client/Legacy/StatsController.cs index a6dee0d7..0d998647 100644 --- a/Plugins/Web/StatsWeb/Controllers/StatsController.cs +++ b/WebfrontCore/Controllers/Client/Legacy/StatsController.cs @@ -8,13 +8,14 @@ using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Interfaces; using Stats.Dtos; -using StatsWeb.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using ILogger = Microsoft.Extensions.Logging.ILogger; +using Data.Abstractions; +using IW4MAdmin.Plugins.Stats.Config; namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers { @@ -25,16 +26,19 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers private readonly IResourceQueryHelper _chatResourceQueryHelper; private readonly ITranslationLookup _translationLookup; private readonly IDatabaseContextFactory _contextFactory; + private readonly IConfigurationHandler _configurationHandler; - public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, ITranslationLookup translationLookup, - IDatabaseContextFactory contextFactory) : base(manager) + public StatsController(ILogger logger, IManager manager, IResourceQueryHelper resourceQueryHelper, ITranslationLookup translationLookup, + IDatabaseContextFactory contextFactory, + IConfigurationHandler configurationHandler) : base(manager) { _logger = logger; _manager = manager; _chatResourceQueryHelper = resourceQueryHelper; _translationLookup = translationLookup; _contextFactory = contextFactory; + _configurationHandler = configurationHandler; } [HttpGet] @@ -42,10 +46,11 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers { ViewBag.Title = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_TITLE"]; ViewBag.Description = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_DESC"]; - ViewBag.Servers = _manager.GetServers().Select(_server => new ServerInfo() { Name = _server.Hostname, ID = _server.EndPoint }); + ViewBag.Servers = _manager.GetServers() + .Select(_server => new ServerInfo() {Name = _server.Hostname, ID = _server.EndPoint}); ViewBag.Localization = _translationLookup; - return View("Index"); + return View("~/Views/Client/Statistics/Index.cshtml"); } [HttpGet] @@ -64,7 +69,9 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers serverId = StatManager.GetIdForServer(server); } - var results = await Plugin.Manager.GetTopStats(offset, count, serverId); + var results = _configurationHandler.Configuration().EnableAdvancedMetrics + ? await Plugin.Manager.GetNewTopStats(offset, count, serverId) + : 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) @@ -72,10 +79,8 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers return Ok(); } - else - { - return View("Components/TopPlayers/_List", results); - } + ViewBag.UseNewStats = _configurationHandler.Configuration().EnableAdvancedMetrics; + return View("~/Views/Client/Statistics/Components/TopPlayers/_List.cshtml", results); } [HttpGet] @@ -92,7 +97,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers SentAfter = whenLower }); - return View("_MessageContext", messages.Results.ToList()); + return View("~/Views/Client/_MessageContext.cshtml", messages.Results.ToList()); } [HttpGet("Message/Find")] @@ -125,11 +130,12 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers } var result = searchRequest != null ? await _chatResourceQueryHelper.QueryResource(searchRequest) : null; - return View("Message/Find", result); + return View("~/Views/Client/Message/Find.cshtml", result); } [HttpGet("Message/FindNext")] - public async Task FindNextMessages([FromQuery] string query, [FromQuery] int count, [FromQuery] int offset) + public async Task FindNextMessages([FromQuery] string query, [FromQuery] int count, + [FromQuery] int offset) { ChatSearchQuery searchRequest; @@ -151,7 +157,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers } var result = await _chatResourceQueryHelper.QueryResource(searchRequest); - return PartialView("Message/_Item", result.Results); + return PartialView("~/Views/Client/Message/_Item.cshtml", result.Results); } [HttpGet] @@ -159,9 +165,10 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers public async Task GetAutomatedPenaltyInfoAsync(int penaltyId) { await using var context = _contextFactory.CreateContext(false); - + var penalty = await context.Penalties - .Select(_penalty => new { _penalty.OffenderId, _penalty.PenaltyId, _penalty.When, _penalty.AutomatedOffense }) + .Select(_penalty => new + {_penalty.OffenderId, _penalty.PenaltyId, _penalty.When, _penalty.AutomatedOffense}) .FirstOrDefaultAsync(_penalty => _penalty.PenaltyId == penaltyId); if (penalty == null) @@ -170,7 +177,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers } // todo: this can be optimized - var iqSnapshotInfo = context.Set() + var iqSnapshotInfo = context.ACSnapshots .Where(s => s.ClientId == penalty.OffenderId) .Include(s => s.LastStrainAngle) .Include(s => s.HitOrigin) @@ -185,13 +192,13 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers if (penaltyInfo.Count > 0) { - return View("_PenaltyInfo", penaltyInfo); + return View("~/Views/Client/_PenaltyInfo.cshtml", penaltyInfo); } // we want to show anything related to the automated offense else { - return View("_MessageContext", new List + return View("~/Views/Client/_MessageContext.cshtml", new List { new MessageResponse() { @@ -203,4 +210,4 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers } } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/ConsoleController.cs b/WebfrontCore/Controllers/ConsoleController.cs index 5d2bddad..910d8223 100644 --- a/WebfrontCore/Controllers/ConsoleController.cs +++ b/WebfrontCore/Controllers/ConsoleController.cs @@ -6,6 +6,7 @@ using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using System.Linq; using System.Threading.Tasks; +using Data.Models; namespace WebfrontCore.Controllers { diff --git a/WebfrontCore/Controllers/HomeController.cs b/WebfrontCore/Controllers/HomeController.cs index d6d73bb9..595ac25f 100644 --- a/WebfrontCore/Controllers/HomeController.cs +++ b/WebfrontCore/Controllers/HomeController.cs @@ -1,10 +1,15 @@ -using Microsoft.AspNetCore.Diagnostics; +using System; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; using SharedLibraryCore; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using System.Linq; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Models.Client; +using Data.Models.Client.Stats; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using static SharedLibraryCore.Server; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -15,11 +20,23 @@ namespace WebfrontCore.Controllers { private readonly ITranslationLookup _translationLookup; private readonly ILogger _logger; + private readonly IDataValueCache _serverStatsCache; + private const string ServerStatKey = nameof(ServerStatKey); - public HomeController(ILogger logger, IManager manager, ITranslationLookup translationLookup) : base(manager) + public HomeController(ILogger logger, IManager manager, ITranslationLookup translationLookup, + IDataValueCache serverStatsCache) : base(manager) { _logger = logger; _translationLookup = translationLookup; + _serverStatsCache = serverStatsCache; + + _serverStatsCache.SetCacheItem(async set => + { + var count = await set.CountAsync(); + var startOfPeriod = DateTime.UtcNow.AddHours(-24); + var recentCount = await set.CountAsync(client => client.LastConnection >= startOfPeriod); + return (count, recentCount); + }, ServerStatKey); } public async Task Index(Game? game = null) @@ -28,14 +45,15 @@ namespace WebfrontCore.Controllers ViewBag.Title = Localization["WEBFRONT_HOME_TITLE"]; ViewBag.Keywords = Localization["WEBFRONT_KEWORDS_HOME"]; - var servers = Manager.GetServers().Where(_server => !game.HasValue ? true : _server.GameName == game); + var servers = Manager.GetServers().Where(_server => !game.HasValue || _server.GameName == game); + var (count, recentCount) = await _serverStatsCache.GetCacheItem(ServerStatKey); var model = new IW4MAdminInfo() { TotalAvailableClientSlots = servers.Sum(_server => _server.MaxClients), TotalOccupiedClientSlots = servers.SelectMany(_server => _server.GetClientsAsList()).Count(), - TotalClientCount = await Manager.GetClientService().GetTotalClientsAsync(), - RecentClientCount = await Manager.GetClientService().GetRecentClientCount(), + TotalClientCount = count, + RecentClientCount = recentCount, Game = game, ActiveServerGames = Manager.GetServers().Select(_server => _server.GameName).Distinct().ToArray() }; @@ -46,7 +64,8 @@ namespace WebfrontCore.Controllers public IActionResult Error() { var exceptionFeature = HttpContext.Features.Get(); - _logger.LogError("[Webfront] {path} {message} {@exception}", exceptionFeature.Path, exceptionFeature.Error.Message, exceptionFeature.Error); + _logger.LogError("[Webfront] {path} {message} {@exception}", exceptionFeature.Path, + exceptionFeature.Error.Message, exceptionFeature.Error); ViewBag.Description = Localization["WEBFRONT_ERROR_DESC"]; ViewBag.Title = Localization["WEBFRONT_ERROR_TITLE"]; return View(exceptionFeature.Error); @@ -71,15 +90,16 @@ namespace WebfrontCore.Controllers .GroupBy(_cmd => { // we need the plugin type the command is defined in - var pluginType = _cmd.GetType().Assembly.GetTypes().FirstOrDefault(_type => _type.Assembly != excludedAssembly && typeof(IPlugin).IsAssignableFrom(_type)); - return pluginType == null ? - _translationLookup["WEBFRONT_HELP_COMMAND_NATIVE"] : + var pluginType = _cmd.GetType().Assembly.GetTypes().FirstOrDefault(_type => + _type.Assembly != excludedAssembly && typeof(IPlugin).IsAssignableFrom(_type)); + return pluginType == null ? _translationLookup["WEBFRONT_HELP_COMMAND_NATIVE"] : pluginType.Name == "ScriptPlugin" ? _translationLookup["WEBFRONT_HELP_SCRIPT_PLUGIN"] : - Manager.Plugins.First(_plugin => _plugin.GetType() == pluginType).Name; // for now we're just returning the name of the plugin, maybe later we'll include more info + Manager.Plugins.First(_plugin => _plugin.GetType() == pluginType) + .Name; // for now we're just returning the name of the plugin, maybe later we'll include more info }) .Select(_grp => (_grp.Key, _grp.AsEnumerable())); return View(commands); } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Controllers/PenaltyController.cs b/WebfrontCore/Controllers/PenaltyController.cs index 7620a165..944cd88f 100644 --- a/WebfrontCore/Controllers/PenaltyController.cs +++ b/WebfrontCore/Controllers/PenaltyController.cs @@ -1,13 +1,13 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using SharedLibraryCore; -using SharedLibraryCore.Database; using SharedLibraryCore.Dtos; using SharedLibraryCore.Interfaces; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using static SharedLibraryCore.Database.Models.EFPenalty; +using Data.Abstractions; +using Data.Models; namespace WebfrontCore.Controllers { @@ -20,7 +20,7 @@ namespace WebfrontCore.Controllers _contextFactory = contextFactory; } - public IActionResult List(PenaltyType showOnly = PenaltyType.Any, bool hideAutomatedPenalties = true) + public IActionResult List(EFPenalty.PenaltyType showOnly = EFPenalty.PenaltyType.Any, bool hideAutomatedPenalties = true) { ViewBag.Description = Localization["WEBFRONT_DESCRIPTION_PENALTIES"]; ViewBag.Title = Localization["WEBFRONT_PENALTY_TITLE"]; @@ -30,7 +30,7 @@ namespace WebfrontCore.Controllers return View(showOnly); } - public async Task ListAsync(int offset = 0, PenaltyType showOnly = PenaltyType.Any, bool hideAutomatedPenalties = true) + public async Task ListAsync(int offset = 0, EFPenalty.PenaltyType showOnly = EFPenalty.PenaltyType.Any, bool hideAutomatedPenalties = true) { return await Task.FromResult(View("_List", new ViewModels.PenaltyFilterInfo() { @@ -52,7 +52,7 @@ namespace WebfrontCore.Controllers await using var ctx = _contextFactory.CreateContext(false); var iqPenalties = ctx.Penalties .AsNoTracking() - .Where(p => p.Type == PenaltyType.Ban && p.Active) + .Where(p => p.Type == EFPenalty.PenaltyType.Ban && p.Active) .OrderByDescending(_penalty => _penalty.When) .Select(p => new PenaltyInfo() { diff --git a/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs b/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs index bc8e4c81..3d9dfb17 100644 --- a/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs +++ b/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; -using static SharedLibraryCore.Database.Models.EFClient; +using Data.Models.Client; using static SharedLibraryCore.GameEvent; namespace WebfrontCore.Middleware @@ -36,10 +36,10 @@ namespace WebfrontCore.Middleware private void OnGameEvent(object sender, GameEvent gameEvent) { if (gameEvent.Type == EventType.ChangePermission && - gameEvent.Extra is Permission perm) + gameEvent.Extra is EFClient.Permission perm) { // we want to remove the claims when the client is demoted - if (perm < Permission.Trusted) + if (perm < EFClient.Permission.Trusted) { lock (_privilegedClientIds) { @@ -47,7 +47,7 @@ namespace WebfrontCore.Middleware } } // and add if promoted - else if (perm > Permission.Trusted && + else if (perm > EFClient.Permission.Trusted && !_privilegedClientIds.Contains(gameEvent.Target.ClientId)) { lock (_privilegedClientIds) diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index 1ec1205d..429636fd 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -4,27 +4,28 @@ using FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Configuration; -using SharedLibraryCore.Database; using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Services; using Stats.Dtos; using Stats.Helpers; -using StatsWeb; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Threading.Tasks; +using Data.Abstractions; +using Data.Helpers; +using IW4MAdmin.Plugins.Stats.Config; +using Stats.Client.Abstractions; using WebfrontCore.Controllers.API.Validation; using WebfrontCore.Middleware; @@ -80,11 +81,14 @@ namespace WebfrontCore }); #if DEBUG - mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); - services.Configure(_options => { - _options.ViewLocationFormats.Add(@"/Views/Plugins/{1}/{0}" + RazorViewEngine.ViewExtension); - }); + mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); + services.Configure(_options => + { + _options.ViewLocationFormats.Add(@"/Views/Plugins/{1}/{0}" + RazorViewEngine.ViewExtension); + _options.ViewLocationFormats.Add("/Views/Plugins/Stats/Advanced.cshtml"); + }); + } #endif foreach (var asm in pluginAssemblies()) @@ -106,7 +110,8 @@ namespace WebfrontCore services.AddTransient, FindClientRequestValidator>(); services.AddSingleton, ClientService>(); services.AddSingleton, StatsResourceQueryHelper>(); - + services.AddSingleton, AdvancedClientStatsResourceQueryHelper>(); + services.AddSingleton(typeof(IDataValueCache<,>), typeof(DataValueCache<,>)); // todo: this needs to be handled more gracefully services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); @@ -116,6 +121,12 @@ namespace WebfrontCore services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); + services.AddSingleton( + Program.ApplicationServiceProvider.GetRequiredService()); + services.AddSingleton(Program.ApplicationServiceProvider + .GetRequiredService>()); + services.AddSingleton(Program.ApplicationServiceProvider + .GetRequiredService>()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs b/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs index ccb1ceae..829656d3 100644 --- a/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs +++ b/WebfrontCore/ViewComponents/PenaltyListViewComponent.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Mvc; -using SharedLibraryCore.Database.Models; using System.Linq; using System.Threading.Tasks; +using Data.Models; namespace WebfrontCore.ViewComponents { diff --git a/WebfrontCore/ViewComponents/TopPlayersViewComponent.cs b/WebfrontCore/ViewComponents/TopPlayersViewComponent.cs new file mode 100644 index 00000000..6e92c5d5 --- /dev/null +++ b/WebfrontCore/ViewComponents/TopPlayersViewComponent.cs @@ -0,0 +1,42 @@ +using System.Linq; +using System.Threading.Tasks; +using IW4MAdmin.Plugins.Stats; +using IW4MAdmin.Plugins.Stats.Config; +using IW4MAdmin.Plugins.Stats.Helpers; +using Microsoft.AspNetCore.Mvc; +using SharedLibraryCore.Interfaces; + +namespace WebfrontCore.ViewComponents +{ + public class TopPlayersViewComponent : ViewComponent + { + private readonly IConfigurationHandler _configurationHandler; + + public TopPlayersViewComponent(IConfigurationHandler configurationHandler) + { + _configurationHandler = configurationHandler; + } + + public async Task InvokeAsync(int count, int offset, long? serverId = null) + { + if (serverId == 0) + { + serverId = null; + } + + var server = Plugin.ServerManager.GetServers().FirstOrDefault(_server => _server.EndPoint == serverId); + + if (server != null) + { + serverId = StatManager.GetIdForServer(server); + } + + + ViewBag.UseNewStats = _configurationHandler.Configuration().EnableAdvancedMetrics; + return View("~/Views/Client/Statistics/Components/TopPlayers/_List.cshtml", + _configurationHandler.Configuration().EnableAdvancedMetrics + ? await Plugin.Manager.GetNewTopStats(offset, count, serverId) + : await Plugin.Manager.GetTopStats(offset, count, serverId)); + } + } +} \ No newline at end of file diff --git a/WebfrontCore/ViewModels/PenaltyFilterInfo.cs b/WebfrontCore/ViewModels/PenaltyFilterInfo.cs index ad1d6436..81ef8a7c 100644 --- a/WebfrontCore/ViewModels/PenaltyFilterInfo.cs +++ b/WebfrontCore/ViewModels/PenaltyFilterInfo.cs @@ -1,4 +1,4 @@ -using static SharedLibraryCore.Database.Models.EFPenalty; +using Data.Models; namespace WebfrontCore.ViewModels { @@ -15,7 +15,7 @@ namespace WebfrontCore.ViewModels /// /// show only a certain type of penalty /// - public PenaltyType ShowOnly { get; set; } + public EFPenalty.PenaltyType ShowOnly { get; set; } /// /// ignore penalties that are automated diff --git a/WebfrontCore/Views/Client/Find/Index.cshtml b/WebfrontCore/Views/Client/Find/Index.cshtml index edcf8e1d..a0fc389e 100644 --- a/WebfrontCore/Views/Client/Find/Index.cshtml +++ b/WebfrontCore/Views/Client/Find/Index.cshtml @@ -1,6 +1,6 @@ @model IList @{ - var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; + var loc = Utilities.CurrentLocalization.LocalizationIndex; }
diff --git a/Plugins/Web/StatsWeb/Views/Stats/Message/Find.cshtml b/WebfrontCore/Views/Client/Message/Find.cshtml similarity index 100% rename from Plugins/Web/StatsWeb/Views/Stats/Message/Find.cshtml rename to WebfrontCore/Views/Client/Message/Find.cshtml diff --git a/Plugins/Web/StatsWeb/Views/Stats/Message/_Item.cshtml b/WebfrontCore/Views/Client/Message/_Item.cshtml similarity index 100% rename from Plugins/Web/StatsWeb/Views/Stats/Message/_Item.cshtml rename to WebfrontCore/Views/Client/Message/_Item.cshtml diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index 8d967d06..2b538627 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -1,17 +1,16 @@ -@using SharedLibraryCore.Database.Models -@using SharedLibraryCore.Interfaces -@using SharedLibraryCore +@using SharedLibraryCore.Interfaces +@using Data.Models @model SharedLibraryCore.Dtos.PlayerInfo @{ string match = System.Text.RegularExpressions.Regex.Match(Model.Name.ToUpper(), "[A-Z]").Value; string shortCode = match == string.Empty ? "?" : match; var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value; - bool isFlagged = Model.LevelInt == (int)SharedLibraryCore.Database.Models.EFClient.Permission.Flagged; - bool isPermBanned = Model.LevelInt == (int)SharedLibraryCore.Database.Models.EFClient.Permission.Banned; + bool isFlagged = Model.LevelInt == (int) SharedLibraryCore.Database.Models.EFClient.Permission.Flagged; + bool isPermBanned = Model.LevelInt == (int) SharedLibraryCore.Database.Models.EFClient.Permission.Banned; bool isTempBanned = Model.ActivePenalty?.Type == EFPenalty.PenaltyType.TempBan; string translationKey = $"WEBFRONT_PROFILE_{Model.ActivePenalty?.Type.ToString().ToUpper()}_INFO"; - var ignoredMetaTypes = new[] { MetaType.Information, MetaType.Other, MetaType.QuickMessage }; + var ignoredMetaTypes = new[] {MetaType.Information, MetaType.Other, MetaType.QuickMessage}; }
@@ -25,7 +24,9 @@
-
+
+ +
@if (ViewBag.Authorized) {
@@ -37,16 +38,18 @@
@foreach (var linked in Model.LinkedAccounts) { - @Html.ActionLink(linked.Value.ToString("X"), "ProfileAsync", "Client", new { id = linked.Key }, new { @class = "link-inverse" })
+ @Html.ActionLink(linked.Value.ToString("X"), "ProfileAsync", "Client", new {id = linked.Key}, new {@class = "link-inverse"})
} - @foreach (string alias in Model.Aliases) + @foreach (var alias in Model.Aliases) { -
+ +
} @foreach (string ip in Model.IPs) { - @ip
+ @ip +
}
} @@ -62,7 +65,7 @@ break; case "time": - @Utilities.HumanizeForCurrentCulture(Model.ActivePenalty.Expires.Value - DateTime.UtcNow) + @((Model.ActivePenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()) break; default: @@ -89,20 +92,21 @@ } }
- @if (ViewBag.Authorized) - { -
+ +
+ @if (ViewBag.Authorized) + { @if (!isPermBanned) { } - @if (Model.LevelInt < (int)ViewBag.User.Level && !Model.HasActivePenalty) + @if (Model.LevelInt < (int) ViewBag.User.Level && !Model.HasActivePenalty) { } - @if (Model.LevelInt < (int)ViewBag.User.Level && Model.HasActivePenalty) + @if (Model.LevelInt < (int) ViewBag.User.Level && Model.HasActivePenalty) { @if (isTempBanned) { @@ -120,12 +124,16 @@ { } -
- } + } + @if (ViewBag.UseNewStats) + { + + } +
- +
@@ -136,7 +144,9 @@
@ViewBag.Localization["META_TYPE_ALL_NAME"] + asp-route-id="@Model.ClientId"> + @ViewBag.Localization["META_TYPE_ALL_NAME"] + @foreach (MetaType type in Enum.GetValues(typeof(MetaType))) { @@ -146,7 +156,9 @@ class="nav-link p-2 pl-3 pr-3 text-center col-12 col-md-auto text-md-left @(Model.MetaFilterType.HasValue && Model.MetaFilterType.Value.ToString() == type.ToString() ? "btn-primary text-white" : "text-muted")" asp-route-id="@Model.ClientId" asp-route-metaFilterType="@type" - data-meta-type="@type">@type.ToTranslatedName() + data-meta-type="@type"> + @type.ToTranslatedName() + } }
@@ -166,7 +178,7 @@
@section targetid { - + } @section scripts { @@ -175,4 +187,4 @@ -} +} \ No newline at end of file diff --git a/WebfrontCore/Views/Client/Profile/Meta/_AdministeredPenaltyResponse.cshtml b/WebfrontCore/Views/Client/Profile/Meta/_AdministeredPenaltyResponse.cshtml index bb573a23..3023b51a 100644 --- a/WebfrontCore/Views/Client/Profile/Meta/_AdministeredPenaltyResponse.cshtml +++ b/WebfrontCore/Views/Client/Profile/Meta/_AdministeredPenaltyResponse.cshtml @@ -26,7 +26,7 @@ else if (match.MatchValue == "reason") { - @if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != SharedLibraryCore.Database.Models.EFPenalty.PenaltyType.Warning) + @if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != Data.Models.EFPenalty.PenaltyType.Warning) { @Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_ANTICHEAT_DETECTION"], Model.AutomatedOffense) diff --git a/WebfrontCore/Views/Client/Profile/Meta/_ReceivedPenaltyResponse.cshtml b/WebfrontCore/Views/Client/Profile/Meta/_ReceivedPenaltyResponse.cshtml index 205d9933..709bf63e 100644 --- a/WebfrontCore/Views/Client/Profile/Meta/_ReceivedPenaltyResponse.cshtml +++ b/WebfrontCore/Views/Client/Profile/Meta/_ReceivedPenaltyResponse.cshtml @@ -1,5 +1,4 @@ @using SharedLibraryCore.Dtos.Meta.Responses -@using SharedLibraryCore @model ReceivedPenaltyResponse @{ @@ -28,7 +27,7 @@ else if (match.MatchValue == "reason") { - @if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != SharedLibraryCore.Database.Models.EFPenalty.PenaltyType.Warning && Model.PenaltyType != SharedLibraryCore.Database.Models.EFPenalty.PenaltyType.Kick) + @if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != Data.Models.EFPenalty.PenaltyType.Warning && Model.PenaltyType != Data.Models.EFPenalty.PenaltyType.Kick) { @Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_ANTICHEAT_DETECTION"], Model.AutomatedOffense) diff --git a/WebfrontCore/Views/Client/Statistics/Advanced.cshtml b/WebfrontCore/Views/Client/Statistics/Advanced.cshtml new file mode 100644 index 00000000..f918c4cb --- /dev/null +++ b/WebfrontCore/Views/Client/Statistics/Advanced.cshtml @@ -0,0 +1,457 @@ +@using SharedLibraryCore.Configuration +@using Data.Models.Client.Stats +@using Stats.Helpers +@using Data.Models.Client +@using Data.Models.Client.Stats.Reference +@using Humanizer +@using Humanizer.Localisation +@using IW4MAdmin.Plugins.Stats +@model Stats.Dtos.AdvancedStatsInfo +@{ + ViewBag.Title = "Advanced Client Statistics"; + ViewBag.Description = Model.ClientName; + + const int maxItems = 5; + const string headshotKey = "MOD_HEAD_SHOT"; + const string meleeKey = "MOD_MELEE"; + + var suicideKeys = new[] {"MOD_SUICIDE", "MOD_FALLING"}; + var config = (GameStringConfiguration) ViewBag.Config; + + var headerClass = Model.Level == EFClient.Permission.Banned ? "bg-danger" : "bg-primary"; + var textClass = Model.Level == EFClient.Permission.Banned ? "text-danger" : "text-primary"; + var borderBottomClass = Model.Level == EFClient.Permission.Banned ? "border-bottom-danger border-top-danger" : "border-bottom border-top"; + var borderClass = Model.Level == EFClient.Permission.Banned ? "border-danger" : "border-primary"; + var buttonClass = Model.Level == EFClient.Permission.Banned ? "btn-danger" : "btn-primary"; + + string GetWeaponNameForHit(EFClientHitStatistic stat) + { + if (stat == null) + { + return null; + } + var rebuiltName = stat.RebuildWeaponName(); + var name = config.GetStringForGame(rebuiltName); + return !rebuiltName.Equals(name, StringComparison.InvariantCultureIgnoreCase) + ? name + : config.GetStringForGame(stat.Weapon.Name); + } + + string GetWeaponAttachmentName(EFWeaponAttachmentCombo attachment) + { + if (attachment == null) + { + return null; + } + + var attachmentText = string.Join('+', new[] + { + config.GetStringForGame(attachment.Attachment1.Name), + config.GetStringForGame(attachment.Attachment2?.Name), + config.GetStringForGame(attachment.Attachment3?.Name) + }.Where(attach => !string.IsNullOrWhiteSpace(attach))); + + return attachmentText; + } + + var weapons = Model.ByWeapon + .Where(hit => hit.DamageInflicted > 0) + .GroupBy(hit => new {hit.WeaponId}) + .Select(group => + { + var withoutAttachments = group.FirstOrDefault(hit => hit.WeaponAttachmentComboId == null); + var mostUsedAttachment = group.Except(new[] {withoutAttachments}) + .OrderByDescending(g => g.DamageInflicted) + .GroupBy(g => g.WeaponAttachmentComboId) + .FirstOrDefault() + ?.FirstOrDefault(); + + if (withoutAttachments == null || mostUsedAttachment == null) + { + return withoutAttachments; + } + + withoutAttachments.WeaponAttachmentComboId = mostUsedAttachment.WeaponAttachmentComboId; + withoutAttachments.WeaponAttachmentCombo = mostUsedAttachment.WeaponAttachmentCombo; + + return withoutAttachments; + }) + .Where(hit => hit != null) + .OrderByDescending(hit => hit.KillCount) + .ToList(); + + var allPerServer = Model.All.Where(hit => hit.ServerId == Model.ServerId).ToList(); + + // if the serverId is supplied we want all the entries with serverID but nothing else + var aggregate = Model.ServerId == null + ? Model.Aggregate + : allPerServer.Where(hit => hit.WeaponId == null) + .Where(hit => hit.HitLocation == null) + .Where(hit => hit.ServerId == Model.ServerId) + .Where(hit => hit.WeaponAttachmentComboId == null) + .FirstOrDefault(hit => hit.MeansOfDeathId == null); + + var filteredHitLocations = Model.ByHitLocation + .Where(hit => hit.HitCount > 0) + .Where(hit => hit.HitLocation.Name != "none") + .Where(hit => hit.HitLocation.Name != "neck") + .Where(hit => hit.ServerId == Model.ServerId) + .OrderByDescending(hit => hit.HitCount) + .ThenBy(hit => hit.HitLocationId) + .ToList(); + + var uniqueWeapons = allPerServer.Any() + ? Model.ByWeapon.Where(hit => hit.ServerId == Model.ServerId) + .Where(weapon => weapon.DamageInflicted > 0) + .GroupBy(weapon => weapon.WeaponId) + .Count() + : (int?) null; // want to default to -- in ui instead of 0 + + var activeTime = weapons.Any() + ? TimeSpan.FromSeconds(weapons.Sum(weapon => weapon.UsageSeconds ?? 0)) + : (TimeSpan?) null; // want to default to -- in ui instead of 0 + + var kdr = aggregate == null + ? null + : Math.Round(aggregate.KillCount / (float) aggregate.DeathCount, 2).ToString(Utilities.CurrentLocalization.Culture); + + var serverLegacyStat = Model.LegacyStats + .FirstOrDefault(stat => stat.ServerId == Model.ServerId); + + // legacy stats section + var performance = Model.Performance; + var skill = Model.ServerId != null ? serverLegacyStat?.Skill.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.Skill), 0).ToNumericalString(); + var elo = Model.ServerId != null ? serverLegacyStat?.EloRating.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.EloRating), 0).ToNumericalString(); + var spm = Model.ServerId != null ? serverLegacyStat?.SPM.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.SPM), 0).ToNumericalString(); + + var performanceHistory = Model.Ratings + .Select(rating => rating.PerformanceMetric); + + if (performance != null) + { + performanceHistory = performanceHistory.Append(performance.Value); + } + + var score = allPerServer.Any() + ? allPerServer.Sum(stat => stat.Score) + : null; + + var headShots = allPerServer.Any() + ? allPerServer.Where(hit => hit.MeansOfDeath?.Name == headshotKey).Sum(hit => hit.HitCount) + : (int?) null; // want to default to -- in ui instead of 0 + + var meleeKills = allPerServer.Any() + ? allPerServer.Where(hit => hit.MeansOfDeath?.Name == meleeKey).Sum(hit => hit.KillCount) + : (int?) null; + + var suicides = allPerServer.Any() + ? allPerServer.Where(hit => suicideKeys.Contains(hit.MeansOfDeath?.Name ?? "")).Sum(hit => hit.KillCount) + : (int?) null; + + var statCards = new[] + { + new + { + Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_KILLS"] as string).Titleize(), + Value = aggregate?.KillCount.ToNumericalString() + }, + new + { + Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_DEATHS"] as string).Titleize(), + Value = aggregate?.DeathCount.ToNumericalString() + }, + new + { + Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_KDR"] as string).Titleize(), + Value = kdr + }, + new + { + Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_SCORE"] as string).Titleize(), + Value = score.ToNumericalString() + }, + new + { + Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_ZSCORE"] as string), + Value = Model.ZScore.ToNumericalString(2) + }, + new + { + Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_SKILL"] as string).ToLower().Titleize(), + Value = skill + }, + new + { + Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_ELO"] as string).Titleize(), + Value = elo + }, + new + { + Name = (ViewBag.Localization["PLUGINS_STATS_META_SPM"] as string).Titleize(), + Value = spm + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_DAMAGE"] as string, + Value = aggregate?.DamageInflicted.ToNumericalString() + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_SUICIDES"] as string, + Value = suicides.ToNumericalString() + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_HEADSHOTS"] as string, + Value = headShots.ToNumericalString() + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_MELEES"] as string, + Value = meleeKills.ToNumericalString() + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_FAV_WEAP"] as string, + Value = GetWeaponNameForHit(weapons.FirstOrDefault()) + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_FAV_ATTACHMENTS"] as string, + Value = GetWeaponAttachmentName(weapons.FirstOrDefault()?.WeaponAttachmentCombo) + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_WEAPONS_USED"] as string, + Value = uniqueWeapons.ToNumericalString() + }, + new + { + Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_ACTIVE_TIME"] as string, + Value = activeTime?.HumanizeForCurrentCulture() + } + }; +} + +
+ +
+
+ +
+
+ @performance +
+
+ + @if (Model.Level == EFClient.Permission.Banned) + { +
@ViewBag.Localization["GLOBAL_PERMISSION_BANNED"]
+ } + else if (Model.ZScore != null) + { + if (Model.ServerId != null) + { +
@((ViewBag.Localization["WEBFRONT_ADV_STATS_PERFORMANCE"] as string).FormatExt(performance.ToNumericalString()))
+ } + + else + { +
@((ViewBag.Localization["WEBFRONT_ADV_STATS_RATING"] as string).FormatExt(Model.Rating.ToNumericalString()))
+ } + + if (Model.Ranking > 0) + { +
@((ViewBag.Localization["WEBFRONT_ADV_STATS_RANKED"] as string).FormatExt(Model.Ranking.ToNumericalString()))
+ } + + else + { +
@ViewBag.Localization["WEBFRONT_ADV_STATS_EXPIRED"]
+ } + } + + else + { +
@ViewBag.Localization["WEBFRONT_STATS_INDEX_UNRANKED"]
+ } +
+
+
+ +
+ +
+ +
+ @foreach (var card in statCards) + { +
+ @if (string.IsNullOrWhiteSpace(card.Value)) + { +
+ } + else + { +
@card.Value
+ } +
@card.Name
+
+ } +
+
+ +
+
+
@ViewBag.Localization["WEBFRONT_ADV_STATS_WEAP_USAGE"]
+
+ + + + + + + + + + @foreach (var weaponHit in weapons.Take(maxItems)) + { + + + @{ var attachments = GetWeaponAttachmentName(weaponHit.WeaponAttachmentCombo); } + @if (string.IsNullOrWhiteSpace(attachments)) + { + + } + else + { + + } + + + + + + } + + @foreach (var weaponHit in weapons.Skip(maxItems)) + { + + + @{ var attachments = GetWeaponAttachmentName(weaponHit.WeaponAttachmentCombo); } + @if (string.IsNullOrWhiteSpace(attachments)) + { + + } + else + { + + } + + + + + + } + +
@ViewBag.Localization["WEBFRONT_ADV_STATS_WEAPON"]@ViewBag.Localization["WEBFRONT_ADV_STATS_FAV_ATTACHMENTS"]@ViewBag.Localization["WEBFRONT_ADV_STATS_KILLS"]@ViewBag.Localization["WEBFRONT_ADV_STATS_HITS"]@ViewBag.Localization["WEBFRONT_ADV_STATS_DAMAGE"]@ViewBag.Localization["WEBFRONT_ADV_STATS_USAGE"]
@GetWeaponNameForHit(weaponHit)@attachments@weaponHit.KillCount.ToNumericalString()@weaponHit.HitCount.ToNumericalString()@weaponHit.DamageInflicted.ToNumericalString()@TimeSpan.FromSeconds(weaponHit.UsageSeconds ?? 0).HumanizeForCurrentCulture(minUnit: TimeUnit.Second)
+ +
+
+
+ +
+
+
@ViewBag.Localization["WEBFRONT_ADV_STATS_HIT_LOCATIONS"]
+
+ + + + + + + + @{ + var totalHits = filteredHitLocations.Sum(hit => hit.HitCount); + } + @foreach (var hitLocation in filteredHitLocations.Take(8)) + { + + + + + + + } + + @foreach (var hitLocation in filteredHitLocations.Skip(8)) + { + + + + + + + } +
@ViewBag.Localization["WEBFRONT_ADV_STATS_LOCATION"]@ViewBag.Localization["WEBFRONT_ADV_STATS_HITS"]@ViewBag.Localization["WEBFRONT_ADV_STATS_PERCENTAGE"]@ViewBag.Localization["WEBFRONT_ADV_STATS_DAMAGE"]
@config.GetStringForGame(hitLocation.HitLocation.Name)@hitLocation.HitCount@Math.Round((hitLocation.HitCount / (float) totalHits) * 100.0).ToString(Utilities.CurrentLocalization.Culture)%@hitLocation.DamageInflicted.ToNumericalString()
+ +
+
+
+ + +
+
+
+ +@{ + var projection = filteredHitLocations.Select(loc => new + { + name = loc.HitLocation.Name, + // we want to count head and neck as the same + percentage = (loc.HitLocation.Name == "head" + ? filteredHitLocations.FirstOrDefault(c => c.HitLocation.Name == "neck")?.HitCount ?? 0 + loc.HitCount + : loc.HitCount) / (float) totalHits + }).ToList(); + var maxPercentage = projection.Any() ? projection.Max(p => p.percentage) : 0; +} + +@section scripts +{ + + + + + +} \ No newline at end of file diff --git a/WebfrontCore/Views/Client/Statistics/Components/TopPlayers/_List.cshtml b/WebfrontCore/Views/Client/Statistics/Components/TopPlayers/_List.cshtml new file mode 100644 index 00000000..b53759e4 --- /dev/null +++ b/WebfrontCore/Views/Client/Statistics/Components/TopPlayers/_List.cshtml @@ -0,0 +1,151 @@ +@using IW4MAdmin.Plugins.Stats +@model List +@{ + Layout = null; + var loc = Utilities.CurrentLocalization.LocalizationIndex.Set; + double getDeviation(double deviations) => Math.Pow(Math.E, 5.259 + (deviations * 0.812)); + string rankIcon(double? elo) + { + if (elo >= getDeviation(-0.75) && elo < getDeviation(1.25)) + { + return "0_no-place/menu_div_no_place.png"; + } + if (elo >= getDeviation(0.125) && elo < getDeviation(0.625)) + { + return "1_iron/menu_div_iron_sub03.png"; + } + if (elo >= getDeviation(0.625) && elo < getDeviation(1.0)) + { + return "2_bronze/menu_div_bronze_sub03.png"; + } + if (elo >= getDeviation(1.0) && elo < getDeviation(1.25)) + { + return "3_silver/menu_div_silver_sub03.png"; + } + if (elo >= getDeviation(1.25) && elo < getDeviation(1.5)) + { + return "4_gold/menu_div_gold_sub03.png"; + } + if (elo >= getDeviation(1.5) && elo < getDeviation(1.75)) + { + return "5_platinum/menu_div_platinum_sub03.png"; + } + if (elo >= getDeviation(1.75) && elo < getDeviation(2.0)) + { + return "6_semipro/menu_div_semipro_sub03.png"; + } + if (elo >= getDeviation(2.0)) + { + return "7_pro/menu_div_pro_sub03.png"; + } + + return "0_no-place/menu_div_no_place.png"; + } +} + +@if (Model.Count == 0) +{ +
@Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_NOQUALIFY"]
+} +@foreach (var stat in Model) +{ +
+ @if (ViewBag.UseNewStats) + { + @stat.Performance + } +
+
+
#@stat.Ranking
+ @if (stat.RatingChange > 0) + { +
+
+
@stat.RatingChange
+
+ } + @if (stat.RatingChange < 0) + { +
+
@Math.Abs(stat.RatingChange)
+
+
+ } + + @if (!ViewBag.UseNewStats) + { + + + + } + else + { + + + + } +
+ + @if (ViewBag.UseNewStats) + { +
+
+ + @stat.Performance.ToNumericalString() + + @if (stat.ServerId == null) + { + @loc["WEBFRONT_ADV_STATS_RATING"].FormatExt("").ToLower() + } + + else + { + @loc["WEBFRONT_ADV_STATS_PERFORMANCE"].FormatExt("").ToLower() + } +
+
+ @stat.Kills.ToNumericalString() @loc["PLUGINS_STATS_TEXT_KILLS"] +
+
+ @stat.Deaths.ToNumericalString() @loc["PLUGINS_STATS_TEXT_DEATHS"]
+
+
+ @stat.KDR @loc["PLUGINS_STATS_TEXT_KDR"] +
+
+ @stat.TimePlayedValue.HumanizeForCurrentCulture() @loc["WEBFRONT_PROFILE_PLAYER"] +
+
+ @stat.LastSeenValue.HumanizeForCurrentCulture() @loc["WEBFRONT_PROFILE_LSEEN"] +
+
+ } + else + { + @stat.Performance @loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"] +
+ @stat.KDR @loc["PLUGINS_STATS_TEXT_KDR"] + @stat.Kills @loc["PLUGINS_STATS_TEXT_KILLS"] + @stat.Deaths @loc["PLUGINS_STATS_TEXT_DEATHS"]
+ @loc["WEBFRONT_PROFILE_PLAYER"] @stat.TimePlayed @loc["GLOBAL_TIME_HOURS"]
+ @loc["WEBFRONT_PROFILE_LSEEN"] @stat.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] + } +
+ +
+ +
+ +
+ @if (ViewBag.UseNewStats) + { + @stat.Performance + } + + else + { + + } +
+
+} diff --git a/Plugins/Web/StatsWeb/Views/Stats/Index.cshtml b/WebfrontCore/Views/Client/Statistics/Index.cshtml similarity index 97% rename from Plugins/Web/StatsWeb/Views/Stats/Index.cshtml rename to WebfrontCore/Views/Client/Statistics/Index.cshtml index 7d8ace74..64d931fe 100644 --- a/Plugins/Web/StatsWeb/Views/Stats/Index.cshtml +++ b/WebfrontCore/Views/Client/Statistics/Index.cshtml @@ -14,7 +14,7 @@
- @await Component.InvokeAsync("TopPlayers", new { count = 10, offset = 0 }) + @await Component.InvokeAsync("TopPlayers", new { count = 25, offset = 0 })
@foreach (var server in ViewBag.Servers) @@ -30,5 +30,5 @@ - + } diff --git a/Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml b/WebfrontCore/Views/Client/_MessageContext.cshtml similarity index 100% rename from Plugins/Web/StatsWeb/Views/Stats/_MessageContext.cshtml rename to WebfrontCore/Views/Client/_MessageContext.cshtml diff --git a/Plugins/Web/StatsWeb/Views/Stats/_PenaltyInfo.cshtml b/WebfrontCore/Views/Client/_PenaltyInfo.cshtml similarity index 91% rename from Plugins/Web/StatsWeb/Views/Stats/_PenaltyInfo.cshtml rename to WebfrontCore/Views/Client/_PenaltyInfo.cshtml index fe20c4be..fc4f9c5a 100644 --- a/Plugins/Web/StatsWeb/Views/Stats/_PenaltyInfo.cshtml +++ b/WebfrontCore/Views/Client/_PenaltyInfo.cshtml @@ -1,4 +1,4 @@ -@model IEnumerable +@model IEnumerable @{ Layout = null; } diff --git a/WebfrontCore/Views/Penalty/List.cshtml b/WebfrontCore/Views/Penalty/List.cshtml index 0966054c..1df43ff4 100644 --- a/WebfrontCore/Views/Penalty/List.cshtml +++ b/WebfrontCore/Views/Penalty/List.cshtml @@ -1,4 +1,4 @@ -@model SharedLibraryCore.Database.Models.EFPenalty.PenaltyType +@model Data.Models.EFPenalty.PenaltyType @{ var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; } @@ -7,11 +7,11 @@