Remove old version
This commit is contained in:
parent
32a1886cf4
commit
0fd5fc7227
439
GC-local-server-rewrite/.gitignore
vendored
439
GC-local-server-rewrite/.gitignore
vendored
@ -1,439 +0,0 @@
|
|||||||
### JetBrains template
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
||||||
|
|
||||||
# User-specific stuff
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/**/usage.statistics.xml
|
|
||||||
.idea/**/dictionaries
|
|
||||||
.idea/**/shelf
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
|
|
||||||
# Sensitive or high-churn files
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
.idea/**/dbnavigator.xml
|
|
||||||
|
|
||||||
# Gradle
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
# Gradle and Maven with auto-import
|
|
||||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
||||||
# since they will be recreated, and may cause churn. Uncomment if using
|
|
||||||
# auto-import.
|
|
||||||
# .idea/artifacts
|
|
||||||
# .idea/compiler.xml
|
|
||||||
# .idea/jarRepositories.xml
|
|
||||||
# .idea/modules.xml
|
|
||||||
# .idea/*.iml
|
|
||||||
# .idea/modules
|
|
||||||
# *.iml
|
|
||||||
# *.ipr
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
# File-based project format
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
out/
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# Editor-based Rest Client
|
|
||||||
.idea/httpRequests
|
|
||||||
|
|
||||||
# Android studio 3.1+ serialized cache file
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
|
|
||||||
### VisualStudio template
|
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
##
|
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.rsuser
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
||||||
*.userprefs
|
|
||||||
|
|
||||||
# Mono auto generated files
|
|
||||||
mono_crash.*
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug/
|
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
|
||||||
[Rr]eleases/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
[Ww][Ii][Nn]32/
|
|
||||||
[Aa][Rr][Mm]/
|
|
||||||
[Aa][Rr][Mm]64/
|
|
||||||
bld/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
[Ll]og/
|
|
||||||
[Ll]ogs/
|
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
|
||||||
.vs/
|
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
||||||
#wwwroot/
|
|
||||||
|
|
||||||
# Visual Studio 2017 auto generated files
|
|
||||||
Generated\ Files/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
# NUnit
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
nunit-*.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# Benchmark Results
|
|
||||||
BenchmarkDotNet.Artifacts/
|
|
||||||
|
|
||||||
# .NET Core
|
|
||||||
project.lock.json
|
|
||||||
project.fragment.lock.json
|
|
||||||
artifacts/
|
|
||||||
|
|
||||||
# ASP.NET Scaffolding
|
|
||||||
ScaffoldingReadMe.txt
|
|
||||||
|
|
||||||
# StyleCop
|
|
||||||
StyleCopReport.xml
|
|
||||||
|
|
||||||
# Files built by Visual Studio
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_h.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.iobj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.ipdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*_wpftmp.csproj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
*.VC.db
|
|
||||||
*.VC.VC.opendb
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
*.sap
|
|
||||||
|
|
||||||
# Visual Studio Trace Files
|
|
||||||
*.e2e
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# AxoCover is a Code Coverage Tool
|
|
||||||
.axoCover/*
|
|
||||||
!.axoCover/settings.json
|
|
||||||
|
|
||||||
# Coverlet is a free, cross platform Code Coverage Tool
|
|
||||||
coverage*.json
|
|
||||||
coverage*.xml
|
|
||||||
coverage*.info
|
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
|
||||||
*.coverage
|
|
||||||
*.coveragexml
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
nCrunchTemp_*
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
|
||||||
# in these scripts will be unencrypted
|
|
||||||
PublishScripts/
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# NuGet Symbol Packages
|
|
||||||
*.snupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/[Pp]ackages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/[Pp]ackages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
|
||||||
#!**/[Pp]ackages/repositories.config
|
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
Package.StoreAssociation.xml
|
|
||||||
_pkginfo.txt
|
|
||||||
*.appx
|
|
||||||
*.appxbundle
|
|
||||||
*.appxupload
|
|
||||||
|
|
||||||
# Visual Studio cache files
|
|
||||||
# files ending in .cache can be ignored
|
|
||||||
*.[Cc]ache
|
|
||||||
# but keep track of directories ending in .cache
|
|
||||||
!?*.[Cc]ache/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
ClientBin/
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.jfm
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
orleans.codegen.cs
|
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
|
||||||
#*.snk
|
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
|
||||||
#bower_components/
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
ServiceFabricBackup/
|
|
||||||
*.rptproj.bak
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
*.ndf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
*.rptproj.rsuser
|
|
||||||
*- [Bb]ackup.rdl
|
|
||||||
*- [Bb]ackup ([0-9]).rdl
|
|
||||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
node_modules/
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
|
||||||
*.vbw
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
paket-files/
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|
||||||
# CodeRush personal settings
|
|
||||||
.cr/personal
|
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
|
||||||
# tools/**
|
|
||||||
# !tools/packages.config
|
|
||||||
|
|
||||||
# Tabs Studio
|
|
||||||
*.tss
|
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
|
||||||
*.jmconfig
|
|
||||||
|
|
||||||
# BizTalk build output
|
|
||||||
*.btp.cs
|
|
||||||
*.btm.cs
|
|
||||||
*.odx.cs
|
|
||||||
*.xsd.cs
|
|
||||||
|
|
||||||
# OpenCover UI analysis results
|
|
||||||
OpenCover/
|
|
||||||
|
|
||||||
# Azure Stream Analytics local run output
|
|
||||||
ASALocalRun/
|
|
||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
|
||||||
*.binlog
|
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
|
||||||
*.nvuser
|
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
|
||||||
.mfractor/
|
|
||||||
|
|
||||||
# Local History for Visual Studio
|
|
||||||
.localhistory/
|
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
|
||||||
healthchecksdb
|
|
||||||
|
|
||||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
|
||||||
MigrationBackup/
|
|
||||||
|
|
||||||
# Ionide (cross platform F# VS Code tools) working folder
|
|
||||||
.ionide/
|
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
|
||||||
FodyWeavers.xsd
|
|
||||||
|
|
||||||
# Ignore card db since we should start from scratch
|
|
||||||
/db/card.db3
|
|
@ -1,74 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<RootNamespace>GCLocalServerRewrite</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CertificateManager" Version="1.0.8" />
|
|
||||||
<PackageReference Include="ChoETL" Version="1.2.1.48" />
|
|
||||||
<PackageReference Include="ConcurrentHashSet" Version="1.3.0" />
|
|
||||||
<PackageReference Include="Config.Net" Version="5.1.3" />
|
|
||||||
<PackageReference Include="Config.Net.Json" Version="4.19.0" />
|
|
||||||
<PackageReference Include="EmbedIO" Version="3.5.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.5.22301.12" />
|
|
||||||
<PackageReference Include="sqlite-net2" Version="2.1.0-preB" />
|
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.2" />
|
|
||||||
<PackageReference Include="System.Security.Cryptography.X509Certificates" Version="4.3.2" />
|
|
||||||
<PackageReference Include="Unosquare.Swan.Lite" Version="3.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="log" />
|
|
||||||
<Folder Include="event\" />
|
|
||||||
<None Remove="db\music.db3" />
|
|
||||||
<None Remove="db\music4MAX465.db3" />
|
|
||||||
<Content Include="db\music.db3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<None Remove="static\favicon.ico" />
|
|
||||||
<Content Include="db\music4MAX465.db3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<Content Include="static\favicon.ico">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<None Remove="static\index.html" />
|
|
||||||
<Content Include="static\index.html">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<None Remove="static\news.png" />
|
|
||||||
<Content Include="static\news.png">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<None Remove="GC-local-server-rewrite.exe.config.xml" />
|
|
||||||
<None Remove="db\music4MAX.db3" />
|
|
||||||
<Content Include="db\music4MAX.db3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<None Update="config.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</None>
|
|
||||||
<None Update="db\music471.db3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\SharedProject\SharedProject.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,107 +0,0 @@
|
|||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.server;
|
|
||||||
using SQLitePCL;
|
|
||||||
using Swan;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite;
|
|
||||||
|
|
||||||
internal class Program
|
|
||||||
{
|
|
||||||
private static void Main(string[] args)
|
|
||||||
{
|
|
||||||
Batteries_V2.Init();
|
|
||||||
|
|
||||||
InitializeLogging();
|
|
||||||
|
|
||||||
LogConfigValues();
|
|
||||||
|
|
||||||
var urlPrefixes =
|
|
||||||
args.Length > 0 ? new List<string>(args) : new List<string> { "http://+:80", "https://+:443" };
|
|
||||||
|
|
||||||
using (var cts = new CancellationTokenSource())
|
|
||||||
{
|
|
||||||
Task.WaitAll(
|
|
||||||
RunWebServerAsync(urlPrefixes, cts.Token),
|
|
||||||
Task.CompletedTask,
|
|
||||||
WaitForUserBreakAsync(cts.Cancel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
"Bye".Info(nameof(Program));
|
|
||||||
Terminal.Flush();
|
|
||||||
|
|
||||||
Console.WriteLine("Press any key to exit.");
|
|
||||||
Console.ReadKey(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitializeLogging()
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(PathHelper.LogRootPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(PathHelper.LogRootPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.RegisterLogger(new FileLogger(Path.Combine(PathHelper.LogRootPath, Configs.LOG_BASE_NAME), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create and run a web server.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="urlPrefixes"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
private static async Task RunWebServerAsync(IEnumerable<string> urlPrefixes, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
using var server = Server.CreateWebServer(urlPrefixes);
|
|
||||||
await server.RunAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prompt the user to press any key;
|
|
||||||
/// when a key is next pressed, call the specified action to cancel operations.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cancel"> Cancel Action to call </param>
|
|
||||||
private static async Task WaitForUserBreakAsync(Action cancel)
|
|
||||||
{
|
|
||||||
// Be sure to run in parallel.
|
|
||||||
await Task.Yield();
|
|
||||||
|
|
||||||
"Press x to stop the web server.".Info(nameof(Program));
|
|
||||||
WaitForKeypress();
|
|
||||||
"Stopping...".Info(nameof(Program));
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clear the console input buffer and wait for a keypress
|
|
||||||
/// </summary>
|
|
||||||
private static void WaitForKeypress()
|
|
||||||
{
|
|
||||||
ConsoleKeyInfo consoleKeyInfo;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
while (Console.KeyAvailable == false)
|
|
||||||
{
|
|
||||||
Thread.Sleep(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
consoleKeyInfo = Console.ReadKey(true);
|
|
||||||
} while (consoleKeyInfo.Key != ConsoleKey.X);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void LogConfigValues()
|
|
||||||
{
|
|
||||||
var paths = $"Paths: {nameof(PathHelper.HtmlRootPath)}: {PathHelper.HtmlRootPath}\n" +
|
|
||||||
$"{nameof(PathHelper.LogRootPath)}: {PathHelper.LogRootPath}\n" +
|
|
||||||
$"{nameof(PathHelper.DataBaseRootPath)}: {PathHelper.DataBaseRootPath}\n" +
|
|
||||||
$"{nameof(PathHelper.ConfigFilePath)}: {PathHelper.ConfigFilePath}\n" +
|
|
||||||
$"{nameof(PathHelper.CertRootPath)}: {PathHelper.CertRootPath}\n";
|
|
||||||
paths.Info();
|
|
||||||
|
|
||||||
var configs = "Config values: \n" +
|
|
||||||
$"{Configs.SETTINGS.Stringify()}";
|
|
||||||
configs.Info();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
|
||||||
<security>
|
|
||||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<!-- UAC 清单选项
|
|
||||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
|
||||||
以下节点之一替换 requestedExecutionLevel 节点。
|
|
||||||
|
|
||||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
|
||||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
|
||||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
|
||||||
|
|
||||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
|
||||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
|
|
||||||
元素。
|
|
||||||
-->
|
|
||||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
|
||||||
</requestedPrivileges>
|
|
||||||
</security>
|
|
||||||
</trustInfo>
|
|
||||||
|
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
||||||
<application>
|
|
||||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
|
||||||
Windows 版本的列表。取消评论适当的元素,
|
|
||||||
Windows 将自动选择最兼容的环境。 -->
|
|
||||||
|
|
||||||
<!-- Windows Vista -->
|
|
||||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 7 -->
|
|
||||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 8 -->
|
|
||||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 8.1 -->
|
|
||||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
|
||||||
|
|
||||||
<!-- Windows 10 -->
|
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
|
||||||
|
|
||||||
</application>
|
|
||||||
</compatibility>
|
|
||||||
|
|
||||||
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
|
||||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
|
||||||
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
|
|
||||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
|
|
||||||
|
|
||||||
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
|
||||||
<!--
|
|
||||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
||||||
<windowsSettings>
|
|
||||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
|
||||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
|
||||||
</windowsSettings>
|
|
||||||
</application>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity
|
|
||||||
type="win32"
|
|
||||||
name="Microsoft.Windows.Common-Controls"
|
|
||||||
version="6.0.0.0"
|
|
||||||
processorArchitecture="*"
|
|
||||||
publicKeyToken="6595b64144ccf1df"
|
|
||||||
language="*"
|
|
||||||
/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</assembly>
|
|
@ -1,238 +0,0 @@
|
|||||||
using System.Security.Cryptography;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using CertificateManager;
|
|
||||||
using CertificateManager.Models;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Swan;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public static class CertificateHelper
|
|
||||||
{
|
|
||||||
private const X509KeyUsageFlags ROOT_CA_X509_KEY_USAGE_FLAGS = X509KeyUsageFlags.KeyCertSign |
|
|
||||||
X509KeyUsageFlags.DataEncipherment |
|
|
||||||
X509KeyUsageFlags.KeyEncipherment |
|
|
||||||
X509KeyUsageFlags.DigitalSignature;
|
|
||||||
|
|
||||||
private const X509KeyStorageFlags X509_KEY_STORAGE_FLAGS_MACHINE = X509KeyStorageFlags.PersistKeySet |
|
|
||||||
X509KeyStorageFlags.MachineKeySet |
|
|
||||||
X509KeyStorageFlags.Exportable;
|
|
||||||
|
|
||||||
private const X509KeyUsageFlags CERT_X509_KEY_USAGE_FLAGS = X509KeyUsageFlags.DataEncipherment |
|
|
||||||
X509KeyUsageFlags.KeyEncipherment |
|
|
||||||
X509KeyUsageFlags.DigitalSignature;
|
|
||||||
|
|
||||||
private static readonly DistinguishedName ROOT_CA_DISTINGUISHED_NAME = new()
|
|
||||||
{
|
|
||||||
CommonName = Configs.ROOT_CA_CN
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly DistinguishedName CERT_DISTINGUISHED_NAME = new()
|
|
||||||
{
|
|
||||||
CommonName = Configs.CERT_CN
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly BasicConstraints ROOT_CA_BASIC_CONSTRAINTS = new()
|
|
||||||
{
|
|
||||||
CertificateAuthority = true,
|
|
||||||
HasPathLengthConstraint = true,
|
|
||||||
PathLengthConstraint = 3,
|
|
||||||
Critical = true
|
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly BasicConstraints CERT_BASIC_CONSTRAINTS = new()
|
|
||||||
{
|
|
||||||
CertificateAuthority = false,
|
|
||||||
HasPathLengthConstraint = false,
|
|
||||||
PathLengthConstraint = 0,
|
|
||||||
Critical = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly SubjectAlternativeName SUBJECT_ALTERNATIVE_NAME = new()
|
|
||||||
{
|
|
||||||
DnsName = Configs.DOMAINS,
|
|
||||||
IpAddress = System.Net.IPAddress.Parse(Configs.SETTINGS.ServerIp)
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly ValidityPeriod VALIDITY_PERIOD = new()
|
|
||||||
{
|
|
||||||
ValidFrom = DateTime.UtcNow,
|
|
||||||
ValidTo = DateTime.UtcNow.AddYears(3)
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly OidCollection OID_COLLECTION = new()
|
|
||||||
{
|
|
||||||
OidLookup.AnyPurpose
|
|
||||||
};
|
|
||||||
|
|
||||||
public static X509Certificate2 InitializeCertificate()
|
|
||||||
{
|
|
||||||
if (CertificateExists())
|
|
||||||
{
|
|
||||||
var existingCert = GetCertificate(StoreName.My, StoreLocation.LocalMachine, Configs.CERT_CN);
|
|
||||||
|
|
||||||
if (existingCert != null)
|
|
||||||
{
|
|
||||||
return existingCert;
|
|
||||||
}
|
|
||||||
"Existing CN not found! Removing old certificates and genrate new ones...".Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemovePreviousCert(StoreName.My, StoreLocation.LocalMachine);
|
|
||||||
RemovePreviousCert(StoreName.Root, StoreLocation.LocalMachine);
|
|
||||||
|
|
||||||
var serviceProvider = new ServiceCollection()
|
|
||||||
.AddCertificateManager().BuildServiceProvider();
|
|
||||||
|
|
||||||
var createCertificates = serviceProvider.GetService<CreateCertificates>();
|
|
||||||
|
|
||||||
if (createCertificates == null)
|
|
||||||
{
|
|
||||||
throw SelfCheck.Failure("Cannot initialize CreateCertificates service!");
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootCa = createCertificates.NewRsaSelfSignedCertificate(
|
|
||||||
ROOT_CA_DISTINGUISHED_NAME,
|
|
||||||
ROOT_CA_BASIC_CONSTRAINTS,
|
|
||||||
VALIDITY_PERIOD,
|
|
||||||
SUBJECT_ALTERNATIVE_NAME,
|
|
||||||
OID_COLLECTION,
|
|
||||||
ROOT_CA_X509_KEY_USAGE_FLAGS,
|
|
||||||
new RsaConfiguration()
|
|
||||||
);
|
|
||||||
|
|
||||||
var cert = createCertificates.NewRsaChainedCertificate(
|
|
||||||
CERT_DISTINGUISHED_NAME,
|
|
||||||
CERT_BASIC_CONSTRAINTS,
|
|
||||||
VALIDITY_PERIOD,
|
|
||||||
SUBJECT_ALTERNATIVE_NAME,
|
|
||||||
rootCa,
|
|
||||||
OID_COLLECTION,
|
|
||||||
CERT_X509_KEY_USAGE_FLAGS,
|
|
||||||
new RsaConfiguration()
|
|
||||||
);
|
|
||||||
|
|
||||||
var exportService = serviceProvider.GetService<ImportExportCertificate>();
|
|
||||||
|
|
||||||
if (exportService == null)
|
|
||||||
{
|
|
||||||
throw SelfCheck.Failure("Cannot initialize ImportExportCertificate service!");
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootCaPfxBytes = exportService.ExportRootPfx(null, rootCa);
|
|
||||||
var certPfxBytes = exportService.ExportChainedCertificatePfx(null, cert, rootCa);
|
|
||||||
|
|
||||||
var rootCaWithPrivateKey = new X509Certificate2(rootCaPfxBytes, (string)null!,
|
|
||||||
X509_KEY_STORAGE_FLAGS_MACHINE);
|
|
||||||
|
|
||||||
var certWithPrivateKey = new X509Certificate2(certPfxBytes, (string)null!,
|
|
||||||
X509_KEY_STORAGE_FLAGS_MACHINE);
|
|
||||||
|
|
||||||
|
|
||||||
AddCertToStore(rootCaWithPrivateKey, StoreName.My, StoreLocation.LocalMachine);
|
|
||||||
AddCertToStore(rootCaWithPrivateKey, StoreName.Root, StoreLocation.LocalMachine);
|
|
||||||
AddCertToStore(certWithPrivateKey, StoreName.My, StoreLocation.LocalMachine);
|
|
||||||
|
|
||||||
Directory.CreateDirectory(PathHelper.CertRootPath);
|
|
||||||
|
|
||||||
File.WriteAllBytes(Path.Combine(PathHelper.CertRootPath, "root.pfx"), rootCaWithPrivateKey.Export(X509ContentType.Pfx));
|
|
||||||
File.WriteAllBytes(Path.Combine(PathHelper.CertRootPath, "cert.pfx"), certWithPrivateKey.Export(X509ContentType.Pfx));
|
|
||||||
|
|
||||||
return certWithPrivateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddCertToStore(X509Certificate2 cert, StoreName storeName, StoreLocation storeLocation)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var store = new X509Store(storeName, storeLocation);
|
|
||||||
store.Open(OpenFlags.ReadWrite);
|
|
||||||
store.Add(cert);
|
|
||||||
|
|
||||||
store.Close();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error(e.Source ?? "", e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RemovePreviousCert(StoreName storeName, StoreLocation storeLocation)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var store = new X509Store(storeName, storeLocation);
|
|
||||||
store.Open(OpenFlags.ReadWrite);
|
|
||||||
var result = store.Certificates.Find(X509FindType.FindByIssuerName, Configs.ROOT_CA_CN, true);
|
|
||||||
|
|
||||||
if (result.Any())
|
|
||||||
{
|
|
||||||
store.RemoveRange(result);
|
|
||||||
"Removed previous certs!".Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
store.Close();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error(e.Source ?? "", e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool CertificateExists()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
|
||||||
store.Open(OpenFlags.ReadOnly);
|
|
||||||
var result = store.Certificates.Find(X509FindType.FindByIssuerName, Configs.ROOT_CA_CN, true);
|
|
||||||
|
|
||||||
if (result.Count == 2)
|
|
||||||
{
|
|
||||||
"Certificate exists!".Info();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
store.Close();
|
|
||||||
"Certificate not found! Will generate new certs...".Info();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error(e.Source ?? "", e.Message);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static X509Certificate2? GetCertificate(StoreName storeName, StoreLocation storeLocation, string commonName)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var store = new X509Store(storeName, storeLocation);
|
|
||||||
store.Open(OpenFlags.ReadWrite);
|
|
||||||
var result = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
|
|
||||||
$"CN={commonName}", true);
|
|
||||||
|
|
||||||
if (result.Any())
|
|
||||||
{
|
|
||||||
$"Certificate CN={commonName} found!".Info();
|
|
||||||
|
|
||||||
return result.First();
|
|
||||||
}
|
|
||||||
|
|
||||||
store.Close();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error(e.Source ?? "", e.Message);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
using Config.Net;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public static class Configs
|
|
||||||
{
|
|
||||||
public const bool USE_FILE_CACHE = true;
|
|
||||||
|
|
||||||
public const string ROOT_CA_CN = "Taito Arcade Machine CA";
|
|
||||||
|
|
||||||
public const string CERT_CN = "GC local server";
|
|
||||||
|
|
||||||
public const string DB_FOLDER = "db";
|
|
||||||
|
|
||||||
public const string LOG_FOLDER = "log";
|
|
||||||
|
|
||||||
public const string CERT_FOLDER = "certs";
|
|
||||||
|
|
||||||
public const string LOG_BASE_NAME = "log";
|
|
||||||
|
|
||||||
public const string CONFIG_FILE_NAME = "config.json";
|
|
||||||
|
|
||||||
public const string STATIC_FOLDER = "static";
|
|
||||||
|
|
||||||
public const string WWWROOT = "wwwroot";
|
|
||||||
|
|
||||||
public const string API_BASE_ROUTE = "/api";
|
|
||||||
|
|
||||||
public const string OPTION_SERVICE_BASE_ROUTE = "/service/option";
|
|
||||||
|
|
||||||
public const string CARD_SERVICE_BASE_ROUTE = "/service/card";
|
|
||||||
|
|
||||||
public const string UPLOAD_SERVICE_BASE_ROUTE = "/service/upload";
|
|
||||||
|
|
||||||
public const string RESPONE_SERVICE_BASE_ROUTE = "/service/respone";
|
|
||||||
|
|
||||||
public const string INCOM_SERVICE_BASE_ROUTE = "/service/incom";
|
|
||||||
|
|
||||||
public const string UPDATE_SERVICE_BASE_ROUTE = "/update/cgi";
|
|
||||||
|
|
||||||
public const string RANK_BASE_ROUTE = "/ranking";
|
|
||||||
|
|
||||||
public const string ALIVE_BASE_ROUTE = "/alive";
|
|
||||||
|
|
||||||
public const string SERVER_BASE_ROUTE = "/server";
|
|
||||||
|
|
||||||
public const string STATIC_BASE_ROUTE = "/static";
|
|
||||||
|
|
||||||
public const string ROOT_XPATH = "/root";
|
|
||||||
|
|
||||||
public const string DATA_XPATH = $"{ROOT_XPATH}/data";
|
|
||||||
|
|
||||||
public const string CARD = "card";
|
|
||||||
|
|
||||||
public const string CARD_XPATH = $"{ROOT_XPATH}/{CARD}";
|
|
||||||
|
|
||||||
public const string CARD_DETAIL = "card_detail";
|
|
||||||
|
|
||||||
public const string CARD_DETAIL_SINGLE_XPATH = $"{ROOT_XPATH}/{CARD_DETAIL}";
|
|
||||||
|
|
||||||
public const string CARD_DETAIL_RECORD_XPATH = $"{CARD_DETAIL_SINGLE_XPATH}/record";
|
|
||||||
|
|
||||||
public const string CARD_BDATA = "card_bdata";
|
|
||||||
|
|
||||||
public const string CARD_BDATA_XPATH = $"{ROOT_XPATH}/{CARD_BDATA}";
|
|
||||||
|
|
||||||
public const string MUSIC = "music";
|
|
||||||
|
|
||||||
public const string MUSIC_XPATH = $"{ROOT_XPATH}/{MUSIC}/record";
|
|
||||||
|
|
||||||
public const string MUSIC_EXTRA = "music_extra";
|
|
||||||
|
|
||||||
public const string MUSIC_EXTRA_XPATH = $"{ROOT_XPATH}/{MUSIC_EXTRA}/record";
|
|
||||||
|
|
||||||
public const string MUSIC_AOU = "music_aou";
|
|
||||||
|
|
||||||
public const string MUSIC_AOU_XPATH = $"{ROOT_XPATH}/{MUSIC_AOU}/record";
|
|
||||||
|
|
||||||
public const string ITEM = "item";
|
|
||||||
|
|
||||||
public const string ITEM_XPATH = $"{ROOT_XPATH}/{ITEM}/record";
|
|
||||||
|
|
||||||
public const string AVATAR = "avatar";
|
|
||||||
|
|
||||||
public const string AVATAR_XPATH = $"{ROOT_XPATH}/{AVATAR}/record";
|
|
||||||
|
|
||||||
public const string SKIN = "skin";
|
|
||||||
|
|
||||||
public const string SKIN_XPATH = $"{ROOT_XPATH}/{SKIN}/record";
|
|
||||||
|
|
||||||
public const string TITLE = "title";
|
|
||||||
|
|
||||||
public const string TITLE_XPATH = $"{ROOT_XPATH}/{TITLE}/record";
|
|
||||||
|
|
||||||
public const string NAVIGATOR = "navigator";
|
|
||||||
|
|
||||||
public const string NAVIGATOR_XPATH = $"{ROOT_XPATH}/{NAVIGATOR}/record";
|
|
||||||
|
|
||||||
public const string COIN = "coin";
|
|
||||||
|
|
||||||
public const string COIN_XPATH = $"{ROOT_XPATH}/{COIN}";
|
|
||||||
|
|
||||||
public const string UNLOCK_REWARD = "unlock_reward";
|
|
||||||
|
|
||||||
public const string UNLOCK_REWARD_XPATH = $"{ROOT_XPATH}/{UNLOCK_REWARD}/record";
|
|
||||||
|
|
||||||
public const string UNLOCK_KEYNUM = "unlock_keynum";
|
|
||||||
|
|
||||||
public const string UNLOCK_KEYNUM_XPATH = $"{ROOT_XPATH}/{UNLOCK_KEYNUM}/record";
|
|
||||||
|
|
||||||
public const string SOUND_EFFECT = "sound_effect";
|
|
||||||
|
|
||||||
public const string SE_XPATH = $"{ROOT_XPATH}/{SOUND_EFFECT}/record";
|
|
||||||
|
|
||||||
public const string GET_MESSAGE = "get_message";
|
|
||||||
|
|
||||||
public const string TOTAL_TROPHY = "total_trophy";
|
|
||||||
|
|
||||||
public const string TOTAL_TROPHY_XPATH = $"{ROOT_XPATH}/{TOTAL_TROPHY}";
|
|
||||||
|
|
||||||
public const string EVENT_REWARD = "event_reward";
|
|
||||||
|
|
||||||
public const string COND = "cond";
|
|
||||||
|
|
||||||
public const string SESSION_XPATH = $"{ROOT_XPATH}/session";
|
|
||||||
|
|
||||||
public const string RANK_STATUS_XPATH = $"{ROOT_XPATH}/ranking_status";
|
|
||||||
|
|
||||||
public const string ONLINE_MATCHING_XPATH = $"{ROOT_XPATH}/online_matching/record";
|
|
||||||
|
|
||||||
public const string ONLINE_BATTLE_RESULT_XPATH = $"{ROOT_XPATH}/online_battle_result";
|
|
||||||
|
|
||||||
public const int FIRST_CONFIG_PCOL1 = 0;
|
|
||||||
public const int SECOND_CONFIG_PCOL1 = 1;
|
|
||||||
public const int CONFIG_PCOL2 = 0;
|
|
||||||
public const int CONFIG_PCOL3 = 0;
|
|
||||||
|
|
||||||
public const int FAVORITE_PCOL1 = 10;
|
|
||||||
|
|
||||||
public const int COUNT_PCOL1 = 20;
|
|
||||||
|
|
||||||
public const int SCORE_PCOL1 = 21;
|
|
||||||
|
|
||||||
public const string MATCHING_URL_BASE = "Matching";
|
|
||||||
|
|
||||||
public const string START_MATCHING_URL = "Start";
|
|
||||||
public const string UPDATE_MATCHING_URL = "Update";
|
|
||||||
public const string FINISH_MATCHING_URL = "Finish";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static readonly List<string> DOMAINS = new()
|
|
||||||
{
|
|
||||||
"localhost",
|
|
||||||
"cert.nesys.jp",
|
|
||||||
"nesys.taito.co.jp",
|
|
||||||
"fjm170920zero.nesica.net"
|
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly IAppSettings SETTINGS =
|
|
||||||
new ConfigurationBuilder<IAppSettings>().UseJsonConfig(PathHelper.ConfigFilePath).Build();
|
|
||||||
|
|
||||||
public const int DEFAULT_AVATAR_COUNT = 323;
|
|
||||||
public const int DEFAULT_NAVIGATOR_COUNT = 94;
|
|
||||||
public const int DEFAULT_ITEM_COUNT = 21;
|
|
||||||
public const int DEFAULT_TITLE_COUNT = 5273;
|
|
||||||
public const int DEFAULT_SKIN_COUNT = 21;
|
|
||||||
public const int DEFAULT_SE_COUNT = 26;
|
|
||||||
public const string DEFAULT_CARD_DB_NAME = "card.db3";
|
|
||||||
public const string DEFAULT_MUSIC_DB_NAME = "music4MAX465.db3";
|
|
||||||
public const string DEFAULT_SERVER_IP = "127.0.0.1";
|
|
||||||
public const string DEFAULT_RELAY_SERVER = "127.0.0.1";
|
|
||||||
public const int DEFAULT_RELAY_PORT = 54321;
|
|
||||||
public const string DEFAULT_EVENT_FOLDER = "event";
|
|
||||||
public const string DEFAULT_MATCHING_SERVER = "127.0.0.1:5000";
|
|
||||||
|
|
||||||
|
|
||||||
public static readonly IReadOnlyList<int> DEFAULT_UNLOCKABLE_SONGS = new[]
|
|
||||||
{
|
|
||||||
11, 13, 149, 273, 291, 320, 321, 371, 378, 384, 464, 471, 474, 475, 492, 494, 498, 520,
|
|
||||||
548, 551, 558, 561, 565, 570, 577, 583, 612, 615, 622, 632, 659, 666, 668, 670, 672, 676,
|
|
||||||
680, 682, 685, 686, 697, 700, 701, 711, 720, 749, 875, 876, 877
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
using GCLocalServerRewrite.models;
|
|
||||||
using SharedProject.models;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public static class Converters
|
|
||||||
{
|
|
||||||
public static OnlineMatchingData ConvertFromEntry(OnlineMatchingEntry entry)
|
|
||||||
{
|
|
||||||
return new OnlineMatchingData
|
|
||||||
{
|
|
||||||
AvatarId = entry.AvatarId,
|
|
||||||
CardId = entry.CardId,
|
|
||||||
ClassId = entry.ClassId,
|
|
||||||
EntryNo = entry.EntryNo,
|
|
||||||
EntryStart = entry.EntryStart,
|
|
||||||
EventId = entry.EventId,
|
|
||||||
GroupId = entry.GroupId,
|
|
||||||
MachineId = entry.MachineId,
|
|
||||||
MatchingId = entry.MatchingId,
|
|
||||||
MatchingRemainingTime = entry.MatchingRemainingTime,
|
|
||||||
Pref = entry.Pref,
|
|
||||||
Status = entry.Status,
|
|
||||||
MatchingTimeout = entry.MatchingTimeout,
|
|
||||||
MessageId = entry.MessageId,
|
|
||||||
PlayerName = entry.PlayerName,
|
|
||||||
PrefId = entry.PrefId,
|
|
||||||
TenpoId = entry.TenpoId,
|
|
||||||
TenpoName = entry.TenpoName,
|
|
||||||
TitleId = entry.TitleId,
|
|
||||||
MatchingWaitTime = entry.MatchingWaitTime
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OnlineMatchingEntry ConvertFromData(OnlineMatchingData entry)
|
|
||||||
{
|
|
||||||
return new OnlineMatchingEntry
|
|
||||||
{
|
|
||||||
AvatarId = entry.AvatarId,
|
|
||||||
CardId = entry.CardId,
|
|
||||||
ClassId = entry.ClassId,
|
|
||||||
EntryNo = entry.EntryNo,
|
|
||||||
EntryStart = entry.EntryStart,
|
|
||||||
EventId = entry.EventId,
|
|
||||||
GroupId = entry.GroupId,
|
|
||||||
MachineId = entry.MachineId,
|
|
||||||
MatchingId = entry.MatchingId,
|
|
||||||
MatchingRemainingTime = entry.MatchingRemainingTime,
|
|
||||||
Pref = entry.Pref,
|
|
||||||
Status = entry.Status,
|
|
||||||
MatchingTimeout = entry.MatchingTimeout,
|
|
||||||
MessageId = entry.MessageId,
|
|
||||||
PlayerName = entry.PlayerName,
|
|
||||||
PrefId = entry.PrefId,
|
|
||||||
TenpoId = entry.TenpoId,
|
|
||||||
TenpoName = entry.TenpoName,
|
|
||||||
TitleId = entry.TitleId,
|
|
||||||
MatchingWaitTime = entry.MatchingWaitTime
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public static class DatabaseHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Static method to allow local data services to initialise their associated database conveniently.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="databaseName">The SQLite database name</param>
|
|
||||||
/// <param name="tables">The SQLite database tables to create (if required)</param>
|
|
||||||
/// <returns>An initialised SQLite database connection</returns>
|
|
||||||
public static SQLiteConnection InitializeLocalDatabase(string databaseName, params Type[] tables)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(PathHelper.DataBaseRootPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(PathHelper.DataBaseRootPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var databasePath = Path.Combine(PathHelper.DataBaseRootPath, databaseName);
|
|
||||||
|
|
||||||
var database = new SQLiteConnection(databasePath);
|
|
||||||
|
|
||||||
foreach (var table in tables)
|
|
||||||
{
|
|
||||||
database.CreateTable(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SQLiteConnection ConnectDatabase(string databaseName)
|
|
||||||
{
|
|
||||||
var databasePath = Path.Combine(PathHelper.DataBaseRootPath, databaseName);
|
|
||||||
|
|
||||||
var database = new SQLiteConnection(databasePath);
|
|
||||||
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
using Config.Net;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public interface IAppSettings
|
|
||||||
{
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_AVATAR_COUNT)]
|
|
||||||
int AvatarCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_NAVIGATOR_COUNT)]
|
|
||||||
int NavigatorCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_ITEM_COUNT)]
|
|
||||||
int ItemCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_TITLE_COUNT)]
|
|
||||||
int TitleCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_SKIN_COUNT)]
|
|
||||||
int SkinCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_SE_COUNT)]
|
|
||||||
int SeCount { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_MUSIC_DB_NAME)]
|
|
||||||
string MusicDbName { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_CARD_DB_NAME)]
|
|
||||||
string CardDbName { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_SERVER_IP)]
|
|
||||||
string ServerIp { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_EVENT_FOLDER)]
|
|
||||||
string EventFolder { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_RELAY_SERVER)]
|
|
||||||
string RelayServer { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_RELAY_PORT)]
|
|
||||||
int RelayPort { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = false)]
|
|
||||||
bool DownloadEvents { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = Configs.DEFAULT_MATCHING_SERVER)]
|
|
||||||
string MatchingServer { get; }
|
|
||||||
|
|
||||||
[Option(DefaultValue = null)]
|
|
||||||
IEnumerable<int>? UnlockableSongIds { get; }
|
|
||||||
|
|
||||||
IEnumerable<IOptionServiceResponse> ResponseData { get; }
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public interface IOptionServiceResponse
|
|
||||||
{
|
|
||||||
string FileName { get; }
|
|
||||||
|
|
||||||
long NotBeforeUnixTime { get; }
|
|
||||||
|
|
||||||
long NotAfterUnixTime { get; }
|
|
||||||
|
|
||||||
string Md5 { get; }
|
|
||||||
|
|
||||||
int Index { get; }
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
using Swan;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.common;
|
|
||||||
|
|
||||||
public static class PathHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the local path of html/static files.
|
|
||||||
/// </summary>
|
|
||||||
public static string HtmlRootPath => Path.Combine(BasePath, Configs.STATIC_FOLDER, Configs.WWWROOT);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Root path for database, when debug, it's under source root, when release, it's the exe dir
|
|
||||||
/// </summary>
|
|
||||||
public static string DataBaseRootPath => Path.Combine(BasePath, Configs.DB_FOLDER);
|
|
||||||
|
|
||||||
public static string LogRootPath => Path.Combine(BasePath, Configs.LOG_FOLDER);
|
|
||||||
|
|
||||||
public static string CertRootPath => Path.Combine(BasePath, Configs.CERT_FOLDER);
|
|
||||||
|
|
||||||
public static string ConfigFilePath => Path.Combine(BasePath, Configs.CONFIG_FILE_NAME);
|
|
||||||
|
|
||||||
private static string BasePath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var assemblyPath = Environment.ProcessPath;
|
|
||||||
if (assemblyPath == null)
|
|
||||||
{
|
|
||||||
throw SelfCheck.Failure("Cannot get assembly path!!!");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
var parentFullName = Directory.GetParent(assemblyPath)?.Parent?.Parent?.Parent?.FullName;
|
|
||||||
|
|
||||||
Debug.Assert(parentFullName != null, $"{nameof(parentFullName)} != null");
|
|
||||||
|
|
||||||
return parentFullName;
|
|
||||||
#else
|
|
||||||
var parent = Directory.GetParent(assemblyPath);
|
|
||||||
if (parent == null)
|
|
||||||
{
|
|
||||||
throw SelfCheck.Failure("Cannot get assembly parent path!!!");
|
|
||||||
}
|
|
||||||
return parent.ToString();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
{
|
|
||||||
"AvatarCount": 356,
|
|
||||||
"NavigatorCount": 118,
|
|
||||||
"ItemCount": 21,
|
|
||||||
"SkinCount": 21,
|
|
||||||
"SeCount": 26,
|
|
||||||
"TitleCount": 5530,
|
|
||||||
"CardDbName": "card.db3",
|
|
||||||
"MusicDbName": "music471omni.db3",
|
|
||||||
"ServerIp": "127.0.0.1",
|
|
||||||
"EventFolder": "event",
|
|
||||||
"DownloadEvents": false,
|
|
||||||
"RelayServer": "127.0.0.1",
|
|
||||||
"RelayPort": 3333,
|
|
||||||
"MatchingServer": "127.0.0.1:5038",
|
|
||||||
"UnlockableSongIds": [
|
|
||||||
11,
|
|
||||||
13,
|
|
||||||
149,
|
|
||||||
273,
|
|
||||||
291,
|
|
||||||
320,
|
|
||||||
321,
|
|
||||||
371,
|
|
||||||
378,
|
|
||||||
384,
|
|
||||||
464,
|
|
||||||
471,
|
|
||||||
474,
|
|
||||||
475,
|
|
||||||
492,
|
|
||||||
494,
|
|
||||||
498,
|
|
||||||
520,
|
|
||||||
548,
|
|
||||||
551,
|
|
||||||
558,
|
|
||||||
561,
|
|
||||||
565,
|
|
||||||
570,
|
|
||||||
577,
|
|
||||||
583,
|
|
||||||
612,
|
|
||||||
615,
|
|
||||||
622,
|
|
||||||
632,
|
|
||||||
659,
|
|
||||||
666,
|
|
||||||
668,
|
|
||||||
670,
|
|
||||||
672,
|
|
||||||
676,
|
|
||||||
680,
|
|
||||||
682,
|
|
||||||
685,
|
|
||||||
686,
|
|
||||||
697,
|
|
||||||
700,
|
|
||||||
701,
|
|
||||||
711,
|
|
||||||
720,
|
|
||||||
749,
|
|
||||||
875,
|
|
||||||
876,
|
|
||||||
877
|
|
||||||
],
|
|
||||||
"ResponseData": [
|
|
||||||
{
|
|
||||||
"FileName": "/event_103_20201125.evt",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "27b503145a62e46f5f611b6f8a91e4f3",
|
|
||||||
"Index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/event_20201125_reg.jpg",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "8e3fe25bf50dcbed13dbb54cc18b1efa",
|
|
||||||
"Index": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/event_20201125_sgreg.png",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "e0abb0503fe0c530d8a68e36994264c6",
|
|
||||||
"Index": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/news_big_20201125_0.jpg",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "4a0f66431f6449279dc046149d1dd882",
|
|
||||||
"Index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/news_big_20201125_2.jpg",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "8e3fe25bf50dcbed13dbb54cc18b1efa",
|
|
||||||
"Index": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/news_small_20201125_1.jpg",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "e20135bcd41c98875aec2b52eb9fcd06",
|
|
||||||
"Index": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/telop_20201125.txt",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "ee228de44d6656a9ec0bb7f1a0ca64e1",
|
|
||||||
"Index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FileName": "/event_unlock_20201125.cmp",
|
|
||||||
"NotBeforeUnixTime": 1335677127,
|
|
||||||
"NotAfterUnixTime": 1966397127,
|
|
||||||
"Md5": "534a253e3de8360c2beff49a5f120105",
|
|
||||||
"Index": 8
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class AliveController : WebApiController
|
|
||||||
{
|
|
||||||
[Route(HttpVerbs.Get, "/i.php")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public string Check()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Html;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "REMOTE ADDRESS: 127.0.0.1\n" +
|
|
||||||
"SERVER NAME:nesys.home\n" +
|
|
||||||
"SERVER ADDR:239.1.1.1";
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/{id}/Alive.txt")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public void AliveFile()
|
|
||||||
{
|
|
||||||
HttpContext.Response.SetEmptyResponse((int)HttpStatusCode.OK);
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,340 +0,0 @@
|
|||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.models;
|
|
||||||
using SharedProject.common;
|
|
||||||
using SharedProject.enums;
|
|
||||||
using SharedProject.models;
|
|
||||||
using SQLite.Net2;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class ApiController : WebApiController
|
|
||||||
{
|
|
||||||
private readonly SQLiteConnection cardSqLiteConnection;
|
|
||||||
|
|
||||||
private readonly Dictionary<int, Music> musics;
|
|
||||||
private readonly Dictionary<int, MusicExtra> musicExtras;
|
|
||||||
|
|
||||||
public ApiController()
|
|
||||||
{
|
|
||||||
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
|
||||||
var musicSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.MusicDbName);
|
|
||||||
musics = musicSqLiteConnection.Table<Music>().ToDictionary(music => music.MusicId);
|
|
||||||
musicExtras = musicSqLiteConnection.Table<MusicExtra>().ToDictionary(music => music.MusicId);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/Users")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public List<User> GetUsers()
|
|
||||||
{
|
|
||||||
var result = cardSqLiteConnection.Table<Card>().ToList().ConvertAll(card => new User
|
|
||||||
{
|
|
||||||
CardId = card.CardId,
|
|
||||||
PlayerName = card.PlayerName
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Post, "/Users/SetPlayerName")]
|
|
||||||
public bool SetPlayerName([JsonData] User data)
|
|
||||||
{
|
|
||||||
var existing = cardSqLiteConnection.Table<Card>().Where(card => card.CardId == data.CardId);
|
|
||||||
if (!existing.Any())
|
|
||||||
{
|
|
||||||
$"Trying to update non existing user's name! Card id {data.CardId}".Warn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var user = existing.First();
|
|
||||||
user.PlayerName = data.PlayerName;
|
|
||||||
return cardSqLiteConnection.Update(user) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Post, "/UserDetail/SetMusicFavorite")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public bool SetFavorite([JsonData] MusicFavoriteData data)
|
|
||||||
{
|
|
||||||
var existing = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == data.CardId
|
|
||||||
&& detail.Pcol1 == Configs.FAVORITE_PCOL1
|
|
||||||
&& detail.Pcol2 == data.MusicId);
|
|
||||||
|
|
||||||
if (!existing.Any())
|
|
||||||
{
|
|
||||||
$"Trying to update non existing song's favorite! Card id {data.CardId}, music id {data.MusicId}".Warn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cardDetail = existing.First();
|
|
||||||
cardDetail.Fcol1 = data.IsFavorite ? 1 : 0;
|
|
||||||
var result = cardSqLiteConnection.Update(cardDetail);
|
|
||||||
|
|
||||||
return result == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Post, "/UserDetail/SetPlayOption")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public bool SetPlayOption([JsonData] PlayOption data)
|
|
||||||
{
|
|
||||||
var firstConfig = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == data.CardId
|
|
||||||
&& detail.Pcol1 == Configs.FIRST_CONFIG_PCOL1
|
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3);
|
|
||||||
|
|
||||||
var secondConfig = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == data.CardId
|
|
||||||
&& detail.Pcol1 == Configs.SECOND_CONFIG_PCOL1
|
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3);
|
|
||||||
|
|
||||||
if (!firstConfig.Any() || !secondConfig.Any())
|
|
||||||
{
|
|
||||||
$"Trying to update non existing card's config! Card id {data.CardId}".Warn();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstDetail = firstConfig.First();
|
|
||||||
firstDetail.ScoreUi1 = (long)data.FastSlowIndicator;
|
|
||||||
firstDetail.ScoreUi2 = (long)data.FeverTrance;
|
|
||||||
firstDetail.ScoreI1 = data.AvatarId;
|
|
||||||
firstDetail.Fcol2 = (int)data.TitleId;
|
|
||||||
|
|
||||||
var secondDetail = secondConfig.First();
|
|
||||||
secondDetail.ScoreI1 = data.NavigatorId;
|
|
||||||
|
|
||||||
var firstResult = cardSqLiteConnection.Update(firstDetail);
|
|
||||||
var secondResult = cardSqLiteConnection.Update(secondDetail);
|
|
||||||
|
|
||||||
return firstResult == 1 && secondResult == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/UserDetail/{cardId}")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public UserDetail? GetUserDetail(long cardId)
|
|
||||||
{
|
|
||||||
var cardResult = cardSqLiteConnection.Table<Card>().Where(card => card.CardId == cardId);
|
|
||||||
|
|
||||||
if (!cardResult.Any())
|
|
||||||
{
|
|
||||||
$"Getting detail for non exisisting card! Card id is {cardId}".Warn();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var card = cardResult.First();
|
|
||||||
|
|
||||||
return ToUserDetail(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserDetail? ToUserDetail(Card card)
|
|
||||||
{
|
|
||||||
if (!cardSqLiteConnection.Table<CardDetail>().Select(detail => detail.CardId == card.CardId).Any())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var userDetail = new UserDetail
|
|
||||||
{
|
|
||||||
CardId = card.CardId,
|
|
||||||
PlayerName = card.PlayerName
|
|
||||||
};
|
|
||||||
var songPlayDataDict = new Dictionary<int, SongPlayData>();
|
|
||||||
|
|
||||||
ProcessCardDetail(userDetail, songPlayDataDict);
|
|
||||||
|
|
||||||
userDetail.SongPlayDataList = songPlayDataDict.Values.ToList();
|
|
||||||
userDetail.TotalSongCount = musics.Count;
|
|
||||||
userDetail.TotalStageCount = userDetail.TotalSongCount * 3 + musicExtras.Count;
|
|
||||||
userDetail.AverageScore = (int)(userDetail.TotalScore / userDetail.PlayedStageCount);
|
|
||||||
userDetail.PlayedSongCount = songPlayDataDict.Count;
|
|
||||||
return userDetail;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessCardDetail(UserDetail userDetail, IDictionary<int, SongPlayData> songPlayDataDict)
|
|
||||||
{
|
|
||||||
var firstOption = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.FirstOrDefault(detail => detail.CardId == userDetail.CardId
|
|
||||||
&& detail.Pcol1 == Configs.FIRST_CONFIG_PCOL1
|
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3
|
|
||||||
, new CardDetail
|
|
||||||
{
|
|
||||||
CardId = userDetail.CardId
|
|
||||||
});
|
|
||||||
var secondOption = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.FirstOrDefault(detail => detail.CardId == userDetail.CardId
|
|
||||||
&& detail.Pcol1 == Configs.SECOND_CONFIG_PCOL1
|
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3
|
|
||||||
, new CardDetail
|
|
||||||
{
|
|
||||||
CardId = userDetail.CardId
|
|
||||||
});
|
|
||||||
|
|
||||||
SetOptions(firstOption, secondOption, userDetail);
|
|
||||||
|
|
||||||
var songCounts = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == Configs.COUNT_PCOL1);
|
|
||||||
|
|
||||||
foreach (var detail in songCounts)
|
|
||||||
{
|
|
||||||
SetCounts(detail, songPlayDataDict, userDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
var songScores = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == Configs.SCORE_PCOL1);
|
|
||||||
|
|
||||||
foreach (var detail in songScores)
|
|
||||||
{
|
|
||||||
SetDetails(detail, songPlayDataDict, userDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
var favorites = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == Configs.FAVORITE_PCOL1)
|
|
||||||
.ToDictionary(detail => detail.Pcol2);
|
|
||||||
|
|
||||||
foreach (var (musicId, songPlayData) in songPlayDataDict)
|
|
||||||
{
|
|
||||||
songPlayData.IsFavorite = favorites[musicId].Fcol1 != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetOptions(CardDetail firstOptionCardDetail, CardDetail secondOptionCardDetail, UserDetail userDetail)
|
|
||||||
{
|
|
||||||
var fastSlow = (int)firstOptionCardDetail.ScoreUi1;
|
|
||||||
var feverTrance = (int)firstOptionCardDetail.ScoreUi2;
|
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(PlayOptions.FastSlowIndicator), fastSlow))
|
|
||||||
{
|
|
||||||
fastSlow = (int)PlayOptions.FastSlowIndicator.NotUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(PlayOptions.FeverTranceShow), feverTrance))
|
|
||||||
{
|
|
||||||
feverTrance = (int)PlayOptions.FeverTranceShow.Show;
|
|
||||||
}
|
|
||||||
|
|
||||||
userDetail.PlayOption = new PlayOption
|
|
||||||
{
|
|
||||||
CardId = firstOptionCardDetail.CardId,
|
|
||||||
FastSlowIndicator = (PlayOptions.FastSlowIndicator)fastSlow,
|
|
||||||
FeverTrance = (PlayOptions.FeverTranceShow)feverTrance,
|
|
||||||
AvatarId = firstOptionCardDetail.ScoreI1,
|
|
||||||
TitleId = firstOptionCardDetail.Fcol2,
|
|
||||||
NavigatorId = secondOptionCardDetail.ScoreI1
|
|
||||||
};
|
|
||||||
}
|
|
||||||
private void SetDetails(CardDetail cardDetail, IDictionary<int, SongPlayData> songPlayDataDict,
|
|
||||||
UserDetail userDetail)
|
|
||||||
{
|
|
||||||
var musicId = cardDetail.Pcol2;
|
|
||||||
|
|
||||||
AddSongPlayDataIfNotExist(songPlayDataDict, musicId);
|
|
||||||
|
|
||||||
for (var i = 0; i < SharedConstants.DIFFICULTY_COUNT; i++)
|
|
||||||
{
|
|
||||||
var songPlayDetailData = songPlayDataDict[musicId].SongPlaySubDataList[i];
|
|
||||||
songPlayDetailData.Difficulty = (Difficulty)i;
|
|
||||||
|
|
||||||
if (i != cardDetail.Pcol3)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
songPlayDetailData.Score = (int)cardDetail.ScoreUi1;
|
|
||||||
songPlayDetailData.MaxChain = (int)cardDetail.ScoreUi3;
|
|
||||||
|
|
||||||
userDetail.TotalScore += cardDetail.ScoreUi1;
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi1 >= SharedConstants.S_SCORE_THRESHOLD)
|
|
||||||
{
|
|
||||||
userDetail.SAboveStageCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi1 >= SharedConstants.S_PLUS_SCORE_THRESHOLD)
|
|
||||||
{
|
|
||||||
userDetail.SPlusAboveStageCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi1 >= SharedConstants.S_PLUS_PLUS_SCORE_THRESHOLD)
|
|
||||||
{
|
|
||||||
userDetail.SPlusPlusAboveStageCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetCounts(CardDetail cardDetail, IDictionary<int, SongPlayData> songPlayDataDict, UserDetail userDetail)
|
|
||||||
{
|
|
||||||
var musicId = cardDetail.Pcol2;
|
|
||||||
|
|
||||||
AddSongPlayDataIfNotExist(songPlayDataDict, musicId);
|
|
||||||
|
|
||||||
for (var i = 0; i < SharedConstants.DIFFICULTY_COUNT; i++)
|
|
||||||
{
|
|
||||||
var songPlayDetailData = songPlayDataDict[musicId].SongPlaySubDataList[i];
|
|
||||||
|
|
||||||
songPlayDetailData.Difficulty = (Difficulty)i;
|
|
||||||
|
|
||||||
if (i != cardDetail.Pcol3)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
songPlayDetailData.PlayCount = (int)cardDetail.ScoreUi1;
|
|
||||||
songPlayDetailData.LastPlayTime = cardDetail.LastPlayTime;
|
|
||||||
songPlayDetailData.ClearState = ClearState.Failed;
|
|
||||||
userDetail.PlayedStageCount++;
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi2 > 0)
|
|
||||||
{
|
|
||||||
userDetail.ClearedStageCount++;
|
|
||||||
songPlayDetailData.ClearState = ClearState.Clear;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi3 > 0)
|
|
||||||
{
|
|
||||||
userDetail.NoMissStageCount++;
|
|
||||||
songPlayDetailData.ClearState = ClearState.NoMiss;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi4 > 0)
|
|
||||||
{
|
|
||||||
userDetail.FullChainStageCount++;
|
|
||||||
songPlayDetailData.ClearState = ClearState.FullChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cardDetail.ScoreUi6 > 0)
|
|
||||||
{
|
|
||||||
userDetail.PerfectStageCount++;
|
|
||||||
songPlayDetailData.ClearState = ClearState.Perfect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddSongPlayDataIfNotExist(IDictionary<int, SongPlayData> songPlayDataDict, int musicId)
|
|
||||||
{
|
|
||||||
if (songPlayDataDict.ContainsKey(musicId))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var musicData = musics[musicId];
|
|
||||||
var songPlayData = new SongPlayData
|
|
||||||
{
|
|
||||||
Artist = musicData.Artist ?? string.Empty,
|
|
||||||
Title = musicData.Title ?? string.Empty,
|
|
||||||
MusicId = musicId,
|
|
||||||
SongPlaySubDataList = new SongPlayDetailData[SharedConstants.DIFFICULTY_COUNT]
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < SharedConstants.DIFFICULTY_COUNT; i++)
|
|
||||||
{
|
|
||||||
songPlayData.SongPlaySubDataList[i] = new SongPlayDetailData();
|
|
||||||
}
|
|
||||||
songPlayDataDict[musicId] = songPlayData;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,806 +0,0 @@
|
|||||||
using System.Net.Http.Json;
|
|
||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using ChoETL;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.models;
|
|
||||||
using SharedProject.models;
|
|
||||||
using SQLite.Net2;
|
|
||||||
using Swan;
|
|
||||||
using Swan.Logging;
|
|
||||||
using Avatar=GCLocalServerRewrite.models.Avatar;
|
|
||||||
using Navigator=GCLocalServerRewrite.models.Navigator;
|
|
||||||
using Title=GCLocalServerRewrite.models.Title;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class CardServiceController : WebApiController
|
|
||||||
{
|
|
||||||
private readonly SQLiteConnection cardSqLiteConnection;
|
|
||||||
private readonly SQLiteConnection musicSqLiteConnection;
|
|
||||||
|
|
||||||
public CardServiceController()
|
|
||||||
{
|
|
||||||
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
|
||||||
musicSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.MusicDbName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Post, "/cardn.cgi")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public async Task<string> CardService([FormField] int gid, [FormField("mac_addr")] string mac, [FormField] int type,
|
|
||||||
[FormField("card_no")] long cardId, [FormField("data")] string xmlData, [FormField("cmd_str")] int cmdType)
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return await ProcessCommand(cmdType, mac, cardId, xmlData, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> ProcessCommand(int cmdType, string mac, long cardId, string xmlData, int type)
|
|
||||||
{
|
|
||||||
if (!Enum.IsDefined(typeof(Command), cmdType))
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(cmdType), cmdType, $"Cmd type is unknown!\n Data is {xmlData}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var command = (Command)cmdType;
|
|
||||||
|
|
||||||
return command switch
|
|
||||||
{
|
|
||||||
Command.CardReadRequest or Command.CardWriteRequest => await ProcessCardRequest(mac, cardId, xmlData, type),
|
|
||||||
Command.ReissueRequest => ProcessReissueRequest(),
|
|
||||||
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ProcessRegisterRequest(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
$"Get card register request, data is \n{xmlData}".Info();
|
|
||||||
Write<Card>(cardId, xmlData);
|
|
||||||
return ConstructResponse(xmlData);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ProcessReissueRequest()
|
|
||||||
{
|
|
||||||
"Get reissue request, returning not reissue".Info();
|
|
||||||
return ConstructResponse("", ReturnCode.NotReissue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> ProcessCardRequest(string mac, long cardId, string xmlData, int type)
|
|
||||||
{
|
|
||||||
if (!Enum.IsDefined(typeof(CardRequestType), type))
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(type), type, "Card request type is unknown!");
|
|
||||||
}
|
|
||||||
|
|
||||||
var requestType = (CardRequestType)type;
|
|
||||||
|
|
||||||
$"Getting card request, type is {requestType}".Info();
|
|
||||||
|
|
||||||
switch (requestType)
|
|
||||||
{
|
|
||||||
#region ReadRequests
|
|
||||||
|
|
||||||
case CardRequestType.ReadCard:
|
|
||||||
{
|
|
||||||
var response = Card(cardId, out var returnCode);
|
|
||||||
|
|
||||||
return ConstructResponse(response, returnCode);
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadCardDetail:
|
|
||||||
{
|
|
||||||
var cardDetail = CardDetail(cardId, xmlData);
|
|
||||||
return ConstructResponse(cardDetail);
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadCardDetails:
|
|
||||||
{
|
|
||||||
return ConstructResponse(CardDetails(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadCardBData:
|
|
||||||
{
|
|
||||||
return ConstructResponse(CardBData(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadAvatar:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<Avatar>(cardId, Configs.SETTINGS.AvatarCount, Configs.AVATAR_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadItem:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<Item>(cardId, Configs.SETTINGS.ItemCount, Configs.ITEM_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadSkin:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<Skin>(cardId, Configs.SETTINGS.SkinCount, Configs.SKIN_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadTitle:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<Title>(cardId, Configs.SETTINGS.TitleCount, Configs.TITLE_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadMusic:
|
|
||||||
{
|
|
||||||
return ConstructResponse(MusicUnlock());
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadEventReward:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GenerateEmptyXml(Configs.EVENT_REWARD));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadNavigator:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<Navigator>(cardId, Configs.SETTINGS.NavigatorCount, Configs.NAVIGATOR_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadMusicExtra:
|
|
||||||
{
|
|
||||||
return ConstructResponse(MusicExtra());
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadMusicAou:
|
|
||||||
{
|
|
||||||
return ConstructResponse(MusicAouUnlock());
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadCoin:
|
|
||||||
{
|
|
||||||
return ConstructResponse(Coin(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadUnlockReward:
|
|
||||||
{
|
|
||||||
return ConstructResponse(UnlockReward(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadUnlockKeynum:
|
|
||||||
{
|
|
||||||
return ConstructResponse(UnlockKeynum(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadSoundEffect:
|
|
||||||
{
|
|
||||||
return ConstructResponse(
|
|
||||||
GetStaticCount<SoundEffect>(cardId, Configs.SETTINGS.SeCount, Configs.SE_XPATH));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadGetMessage:
|
|
||||||
{
|
|
||||||
return ConstructResponse(GenerateEmptyXml(Configs.GET_MESSAGE));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadCond:
|
|
||||||
{
|
|
||||||
return ConstructResponse(GenerateEmptyXml(Configs.COND));
|
|
||||||
}
|
|
||||||
case CardRequestType.ReadTotalTrophy:
|
|
||||||
{
|
|
||||||
return ConstructResponse(TotalTrophy(cardId));
|
|
||||||
}
|
|
||||||
case CardRequestType.StartSession:
|
|
||||||
case CardRequestType.GetSession:
|
|
||||||
{
|
|
||||||
return ConstructResponse(GetSession(cardId, mac));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region WriteRequests
|
|
||||||
|
|
||||||
case CardRequestType.WriteCard:
|
|
||||||
{
|
|
||||||
$"Card Write data is {xmlData}".Info();
|
|
||||||
Write<Card>(cardId, xmlData);
|
|
||||||
return ConstructResponse(xmlData);
|
|
||||||
}
|
|
||||||
case CardRequestType.WriteCardDetail:
|
|
||||||
{
|
|
||||||
$"Card Detail Write data is {xmlData}".Info();
|
|
||||||
WriteCardDetail(cardId, xmlData);
|
|
||||||
return ConstructResponse(xmlData);
|
|
||||||
}
|
|
||||||
case CardRequestType.WriteCardBData:
|
|
||||||
{
|
|
||||||
$"Card BData Write data is {xmlData}".Info();
|
|
||||||
Write<CardBData>(cardId, xmlData);
|
|
||||||
WriteCardPlayCount(cardId);
|
|
||||||
return ConstructResponse(xmlData);
|
|
||||||
}
|
|
||||||
// TODO: Maybe one day implement these
|
|
||||||
case CardRequestType.WriteAvatar:
|
|
||||||
case CardRequestType.WriteItem:
|
|
||||||
case CardRequestType.WriteTitle:
|
|
||||||
case CardRequestType.WriteMusicDetail:
|
|
||||||
case CardRequestType.WriteNavigator:
|
|
||||||
case CardRequestType.WriteCoin:
|
|
||||||
case CardRequestType.WriteSkin:
|
|
||||||
case CardRequestType.WriteUnlockKeynum:
|
|
||||||
case CardRequestType.WriteSoundEffect:
|
|
||||||
{
|
|
||||||
$"Card Write data is {xmlData}".Info();
|
|
||||||
return ConstructResponse(xmlData);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
#region OnlineMatching
|
|
||||||
|
|
||||||
case CardRequestType.StartOnlineMatching:
|
|
||||||
{
|
|
||||||
$"Start Online Matching, data is {xmlData}".Info();
|
|
||||||
var resultString = await StartOnlineMatching(cardId, xmlData);
|
|
||||||
return ConstructResponse(resultString);
|
|
||||||
}
|
|
||||||
|
|
||||||
case CardRequestType.UpdateOnlineMatching:
|
|
||||||
{
|
|
||||||
$"Update Online Matching, data is {xmlData}".Info();
|
|
||||||
var resultString = await UpdateOnlineMatching(cardId, xmlData);
|
|
||||||
return ConstructResponse(resultString);
|
|
||||||
}
|
|
||||||
|
|
||||||
case CardRequestType.UploadOnlineMatchingResult:
|
|
||||||
{
|
|
||||||
$"Get Online Matching result, data is {xmlData}".Info();
|
|
||||||
var resultString = await UploadOnlineMatchingResult(cardId, xmlData);
|
|
||||||
return ConstructResponse(resultString);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(requestType), requestType, "Request type not captured, should never happen!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region ReadImplementation
|
|
||||||
|
|
||||||
private string Card(long cardId, out ReturnCode returnCode)
|
|
||||||
{
|
|
||||||
var result = cardSqLiteConnection.Table<Card>().Where(card => card.CardId == cardId);
|
|
||||||
|
|
||||||
if (!result.Any())
|
|
||||||
{
|
|
||||||
returnCode = ReturnCode.CardNotRegistered;
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var card = result.First();
|
|
||||||
|
|
||||||
returnCode = ReturnCode.Ok;
|
|
||||||
return GenerateSingleXml(card, Configs.CARD_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CardDetail(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
var reader = new ChoXmlReader<CardDetailReadData>(new StringReader(xmlData));
|
|
||||||
var data = reader.Read();
|
|
||||||
|
|
||||||
var result = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == cardId &&
|
|
||||||
detail.Pcol1 == data.Pcol1 && detail.Pcol2 == data.Pcol2 &&
|
|
||||||
detail.Pcol3 == data.Pcol3);
|
|
||||||
|
|
||||||
if (!result.Any())
|
|
||||||
{
|
|
||||||
return GenerateEmptyXml(Configs.CARD_DETAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cardDetail = result.First();
|
|
||||||
return GenerateSingleXml(cardDetail, Configs.CARD_DETAIL_SINGLE_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CardDetails(long cardId)
|
|
||||||
{
|
|
||||||
var result = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == cardId);
|
|
||||||
|
|
||||||
if (!result.Any())
|
|
||||||
{
|
|
||||||
return GenerateEmptyXml(Configs.CARD_DETAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cardDetails = result.ToList();
|
|
||||||
|
|
||||||
return GenerateRecordsXml(cardDetails, Configs.CARD_DETAIL_RECORD_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CardBData(long cardId)
|
|
||||||
{
|
|
||||||
var result = cardSqLiteConnection.Table<CardBData>()
|
|
||||||
.Where(detail => detail.CardId == cardId);
|
|
||||||
|
|
||||||
if (!result.Any())
|
|
||||||
{
|
|
||||||
return GenerateEmptyXml(Configs.CARD_BDATA);
|
|
||||||
}
|
|
||||||
var cardBData = result.First();
|
|
||||||
|
|
||||||
return GenerateSingleXml(cardBData, Configs.CARD_BDATA_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetStaticCount<T>(long cardId, int count, string xpath)
|
|
||||||
where T : Record, IIdModel, ICardIdModel, new()
|
|
||||||
{
|
|
||||||
var models = new List<T>();
|
|
||||||
|
|
||||||
for (var id = 1; id <= count; id++)
|
|
||||||
{
|
|
||||||
var model = new T();
|
|
||||||
model.SetId(id);
|
|
||||||
model.SetCardId(cardId);
|
|
||||||
models.Add(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GenerateRecordsXml(models, xpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetSession(long cardId, string mac)
|
|
||||||
{
|
|
||||||
var session = new Session
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
Mac = mac,
|
|
||||||
SessionId = "12345678901234567890123456789012",
|
|
||||||
Expires = 9999,
|
|
||||||
PlayerId = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
return GenerateSingleXml(session, Configs.SESSION_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string TotalTrophy(long cardId)
|
|
||||||
{
|
|
||||||
var trophy = new TotalTrophy
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
TrophyNum = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
return GenerateSingleXml(trophy, Configs.TOTAL_TROPHY_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string Coin(long cardId)
|
|
||||||
{
|
|
||||||
var coin = new Coin
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
CurrentCoins = 999999,
|
|
||||||
TotalCoins = 999999,
|
|
||||||
MonthlyCoins = 999999
|
|
||||||
};
|
|
||||||
|
|
||||||
return GenerateSingleXml(coin, Configs.COIN_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string UnlockReward(long cardId)
|
|
||||||
{
|
|
||||||
var unlockRewards = new List<UnlockReward>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
RewardType = 1,
|
|
||||||
RewardId = 1,
|
|
||||||
TargetId = 1,
|
|
||||||
TargetNum = 1,
|
|
||||||
KeyNum = 3
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return GenerateRecordsXml(unlockRewards, Configs.UNLOCK_REWARD_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string UnlockKeynum(long cardId)
|
|
||||||
{
|
|
||||||
var unlockKeynums = new List<UnlockKeynum>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
RewardId = 1,
|
|
||||||
KeyNum = 0,
|
|
||||||
RewardCount = 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return GenerateRecordsXml(unlockKeynums, Configs.UNLOCK_KEYNUM_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string MusicUnlock()
|
|
||||||
{
|
|
||||||
var result = musicSqLiteConnection.Table<Music>().ToList();
|
|
||||||
|
|
||||||
return GenerateRecordsXml(result, Configs.MUSIC_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string MusicAouUnlock()
|
|
||||||
{
|
|
||||||
var result = musicSqLiteConnection.Table<MusicAou>().ToList();
|
|
||||||
|
|
||||||
return !result.Any() ? GenerateEmptyXml(Configs.MUSIC_AOU) : GenerateRecordsXml(result, Configs.MUSIC_AOU_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string MusicExtra()
|
|
||||||
{
|
|
||||||
var result = musicSqLiteConnection.Table<MusicExtra>().ToList();
|
|
||||||
|
|
||||||
return GenerateRecordsXml(result, Configs.MUSIC_EXTRA_XPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region HelperMethods
|
|
||||||
|
|
||||||
private static string ConstructResponse(string xml, ReturnCode returnCode = ReturnCode.Ok)
|
|
||||||
{
|
|
||||||
var returnCodeInt = (int)returnCode;
|
|
||||||
if (returnCodeInt == 1)
|
|
||||||
{
|
|
||||||
return $"{returnCodeInt}\n" +
|
|
||||||
"1,1\n" +
|
|
||||||
xml;
|
|
||||||
}
|
|
||||||
return $"{returnCodeInt}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GenerateEmptyXml(string fieldName)
|
|
||||||
{
|
|
||||||
var xml = new XDocument(new XElement("root",
|
|
||||||
new XElement(fieldName)));
|
|
||||||
xml.Declaration = new XDeclaration("1.0", "UTF-8", null);
|
|
||||||
|
|
||||||
return xml.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GenerateSingleXml<T>(T obj, string xpath) where T : class
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
using (var writer = new ChoXmlWriter<T>(sb))
|
|
||||||
{
|
|
||||||
writer.Configuration.OmitXmlDeclaration = false;
|
|
||||||
writer.Configuration.UseXmlSerialization = true;
|
|
||||||
writer.WithXPath(xpath);
|
|
||||||
|
|
||||||
writer.Write(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GenerateRecordsXml<T>(IReadOnlyList<T> list, string xpath) where T : Record
|
|
||||||
{
|
|
||||||
var stringBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
for (var i = 0; i < list.Count; i++)
|
|
||||||
{
|
|
||||||
var obj = list[i];
|
|
||||||
obj.RecordId = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var writer = new ChoXmlWriter<T>(stringBuilder))
|
|
||||||
{
|
|
||||||
writer.Configuration.OmitXmlDeclaration = false;
|
|
||||||
writer.Configuration.UseXmlSerialization = true;
|
|
||||||
writer.WithXPath(xpath);
|
|
||||||
writer.Write(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringBuilder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region WriteImplementation
|
|
||||||
|
|
||||||
private void Write<T>(long cardId, string xmlData) where T : class, ICardIdModel
|
|
||||||
{
|
|
||||||
var reader = new ChoXmlReader<T>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
|
||||||
var writeObject = reader.Read();
|
|
||||||
|
|
||||||
if (writeObject == null)
|
|
||||||
{
|
|
||||||
throw new HttpRequestException();
|
|
||||||
}
|
|
||||||
|
|
||||||
writeObject.SetCardId(cardId);
|
|
||||||
var rowsAffected = cardSqLiteConnection.InsertOrReplace(writeObject, typeof(T));
|
|
||||||
|
|
||||||
if (rowsAffected == 0)
|
|
||||||
{
|
|
||||||
throw new ApplicationException("Update database failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
$"Updated {typeof(T)}".Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteCardPlayCount(long cardId)
|
|
||||||
{
|
|
||||||
var record = cardSqLiteConnection.Table<CardPlayCount>().Where(count => count.CardId == cardId);
|
|
||||||
|
|
||||||
if (!record.Any())
|
|
||||||
{
|
|
||||||
$"Created new play count data for card {cardId}".Info();
|
|
||||||
var playCount = new CardPlayCount
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
PlayCount = 1,
|
|
||||||
LastPlayed = DateTime.Now
|
|
||||||
};
|
|
||||||
cardSqLiteConnection.InsertOrReplace(playCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = record.First();
|
|
||||||
var now = DateTime.Now;
|
|
||||||
var lastPlayedTime = data.LastPlayed;
|
|
||||||
|
|
||||||
if (now <= lastPlayedTime)
|
|
||||||
{
|
|
||||||
$"Current time {now} is less than or equal to last played time! Clock skew detected!".Warn();
|
|
||||||
data.PlayCount = 0;
|
|
||||||
data.LastPlayed = DateTime.Now;
|
|
||||||
cardSqLiteConnection.InsertOrReplace(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime start;
|
|
||||||
DateTime end;
|
|
||||||
|
|
||||||
if (now.Hour >= 8)
|
|
||||||
{
|
|
||||||
start = DateTime.Today.AddHours(8);
|
|
||||||
end = start.AddHours(24);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = DateTime.Today.AddHours(8);
|
|
||||||
start = end.AddHours(-24);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.PlayCount = lastPlayedTime.IsBetween(start, end) ? data.PlayCount + 1 : 0;
|
|
||||||
cardSqLiteConnection.InsertOrReplace(data);
|
|
||||||
$"Updated card play count, current count is {data.PlayCount}".Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteCardDetail(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
var result = cardSqLiteConnection.Table<CardDetail>()
|
|
||||||
.Where(detail => detail.CardId == cardId);
|
|
||||||
|
|
||||||
// Unlock all unlockable songs in card details table when write card detail for the first time
|
|
||||||
if (!result.Any())
|
|
||||||
{
|
|
||||||
UnlockSongs(cardId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var reader = new ChoXmlReader<CardDetail>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
|
||||||
var cardDetail = reader.Read();
|
|
||||||
|
|
||||||
if (cardDetail is null)
|
|
||||||
{
|
|
||||||
throw new HttpRequestException("Write object is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
cardDetail.SetCardId(cardId);
|
|
||||||
cardDetail.LastPlayTime = DateTime.Now;
|
|
||||||
var rowsAffected = cardSqLiteConnection.InsertOrReplace(cardDetail);
|
|
||||||
if (rowsAffected == 0)
|
|
||||||
{
|
|
||||||
throw new ApplicationException("Update database failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
"Updated card detail".Info();
|
|
||||||
}
|
|
||||||
private void UnlockSongs(long cardId)
|
|
||||||
{
|
|
||||||
var unlockableSongIds = Configs.SETTINGS.UnlockableSongIds;
|
|
||||||
|
|
||||||
if (unlockableSongIds is null)
|
|
||||||
{
|
|
||||||
unlockableSongIds = Configs.DEFAULT_UNLOCKABLE_SONGS;
|
|
||||||
}
|
|
||||||
var detailList = unlockableSongIds.Select(id => new CardDetail
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
Pcol1 = 10,
|
|
||||||
Pcol2 = id,
|
|
||||||
Pcol3 = 0,
|
|
||||||
ScoreUi2 = 1,
|
|
||||||
ScoreUi6 = 1,
|
|
||||||
LastPlayTime = DateTime.Now
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
cardSqLiteConnection.InsertOrIgnoreAll(detailList);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region OnlineMatchingImplementation
|
|
||||||
|
|
||||||
private static async Task<string> StartOnlineMatching(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
var reader = new ChoXmlReader<OnlineMatchingEntry>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
|
||||||
var entry = reader.Read();
|
|
||||||
|
|
||||||
var request = Converters.ConvertFromEntry(entry) ;
|
|
||||||
request.CardId = cardId;
|
|
||||||
request.EntryStart = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
request.MatchingTimeout = 20;
|
|
||||||
request.MatchingRemainingTime = 3;
|
|
||||||
request.MatchingWaitTime = 10;
|
|
||||||
request.Status = 1;
|
|
||||||
|
|
||||||
var client = new HttpClient();
|
|
||||||
var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.START_MATCHING_URL}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await client.PostAsJsonAsync(url, request);
|
|
||||||
var dataList = await response.Content.ReadFromJsonAsync<List<OnlineMatchingData>>();
|
|
||||||
if (dataList is null)
|
|
||||||
{
|
|
||||||
throw new HttpRequestException("Start matching request fail");
|
|
||||||
}
|
|
||||||
var result = dataList.ConvertAll(input => Converters.ConvertFromData(input));
|
|
||||||
return GenerateRecordsXml(result, Configs.ONLINE_MATCHING_XPATH);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error("", "Http request failed");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<string> UpdateOnlineMatching(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
var reader = new ChoXmlReader<OnlineMatchingUpdateData>(new StringReader(xmlData));
|
|
||||||
var data = reader.Read();
|
|
||||||
var request = new OnlineMatchingUpdateRequest
|
|
||||||
{
|
|
||||||
Action = data.Action,
|
|
||||||
CardId = cardId,
|
|
||||||
EventId = data.EventId,
|
|
||||||
MatchingId = data.MatchingId,
|
|
||||||
MessageId = data.MessageId
|
|
||||||
};
|
|
||||||
var client = new HttpClient();
|
|
||||||
var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.UPDATE_MATCHING_URL}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await client.PostAsJsonAsync(url, request);
|
|
||||||
var dataList = await response.Content.ReadFromJsonAsync<List<OnlineMatchingEntry>>();
|
|
||||||
if (dataList is null)
|
|
||||||
{
|
|
||||||
throw new HttpRequestException("Update matching request fail");
|
|
||||||
}
|
|
||||||
return GenerateRecordsXml(dataList, Configs.ONLINE_MATCHING_XPATH);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error("", "Http request failed");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<string> UploadOnlineMatchingResult(long cardId, string xmlData)
|
|
||||||
{
|
|
||||||
var reader = new ChoXmlReader<OnlineMatchingResultData>(new StringReader(xmlData));
|
|
||||||
var data = reader.Read();
|
|
||||||
var request = new OnlineMatchingFinishRequest
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
MatchingId = data.MatchingId
|
|
||||||
};
|
|
||||||
var client = new HttpClient();
|
|
||||||
var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.UPDATE_MATCHING_URL}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await client.PostAsJsonAsync(url, request);
|
|
||||||
var success = await response.Content.ReadFromJsonAsync<bool>();
|
|
||||||
|
|
||||||
var result = new OnlineMatchingResult
|
|
||||||
{
|
|
||||||
Status = success ? 1:0
|
|
||||||
};
|
|
||||||
return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.Error("", "Http request failed");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
/*var entries = OnlineMatchingEntries[0xDEADBEEF];
|
|
||||||
var entry = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
|
|
||||||
if (entry is null)
|
|
||||||
{
|
|
||||||
throw new HttpException(400,"Entry for this card id does not exist!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.MatchingId != data.MatchingId)
|
|
||||||
{
|
|
||||||
throw new HttpException(400,"Matching Id mismatch!");
|
|
||||||
}
|
|
||||||
|
|
||||||
OnlineMatchingEntries[0xDEADBEEF].Remove(entry);
|
|
||||||
var result = new OnlineMatchingResult
|
|
||||||
{
|
|
||||||
Status = 1
|
|
||||||
};
|
|
||||||
return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);*/
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private enum CardRequestType
|
|
||||||
{
|
|
||||||
// Read data
|
|
||||||
ReadCard = 259,
|
|
||||||
ReadCardDetail = 260,
|
|
||||||
ReadCardDetails = 261,
|
|
||||||
ReadCardBData = 264,
|
|
||||||
ReadAvatar = 418,
|
|
||||||
ReadItem = 420,
|
|
||||||
ReadSkin = 422,
|
|
||||||
ReadTitle = 424,
|
|
||||||
ReadMusic = 428,
|
|
||||||
ReadEventReward = 441,
|
|
||||||
ReadNavigator = 443,
|
|
||||||
ReadMusicExtra = 465,
|
|
||||||
ReadMusicAou = 467,
|
|
||||||
ReadCoin = 468,
|
|
||||||
ReadUnlockReward = 507,
|
|
||||||
ReadUnlockKeynum = 509,
|
|
||||||
ReadSoundEffect = 8458,
|
|
||||||
ReadGetMessage = 8461,
|
|
||||||
ReadCond = 8465,
|
|
||||||
ReadTotalTrophy = 8468,
|
|
||||||
|
|
||||||
// Sessions
|
|
||||||
GetSession = 401,
|
|
||||||
StartSession = 402,
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
WriteCard = 771,
|
|
||||||
WriteCardDetail = 772,
|
|
||||||
WriteCardBData = 776,
|
|
||||||
WriteAvatar = 929,
|
|
||||||
WriteItem = 931,
|
|
||||||
WriteTitle = 935,
|
|
||||||
WriteMusicDetail = 941,
|
|
||||||
WriteNavigator = 954,
|
|
||||||
WriteCoin = 980,
|
|
||||||
WriteSkin = 933,
|
|
||||||
WriteUnlockKeynum = 1020,
|
|
||||||
WriteSoundEffect = 8969,
|
|
||||||
|
|
||||||
// Online matching
|
|
||||||
StartOnlineMatching = 8705,
|
|
||||||
UpdateOnlineMatching = 8961,
|
|
||||||
UploadOnlineMatchingResult = 8709
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Command
|
|
||||||
{
|
|
||||||
CardReadRequest = 256,
|
|
||||||
CardWriteRequest = 768,
|
|
||||||
RegisterRequest = 512,
|
|
||||||
ReissueRequest = 1536
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum ReturnCode
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 処理は正常に完了しました in debug string
|
|
||||||
/// </summary>
|
|
||||||
Ok = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 未登録のカードです in debug string
|
|
||||||
/// </summary>
|
|
||||||
CardNotRegistered = 23,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 再発行予約がありません in debug string
|
|
||||||
/// </summary>
|
|
||||||
NotReissue = 27
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class IncomServiceController : WebApiController
|
|
||||||
{
|
|
||||||
[Route(HttpVerbs.Post, "/incom.php")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public string IncomService()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1+1";
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Post, "/incomALL.php")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public string IncomAllService()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1+1";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.models;
|
|
||||||
using SQLite.Net2;
|
|
||||||
using Swan;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class OptionServiceController : WebApiController
|
|
||||||
{
|
|
||||||
|
|
||||||
private readonly SQLiteConnection cardSqLiteConnection;
|
|
||||||
|
|
||||||
public OptionServiceController()
|
|
||||||
{
|
|
||||||
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/PlayInfo.php")]
|
|
||||||
public string OptionService([QueryField("card_id")] long cardId)
|
|
||||||
{
|
|
||||||
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1\n" +
|
|
||||||
$"{GetPlayCount(cardId)}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetPlayCount(long cardId)
|
|
||||||
{
|
|
||||||
var record = cardSqLiteConnection.Table<CardPlayCount>().Where(count => count.CardId == cardId);
|
|
||||||
|
|
||||||
if (!record.Any())
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var now = DateTime.Now;
|
|
||||||
var data = record.First();
|
|
||||||
var lastPlayedTime = data.LastPlayed;
|
|
||||||
|
|
||||||
if (now <= lastPlayedTime)
|
|
||||||
{
|
|
||||||
$"Current time {now} is less than or equal to last played time! Clock skew detected!".Warn();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime start;
|
|
||||||
DateTime end;
|
|
||||||
if (now.Hour >= 8)
|
|
||||||
{
|
|
||||||
start = DateTime.Today.AddHours(8);
|
|
||||||
end = start.AddHours(24);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = DateTime.Today.AddHours(8);
|
|
||||||
start = end.AddHours(-24);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lastPlayedTime.IsBetween(start, end) ? data.PlayCount : 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,178 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using System.Xml;
|
|
||||||
using ChoETL;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.models;
|
|
||||||
using SQLite.Net2;
|
|
||||||
using Swan;
|
|
||||||
using Swan.Logging;
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class RankController : WebApiController
|
|
||||||
{
|
|
||||||
private readonly SQLiteConnection cardSqLiteConnection;
|
|
||||||
private readonly SQLiteConnection musicSqLiteConnection;
|
|
||||||
|
|
||||||
public RankController()
|
|
||||||
{
|
|
||||||
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
|
||||||
musicSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.MusicDbName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/ranking.php")]
|
|
||||||
public string Rank([QueryField("cmd_type")] int type)
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(RankType), type))
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(type), type, "Rank type out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
var requestType = (RankType)type;
|
|
||||||
|
|
||||||
switch (requestType)
|
|
||||||
{
|
|
||||||
case RankType.GlobalRank:
|
|
||||||
case RankType.UnknownRank1:
|
|
||||||
case RankType.UnknownRank2:
|
|
||||||
case RankType.UnknownRank3:
|
|
||||||
$"Getting rank request, type is {requestType}".Info();
|
|
||||||
|
|
||||||
return ConstructResponse(RankTemp("score_rank"));
|
|
||||||
case RankType.PlayNumRank:
|
|
||||||
$"Getting rank request, type is {requestType}".Info();
|
|
||||||
|
|
||||||
return ConstructResponse(PlayNumRank());
|
|
||||||
case RankType.EventRank:
|
|
||||||
$"Getting rank request, type is {requestType}".Info();
|
|
||||||
|
|
||||||
return ConstructResponse(RankTemp("event_rank"));
|
|
||||||
default:
|
|
||||||
#pragma warning disable CA2208
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(requestType));
|
|
||||||
#pragma warning restore CA2208
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ConstructResponse(string xml)
|
|
||||||
{
|
|
||||||
return "1\n" +
|
|
||||||
xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Add proper rank support
|
|
||||||
private static string RankTemp(string rankType)
|
|
||||||
{
|
|
||||||
var rankStatus = new RankStatus
|
|
||||||
{
|
|
||||||
Rows = 0,
|
|
||||||
Status = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
using (var writer = new ChoXmlWriter<RankStatus>(sb))
|
|
||||||
{
|
|
||||||
writer.Configuration.OmitXmlDeclaration = false;
|
|
||||||
writer.Configuration.UseXmlSerialization = true;
|
|
||||||
writer.WithXPath(Configs.RANK_STATUS_XPATH);
|
|
||||||
|
|
||||||
writer.Write(rankStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
var document = new XmlDocument();
|
|
||||||
document.LoadXml(sb.ToString());
|
|
||||||
var root = document.DocumentElement;
|
|
||||||
|
|
||||||
if (root == null)
|
|
||||||
{
|
|
||||||
throw SelfCheck.Failure("Internal XML error!");
|
|
||||||
}
|
|
||||||
|
|
||||||
root.AppendChild(document.CreateElement(rankType));
|
|
||||||
|
|
||||||
var stringWriter = new StringWriter();
|
|
||||||
var xmlTextWriter = new XmlTextWriter(stringWriter);
|
|
||||||
document.WriteTo(xmlTextWriter);
|
|
||||||
|
|
||||||
return stringWriter.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string PlayNumRank()
|
|
||||||
{
|
|
||||||
var rankStatus = new RankStatus
|
|
||||||
{
|
|
||||||
Rows = 30,
|
|
||||||
TableName = "play_num_rank",
|
|
||||||
Status = 1,
|
|
||||||
EndDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
|
||||||
};
|
|
||||||
|
|
||||||
var playNumRankContainer = new PlayNumRankContainer
|
|
||||||
{
|
|
||||||
PlayNumRankRecords = GetPlayNumRankRecords(),
|
|
||||||
RankStatus = rankStatus
|
|
||||||
};
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
using (var writer = new ChoXmlWriter<PlayNumRankContainer>(sb))
|
|
||||||
{
|
|
||||||
writer.Configuration.UseXmlSerialization = true;
|
|
||||||
writer.Configuration.OmitXmlDeclaration = false;
|
|
||||||
writer.Configuration.IgnoreRootName = true;
|
|
||||||
writer.Write(playNumRankContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<PlayNumRankRecord> GetPlayNumRankRecords()
|
|
||||||
{
|
|
||||||
var records = new List<PlayNumRankRecord>();
|
|
||||||
var musics = musicSqLiteConnection.Table<Music>().ToList().OrderBy(arg => Guid.NewGuid()).Take(30).ToList();
|
|
||||||
|
|
||||||
for (var i = 0; i < musics.Count; i++)
|
|
||||||
{
|
|
||||||
var music = musics[i];
|
|
||||||
var index = i + 1;
|
|
||||||
var record = new PlayNumRankRecord
|
|
||||||
{
|
|
||||||
Id = index,
|
|
||||||
Rank = index,
|
|
||||||
Rank2 = index + 1,
|
|
||||||
PrevRank = musics.Count - i,
|
|
||||||
PrevRank2 = index + 1,
|
|
||||||
Artist = music.Artist,
|
|
||||||
Pcol1 = music.MusicId,
|
|
||||||
ScoreBi1 = index,
|
|
||||||
Title = music.Title
|
|
||||||
};
|
|
||||||
records.Add(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private enum RankType
|
|
||||||
{
|
|
||||||
GlobalRank = 4119,
|
|
||||||
PlayNumRank = 6657,
|
|
||||||
EventRank = 6661,
|
|
||||||
UnknownRank1 = 6666,
|
|
||||||
UnknownRank2 = 6667,
|
|
||||||
UnknownRank3 = 4098
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class ResponeServiceController : WebApiController
|
|
||||||
{
|
|
||||||
[Route(HttpVerbs.Post, "/respone.php")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public string ResponeService()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
using System.Collections.Specialized;
|
|
||||||
using System.Net.Mime;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class ServerController : WebApiController
|
|
||||||
{
|
|
||||||
private static readonly string DataUrl = $"https://cert.nesys.jp/{Configs.STATIC_FOLDER}/{Configs.SETTINGS.EventFolder}";
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/certify.php")]
|
|
||||||
public string Certify([QueryData] NameValueCollection parameters)
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
var gid = parameters["gid"];
|
|
||||||
var mac = parameters["mac"];
|
|
||||||
var random = parameters["r"];
|
|
||||||
var hash = parameters["md"];
|
|
||||||
|
|
||||||
if (gid == null)
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorNoGid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mac == null)
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorNoMac);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (random == null)
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorNoRandom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash == null)
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorNoHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MacValid(mac))
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorInvalidMac);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Md5Valid(hash))
|
|
||||||
{
|
|
||||||
return QuitWithError(ErrorCode.ErrorInvalidHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var md5 = MD5.Create();
|
|
||||||
|
|
||||||
var ticket = string.Join(string.Empty,
|
|
||||||
md5.ComputeHash(Encoding.UTF8.GetBytes(gid)).Select(b => b.ToString("x2")));
|
|
||||||
|
|
||||||
|
|
||||||
var response = $"host=card_id=7020392000147361,relay_addr={Configs.SETTINGS.RelayServer},relay_port={Configs.SETTINGS.RelayPort}\n" +
|
|
||||||
"no=1337\n" +
|
|
||||||
"name=123\n" +
|
|
||||||
"pref=nesys\n" +
|
|
||||||
"addr=nesys@home\n" +
|
|
||||||
"x-next-time=15\n" +
|
|
||||||
$"x-img=http://{Configs.SETTINGS.ServerIp}{Configs.STATIC_BASE_ROUTE}/news.png\n" +
|
|
||||||
$"x-ranking=http://{Configs.SETTINGS.ServerIp}{Configs.RANK_BASE_ROUTE}/ranking.php\n" +
|
|
||||||
$"ticket={ticket}";
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/cursel.php")]
|
|
||||||
public string Cursel()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/data.php")]
|
|
||||||
public string Data()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
var responseList = Configs.SETTINGS.ResponseData.ToList();
|
|
||||||
var count = responseList.Count;
|
|
||||||
var dataString = new StringBuilder();
|
|
||||||
for (var i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var data = responseList[i];
|
|
||||||
var fileUrl = data.FileName.StartsWith("/") ? $"{DataUrl}{data.FileName}" : $"{DataUrl}/{data.FileName}";
|
|
||||||
dataString.Append($"{i},{fileUrl},{data.NotBeforeUnixTime},{data.NotAfterUnixTime},{data.Md5},{data.Index}");
|
|
||||||
dataString.Append('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"count={count}\n" +
|
|
||||||
"nexttime=1\n" +
|
|
||||||
(Configs.SETTINGS.DownloadEvents ? dataString.ToString().TrimEnd('\n') : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/gameinfo.php")]
|
|
||||||
public string GameInfo()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "0\n" +
|
|
||||||
"3\n" +
|
|
||||||
"301000,test1\n" +
|
|
||||||
"302000,test2\n" +
|
|
||||||
"303000,test3";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool MacValid(string mac)
|
|
||||||
{
|
|
||||||
return Regex.IsMatch(mac, "^[a-fA-F0-9]{12}$");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool Md5Valid(string md5)
|
|
||||||
{
|
|
||||||
return Regex.IsMatch(md5, "^[a-fA-F0-9]{32}$");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string QuitWithError(ErrorCode errorCode)
|
|
||||||
{
|
|
||||||
return $"error={(int)errorCode}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum ErrorCode
|
|
||||||
{
|
|
||||||
ErrorNoGid,
|
|
||||||
ErrorNoMac,
|
|
||||||
ErrorNoRandom,
|
|
||||||
ErrorNoHash,
|
|
||||||
ErrorInvalidMac,
|
|
||||||
ErrorInvalidHash
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using Swan.Logging;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers
|
|
||||||
{
|
|
||||||
// TODO: Add proper update check response
|
|
||||||
public class UpdateController : WebApiController
|
|
||||||
{
|
|
||||||
[Route(HttpVerbs.Get, "/check.php")]
|
|
||||||
public string CheckUpdate()
|
|
||||||
{
|
|
||||||
var parameters = HttpContext.GetRequestQueryData();
|
|
||||||
foreach (var key in parameters.AllKeys)
|
|
||||||
{
|
|
||||||
$"Key {key}: {parameters[key]}".Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpContext.Response.StatusCode = 404;
|
|
||||||
return "Not found";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Text;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Routing;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
|
||||||
|
|
||||||
public class UploadServiceController : WebApiController
|
|
||||||
{
|
|
||||||
[Route(HttpVerbs.Post, "/upload.php")]
|
|
||||||
// ReSharper disable once UnusedMember.Global
|
|
||||||
public string UploadService()
|
|
||||||
{
|
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Text.Plain;
|
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
|
||||||
HttpContext.Response.KeepAlive = true;
|
|
||||||
|
|
||||||
return "1\n" +
|
|
||||||
"OK";
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Avatar : Record , IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "avatar_id")]
|
|
||||||
public int AvatarId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
AvatarId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using ChoETL;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("card_main")]
|
|
||||||
public class Card : ICardIdModel
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("card_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "card_id")]
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[Column("player_name")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "player_name")]
|
|
||||||
[XmlElement(ElementName = "player_name")]
|
|
||||||
public string PlayerName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Column("score_i1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_i1")]
|
|
||||||
[XmlElement("score_i1")]
|
|
||||||
public int Score { get; set; }
|
|
||||||
|
|
||||||
[Column("fcol1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol1")]
|
|
||||||
[XmlElement("fcol1")]
|
|
||||||
public int Fcol1 { get; set; }
|
|
||||||
|
|
||||||
[Column("fcol2")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol2")]
|
|
||||||
[XmlElement("fcol2")]
|
|
||||||
public int Fcol2 { get; set; }
|
|
||||||
|
|
||||||
[Column("fcol3")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol3")]
|
|
||||||
[XmlElement("fcol3")]
|
|
||||||
public int Fcol3 { get; set; }
|
|
||||||
|
|
||||||
[Column("achieve_status")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "achieve_status")]
|
|
||||||
[XmlElement("achieve_status")]
|
|
||||||
public string AchieveStatus { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Column("created")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "created")]
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "2017-01-01 08:00:00";
|
|
||||||
|
|
||||||
[Column("modified")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "modified")]
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "2017-01-01 08:00:00";
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using ChoETL;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("card_bdata")]
|
|
||||||
public class CardBData : ICardIdModel
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("card_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "card_id")]
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[Column("bdata")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "bdata")]
|
|
||||||
[XmlElement(ElementName = "bdata")]
|
|
||||||
public string BData { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Column("bdata_size")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "bdata_size")]
|
|
||||||
[XmlElement(ElementName = "bdata_size")]
|
|
||||||
public int BDataSize { get; set; }
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using ChoETL;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("card_detail")]
|
|
||||||
public class CardDetail : Record, ICardIdModel
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("card_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "card_id")]
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("pcol1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol1")]
|
|
||||||
[XmlElement(ElementName = "pcol1")]
|
|
||||||
public int Pcol1 { get; set; }
|
|
||||||
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("pcol2")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol2")]
|
|
||||||
[XmlElement(ElementName = "pcol2")]
|
|
||||||
public int Pcol2 { get; set; }
|
|
||||||
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("pcol3")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol3")]
|
|
||||||
[XmlElement(ElementName = "pcol3")]
|
|
||||||
public int Pcol3 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_i1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_i1")]
|
|
||||||
[XmlElement(ElementName = "score_i1")]
|
|
||||||
public long ScoreI1 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui1")]
|
|
||||||
[XmlElement(ElementName = "score_ui1")]
|
|
||||||
public long ScoreUi1 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui2")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui2")]
|
|
||||||
[XmlElement(ElementName = "score_ui2")]
|
|
||||||
public long ScoreUi2 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui3")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui3")]
|
|
||||||
[XmlElement(ElementName = "score_ui3")]
|
|
||||||
public long ScoreUi3 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui4")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui4")]
|
|
||||||
[XmlElement(ElementName = "score_ui4")]
|
|
||||||
public long ScoreUi4 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui5")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui5")]
|
|
||||||
[XmlElement(ElementName = "score_ui5")]
|
|
||||||
public long ScoreUi5 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_ui6")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_ui6")]
|
|
||||||
[XmlElement(ElementName = "score_ui6")]
|
|
||||||
public long ScoreUi6 { get; set; }
|
|
||||||
|
|
||||||
[Column("score_bi1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "score_bi1")]
|
|
||||||
[XmlElement(ElementName = "score_bi1")]
|
|
||||||
public long ScoreBi1 { get; set; }
|
|
||||||
|
|
||||||
[Column("last_play_tenpo_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "last_play_tenpo_id")]
|
|
||||||
[XmlElement(ElementName = "last_play_tenpo_id")]
|
|
||||||
public string LastPlayShopId { get; set; } = "1337";
|
|
||||||
|
|
||||||
[Column("fcol1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol1")]
|
|
||||||
[XmlElement("fcol1")]
|
|
||||||
public int Fcol1 { get; set; }
|
|
||||||
|
|
||||||
[Column("fcol2")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol2")]
|
|
||||||
[XmlElement("fcol2")]
|
|
||||||
public int Fcol2 { get; set; }
|
|
||||||
|
|
||||||
[Column("fcol3")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "fcol3")]
|
|
||||||
[XmlElement("fcol3")]
|
|
||||||
public int Fcol3 { get; set; }
|
|
||||||
|
|
||||||
[Column("last_play_time")]
|
|
||||||
[XmlIgnore]
|
|
||||||
public DateTime LastPlayTime { get; set; } = DateTime.MinValue;
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using ChoETL;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[ChoXmlRecordObject(XPath = "/root/data")]
|
|
||||||
public class CardDetailReadData
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "pcol1")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol1")]
|
|
||||||
public int Pcol1 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "pcol2")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol2")]
|
|
||||||
public int Pcol2 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "pcol3")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pcol3")]
|
|
||||||
public int Pcol3 { get; set; }
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class CardPlayCount
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[Column("play_count")]
|
|
||||||
public int PlayCount { get; set; }
|
|
||||||
|
|
||||||
[Column("last_played_time")]
|
|
||||||
public DateTime LastPlayed { get; set; }
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Coin
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "current")]
|
|
||||||
public int CurrentCoins { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "total")]
|
|
||||||
public int TotalCoins { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("monthly")]
|
|
||||||
public int MonthlyCoins { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public interface ICardIdModel
|
|
||||||
{
|
|
||||||
public void SetCardId(long cardId);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public interface IIdModel
|
|
||||||
{
|
|
||||||
public void SetId(int id);
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Item : Record, IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "item_id")]
|
|
||||||
public int ItemId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "item_num")]
|
|
||||||
public int ItemNum { get; set; } = 90;
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
ItemId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("music_unlock")]
|
|
||||||
public class Music : Record
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("music_id")]
|
|
||||||
[XmlElement("music_id")]
|
|
||||||
public int MusicId { get; set; }
|
|
||||||
|
|
||||||
[Column("title")]
|
|
||||||
[XmlElement(ElementName = "title")]
|
|
||||||
public string? Title { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[Column("artist")]
|
|
||||||
[XmlElement(ElementName = "artist")]
|
|
||||||
public string? Artist
|
|
||||||
{
|
|
||||||
get => _artist;
|
|
||||||
set => _artist = value ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string? _artist = string.Empty;
|
|
||||||
|
|
||||||
[Column("release_date")]
|
|
||||||
[XmlElement(ElementName = "release_date")]
|
|
||||||
public string ReleaseDate { get; set; } = "2013-01-01 08:00:00";
|
|
||||||
|
|
||||||
[Column("end_date")]
|
|
||||||
[XmlElement(ElementName = "end_date")]
|
|
||||||
public string EndDate { get; set; } = "2030-01-01 08:00:00";
|
|
||||||
|
|
||||||
[Column("new_flag")]
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[Column("use_flag")]
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; }
|
|
||||||
|
|
||||||
[Ignore]
|
|
||||||
[XmlElement("calc_flag")]
|
|
||||||
public uint CalcFlag { get; set; } = 2;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("music_aou")]
|
|
||||||
public class MusicAou : Record
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("music_id")]
|
|
||||||
[XmlElement("music_id")]
|
|
||||||
public int MusicId { get; set; }
|
|
||||||
|
|
||||||
[Column("use_flag")]
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[Table("music_extra")]
|
|
||||||
public class MusicExtra : Record
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
[Column("music_id")]
|
|
||||||
[XmlElement("music_id")]
|
|
||||||
public int MusicId { get; set; }
|
|
||||||
|
|
||||||
[Column("use_flag")]
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; }
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Navigator : Record, IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "navigator_id")]
|
|
||||||
public int NavigatorId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
NavigatorId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using ChoETL;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class OnlineMatchingEntry: Record
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "machine_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "machine_id")]
|
|
||||||
public long MachineId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "event_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "event_id")]
|
|
||||||
public long EventId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "matching_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_id")]
|
|
||||||
public long MatchingId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "entry_no")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "entry_no")]
|
|
||||||
public long EntryNo { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "entry_start")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "entry_start")]
|
|
||||||
public string EntryStart { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "status")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "status")]
|
|
||||||
public long Status { get; set; } = 1;
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "player_name")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "player_name")]
|
|
||||||
public string PlayerName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "avatar_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "avatar_id")]
|
|
||||||
public long AvatarId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "title_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "title_id")]
|
|
||||||
public long TitleId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "class_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "class_id")]
|
|
||||||
public long ClassId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "group_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "group_id")]
|
|
||||||
public long GroupId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "tenpo_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "tenpo_id")]
|
|
||||||
public long TenpoId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "tenpo_name")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "tenpo_name")]
|
|
||||||
public string TenpoName { get; set; } = "1337";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "pref_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pref_id")]
|
|
||||||
public long PrefId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "pref")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "pref")]
|
|
||||||
public string Pref { get; set; } = "nesys";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "message_id")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "message_id")]
|
|
||||||
public long MessageId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Communication timeout?
|
|
||||||
/// </summary>
|
|
||||||
[XmlElement(ElementName = "matching_timeout")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_timeout")]
|
|
||||||
public long MatchingTimeout { get; set; } = 99;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wait time
|
|
||||||
/// </summary>
|
|
||||||
[XmlElement(ElementName = "matching_wait_time")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_wait_time")]
|
|
||||||
public long MatchingWaitTime { get; set; } = 10;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Seems not used
|
|
||||||
/// </summary>
|
|
||||||
[XmlElement(ElementName = "matching_remaining_time")]
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_remaining_time")]
|
|
||||||
public long MatchingRemainingTime { get; set; } = 89;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class OnlineMatchingResult
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "status")]
|
|
||||||
public int Status { get; set; }
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
using ChoETL;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[ChoXmlRecordObject(XPath = "/root/data")]
|
|
||||||
public class OnlineMatchingResultData
|
|
||||||
{
|
|
||||||
[ChoXmlElementRecordField(FieldName = "event_id")]
|
|
||||||
public long EventId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_id")]
|
|
||||||
public long MatchingId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "class_id")]
|
|
||||||
public long ClassId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "group_id")]
|
|
||||||
public long GroupId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "result_score")]
|
|
||||||
public long ResultScore { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "result_star")]
|
|
||||||
public long ResultStar { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "result_rank")]
|
|
||||||
public long ResultRank { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "music_id_1st")]
|
|
||||||
public long MusicIdFirst { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "music_id_2nd")]
|
|
||||||
public long MusicIdSecond { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "music_id_3rd")]
|
|
||||||
public long MusicIdThird { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "difficulty_lv_1st")]
|
|
||||||
public long DifficultyFirst { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "difficulty_lv_2nd")]
|
|
||||||
public long DifficultySecond { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "difficulty_lv_3rd")]
|
|
||||||
public long DifficultyThird { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "item_id_1st")]
|
|
||||||
public long ItemIdFirst { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "item_id_2nd")]
|
|
||||||
public long ItemIdSecond { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "item_id_3rd")]
|
|
||||||
public long ItemIdThird { get; set; }
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using ChoETL;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[ChoXmlRecordObject(XPath = "/root/data")]
|
|
||||||
// ReSharper disable once ClassNeverInstantiated.Global
|
|
||||||
public class OnlineMatchingUpdateData
|
|
||||||
{
|
|
||||||
[ChoXmlElementRecordField(FieldName = "action")]
|
|
||||||
public long Action { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "event_id")]
|
|
||||||
public long EventId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "matching_id")]
|
|
||||||
public long MatchingId { get; set; }
|
|
||||||
|
|
||||||
[ChoXmlElementRecordField(FieldName = "message_id")]
|
|
||||||
public long MessageId { get; set; }
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[XmlRoot("root")]
|
|
||||||
public class PlayNumRankContainer
|
|
||||||
{
|
|
||||||
[XmlArray("play_num_rank")]
|
|
||||||
public List<PlayNumRankRecord> PlayNumRankRecords { get; set; } = new();
|
|
||||||
|
|
||||||
[XmlElement("ranking_status")]
|
|
||||||
public RankStatus? RankStatus { get; set; }
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[XmlType("record")]
|
|
||||||
public class PlayNumRankRecord
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "id")]
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("rank")]
|
|
||||||
public int Rank { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("rank2")]
|
|
||||||
public int Rank2 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("prev_rank")]
|
|
||||||
public int PrevRank { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("prev_rank2")]
|
|
||||||
public int PrevRank2 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("pcol1")]
|
|
||||||
public int Pcol1 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("score_bi1")]
|
|
||||||
public int ScoreBi1 { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("title")]
|
|
||||||
public string? Title { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("artist")]
|
|
||||||
public string? Artist { get; set; }
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
[XmlType("ranking_status")]
|
|
||||||
public class RankStatus
|
|
||||||
{
|
|
||||||
[XmlElement("table_name")]
|
|
||||||
public string TableName { get; set; } = "rank_table";
|
|
||||||
|
|
||||||
[XmlElement("start_date")]
|
|
||||||
public string StartDate { get; set; } = "2021-05-30";
|
|
||||||
|
|
||||||
[XmlElement("end_date")]
|
|
||||||
public string EndDate { get; set; } = "2022-06-08";
|
|
||||||
|
|
||||||
[XmlElement("status")]
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("rows")]
|
|
||||||
public int Rows { get; set; }
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
using SQLite.Net2;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Record
|
|
||||||
{
|
|
||||||
[XmlAttribute(AttributeName = "id")]
|
|
||||||
[Ignore]
|
|
||||||
public int RecordId { get; set; }
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Session
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "mac_addr")]
|
|
||||||
public string Mac { get; set; } = "000000000000";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "session_id")]
|
|
||||||
public string SessionId { get; set; } = "12345678901234567890123456789012";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "expires")]
|
|
||||||
public int Expires { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "player_id")]
|
|
||||||
public int PlayerId { get; set; }
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Skin : Record, IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "skin_id")]
|
|
||||||
public int SkinId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
SkinId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class SoundEffect : Record, IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "sound_effect_id")]
|
|
||||||
public int SeId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
SeId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class Title : Record, IIdModel, ICardIdModel
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "title_id")]
|
|
||||||
public int TitleId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("new_flag")]
|
|
||||||
public int NewFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
public void SetId(int id)
|
|
||||||
{
|
|
||||||
TitleId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
|
||||||
{
|
|
||||||
CardId = cardId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class TotalTrophy
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "total_trophy_num")]
|
|
||||||
public int TrophyNum { get; set; }
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class UnlockKeynum : Record
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "reward_id")]
|
|
||||||
public int RewardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "key_num")]
|
|
||||||
public int KeyNum { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "reward_count")]
|
|
||||||
public int RewardCount { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("expired_flag")]
|
|
||||||
public int ExpiredFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
[XmlElement("cash_flag")]
|
|
||||||
public int CashFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.models;
|
|
||||||
|
|
||||||
public class UnlockReward : Record
|
|
||||||
{
|
|
||||||
[XmlElement(ElementName = "card_id")]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "reward_id")]
|
|
||||||
public int RewardId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "reward_type")]
|
|
||||||
public int RewardType { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "open_date")]
|
|
||||||
public string OpenDate { get; set; } = "2021-05-30";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "close_date")]
|
|
||||||
public string CloseDate { get; set; } = "2030-05-30";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "open_time")]
|
|
||||||
public string OpenTime { get; set; } = "00:00:01";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "close_time")]
|
|
||||||
public string CloseTime { get; set; } = "23:59:59";
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "target_id")]
|
|
||||||
public int TargetId { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "target_num")]
|
|
||||||
public int TargetNum { get; set; }
|
|
||||||
|
|
||||||
[XmlElement(ElementName = "key_num")]
|
|
||||||
public int KeyNum { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("display_flag")]
|
|
||||||
public int DisplayFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
[XmlElement("use_flag")]
|
|
||||||
public int UseFlag { get; set; } = 1;
|
|
||||||
|
|
||||||
[XmlElement("limited_flag")]
|
|
||||||
public int LimitedFlag { get; set; }
|
|
||||||
|
|
||||||
[XmlElement("open_unixtime")]
|
|
||||||
public long OpenUnixTime { get; set; } = 1622304001;
|
|
||||||
|
|
||||||
[XmlElement("close_unixtime")]
|
|
||||||
public long CloseUnixTime { get; set; } = 1906387199;
|
|
||||||
|
|
||||||
[XmlElement("created")]
|
|
||||||
public string Created { get; set; } = "1";
|
|
||||||
|
|
||||||
[XmlElement("modified")]
|
|
||||||
public string Modified { get; set; } = "1";
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using EmbedIO;
|
|
||||||
using EmbedIO.Actions;
|
|
||||||
using EmbedIO.Files;
|
|
||||||
using EmbedIO.WebApi;
|
|
||||||
using GCLocalServerRewrite.common;
|
|
||||||
using GCLocalServerRewrite.controllers;
|
|
||||||
using GCLocalServerRewrite.models;
|
|
||||||
using Swan.Logging;
|
|
||||||
using System.Text;
|
|
||||||
using Swan;
|
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.server;
|
|
||||||
|
|
||||||
public class Server
|
|
||||||
{
|
|
||||||
public static WebServer CreateWebServer(IEnumerable<string> urlPrefixes)
|
|
||||||
{
|
|
||||||
InitializeDatabase();
|
|
||||||
X509Certificate2 cert;
|
|
||||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
|
||||||
{
|
|
||||||
cert = CertificateHelper.InitializeCertificate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var certPath = Path.Combine(PathHelper.CertRootPath, "cert.pfx");
|
|
||||||
var certPassword = string.Empty;
|
|
||||||
var collection = new X509Certificate2Collection();
|
|
||||||
collection.Import(certPath, null, X509KeyStorageFlags.PersistKeySet |
|
|
||||||
X509KeyStorageFlags.MachineKeySet |
|
|
||||||
X509KeyStorageFlags.Exportable);
|
|
||||||
if (!collection.Any())
|
|
||||||
{
|
|
||||||
SelfCheck.Failure("Failed to import certificate!!!");
|
|
||||||
}
|
|
||||||
cert = collection.First();
|
|
||||||
}
|
|
||||||
|
|
||||||
var server = new WebServer(webServerOptions => webServerOptions
|
|
||||||
.WithUrlPrefixes(urlPrefixes)
|
|
||||||
.WithCertificate(cert)
|
|
||||||
.WithMode(HttpListenerMode.EmbedIO))
|
|
||||||
.WithLocalSessionManager()
|
|
||||||
.WithCors()
|
|
||||||
.WithWebApi(Configs.API_BASE_ROUTE, module => module.WithController<ApiController>())
|
|
||||||
.WithWebApi(Configs.CARD_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<CardServiceController>())
|
|
||||||
.WithWebApi(Configs.OPTION_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<OptionServiceController>())
|
|
||||||
.WithWebApi(Configs.UPLOAD_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<UploadServiceController>())
|
|
||||||
.WithWebApi(Configs.RESPONE_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<ResponeServiceController>())
|
|
||||||
.WithWebApi(Configs.INCOM_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<IncomServiceController>())
|
|
||||||
.WithWebApi(Configs.ALIVE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<AliveController>())
|
|
||||||
.WithWebApi(Configs.SERVER_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<ServerController>())
|
|
||||||
.WithWebApi(Configs.RANK_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<RankController>())
|
|
||||||
.WithWebApi(Configs.UPDATE_SERVICE_BASE_ROUTE, ResponseSerializer.None(true),
|
|
||||||
module => module.WithController<UpdateController>())
|
|
||||||
.WithStaticFolder(Configs.STATIC_BASE_ROUTE, PathHelper.HtmlRootPath, true, m => m
|
|
||||||
.WithContentCaching(Configs.USE_FILE_CACHE))
|
|
||||||
// Add static files after other modules to avoid conflicts
|
|
||||||
.WithStaticFolder("/", PathHelper.HtmlRootPath, true, m =>
|
|
||||||
{
|
|
||||||
m.WithContentCaching(Configs.USE_FILE_CACHE);
|
|
||||||
m.OnMappingFailed = async (context, info) =>
|
|
||||||
{
|
|
||||||
var htmlContents = await File.ReadAllTextAsync(Path.Combine(PathHelper.HtmlRootPath, "index.html"));
|
|
||||||
context.Response.StatusCode = 200;
|
|
||||||
await context.SendStringAsync(htmlContents, "text/html", Encoding.UTF8);
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.WithModule(new ActionModule("/", HttpVerbs.Any,
|
|
||||||
ctx => ctx.SendDataAsync(new { Message = "Error" })));
|
|
||||||
server.AddCustomMimeType(".dll", "application/octet-stream");
|
|
||||||
server.AddCustomMimeType(".blat", "application/octet-stream");
|
|
||||||
server.AddCustomMimeType(".dat", "application/octet-stream");
|
|
||||||
server.AddCustomMimeType(".json", "application/json");
|
|
||||||
server.AddCustomMimeType(".wasm", "application/wasm");
|
|
||||||
server.AddCustomMimeType(".woff", "application/font-woff");
|
|
||||||
server.AddCustomMimeType(".woff2", "application/font-woff2");
|
|
||||||
|
|
||||||
// Listen for state changes.
|
|
||||||
server.StateChanged += (_, e) => $"WebServer New State - {e.NewState}".Info();
|
|
||||||
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitializeDatabase()
|
|
||||||
{
|
|
||||||
DatabaseHelper.InitializeLocalDatabase(Configs.SETTINGS.CardDbName,
|
|
||||||
typeof(Card), typeof(CardBData), typeof(CardDetail), typeof(CardPlayCount));
|
|
||||||
DatabaseHelper.InitializeLocalDatabase(Configs.SETTINGS.MusicDbName,
|
|
||||||
typeof(Music), typeof(MusicAou), typeof(MusicExtra));
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
Hello world!
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 818 B |
@ -1,131 +0,0 @@
|
|||||||
using MatchServer.Storage;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using SharedProject.models;
|
|
||||||
|
|
||||||
namespace MatchServer.Controllers;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class MatchingController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ILogger<MatchingController> logger;
|
|
||||||
|
|
||||||
|
|
||||||
public MatchingController(ILogger<MatchingController> logger) {
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("Start")]
|
|
||||||
public ActionResult<IEnumerable<OnlineMatchingData>> StartOnlineMatching(OnlineMatchingData startData)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Start matching, card id {CardId}, player name {PlayerName}", startData.CardId, startData.PlayerName);
|
|
||||||
var matchingDb = MatchingDb.GetInstance;
|
|
||||||
|
|
||||||
lock (matchingDb.DbLock)
|
|
||||||
{
|
|
||||||
foreach (var (matchingId, entries) in matchingDb.MatchingDictionary)
|
|
||||||
{
|
|
||||||
if (entries.Count >= 4)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entries.Any(data => data.CardId == startData.CardId))
|
|
||||||
{
|
|
||||||
logger.LogWarning("Card id {CardId} already exists in matching id {MatchingId}", startData.CardId, matchingId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.Add(startData);
|
|
||||||
startData.MatchingId = matchingId;
|
|
||||||
startData.EntryNo = entries.Count - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startData.MatchingId != 0)
|
|
||||||
{
|
|
||||||
return Ok(matchingDb.MatchingDictionary[startData.MatchingId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
startData.MatchingId = matchingDb.MatchingDictionary.Count + 1;
|
|
||||||
startData.EntryNo = 0;
|
|
||||||
matchingDb.MatchingDictionary[startData.MatchingId] = new List<OnlineMatchingData>
|
|
||||||
{
|
|
||||||
startData
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(matchingDb.MatchingDictionary[startData.MatchingId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("Update")]
|
|
||||||
public ActionResult<IEnumerable<OnlineMatchingUpdateRequest>> UpdateOnlineMatching(OnlineMatchingUpdateRequest updateData)
|
|
||||||
{
|
|
||||||
var matchingDb = MatchingDb.GetInstance;
|
|
||||||
var matchingId = updateData.MatchingId;
|
|
||||||
|
|
||||||
logger.LogInformation("Update matching, card id is {CardId}, matching id is {MatchingId}", updateData.CardId, updateData.MatchingId);
|
|
||||||
|
|
||||||
if (!matchingDb.MatchingDictionary.ContainsKey(matchingId))
|
|
||||||
{
|
|
||||||
return BadRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
var dataList = matchingDb.MatchingDictionary[matchingId];
|
|
||||||
|
|
||||||
var data = dataList.Find(data => data.CardId == updateData.CardId);
|
|
||||||
if (data is null)
|
|
||||||
{
|
|
||||||
return BadRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
data.MessageId = updateData.MessageId;
|
|
||||||
if (data.MatchingRemainingTime <= 0)
|
|
||||||
{
|
|
||||||
data.Status = 3;
|
|
||||||
return Ok(dataList);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.MatchingRemainingTime--;
|
|
||||||
return Ok(dataList);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("Finish")]
|
|
||||||
public ActionResult<bool> FinishOnlineMatching(OnlineMatchingFinishRequest request)
|
|
||||||
{
|
|
||||||
var matchingDb = MatchingDb.GetInstance;
|
|
||||||
var matchingId = request.MatchingId;
|
|
||||||
|
|
||||||
lock (matchingDb.DbLock)
|
|
||||||
{
|
|
||||||
if (!matchingDb.MatchingDictionary.ContainsKey(matchingId))
|
|
||||||
{
|
|
||||||
return BadRequest();
|
|
||||||
}
|
|
||||||
var dataList = matchingDb.MatchingDictionary[matchingId];
|
|
||||||
|
|
||||||
var index = dataList.FindIndex(data => data.CardId == request.CardId);
|
|
||||||
dataList.RemoveAt(index);
|
|
||||||
}
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("Debug")]
|
|
||||||
public ActionResult<Dictionary<long, List<OnlineMatchingUpdateRequest>>> InspectOnlineMatching()
|
|
||||||
{
|
|
||||||
var matchingDb = MatchingDb.GetInstance;
|
|
||||||
|
|
||||||
return Ok(matchingDb.MatchingDictionary);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("Clear")]
|
|
||||||
public ActionResult<bool> Clear()
|
|
||||||
{
|
|
||||||
var matchingDb = MatchingDb.GetInstance;
|
|
||||||
lock (matchingDb.DbLock)
|
|
||||||
{
|
|
||||||
matchingDb.MatchingDictionary.Clear();
|
|
||||||
}
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\SharedProject\SharedProject.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,21 +0,0 @@
|
|||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
|
||||||
builder.Services.AddSwaggerGen();
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseSwagger();
|
|
||||||
app.UseSwaggerUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
app.Run();
|
|
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:45319",
|
|
||||||
"sslPort": 44313
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"MatchServer": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "swagger",
|
|
||||||
"applicationUrl": "https://localhost:7023;http://localhost:5038",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "swagger",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
using SharedProject.models;
|
|
||||||
|
|
||||||
namespace MatchServer.Storage;
|
|
||||||
|
|
||||||
public class MatchingDb
|
|
||||||
{
|
|
||||||
public Dictionary<long, List<OnlineMatchingData>> MatchingDictionary;
|
|
||||||
|
|
||||||
public object DbLock = new();
|
|
||||||
|
|
||||||
static MatchingDb()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private MatchingDb()
|
|
||||||
{
|
|
||||||
MatchingDictionary = new Dictionary<long, List<OnlineMatchingData>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MatchingDb GetInstance { get; } = new MatchingDb();
|
|
||||||
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*"
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
<Router AppAssembly="@typeof(App).Assembly">
|
|
||||||
<Found Context="routeData">
|
|
||||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
|
||||||
</Found>
|
|
||||||
<NotFound>
|
|
||||||
<PageTitle>Not found</PageTitle>
|
|
||||||
<LayoutView Layout="@typeof(MainLayout)">
|
|
||||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
|
||||||
</LayoutView>
|
|
||||||
</NotFound>
|
|
||||||
</Router>
|
|
@ -1,12 +0,0 @@
|
|||||||
<linker>
|
|
||||||
<assembly fullname="MudBlazor" preserve="all">
|
|
||||||
<type fullname="MudBlazor.FilterOperator" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterOperator/String" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterOperator/Number" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterOperator/Enum" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterOperator/Boolean" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterOperator/DateTime" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.FilterDefinition`1" preserve="all" />
|
|
||||||
<type fullname="MudBlazor.Filter" preserve="all" />
|
|
||||||
</assembly>
|
|
||||||
</linker>
|
|
@ -1,81 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<RunAOTCompilation>False</RunAOTCompilation>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
|
||||||
<RunAOTCompilation>True</RunAOTCompilation>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
|
||||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="ILLink.Descriptors.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="ILLink.Descriptors.xml">
|
|
||||||
<LogicalName>ILLink.Descriptors.xml</LogicalName>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="GenFu" Version="1.6.0" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.10" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.10" PrivateAssets="all" />
|
|
||||||
<PackageReference Include="MudBlazor" Version="6.0.17" />
|
|
||||||
<PackageReference Include="protobuf-net" Version="3.1.22" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\SharedProject\SharedProject.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Update="wwwroot\appsettings.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\avatar.dat">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\avatar.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\navigator.dat">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\navigator.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\title.dat">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\data\title.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
<Content Update="wwwroot\news.png">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Utils" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.0.31717.71
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MudAdmin", "MudAdmin.csproj", "{D6DF8A15-5B8D-4302-90D2-FC71264B18CC}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{D6DF8A15-5B8D-4302-90D2-FC71264B18CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D6DF8A15-5B8D-4302-90D2-FC71264B18CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D6DF8A15-5B8D-4302-90D2-FC71264B18CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D6DF8A15-5B8D-4302-90D2-FC71264B18CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {58C61F27-917C-435B-8900-9B3CE8F8DCD4}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,73 +0,0 @@
|
|||||||
@using SharedProject.common
|
|
||||||
@using System.Text.RegularExpressions
|
|
||||||
@inject HttpClient Client
|
|
||||||
@inject ILogger<ChangePlayerNameDialog> Logger
|
|
||||||
|
|
||||||
<MudDialog>
|
|
||||||
<TitleContent>
|
|
||||||
<MudText Typo="Typo.h6">
|
|
||||||
Change Player Name
|
|
||||||
</MudText>
|
|
||||||
</TitleContent>
|
|
||||||
<DialogContent>
|
|
||||||
<MudForm @bind-IsValid="IsValid">
|
|
||||||
<MudTextField Value="@Data.CardId" Label="CardId" ReadOnly="true"/>
|
|
||||||
<MudTextField @bind-Value="Data.PlayerName"
|
|
||||||
Immediate="true"
|
|
||||||
Counter="SharedConstants.MAX_PLAYER_NAME_LENGTH"
|
|
||||||
MaxLength="SharedConstants.MAX_PLAYER_NAME_LENGTH"
|
|
||||||
Validation="ValidatePlayerName"/>
|
|
||||||
</MudForm>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
|
||||||
<MudButton Color="Color.Primary" OnClick="Submit" Disabled="@(!IsValid)">Confirm</MudButton>
|
|
||||||
</DialogActions>
|
|
||||||
</MudDialog>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[CascadingParameter]
|
|
||||||
MudDialogInstance MudDialog { get; set; } = null!;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public SharedProject.models.User Data { get; set; } = null!;
|
|
||||||
|
|
||||||
private string originalName = string.Empty;
|
|
||||||
|
|
||||||
private bool IsValid { get; set; }
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
base.OnInitialized();
|
|
||||||
originalName = new string(Data.PlayerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task Submit()
|
|
||||||
{
|
|
||||||
Logger.LogInformation("Data is {cardId}, {name}", Data.CardId, Data.PlayerName);
|
|
||||||
var response = await Client.PostAsJsonAsync("api/Users/SetPlayerName", Data);
|
|
||||||
var result = await response.Content.ReadFromJsonAsync<bool>();
|
|
||||||
Logger.LogInformation("SetPlayerName result is {result}", result);
|
|
||||||
MudDialog.Close(DialogResult.Ok(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cancel()
|
|
||||||
{
|
|
||||||
Data.PlayerName = originalName;
|
|
||||||
MudDialog.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string? ValidatePlayerName(string playerName)
|
|
||||||
{
|
|
||||||
const string pattern = @"^[a-zA-Z0-9!?,./\-+:<>_\\@*#&=() ]{1,8}$";
|
|
||||||
|
|
||||||
return playerName.Length switch
|
|
||||||
{
|
|
||||||
0 => "Player name cannot be empty!",
|
|
||||||
> 8 => "Player name cannot be longer than 8 characters!",
|
|
||||||
_ => !Regex.IsMatch(playerName, pattern) ? "Player name contains invalid character!" : null
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
@using SharedProject.models
|
|
||||||
@inject HttpClient Client
|
|
||||||
@inject ILogger<FavoriteDialog> Logger
|
|
||||||
|
|
||||||
<MudDialog>
|
|
||||||
<TitleContent>
|
|
||||||
@if (!Data.IsFavorite)
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h6">
|
|
||||||
<MudIcon Icon="@Icons.Material.Filled.BookmarkAdd" Color="Color.Secondary"/>
|
|
||||||
Add to favorite?
|
|
||||||
</MudText>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h6">
|
|
||||||
<MudIcon Icon="@Icons.Material.Filled.BookmarkRemove" Color="Color.Secondary"/>
|
|
||||||
Remove from favorite?
|
|
||||||
</MudText>
|
|
||||||
}
|
|
||||||
</TitleContent>
|
|
||||||
<DialogContent>
|
|
||||||
<MudTextField Value="@Data.Title" Label="Song Title" ReadOnly="true"/>
|
|
||||||
<MudTextField Value="@Data.Artist" Label="Artist Name" ReadOnly="true"/>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
|
||||||
<MudButton Color="Color.Primary" OnClick="Submit">Confirm</MudButton>
|
|
||||||
</DialogActions>
|
|
||||||
</MudDialog>
|
|
||||||
@code {
|
|
||||||
[CascadingParameter]
|
|
||||||
MudDialogInstance MudDialog { get; set; } = null!;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public SongPlayData Data { get; set; } = null!;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
async Task Submit()
|
|
||||||
{
|
|
||||||
var postData = new MusicFavoriteData
|
|
||||||
{
|
|
||||||
CardId = CardId,
|
|
||||||
IsFavorite = !Data.IsFavorite,
|
|
||||||
MusicId = Data.MusicId
|
|
||||||
};
|
|
||||||
Logger.LogInformation("Data is {cardId}, {musicId}", CardId, Data.MusicId);
|
|
||||||
var response = await Client.PostAsJsonAsync("api/UserDetail/SetMusicFavorite", postData);
|
|
||||||
var result = await response.Content.ReadFromJsonAsync<bool>();
|
|
||||||
Logger.LogInformation("Favorite result is {result}", result);
|
|
||||||
MudDialog.Close(DialogResult.Ok(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cancel() => MudDialog.Cancel();
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
@page "/"
|
|
||||||
|
|
||||||
<PageTitle>Index</PageTitle>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h3" GutterBottom="true">Admin page for GC local server</MudText>
|
|
||||||
<MudText Class="mb-8">Powered by MudBlazor</MudText>
|
|
@ -1,305 +0,0 @@
|
|||||||
@page "/user/{CardId:long}"
|
|
||||||
@using SharedProject.models
|
|
||||||
@using SharedProject.enums
|
|
||||||
|
|
||||||
<PageTitle>User</PageTitle>
|
|
||||||
<MudContainer>
|
|
||||||
@if (pageLoading)
|
|
||||||
{
|
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (userDetail is null)
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h3">No Data</MudText>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudExpansionPanels>
|
|
||||||
<MudExpansionPanel Text="Total Result">
|
|
||||||
<MudList>
|
|
||||||
<MudListSubheader>Player Name: @userDetail.PlayerName</MudListSubheader>
|
|
||||||
<MudListItem>Total Score: @userDetail.TotalScore</MudListItem>
|
|
||||||
<MudListItem>Average Score: @userDetail.AverageScore</MudListItem>
|
|
||||||
<MudListItem>Played Song Count: @userDetail.PlayedSongCount / @userDetail.TotalSongCount</MudListItem>
|
|
||||||
<MudListItem>Cleared Stage Count: @userDetail.ClearedStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>No Miss Stage Count: @userDetail.NoMissStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>Full Chain Stage Count: @userDetail.FullChainStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>Perfect Stage Count: @userDetail.PerfectStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>S and Above Stage Count: @userDetail.SAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>S+ and Above Stage Count: @userDetail.SPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
<MudListItem>S++ and Above Stage Count: @userDetail.SPlusPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
|
||||||
</MudList>
|
|
||||||
</MudExpansionPanel>
|
|
||||||
<MudExpansionPanel Text="PlayOptions">
|
|
||||||
<MudStack>
|
|
||||||
<MudSelect @bind-Value="@playOption.FastSlowIndicator"
|
|
||||||
Label="FAST/SLOW show setting">
|
|
||||||
@foreach (var item in Enum.GetValues<PlayOptions.FastSlowIndicator>())
|
|
||||||
{
|
|
||||||
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
|
||||||
}
|
|
||||||
</MudSelect>
|
|
||||||
|
|
||||||
<MudSelect @bind-Value="@playOption.FeverTrance"
|
|
||||||
Label="FEVER/TRANCE show setting">
|
|
||||||
@foreach (var item in Enum.GetValues<PlayOptions.FeverTranceShow>())
|
|
||||||
{
|
|
||||||
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
|
||||||
}
|
|
||||||
</MudSelect>
|
|
||||||
|
|
||||||
<MudStack Row="true">
|
|
||||||
<MudField Label="Navigator setting">
|
|
||||||
@NavigatorIdToString(playOption.NavigatorId)
|
|
||||||
</MudField>
|
|
||||||
<MudButton Variant="Variant.Text"
|
|
||||||
|
|
||||||
OnClick="OnChangeNavigatorButtonClick">
|
|
||||||
Change Navigator
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
|
|
||||||
<MudStack Row="true">
|
|
||||||
<MudField Label="Avatar setting">
|
|
||||||
@AvatarIdToString(playOption.AvatarId)
|
|
||||||
</MudField>
|
|
||||||
<MudButton Variant="Variant.Text"
|
|
||||||
OnClick="OnChangeAvatarButtonClick">
|
|
||||||
Change Avatar
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
|
|
||||||
<MudStack Row="true">
|
|
||||||
<MudField Label="Title setting">
|
|
||||||
@TitleIdToString(playOption.TitleId)
|
|
||||||
</MudField>
|
|
||||||
<MudButton Variant="Variant.Text"
|
|
||||||
OnClick="OnChangeTitleButtonClick">
|
|
||||||
Change Title
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
|
|
||||||
<MudOverlay @bind-Visible="IsNavigatorOverlayVisible"
|
|
||||||
DarkBackground="true">
|
|
||||||
<MudPaper>
|
|
||||||
<MudContainer MaxWidth="MaxWidth.Large">
|
|
||||||
<MudStack>
|
|
||||||
<MudDataGrid T="Navigator"
|
|
||||||
MultiSelection="false" @bind-SelectedItem="SelectedNavigator"
|
|
||||||
FixedHeader="true" FixedFooter="true" Height="70vh"
|
|
||||||
Items="navigatorDictionary.Values" ReadOnly="true" Hover="true"
|
|
||||||
Sortable="true" Filterable="true" Hideable="true">
|
|
||||||
<ToolBarContent>
|
|
||||||
<MudText Typo="Typo.h6">Navigators</MudText>
|
|
||||||
<MudSpacer/>
|
|
||||||
</ToolBarContent>
|
|
||||||
<Columns>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.Id)"/>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.IdString)"/>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.NameEntryString)" Title="Navigator Name"
|
|
||||||
SortBy="NameEntrySortByFunc"/>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.ToolTipJp)" Title="Navigator Description (Japanese)"/>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.ToolTipEn)" Title="Navigator Description (English)"/>
|
|
||||||
<Column T="Navigator" Field="@nameof(Navigator.Genre)" Title="Navigator Type"/>
|
|
||||||
</Columns>
|
|
||||||
<PagerContent>
|
|
||||||
<MudDataGridPager T="Navigator"/>
|
|
||||||
</PagerContent>
|
|
||||||
</MudDataGrid>
|
|
||||||
<MudText Align="Align.Left">
|
|
||||||
Currently selected navigator:<br>
|
|
||||||
@SelectedNavigator
|
|
||||||
</MudText>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
|
||||||
OnClick="OnNavigatorOverlayClosed">
|
|
||||||
Close
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</MudContainer>
|
|
||||||
</MudPaper>
|
|
||||||
</MudOverlay>
|
|
||||||
|
|
||||||
<MudOverlay @bind-Visible="IsAvatarOverlayVisible"
|
|
||||||
DarkBackground="true">
|
|
||||||
<MudPaper>
|
|
||||||
<MudContainer MaxWidth="MaxWidth.Large">
|
|
||||||
<MudStack>
|
|
||||||
<MudDataGrid T="Avatar"
|
|
||||||
MultiSelection="false" @bind-SelectedItem="SelectedAvatar"
|
|
||||||
FixedHeader="true" FixedFooter="true" Height="70vh"
|
|
||||||
Items="avatarDictionary.Values" ReadOnly="true" Hover="true"
|
|
||||||
Sortable="true" Filterable="true" Hideable="true">
|
|
||||||
<ToolBarContent>
|
|
||||||
<MudText Typo="Typo.h6">Avatars</MudText>
|
|
||||||
<MudSpacer/>
|
|
||||||
</ToolBarContent>
|
|
||||||
<Columns>
|
|
||||||
<Column T="Avatar" Field="@nameof(Avatar.Id)"/>
|
|
||||||
<Column T="Avatar" Field="@nameof(Avatar.IdString)"/>
|
|
||||||
<Column T="Avatar" Field="@nameof(Avatar.FullName)" Title="Avatar Name"/>
|
|
||||||
<Column T="Avatar" Field="@nameof(Avatar.AcquireMethodJp)" Title="Acquire Method (Japanese)"/>
|
|
||||||
<Column T="Avatar" Field="@nameof(Avatar.AcquireMethodEn)" Title="Acquire Method (English)"/>
|
|
||||||
</Columns>
|
|
||||||
<PagerContent>
|
|
||||||
<MudDataGridPager T="Avatar"/>
|
|
||||||
</PagerContent>
|
|
||||||
</MudDataGrid>
|
|
||||||
<MudText Align="Align.Left">
|
|
||||||
Currently selected avatar:<br>
|
|
||||||
@SelectedAvatar
|
|
||||||
</MudText>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
|
||||||
OnClick="OnAvatarOverlayClosed">
|
|
||||||
Close
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</MudContainer>
|
|
||||||
</MudPaper>
|
|
||||||
</MudOverlay>
|
|
||||||
|
|
||||||
<MudOverlay @bind-Visible="IsTitleOverlayVisible"
|
|
||||||
DarkBackground="true">
|
|
||||||
<MudPaper>
|
|
||||||
<MudContainer MaxWidth="MaxWidth.Large">
|
|
||||||
<MudStack>
|
|
||||||
<MudDataGrid T="Title"
|
|
||||||
MultiSelection="false" @bind-SelectedItem="SelectedTitle"
|
|
||||||
FixedHeader="true" FixedFooter="true" Height="70vh"
|
|
||||||
Items="titleDictionary.Values" ReadOnly="true" Hover="true"
|
|
||||||
Sortable="true" Filterable="true" Hideable="true">
|
|
||||||
<ToolBarContent>
|
|
||||||
<MudText Typo="Typo.h6">Titles</MudText>
|
|
||||||
<MudSpacer/>
|
|
||||||
</ToolBarContent>
|
|
||||||
<Columns>
|
|
||||||
<Column T="Title" Field="@nameof(Title.Id)"/>
|
|
||||||
<Column T="Title" Field="@nameof(Title.IdString)"/>
|
|
||||||
<Column T="Title" Field="@nameof(Title.NameJp)" Title="Title Name"/>
|
|
||||||
<Column T="Title" Field="@nameof(Title.UnlockRequirementJp)" Title="Unlock Requirement (Japanese)"/>
|
|
||||||
<Column T="Title" Field="@nameof(Title.UnlockRequirementEng)" Title="Unlock Requirement (English)"/>
|
|
||||||
<Column T="Title" Field="@nameof(Title.Type)" Title="Title Type"/>
|
|
||||||
</Columns>
|
|
||||||
<PagerContent>
|
|
||||||
<MudDataGridPager T="Title"/>
|
|
||||||
</PagerContent>
|
|
||||||
</MudDataGrid>
|
|
||||||
<MudText Align="Align.Left">
|
|
||||||
Currently selected title:<br>
|
|
||||||
@SelectedTitle
|
|
||||||
</MudText>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
|
||||||
OnClick="OnTitleOverlayClosed">
|
|
||||||
Close
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</MudContainer>
|
|
||||||
</MudPaper>
|
|
||||||
</MudOverlay>
|
|
||||||
|
|
||||||
<MudButton Disabled="@isSavingOptions"
|
|
||||||
OnClick="SaveOptions"
|
|
||||||
Variant="Variant.Filled"
|
|
||||||
Color="Color.Info">
|
|
||||||
@if (isSavingOptions)
|
|
||||||
{
|
|
||||||
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
|
|
||||||
<MudText Class="ms-2">Saving...</MudText>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudIcon Icon="@Icons.Filled.Save"></MudIcon>
|
|
||||||
<MudText>Save</MudText>
|
|
||||||
}
|
|
||||||
</MudButton>
|
|
||||||
</MudStack>
|
|
||||||
</MudExpansionPanel>
|
|
||||||
<MudExpansionPanel Text="SongPlayData">
|
|
||||||
<MudDataGrid T="SongPlayData"
|
|
||||||
Items="@songPlayDataList"
|
|
||||||
Sortable="true"
|
|
||||||
Filterable="true">
|
|
||||||
<ToolBarContent>
|
|
||||||
<MudText Typo="Typo.h6">Played Songs</MudText>
|
|
||||||
</ToolBarContent>
|
|
||||||
<Columns>
|
|
||||||
<Column T="SongPlayData" Sortable="false" Filterable="false">
|
|
||||||
<CellTemplate>
|
|
||||||
<MudButton Variant="Variant.Outlined" Size="Size.Small"
|
|
||||||
OnClick="@(() => OnShowDetailsClick(context.Item))">
|
|
||||||
@(context.Item.ShowDetails ? "Hide" : "Show") Song Play Details
|
|
||||||
</MudButton>
|
|
||||||
</CellTemplate>
|
|
||||||
</Column>
|
|
||||||
<Column T="SongPlayData" Field="@nameof(SongPlayData.IsFavorite)" Sortable="false" Title="Favorite">
|
|
||||||
<CellTemplate>
|
|
||||||
<MudToggleIconButton Toggled="@context.Item.IsFavorite"
|
|
||||||
ToggledChanged="@(() => OnFavoriteToggled(context.Item))"
|
|
||||||
Icon="@Icons.Material.Filled.FavoriteBorder"
|
|
||||||
Color="@Color.Secondary"
|
|
||||||
Title="Add to favorite"
|
|
||||||
ToggledIcon="@Icons.Material.Filled.Favorite"
|
|
||||||
ToggledColor="@Color.Secondary"
|
|
||||||
ToggledTitle="Remove from favorite"/>
|
|
||||||
</CellTemplate>
|
|
||||||
</Column>
|
|
||||||
<Column T="SongPlayData" Field="@nameof(SongPlayData.Title)" Title="Song Title"/>
|
|
||||||
<Column T="SongPlayData" Field="@nameof(SongPlayData.Artist)" Title="Artist"/>
|
|
||||||
<Column T="SongPlayData" Field="@nameof(SongPlayData.TotalPlayCount)" Title="Total Play Count"/>
|
|
||||||
<Column T="SongPlayData" Field="@nameof(SongPlayData.LastPlayTime)" Title="Last Play Time"/>
|
|
||||||
</Columns>
|
|
||||||
<ChildRowContent>
|
|
||||||
@if (context.Item.ShowDetails)
|
|
||||||
{
|
|
||||||
<MudTr>
|
|
||||||
<td colspan="5">
|
|
||||||
<MudCard Elevation="0">
|
|
||||||
<MudCardHeader>
|
|
||||||
<CardHeaderContent>
|
|
||||||
<MudText Typo="Typo.body1">Song Play Details</MudText>
|
|
||||||
</CardHeaderContent>
|
|
||||||
</MudCardHeader>
|
|
||||||
<MudCardContent Class="pa-0">
|
|
||||||
<MudTable Items="@context.Item.SongPlaySubDataList"
|
|
||||||
Context="SongPlayDetail"
|
|
||||||
Elevation="0"
|
|
||||||
Filter="data => data.ClearState != ClearState.NotPlayed">
|
|
||||||
<HeaderContent>
|
|
||||||
<MudTh>Difficulty</MudTh>
|
|
||||||
<MudTh>Clear State</MudTh>
|
|
||||||
<MudTh>Play Count</MudTh>
|
|
||||||
<MudTh>Rating</MudTh>
|
|
||||||
<MudTh>Score</MudTh>
|
|
||||||
<MudTh>Max Chain</MudTh>
|
|
||||||
<MudTh>Last Play Time</MudTh>
|
|
||||||
</HeaderContent>
|
|
||||||
<RowTemplate>
|
|
||||||
<MudTd DataLabel="Difficulty">@SongPlayDetail.Difficulty</MudTd>
|
|
||||||
<MudTd DataLabel="Clear State">
|
|
||||||
@(SongPlayDetail.Score != 1000000 ? SongPlayDetail.ClearState : ClearState.Perfect)
|
|
||||||
</MudTd>
|
|
||||||
<MudTd DataLabel="Play Count">@SongPlayDetail.PlayCount</MudTd>
|
|
||||||
<MudTd DataLabel="Rating">@CalculateRating(SongPlayDetail.Score)</MudTd>
|
|
||||||
<MudTd DataLabel="Score">@SongPlayDetail.Score</MudTd>
|
|
||||||
<MudTd DataLabel="Max Chain">@SongPlayDetail.MaxChain</MudTd>
|
|
||||||
<MudTd DataLabel="Last Play Time">@SongPlayDetail.LastPlayTime</MudTd>
|
|
||||||
</RowTemplate>
|
|
||||||
</MudTable>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
</td>
|
|
||||||
</MudTr>
|
|
||||||
}
|
|
||||||
</ChildRowContent>
|
|
||||||
<PagerContent>
|
|
||||||
<MudDataGridPager T="SongPlayData"/>
|
|
||||||
</PagerContent>
|
|
||||||
</MudDataGrid>
|
|
||||||
</MudExpansionPanel>
|
|
||||||
</MudExpansionPanels>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</MudContainer>
|
|
@ -1,228 +0,0 @@
|
|||||||
using System.Net.Http.Json;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using MudBlazor;
|
|
||||||
using ProtoBuf;
|
|
||||||
using SharedProject.common;
|
|
||||||
using SharedProject.models;
|
|
||||||
|
|
||||||
namespace MudAdmin.Pages;
|
|
||||||
|
|
||||||
public partial class User
|
|
||||||
{
|
|
||||||
[Inject]
|
|
||||||
public HttpClient Client { get; set; } = null!;
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
public IDialogService DialogService { get; set; } = null!;
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
public ILogger<User> Logger { get; set; } = null!;
|
|
||||||
|
|
||||||
private Dictionary<long, Avatar> avatarDictionary = new();
|
|
||||||
|
|
||||||
private bool isSavingOptions;
|
|
||||||
|
|
||||||
private Dictionary<long, Navigator> navigatorDictionary = new();
|
|
||||||
|
|
||||||
private bool pageLoading = true;
|
|
||||||
|
|
||||||
private PlayOption playOption = new();
|
|
||||||
|
|
||||||
private List<SongPlayData> songPlayDataList = new();
|
|
||||||
|
|
||||||
private Dictionary<long, Title> titleDictionary = new();
|
|
||||||
|
|
||||||
private UserDetail? userDetail;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
private bool IsTitleOverlayVisible { get; set; }
|
|
||||||
|
|
||||||
private bool IsNavigatorOverlayVisible { get; set; }
|
|
||||||
|
|
||||||
private bool IsAvatarOverlayVisible { get; set; }
|
|
||||||
|
|
||||||
private Title? SelectedTitle { get; set; }
|
|
||||||
|
|
||||||
private Avatar? SelectedAvatar { get; set; }
|
|
||||||
|
|
||||||
private Navigator? SelectedNavigator { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await base.OnInitializedAsync();
|
|
||||||
userDetail = await Client.GetFromJsonAsync<UserDetail>($"api/UserDetail/{CardId}");
|
|
||||||
if (userDetail is null)
|
|
||||||
{
|
|
||||||
pageLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
songPlayDataList = userDetail.SongPlayDataList ?? new List<SongPlayData>();
|
|
||||||
playOption = userDetail.PlayOption;
|
|
||||||
|
|
||||||
var navigatorStream = await Client.GetStreamAsync(SharedConstants.NAVIGATOR_DAT_URI);
|
|
||||||
var navigators = Serializer.Deserialize<Navigators>(navigatorStream);
|
|
||||||
if (navigators?.NavigatorList != null)
|
|
||||||
{
|
|
||||||
navigatorDictionary = navigators.NavigatorList.ToDictionary(navigator => (long)navigator.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
var avatarStream = await Client.GetStreamAsync(SharedConstants.AVATAR_DAT_URI);
|
|
||||||
var avatars = Serializer.Deserialize<List<Avatar>>(avatarStream);
|
|
||||||
if (avatars != null)
|
|
||||||
{
|
|
||||||
avatarDictionary = avatars.ToDictionary(avatar => (long)avatar.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
var titleStream = await Client.GetStreamAsync(SharedConstants.TITLE_DAT_URI);
|
|
||||||
var titles = Serializer.Deserialize<List<Title>>(titleStream);
|
|
||||||
if (titles != null)
|
|
||||||
{
|
|
||||||
titleDictionary = titles.ToDictionary(title => (long)title.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSelected();
|
|
||||||
pageLoading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetSelected()
|
|
||||||
{
|
|
||||||
SelectedTitle = titleDictionary.GetValueOrDefault(playOption.TitleId);
|
|
||||||
SelectedAvatar = avatarDictionary.GetValueOrDefault(playOption.AvatarId);
|
|
||||||
SelectedNavigator = navigatorDictionary.GetValueOrDefault(playOption.NavigatorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnShowDetailsClick(SongPlayData data)
|
|
||||||
{
|
|
||||||
data.ShowDetails = !data.ShowDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveOptions()
|
|
||||||
{
|
|
||||||
isSavingOptions = true;
|
|
||||||
var postData = new PlayOption
|
|
||||||
{
|
|
||||||
CardId = CardId,
|
|
||||||
FastSlowIndicator = playOption.FastSlowIndicator,
|
|
||||||
FeverTrance = playOption.FeverTrance,
|
|
||||||
AvatarId = playOption.AvatarId,
|
|
||||||
NavigatorId = playOption.NavigatorId,
|
|
||||||
TitleId = playOption.TitleId
|
|
||||||
};
|
|
||||||
var result = await Client.PostAsJsonAsync("api/UserDetail/SetPlayOption", postData);
|
|
||||||
isSavingOptions = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CalculateRating(int score)
|
|
||||||
{
|
|
||||||
var grade = SharedConstants.Grades.Where(g => g.Score <= score).Select(g => g.Grade).Last();
|
|
||||||
return grade;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnFavoriteToggled(SongPlayData data)
|
|
||||||
{
|
|
||||||
var options = new DialogOptions
|
|
||||||
{
|
|
||||||
CloseOnEscapeKey = false,
|
|
||||||
DisableBackdropClick = true,
|
|
||||||
FullWidth = true
|
|
||||||
};
|
|
||||||
var parameters = new DialogParameters();
|
|
||||||
parameters.Add("Data", data);
|
|
||||||
parameters.Add("CardId", CardId);
|
|
||||||
var dialog = DialogService.Show<FavoriteDialog>("Favorite", parameters, options);
|
|
||||||
var result = await dialog.Result;
|
|
||||||
|
|
||||||
if (result.Cancelled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((bool)result.Data)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("Changed!");
|
|
||||||
data.IsFavorite = !data.IsFavorite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<IEnumerable<long>> SearchAvatar(string value)
|
|
||||||
{
|
|
||||||
var result = string.IsNullOrEmpty(value) ? avatarDictionary.Keys : avatarDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
|
||||||
return Task.FromResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<IEnumerable<long>> SearchTitle(string value)
|
|
||||||
{
|
|
||||||
var result = string.IsNullOrEmpty(value) ? titleDictionary.Keys : titleDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
|
||||||
return Task.FromResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<IEnumerable<long>> SearchNavigator(string value)
|
|
||||||
{
|
|
||||||
var result = string.IsNullOrEmpty(value) ? navigatorDictionary.Keys : navigatorDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
|
||||||
return Task.FromResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string AvatarIdToString(long id)
|
|
||||||
{
|
|
||||||
return avatarDictionary.ContainsKey(id) ? avatarDictionary[id].ToString() : $"No Data for {id}!";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string NavigatorIdToString(long id)
|
|
||||||
{
|
|
||||||
return navigatorDictionary.ContainsKey(id) ? navigatorDictionary[id].ToString() : $"No Data for {id}!";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string TitleIdToString(long id)
|
|
||||||
{
|
|
||||||
return titleDictionary.ContainsKey(id) ? titleDictionary[id].ToString() : $"No Data for {id}!";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnChangeTitleButtonClick()
|
|
||||||
{
|
|
||||||
IsTitleOverlayVisible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnChangeNavigatorButtonClick()
|
|
||||||
{
|
|
||||||
IsNavigatorOverlayVisible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnChangeAvatarButtonClick()
|
|
||||||
{
|
|
||||||
IsAvatarOverlayVisible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTitleOverlayClosed()
|
|
||||||
{
|
|
||||||
IsTitleOverlayVisible = false;
|
|
||||||
if (SelectedTitle != null)
|
|
||||||
{
|
|
||||||
playOption.TitleId = SelectedTitle.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnNavigatorOverlayClosed()
|
|
||||||
{
|
|
||||||
IsNavigatorOverlayVisible = false;
|
|
||||||
if (SelectedNavigator != null)
|
|
||||||
{
|
|
||||||
playOption.NavigatorId = SelectedNavigator.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAvatarOverlayClosed()
|
|
||||||
{
|
|
||||||
IsAvatarOverlayVisible = false;
|
|
||||||
if (SelectedAvatar != null)
|
|
||||||
{
|
|
||||||
playOption.AvatarId = SelectedAvatar.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static object NameEntrySortByFunc(Navigator navigator)
|
|
||||||
{
|
|
||||||
return navigator.NameEntry1?.ToString().ToLowerInvariant() ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
@page "/users"
|
|
||||||
@using models = SharedProject.models
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
@inject HttpClient Client
|
|
||||||
@inject IDialogService DialogService
|
|
||||||
@inject ILogger<Users> Logger
|
|
||||||
|
|
||||||
<PageTitle>Users</PageTitle>
|
|
||||||
|
|
||||||
<MudContainer>
|
|
||||||
@if (users is null)
|
|
||||||
{
|
|
||||||
<MudGrid>
|
|
||||||
@for (var i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
<MudItem>
|
|
||||||
<MudCard>
|
|
||||||
<MudCardHeader>
|
|
||||||
<CardHeaderContent>
|
|
||||||
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Height="32px"/>
|
|
||||||
</CardHeaderContent>
|
|
||||||
</MudCardHeader>
|
|
||||||
<MudCardContent>
|
|
||||||
<MudSkeleton Width="80px" Height="32px"/>
|
|
||||||
<MudSkeleton Width="147px" Height="28px"/>
|
|
||||||
</MudCardContent>
|
|
||||||
<MudCardActions>
|
|
||||||
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Width="99px" Height="25px" Class="ml-2"/>
|
|
||||||
</MudCardActions>
|
|
||||||
</MudCard>
|
|
||||||
</MudItem>
|
|
||||||
}
|
|
||||||
</MudGrid>
|
|
||||||
}
|
|
||||||
else if (users.Count != 0)
|
|
||||||
{
|
|
||||||
<MudGrid>
|
|
||||||
@foreach (var user in users)
|
|
||||||
{
|
|
||||||
<MudItem>
|
|
||||||
<MudCard>
|
|
||||||
<MudCardHeader>
|
|
||||||
<CardHeaderContent>
|
|
||||||
<MudText Typo="Typo.h5">@user.PlayerName</MudText>
|
|
||||||
</CardHeaderContent>
|
|
||||||
<CardHeaderActions>
|
|
||||||
<MudIconButton Icon="@Icons.Filled.Edit" Color="Color.Default"
|
|
||||||
OnClick="() => OnEditPlayerNameClicked(user)"/>
|
|
||||||
</CardHeaderActions>
|
|
||||||
</MudCardHeader>
|
|
||||||
<MudCardContent>
|
|
||||||
<MudText Typo="Typo.h6">Card ID</MudText>
|
|
||||||
<MudText>@user.CardId</MudText>
|
|
||||||
</MudCardContent>
|
|
||||||
<MudCardActions>
|
|
||||||
<MudButton Variant="Variant.Text" Color="Color.Primary" OnClick="() => OnCheckDetailClick(user)">Check detail</MudButton>
|
|
||||||
</MudCardActions>
|
|
||||||
</MudCard>
|
|
||||||
</MudItem>
|
|
||||||
}
|
|
||||||
</MudGrid>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h3">No Data</MudText>
|
|
||||||
}
|
|
||||||
</MudContainer>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<models.User>? users;
|
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await base.OnInitializedAsync();
|
|
||||||
users = await Client.GetFromJsonAsync<List<models.User>>("api/Users") ?? new List<models.User>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCheckDetailClick(models.User user)
|
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo($"user/{user.CardId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnEditPlayerNameClicked(models.User user)
|
|
||||||
{
|
|
||||||
var options = new DialogOptions
|
|
||||||
{
|
|
||||||
CloseOnEscapeKey = false,
|
|
||||||
DisableBackdropClick = true,
|
|
||||||
FullWidth = true
|
|
||||||
};
|
|
||||||
var parameters = new DialogParameters();
|
|
||||||
parameters.Add("Data", user);
|
|
||||||
var dialog = DialogService.Show<ChangePlayerNameDialog>("Favorite", parameters, options);
|
|
||||||
var result = await dialog.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|
||||||
using MudAdmin;
|
|
||||||
using MudBlazor.Services;
|
|
||||||
|
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
|
||||||
builder.RootComponents.Add<App>("#app");
|
|
||||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
|
||||||
|
|
||||||
builder.Services.AddScoped(sp => new HttpClient
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(builder.Configuration.GetValue<string>("BaseUrl"))
|
|
||||||
});
|
|
||||||
builder.Services.AddMudServices();
|
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:65283",
|
|
||||||
"sslPort": 44398
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Mudblazor.Template": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": "true",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
@inherits LayoutComponentBase
|
|
||||||
|
|
||||||
<MudThemeProvider @ref="@MudThemeProvider" @bind-IsDarkMode="@IsDarkMode"/>
|
|
||||||
<MudDialogProvider/>
|
|
||||||
<MudSnackbarProvider/>
|
|
||||||
|
|
||||||
<MudLayout>
|
|
||||||
<MudAppBar Elevation="0" Dense="true">
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start"
|
|
||||||
OnClick="@((e) => DrawerToggle())"/>
|
|
||||||
<MudSpacer/>
|
|
||||||
<MudTooltip Duration="1000" Text="Powered by MudBlazor">
|
|
||||||
<MudIconButton Icon="@Icons.Custom.Brands.MudBlazor" Color="Color.Inherit"
|
|
||||||
Link="https://mudblazor.com/" Target="_blank"/>
|
|
||||||
</MudTooltip>
|
|
||||||
<MudTooltip Duration="1000" Text="Github Repository">
|
|
||||||
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Inherit"
|
|
||||||
Link="https://github.com/asesidaa/GC-local-server-rewrite/" Target="_blank"/>
|
|
||||||
</MudTooltip>
|
|
||||||
<MudTooltip Duration="1000" Text="@(IsDarkMode ? "Switch to Light Mode" : "Switch to DarkMode")">
|
|
||||||
<MudToggleIconButton @bind-Toggled="@IsDarkMode"
|
|
||||||
Icon="@Icons.Material.Outlined.DarkMode" Color="Color.Inherit"
|
|
||||||
ToggledIcon="@Icons.Material.Filled.LightMode"/>
|
|
||||||
</MudTooltip>
|
|
||||||
</MudAppBar>
|
|
||||||
<MudDrawer @bind-Open="drawerOpen" Elevation="1">
|
|
||||||
<MudDrawerHeader>
|
|
||||||
<MudText Typo="Typo.h6">GC local server Admin</MudText>
|
|
||||||
</MudDrawerHeader>
|
|
||||||
<NavMenu/>
|
|
||||||
</MudDrawer>
|
|
||||||
<MudMainContent>
|
|
||||||
<MudContainer MaxWidth="MaxWidth.Large" Class="my-16 pt-16">
|
|
||||||
@Body
|
|
||||||
</MudContainer>
|
|
||||||
</MudMainContent>
|
|
||||||
</MudLayout>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
bool drawerOpen = true;
|
|
||||||
|
|
||||||
public bool IsDarkMode { get; set; }
|
|
||||||
|
|
||||||
public MudThemeProvider MudThemeProvider { get; set; } = null!;
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (firstRender)
|
|
||||||
{
|
|
||||||
IsDarkMode = await MudThemeProvider.GetSystemPreference();
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawerToggle()
|
|
||||||
{
|
|
||||||
drawerOpen = !drawerOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<MudNavMenu>
|
|
||||||
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
|
|
||||||
<MudNavLink Href="Cards" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Cards</MudNavLink>
|
|
||||||
</MudNavMenu>
|
|
@ -1,11 +0,0 @@
|
|||||||
@using System.Net.Http
|
|
||||||
@using System.Net.Http.Json
|
|
||||||
@using Microsoft.AspNetCore.Components.Forms
|
|
||||||
@using Microsoft.AspNetCore.Components.Routing
|
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
|
||||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
|
||||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
|
||||||
@using Microsoft.JSInterop
|
|
||||||
@using MudBlazor
|
|
||||||
@using MudAdmin
|
|
||||||
@using MudAdmin.Shared
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Debug",
|
|
||||||
"System": "Information",
|
|
||||||
"Microsoft": "Information"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"BaseUrl": "https://127.0.0.1"
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
||||||
<title>MudAdmin</title>
|
|
||||||
<base href="/" />
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
|
||||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app">Loading...</div>
|
|
||||||
|
|
||||||
<div id="blazor-error-ui">
|
|
||||||
An unhandled error has occurred.
|
|
||||||
<a href="" class="reload">Reload</a>
|
|
||||||
<a class="dismiss">🗙</a>
|
|
||||||
</div>
|
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
|
||||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 818 B |
@ -1,14 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<RootNamespace>SharedProject</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="protobuf-net" Version="3.1.22" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace SharedProject.common;
|
|
||||||
|
|
||||||
public record ScoreGradeMap(int Score, string Grade)
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{{ Score = {Score}, Grade = {Grade} }}";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
namespace SharedProject.common;
|
|
||||||
|
|
||||||
public static class SharedConstants
|
|
||||||
{
|
|
||||||
public const int DIFFICULTY_COUNT = 4;
|
|
||||||
|
|
||||||
public const int E_SCORE_THRESHOLD = 0;
|
|
||||||
|
|
||||||
public const int D_SCORE_THRESHOLD = 300000;
|
|
||||||
|
|
||||||
public const int C_SCORE_THRESHOLD = 500000;
|
|
||||||
|
|
||||||
public const int B_SCORE_THRESHOLD = 700000;
|
|
||||||
|
|
||||||
public const int A_SCORE_THRESHOLD = 800000;
|
|
||||||
|
|
||||||
public const int S_SCORE_THRESHOLD = 900000;
|
|
||||||
|
|
||||||
public const int S_PLUS_SCORE_THRESHOLD = 950000;
|
|
||||||
|
|
||||||
public const int S_PLUS_PLUS_SCORE_THRESHOLD = 990000;
|
|
||||||
|
|
||||||
public const int MAX_PLAYER_NAME_LENGTH = 8;
|
|
||||||
|
|
||||||
public const string NAVIGATOR_DAT_URI = "data/navigator.dat";
|
|
||||||
|
|
||||||
public const string AVATAR_DAT_URI = "data/avatar.dat";
|
|
||||||
|
|
||||||
public const string TITLE_DAT_URI = "data/title.dat";
|
|
||||||
|
|
||||||
public static readonly ScoreGradeMap[] Grades =
|
|
||||||
{
|
|
||||||
new(E_SCORE_THRESHOLD, "E"),
|
|
||||||
new(D_SCORE_THRESHOLD, "D"),
|
|
||||||
new(C_SCORE_THRESHOLD, "C"),
|
|
||||||
new(B_SCORE_THRESHOLD, "B"),
|
|
||||||
new(A_SCORE_THRESHOLD, "A"),
|
|
||||||
new(S_SCORE_THRESHOLD, "S"),
|
|
||||||
new(S_PLUS_SCORE_THRESHOLD, "S+"),
|
|
||||||
new(S_PLUS_PLUS_SCORE_THRESHOLD, "S++")
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
public enum ClearState
|
|
||||||
{
|
|
||||||
NotPlayed = 0,
|
|
||||||
Failed,
|
|
||||||
Clear,
|
|
||||||
NoMiss,
|
|
||||||
FullChain,
|
|
||||||
Perfect
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
public enum Difficulty
|
|
||||||
{
|
|
||||||
Simple = 0,
|
|
||||||
Normal = 1,
|
|
||||||
Hard = 2,
|
|
||||||
Extra = 3
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
public static string GetHelpText(this PlayOptions.FastSlowIndicator indicator)
|
|
||||||
{
|
|
||||||
return indicator switch
|
|
||||||
{
|
|
||||||
PlayOptions.FastSlowIndicator.NotUsed => "Do not show FAST/SLOW indicator",
|
|
||||||
PlayOptions.FastSlowIndicator.NearAvatar => "Show FAST/SLOW indicator near avatar",
|
|
||||||
PlayOptions.FastSlowIndicator.NearJudgement => "Show FAST/SLOW indicator near judgement text",
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(indicator), indicator, null)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetHelpText(this PlayOptions.FeverTranceShow show)
|
|
||||||
{
|
|
||||||
return show switch
|
|
||||||
{
|
|
||||||
PlayOptions.FeverTranceShow.NotUsed => "Do not show FEVER/TRANCE",
|
|
||||||
PlayOptions.FeverTranceShow.Show => "Show FEVER/TRANCE",
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(show), show, null)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using ProtoBuf;
|
|
||||||
|
|
||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
[ProtoContract]
|
|
||||||
public enum NavigatorDefaultAvailability
|
|
||||||
{
|
|
||||||
NotAvailable = 0,
|
|
||||||
Available = 1,
|
|
||||||
AvailableWithVoice = 2,
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using ProtoBuf;
|
|
||||||
|
|
||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
[ProtoContract]
|
|
||||||
public enum NavigatorGenre
|
|
||||||
{
|
|
||||||
Default = 1,
|
|
||||||
Original = 2,
|
|
||||||
Game = 3,
|
|
||||||
Touhou = 4,
|
|
||||||
Vocaloid = 5,
|
|
||||||
Collab = 6,
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
public static class PlayOptions
|
|
||||||
{
|
|
||||||
public enum FastSlowIndicator
|
|
||||||
{
|
|
||||||
NotUsed = 3,
|
|
||||||
NearAvatar = 1,
|
|
||||||
NearJudgement = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum FeverTranceShow
|
|
||||||
{
|
|
||||||
NotUsed = 2,
|
|
||||||
Show = 1
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
using ProtoBuf;
|
|
||||||
|
|
||||||
namespace SharedProject.enums;
|
|
||||||
|
|
||||||
[ProtoContract]
|
|
||||||
public enum TitleUnlockType
|
|
||||||
{
|
|
||||||
Invalid = 0,
|
|
||||||
Default = 1,
|
|
||||||
Clear = 2,
|
|
||||||
NoMiss = 3,
|
|
||||||
FullChain = 4,
|
|
||||||
SRankSimpleStages = 5,
|
|
||||||
SRankNormalStages = 6,
|
|
||||||
SRankHardStages = 7,
|
|
||||||
SRankExtraStages = 8,
|
|
||||||
SRankAllDifficulties = 9,
|
|
||||||
SPlusRankAllDifficulties = 10,
|
|
||||||
SPlusPlusRankAllDifficulties = 11,
|
|
||||||
Event = 12,
|
|
||||||
Prefecture = 13,
|
|
||||||
ChainMilestone = 14,
|
|
||||||
Adlibs = 15,
|
|
||||||
ConsecutiveNoMiss = 16,
|
|
||||||
ClearsUsingItems = 17,
|
|
||||||
Avatars = 18,
|
|
||||||
MultiplayerStarsTotal = 19,
|
|
||||||
SongSet20 = 20,
|
|
||||||
SongSet21 = 21,
|
|
||||||
SongSet22 = 22,
|
|
||||||
SongSet23 = 23,
|
|
||||||
SongSet24 = 24,
|
|
||||||
SongSet25 = 25,
|
|
||||||
SongSet26 = 26,
|
|
||||||
ProfileLevel = 27,
|
|
||||||
Perfect = 28,
|
|
||||||
OnlineMatching = 29,
|
|
||||||
Trophies = 30,
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using ProtoBuf;
|
|
||||||
|
|
||||||
namespace SharedProject.models;
|
|
||||||
|
|
||||||
[ProtoContract]
|
|
||||||
public class Avatar
|
|
||||||
{
|
|
||||||
[ProtoMember(1)]
|
|
||||||
public uint Id { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(2)]
|
|
||||||
public string? IdString { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(3)]
|
|
||||||
public string? FullName { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(4)]
|
|
||||||
public string? Name { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(5)]
|
|
||||||
public string? Variant { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(6)]
|
|
||||||
public string? AcquireMethodJp { get; set; }
|
|
||||||
|
|
||||||
[ProtoMember(7)]
|
|
||||||
public string? AcquireMethodEn { get; set; }
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return $"{Id}: {FullName}, {AcquireMethodEn}";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace SharedProject.models;
|
|
||||||
|
|
||||||
public class MusicFavoriteData
|
|
||||||
{
|
|
||||||
[JsonPropertyName(nameof(CardId))]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName(nameof(MusicId))]
|
|
||||||
public int MusicId { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName(nameof(IsFavorite))]
|
|
||||||
public bool IsFavorite { get; set; }
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user