From ed89de631be2000d6ee387e5289c4ad1214eef23 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Thu, 2 May 2024 15:24:13 -0700 Subject: [PATCH] Update MD2 --- .../CombinedKeyCrudDALCBase - Copy.cs | 23 +- .../{ => Core}/CombinedKeyCrudDALCBase.cs | 31 +- .../{ => Core}/CrudDALCBase.cs | 43 +- .../{ => Core}/DatabaseOptions.cs | 2 +- .../{ => DBContext}/ChurchNetContext.cs | 31 +- .../{ => Interface}/ICrudDAL.cs | 2 +- .../20240502213000_AddMD2MobInfo.Designer.cs | 984 ++++++++++++++++++ .../20240502213000_AddMD2MobInfo.cs | 71 ++ ...02213603_AddMD2MobInfoUpdateId.Designer.cs | 978 +++++++++++++++++ .../20240502213603_AddMD2MobInfoUpdateId.cs | 168 +++ .../ChurchNetContextModelSnapshot.cs | 59 ++ Church.Net.Entity2/Games/MD2/MobInfo.cs | 149 +++ Church.Net.Entity2/Interface/IEntity.cs | 4 + .../.config/dotnet-tools.json | 0 .../App_Data/Files/BigTresureChest-Epic.jpg | Bin 0 -> 33146 bytes .../App_Data/LinePostLog.txt | 0 .../App_Data/LinePostRawLog.txt | 0 .../App_Data/ScaneMeQrCode.png | Bin .../App_Data/arial.ttf | Bin .../Church.Net.WebAPI.csproj | 6 +- .../Controllers/ApiControllerBase.cs | 2 + .../Controllers/BestController.cs | 0 ...ellGroupRoutineEventAttendeesController.cs | 0 .../CellGroupRoutineEventsController.cs | 0 .../Controllers/ContributionController.cs | 0 .../Controllers/FileListController.cs | 42 + .../Controllers/FilesController.cs | 40 + .../Controllers/GameRoomController.cs | 57 + .../Controllers/GameRoomMessageController.cs | 55 + .../Controllers/HappinessCostController.cs | 0 .../HappinessWeekTaskController.cs | 0 .../Controllers/LineMessageController.cs | 2 +- .../LineMessagingAccountController.cs | 0 .../Controllers/LogController.cs | 0 .../Controllers/MD2Controller.cs | 19 + .../Controllers/MemberController.cs | 0 .../Controllers/NewVisitorController.cs | 0 .../Controllers/PasswordLoginController.cs | 2 +- .../Controllers/PastoralDomainController.cs | 0 .../Controllers/PingController.cs | 0 .../Controllers/QRCodeController.cs | 93 ++ .../Controllers/VersionController.cs | 26 + .../Controllers/WeatherForecastController.cs | 0 .../Controllers/WhoIsSpyController.cs | 0 {WebAPI => Church.Net.WebAPI}/Dockerfile | 12 +- Church.Net.WebAPI/GameRoomLogic.cs | 141 +++ .../HandleExceptionFilter.cs | 0 ...sicAuthorizationMiddlewareResultHandler.cs | 0 .../Hubs/AvalonHub.cs | 0 {WebAPI => Church.Net.WebAPI}/Hubs/BaseHub.cs | 0 Church.Net.WebAPI/Hubs/GameRoomHub.cs | 121 +++ .../Hubs/WhoIsSpyHub.cs | 0 .../Logics/Core/CombinedKeyLogicBase.cs | 2 +- .../Logics/Core/LogicBase.cs | 2 +- .../Logics/Core/LogicService.cs | 0 .../Logics/Interface/ICrudLogic.cs | 0 .../Logics/LineMessagingAccountLogic.cs | 2 +- .../Logics/MemberLogic.cs | 2 +- .../Logics/PastoralDomainLogic.cs | 4 +- .../Logics/VideoDownloadLogic.cs | 0 .../Models/IceBreak.cs | 44 +- Church.Net.WebAPI/Models/SigmalRMessage.cs | 72 ++ Church.Net.WebAPI/Program.cs | 151 +++ .../Properties/launchSettings.json | 0 {WebAPI => Church.Net.WebAPI}/ServerUtils.cs | 0 .../AutoReplyCommands/ArArkCellGroupDinner.cs | 0 .../AutoReplyCommands/ArArkCellGroupInfo.cs | 0 .../AutoReplyCommands/ArArkCellGroupPrayer.cs | 0 .../AutoReplyCommands/ArChurchInfo.cs | 0 .../AutoReplyCommands/ArHappinessBEST.cs | 0 .../AutoReplyCommands/ArHappinessGroupTask.cs | 0 .../Services/DbLoggingService.cs | 2 +- .../Services/IdentityService.cs | 0 .../Services/Interfaces/IAutoReplyCommand.cs | 0 .../Services/Interfaces/ILoggingService.cs | 0 .../Services/Interfaces/IScheduledTask.cs | 0 .../Services/LineAutoBotService.cs | 2 +- .../Services/ScheduledTask/MorningPrayer.cs | 0 .../Services/WorkerService.cs | 0 {WebAPI => Church.Net.WebAPI}/Startup.cs | 22 +- .../ViewModel/RegisterViewModel.cs | 0 .../WeatherForecast.cs | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 {WebAPI => Church.Net.WebAPI}/web.config | 0 Church.Net.sln | 2 +- TestProject/DateTimeTest.cs | 2 +- TestProject/FamilyMemberTest.cs | 2 +- TestProject/LineMessageTest.cs | 2 +- TestProject/TestBase.cs | 5 +- TestProject/TestProject.csproj | 2 +- WebAPI/GameRoomLogic.cs | 35 - WebAPI/Program.cs | 26 - 93 files changed, 3392 insertions(+), 152 deletions(-) rename Church.Net.DAL.EFCoreDBF/{ => Core}/CombinedKeyCrudDALCBase - Copy.cs (91%) rename Church.Net.DAL.EFCoreDBF/{ => Core}/CombinedKeyCrudDALCBase.cs (91%) rename Church.Net.DAL.EFCoreDBF/{ => Core}/CrudDALCBase.cs (84%) rename Church.Net.DAL.EFCoreDBF/{ => Core}/DatabaseOptions.cs (89%) rename Church.Net.DAL.EFCoreDBF/{ => DBContext}/ChurchNetContext.cs (80%) rename Church.Net.DAL.EFCoreDBF/{ => Interface}/ICrudDAL.cs (97%) create mode 100644 Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.Designer.cs create mode 100644 Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.cs create mode 100644 Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.Designer.cs create mode 100644 Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.cs create mode 100644 Church.Net.Entity2/Games/MD2/MobInfo.cs rename {WebAPI => Church.Net.WebAPI}/.config/dotnet-tools.json (100%) create mode 100644 Church.Net.WebAPI/App_Data/Files/BigTresureChest-Epic.jpg rename {WebAPI => Church.Net.WebAPI}/App_Data/LinePostLog.txt (100%) rename {WebAPI => Church.Net.WebAPI}/App_Data/LinePostRawLog.txt (100%) rename {WebAPI => Church.Net.WebAPI}/App_Data/ScaneMeQrCode.png (100%) rename {WebAPI => Church.Net.WebAPI}/App_Data/arial.ttf (100%) rename WebAPI/WebAPI.csproj => Church.Net.WebAPI/Church.Net.WebAPI.csproj (93%) rename {WebAPI => Church.Net.WebAPI}/Controllers/ApiControllerBase.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Controllers/BestController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/CellGroupRoutineEventAttendeesController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/CellGroupRoutineEventsController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/ContributionController.cs (100%) create mode 100644 Church.Net.WebAPI/Controllers/FileListController.cs create mode 100644 Church.Net.WebAPI/Controllers/FilesController.cs create mode 100644 Church.Net.WebAPI/Controllers/GameRoomController.cs create mode 100644 Church.Net.WebAPI/Controllers/GameRoomMessageController.cs rename {WebAPI => Church.Net.WebAPI}/Controllers/HappinessCostController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/HappinessWeekTaskController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/LineMessageController.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Controllers/LineMessagingAccountController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/LogController.cs (100%) create mode 100644 Church.Net.WebAPI/Controllers/MD2Controller.cs rename {WebAPI => Church.Net.WebAPI}/Controllers/MemberController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/NewVisitorController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/PasswordLoginController.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Controllers/PastoralDomainController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/PingController.cs (100%) create mode 100644 Church.Net.WebAPI/Controllers/QRCodeController.cs create mode 100644 Church.Net.WebAPI/Controllers/VersionController.cs rename {WebAPI => Church.Net.WebAPI}/Controllers/WeatherForecastController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Controllers/WhoIsSpyController.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Dockerfile (62%) create mode 100644 Church.Net.WebAPI/GameRoomLogic.cs rename {WebAPI => Church.Net.WebAPI}/HandleExceptionFilter.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Handlers/BasicAuthorizationMiddlewareResultHandler.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Hubs/AvalonHub.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Hubs/BaseHub.cs (100%) create mode 100644 Church.Net.WebAPI/Hubs/GameRoomHub.cs rename {WebAPI => Church.Net.WebAPI}/Hubs/WhoIsSpyHub.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Logics/Core/CombinedKeyLogicBase.cs (98%) rename {WebAPI => Church.Net.WebAPI}/Logics/Core/LogicBase.cs (98%) rename {WebAPI => Church.Net.WebAPI}/Logics/Core/LogicService.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Logics/Interface/ICrudLogic.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Logics/LineMessagingAccountLogic.cs (96%) rename {WebAPI => Church.Net.WebAPI}/Logics/MemberLogic.cs (92%) rename {WebAPI => Church.Net.WebAPI}/Logics/PastoralDomainLogic.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Logics/VideoDownloadLogic.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Models/IceBreak.cs (72%) create mode 100644 Church.Net.WebAPI/Models/SigmalRMessage.cs create mode 100644 Church.Net.WebAPI/Program.cs rename {WebAPI => Church.Net.WebAPI}/Properties/launchSettings.json (100%) rename {WebAPI => Church.Net.WebAPI}/ServerUtils.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArArkCellGroupDinner.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArArkCellGroupInfo.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArChurchInfo.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArHappinessBEST.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/AutoReplyCommands/ArHappinessGroupTask.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/DbLoggingService.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Services/IdentityService.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/Interfaces/IAutoReplyCommand.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/Interfaces/ILoggingService.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/Interfaces/IScheduledTask.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/LineAutoBotService.cs (99%) rename {WebAPI => Church.Net.WebAPI}/Services/ScheduledTask/MorningPrayer.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Services/WorkerService.cs (100%) rename {WebAPI => Church.Net.WebAPI}/Startup.cs (89%) rename {WebAPI => Church.Net.WebAPI}/ViewModel/RegisterViewModel.cs (100%) rename {WebAPI => Church.Net.WebAPI}/WeatherForecast.cs (100%) rename {WebAPI => Church.Net.WebAPI}/appsettings.Development.json (100%) rename {WebAPI => Church.Net.WebAPI}/appsettings.json (100%) rename {WebAPI => Church.Net.WebAPI}/web.config (100%) delete mode 100644 WebAPI/GameRoomLogic.cs delete mode 100644 WebAPI/Program.cs diff --git a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs b/Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase - Copy.cs similarity index 91% rename from Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs rename to Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase - Copy.cs index 2a50922..33e6631 100644 --- a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase - Copy.cs +++ b/Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase - Copy.cs @@ -12,8 +12,9 @@ using System.Reflection; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Church.Net.DAL.EFCoreDBF.Interface; -namespace Church.Net.DAL.EFCoreDBF +namespace Church.Net.DAL.EFCoreDBF.Core { public class CrudDALCBase1 : ICrudDAL where T : class, IEntity, new() { @@ -21,7 +22,7 @@ namespace Church.Net.DAL.EFCoreDBF public CrudDALCBase1(DatabaseOptions databaseOptions) { - this.dbContext = databaseOptions.GetDbContext(); + dbContext = databaseOptions.GetDbContext(); InitKeyProperty(); } public IQueryable GetDbSet() @@ -39,7 +40,7 @@ namespace Church.Net.DAL.EFCoreDBF public virtual T GetById(string Id) { - return this.GetQuery(new string[] { Id }).FirstOrDefault(); + return GetQuery(new string[] { Id }).FirstOrDefault(); } //public virtual T GetByRefndx(string refndx) @@ -58,16 +59,16 @@ namespace Church.Net.DAL.EFCoreDBF public virtual int Create(T entity) { - this.CheckKeyIsEmpty(entity); - this.ConvertUTCTime(entity); + CheckKeyIsEmpty(entity); + ConvertUTCTime(entity); dbContext.Add(entity); return dbContext.SaveChanges(); } public virtual Task CreateAsync(T entity) { - this.CheckKeyIsEmpty(entity); - this.ConvertUTCTime(entity); + CheckKeyIsEmpty(entity); + ConvertUTCTime(entity); dbContext.Add(entity); //CreateDone(entity, newDbObj); @@ -78,14 +79,14 @@ namespace Church.Net.DAL.EFCoreDBF public int CreateOrUpdate(T entity) { int result = 0; - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); if (CheckExist(entity)) { - result = this.Update(entity); + result = Update(entity); } else { - result = this.Create(entity); + result = Create(entity); } return result; } @@ -97,7 +98,7 @@ namespace Church.Net.DAL.EFCoreDBF //{ // throw new ArgumentNullException("the Id is not exist."); //} - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); dbContext.Update(entity); diff --git a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs b/Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase.cs similarity index 91% rename from Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs rename to Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase.cs index c5fa1fd..da7bdab 100644 --- a/Church.Net.DAL.EFCoreDBF/CombinedKeyCrudDALCBase.cs +++ b/Church.Net.DAL.EFCoreDBF/Core/CombinedKeyCrudDALCBase.cs @@ -12,15 +12,16 @@ using System.Reflection; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Church.Net.DAL.EFCoreDBF.Interface; -namespace Church.Net.DAL.EFCoreDBF +namespace Church.Net.DAL.EFCoreDBF.Core { - public class CombinedKeyCrudDALCBase : ICombinedKeyCrudDAL where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new() + public class CombinedKeyCrudDALCBase : ICombinedKeyCrudDAL where T : class, ICombinedKeyEntity, new() { private readonly DatabaseOptions databaseOptions; public CombinedKeyCrudDALCBase(DatabaseOptions databaseOptions) - { + { this.databaseOptions = databaseOptions; InitKeyProperty(); } @@ -49,7 +50,7 @@ namespace Church.Net.DAL.EFCoreDBF public virtual T GetById(IEnumerable Ids) { - return this.GetQuery(Ids).FirstOrDefault(); + return GetQuery(Ids).FirstOrDefault(); } //public virtual T GetByRefndx(string refndx) @@ -71,13 +72,13 @@ namespace Church.Net.DAL.EFCoreDBF //IEnumerable list = GetDbSet().Where(filter ?? (s => true)).ToList(); - return GetDbSet().AsNoTracking().Where(filter ?? (s => true)).AsQueryable(); + return GetDbSet().AsNoTracking().Where(filter ?? (s => true)).AsQueryable(); } public virtual int Create(T entity) { - this.CheckCombinedKeyIsEmpty(entity); - this.ConvertUTCTime(entity); + CheckCombinedKeyIsEmpty(entity); + ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { @@ -88,8 +89,8 @@ namespace Church.Net.DAL.EFCoreDBF } public virtual Task CreateAsync(T entity) { - this.CheckCombinedKeyIsEmpty(entity); - this.ConvertUTCTime(entity); + CheckCombinedKeyIsEmpty(entity); + ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { dbContext.Add(entity); @@ -103,14 +104,14 @@ namespace Church.Net.DAL.EFCoreDBF public int CreateOrUpdate(T entity) { int result = 0; - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); if (CheckExist(entity)) { - result = this.Update(entity); + result = Update(entity); } else { - result = this.Create(entity); + result = Create(entity); } return result; } @@ -122,7 +123,7 @@ namespace Church.Net.DAL.EFCoreDBF //{ // throw new ArgumentNullException("the Id is not exist."); //} - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { @@ -163,8 +164,8 @@ namespace Church.Net.DAL.EFCoreDBF public virtual int Delete(IEnumerable combinedKeyIds) { - var obj = this.GetById(combinedKeyIds); - return obj == null ? this.Delete(obj) : 0; + var obj = GetById(combinedKeyIds); + return obj == null ? Delete(obj) : 0; } public int Delete(Func filter) diff --git a/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs b/Church.Net.DAL.EFCoreDBF/Core/CrudDALCBase.cs similarity index 84% rename from Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs rename to Church.Net.DAL.EFCoreDBF/Core/CrudDALCBase.cs index 1cc6a3a..bf22333 100644 --- a/Church.Net.DAL.EFCoreDBF/CrudDALCBase.cs +++ b/Church.Net.DAL.EFCoreDBF/Core/CrudDALCBase.cs @@ -7,10 +7,11 @@ using System.Linq; using Church.Net.Utility; using System.Threading.Tasks; using Church.Net.Entity.Interface; +using Church.Net.DAL.EFCoreDBF.Interface; -namespace Church.Net.DAL.EFCoreDBF +namespace Church.Net.DAL.EFCoreDBF.Core { - public class CrudDALCBase : ICrudDAL where T : class, Church.Net.Entity.Interface.IEntity, new() + public class CrudDALCBase : ICrudDAL where T : class, IEntity, new() { private readonly DatabaseOptions databaseOptions; @@ -21,6 +22,10 @@ namespace Church.Net.DAL.EFCoreDBF this.databaseOptions = databaseOptions; //this.dbContext = databaseOptions.GetDbContext(); } + public virtual IQueryable InitQuery(ChurchNetContext dbContext) + { + return dbContext.Set(); + } public ChurchNetContext GetDbContext() { //var result = (DbSet)typeof(ChurchNetContext).GetMethod("Set").MakeGenericMethod(typeof(T)).Invoke(dbContext, null); @@ -33,7 +38,7 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - return dbContext.Set().Where(filter ?? (s => true)).FirstOrDefault(); + return InitQuery(dbContext).Where(filter ?? (s => true)).FirstOrDefault(); } } @@ -41,7 +46,7 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - return dbContext.Set().FirstOrDefault(e => e.Id == Id); + return InitQuery(dbContext).FirstOrDefault(e => e.Id == Id); } } @@ -54,7 +59,7 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - return dbContext.Set().Where(filter ?? (s => true)).ToList(); + return InitQuery(dbContext).Where(filter ?? (s => true)).ToList(); } //var dbObjs = GetDbContext().ToArray(); @@ -72,7 +77,7 @@ namespace Church.Net.DAL.EFCoreDBF //var list = new List(); - return dbContext.Set().Where(e => RowIds.Any(id => id == e.Id)).ToArray(); + return InitQuery(dbContext).Where(e => RowIds.Any(id => id == e.Id)).ToArray(); } } private bool needGenId(T entity) @@ -88,7 +93,7 @@ namespace Church.Net.DAL.EFCoreDBF entity.Id = StringHelper.Get33BaseGuid(); } - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); using (var dbContext = GetDbContext()) { @@ -100,7 +105,7 @@ namespace Church.Net.DAL.EFCoreDBF public virtual Task CreateAsync(T entity) { int result = 0; - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); if (needGenId(entity)) { entity.Id = StringHelper.Get33BaseGuid(); @@ -122,7 +127,7 @@ namespace Church.Net.DAL.EFCoreDBF } public virtual string CreateReturnId(T entity) { - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); if (Create(entity) > 0) { return entity.Id; @@ -135,7 +140,7 @@ namespace Church.Net.DAL.EFCoreDBF public int CreateOrUpdate(T entity) { - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); using (var dbContext = GetDbContext()) @@ -161,12 +166,12 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - //var dbObj = dbContext.Set().Any(e => e.Id == entity.Id); - if (!dbContext.Set().Any(e => e.Id == entity.Id)) + //var dbObj = this.InitQuery(dbContext).Any(e => e.Id == entity.Id); + if (!InitQuery(dbContext).Any(e => e.Id == entity.Id)) { throw new ArgumentNullException("the Id is not exist."); } - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); dbContext.Update(entity); @@ -187,7 +192,7 @@ namespace Church.Net.DAL.EFCoreDBF { foreach (var entity in entities) { - this.ConvertUTCTime(entity); + ConvertUTCTime(entity); } using (var dbContext = GetDbContext()) { @@ -201,7 +206,7 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - dbContext.Remove(dbContext.Set().FirstOrDefault(e => e.Id == obj.Id.ToString())); + dbContext.Remove(InitQuery(dbContext).FirstOrDefault(e => e.Id == obj.Id.ToString())); return dbContext.SaveChanges(); } } @@ -211,7 +216,7 @@ namespace Church.Net.DAL.EFCoreDBF using (var dbContext = GetDbContext()) { - var list = dbContext.Set().Where(filter).ToList(); + var list = InitQuery(dbContext).Where(filter).ToList(); if (list.Count > 0) { dbContext.RemoveRange(list); @@ -225,7 +230,7 @@ namespace Church.Net.DAL.EFCoreDBF { using (var dbContext = GetDbContext()) { - return dbContext.Set().Any(e => e.Id == obj.Id); + return InitQuery(dbContext).Any(e => e.Id == obj.Id); } } @@ -238,7 +243,7 @@ namespace Church.Net.DAL.EFCoreDBF if (prop.PropertyType == typeof(DateTime)) { //do stuff like prop.SetValue(t, DateTime.Now, null); - DateTime localTime = ((DateTime)prop.GetValue(entity)); + DateTime localTime = (DateTime)prop.GetValue(entity); if (localTime.Kind != DateTimeKind.Utc) { localTime = new DateTime(localTime.Year, localTime.Month, localTime.Day, @@ -253,7 +258,7 @@ namespace Church.Net.DAL.EFCoreDBF } else if (prop.PropertyType == typeof(DateTime?)) { - DateTime? localTime = ((DateTime?)prop.GetValue(entity)); + DateTime? localTime = (DateTime?)prop.GetValue(entity); if (localTime.HasValue) { if (localTime.Value.Kind != DateTimeKind.Utc) diff --git a/Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs b/Church.Net.DAL.EFCoreDBF/Core/DatabaseOptions.cs similarity index 89% rename from Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs rename to Church.Net.DAL.EFCoreDBF/Core/DatabaseOptions.cs index d52bc35..6dd6267 100644 --- a/Church.Net.DAL.EFCoreDBF/DatabaseOptions.cs +++ b/Church.Net.DAL.EFCoreDBF/Core/DatabaseOptions.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Church.Net.DAL.EFCoreDBF +namespace Church.Net.DAL.EFCoreDBF.Core { public class DatabaseOptions { diff --git a/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs b/Church.Net.DAL.EFCoreDBF/DBContext/ChurchNetContext.cs similarity index 80% rename from Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs rename to Church.Net.DAL.EFCoreDBF/DBContext/ChurchNetContext.cs index 7ba455b..e1d86b9 100644 --- a/Church.Net.DAL.EFCoreDBF/ChurchNetContext.cs +++ b/Church.Net.DAL.EFCoreDBF/DBContext/ChurchNetContext.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Xml.Linq; using Church.Net.Entity; +using Church.Net.Entity.Games.MD2; using Church.Net.Entity.Messenger; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -40,7 +42,7 @@ namespace Church.Net.DAL.EF private static bool _created = true; private readonly string connectionString; - + public ChurchNetContext(DbContextOptions options) : base(options) { @@ -98,13 +100,33 @@ namespace Church.Net.DAL.EF .HasOne(tt => tt.PastoralDomain) .WithMany(t => t.AutoReplyItemRelations) .HasForeignKey(tt => tt.PastoralDomainCommunityAppId); - //.HasPrincipalKey(tt => tt.L); + //.HasPrincipalKey(tt => tt.L); //modelBuilder.Entity() // .HasOne(t => t.PastoralDomain) // .WithMany(tt => tt.FamilyMember) // .HasForeignKey(f => f.ParentId); + modelBuilder.Entity().Property(x => x.Id).HasDefaultValueSql("uuid_generate_v4()"); + modelBuilder.Entity(entity => + { + entity.Property(x => x.Id).HasDefaultValueSql("uuid_generate_v4()"); + entity.HasMany(e => e.MobLevelInfos).WithOne().OnDelete(DeleteBehavior.Cascade); + entity.HasMany(e => e.Skills).WithOne(x=>x.MobInfo).OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.Id).HasDefaultValueSql("uuid_generate_v4()"); + entity.HasMany(e => e.Skills).WithOne(x => x.MobLevelInfo).OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.Id).HasDefaultValueSql("uuid_generate_v4()"); + entity.Property(x => x.MobInfoId).IsRequired(false); + entity.Property(x => x.MobLevelInfoId).IsRequired(false); + }); } public string DbPath { get; } @@ -137,11 +159,14 @@ namespace Church.Net.DAL.EF public DbSet LineMessageClients { get; set; } public DbSet LineMessagingAccounts { get; set; } - + public DbSet Contributions { get; set; } public DbSet HappinessCosts { get; set; } + //public DbSet GamePlayers { get; set; } + public DbSet Md2MobInfos { get; set; } + public DbSet Md2MobLevelInfos { get; set; } #endregion diff --git a/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs b/Church.Net.DAL.EFCoreDBF/Interface/ICrudDAL.cs similarity index 97% rename from Church.Net.DAL.EFCoreDBF/ICrudDAL.cs rename to Church.Net.DAL.EFCoreDBF/Interface/ICrudDAL.cs index d25fba9..7e1e9bb 100644 --- a/Church.Net.DAL.EFCoreDBF/ICrudDAL.cs +++ b/Church.Net.DAL.EFCoreDBF/Interface/ICrudDAL.cs @@ -7,7 +7,7 @@ using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; -namespace Church.Net.DAL.EFCoreDBF +namespace Church.Net.DAL.EFCoreDBF.Interface { public interface ICrudDAL where T : class, IEntity { diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.Designer.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.Designer.cs new file mode 100644 index 0000000..7106616 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.Designer.cs @@ -0,0 +1,984 @@ +// +using System; +using Church.Net.DAL.EF; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + [DbContext(typeof(ChurchNetContext))] + [Migration("20240502213000_AddMD2MobInfo")] + partial class AddMD2MobInfo + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Church.Net.Entity.AddressInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Zip") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AddressInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplyItems"); + }); + + modelBuilder.Entity("Church.Net.Entity.Career", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Careers"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("PastoralDomainId") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PastoralDomainId"); + + b.ToTable("CellGroupRoutineEvents"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("Id") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("JoinPotluck") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("PotluckItem") + .HasColumnType("text"); + + b.HasKey("EventId", "Id"); + + b.ToTable("CellGroupRoutineEventAttendees"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("MemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Prayer") + .HasColumnType("text"); + + b.HasKey("EventId", "MemberId"); + + b.ToTable("CellGroupRoutineEventPrayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Contribution", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Contributor") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("Contributions"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("AvatarImage") + .HasColumnType("text"); + + b.Property("Baptized") + .HasColumnType("boolean"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("CareerId") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DateOfBaptized") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfWalkIn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Married") + .HasColumnType("boolean"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CareerId"); + + b.ToTable("FamilyMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("OAuthType") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("OAuthAccessToken") + .HasColumnType("text"); + + b.HasKey("FamilyMemberId", "OAuthType"); + + b.ToTable("FamilyMemberOAuths"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("From") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Md2MobInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("MobInfoId") + .HasColumnType("uuid"); + + b.Property("MobInfoId1") + .HasColumnType("uuid"); + + b.Property("MobInfoId2") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MobInfoId"); + + b.HasIndex("MobInfoId1"); + + b.ToTable("Md2MobLevelInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessBESTs"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessCost", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessCosts"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("SEQ") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessWeeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ChatToken") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Seq") + .HasColumnType("integer"); + + b.Property("TotalUsage") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LineMessagingAccounts"); + }); + + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DetailMessage") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("StackTrace") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("TrackNo") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrackNo")); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LogInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("IsGroup") + .HasColumnType("boolean"); + + b.Property("IsManager") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LineMessageClients"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("ReligionId") + .HasColumnType("integer"); + + b.Property("VisitingDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReligionId"); + + b.ToTable("NewVisitors"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Image1") + .HasColumnType("text"); + + b.Property("Image2") + .HasColumnType("text"); + + b.Property("Image3") + .HasColumnType("text"); + + b.Property("Image4") + .HasColumnType("text"); + + b.Property("Image5") + .HasColumnType("text"); + + b.Property("LeaderMemberId") + .HasColumnType("text"); + + b.Property("LineAccountId") + .HasColumnType("text"); + + b.Property("LineGroupId") + .HasColumnType("text"); + + b.Property("LogoImage") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ServiceAddressId") + .HasColumnType("text"); + + b.Property("ServiceTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TimeZone") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("LeaderMemberId"); + + b.HasIndex("LineAccountId"); + + b.HasIndex("ServiceAddressId"); + + b.ToTable("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.Property("PastoralDomainCommunityAppId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("AutoReplyItemId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId"); + + b.HasIndex("AutoReplyItemId"); + + b.ToTable("PastoralDomainAutoReplys"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.Property("PastoralDomainId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainId", "FamilyMemberId"); + + b.HasIndex("FamilyMemberId"); + + b.ToTable("PastoralDomainMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Religion", b => + { + b.Property("ReligionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReligionId")); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("ReligionId"); + + b.ToTable("Religions"); + }); + + modelBuilder.Entity("Church.Net.Entity.Vocabulary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefinitionCh") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionEn") + .IsRequired() + .HasColumnType("text"); + + b.Property("FlashCardTimes") + .HasColumnType("integer"); + + b.Property("ImagesUrl") + .HasColumnType("text"); + + b.Property("InsertDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NounPlural") + .HasColumnType("text"); + + b.Property("PartOfSpeech") + .HasColumnType("integer"); + + b.Property("PracticeApply") + .HasColumnType("boolean"); + + b.Property("PracticeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PracticeMemorized") + .HasColumnType("boolean"); + + b.Property("PracticeReview") + .HasColumnType("boolean"); + + b.Property("PracticeSelect") + .HasColumnType("boolean"); + + b.Property("PracticeSentence") + .HasColumnType("text"); + + b.Property("PracticeStage") + .HasColumnType("integer"); + + b.Property("PracticeVisualize") + .HasColumnType("boolean"); + + b.Property("VerbParticiple") + .HasColumnType("text"); + + b.Property("VerbPast") + .HasColumnType("text"); + + b.Property("Word") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Vocabulary"); + }); + + modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer1Chs") + .HasColumnType("text"); + + b.Property("Answer1Cht") + .HasColumnType("text"); + + b.Property("Answer1En") + .HasColumnType("text"); + + b.Property("Answer2Chs") + .HasColumnType("text"); + + b.Property("Answer2Cht") + .HasColumnType("text"); + + b.Property("Answer2En") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("WhoIsSpy"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "CellGroupInfo") + .WithMany() + .HasForeignKey("PastoralDomainId"); + + b.Navigation("CellGroupInfo"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Attendees") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Prayers") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.Contribution", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("Contributions") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.HasOne("Church.Net.Entity.Career", "Career") + .WithMany() + .HasForeignKey("CareerId"); + + b.Navigation("Career"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", null) + .WithMany("OAuthInfos") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", "MobInfo") + .WithMany() + .HasForeignKey("MobInfoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", null) + .WithMany("MobLevelInfos") + .HasForeignKey("MobInfoId1") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MobInfo"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("Bests") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessCost", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Costs") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("HappinessWeeks") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.HasOne("Church.Net.Entity.Religion", "Religion") + .WithMany() + .HasForeignKey("ReligionId"); + + b.Navigation("Religion"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "Leader") + .WithMany() + .HasForeignKey("LeaderMemberId"); + + b.HasOne("Church.Net.Entity.LineMessagingAccount", "LineMessagingAccount") + .WithMany() + .HasForeignKey("LineAccountId"); + + b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress") + .WithMany() + .HasForeignKey("ServiceAddressId"); + + b.Navigation("Leader"); + + b.Navigation("LineMessagingAccount"); + + b.Navigation("ServiceAddress"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("AutoReplyItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("PastoralDomainCommunityAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember") + .WithMany("PastoralDomains") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("Members") + .HasForeignKey("PastoralDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Navigation("AutoReplyItemRelations"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Navigation("Attendees"); + + b.Navigation("Prayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Navigation("OAuthInfos"); + + b.Navigation("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Navigation("MobLevelInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Costs"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Navigation("AutoReplyItemRelations"); + + b.Navigation("Bests"); + + b.Navigation("Contributions"); + + b.Navigation("HappinessWeeks"); + + b.Navigation("Members"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.cs new file mode 100644 index 0000000..909800a --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213000_AddMD2MobInfo.cs @@ -0,0 +1,71 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + public partial class AddMD2MobInfo : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Md2MobInfos", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"), + Type = table.Column(type: "integer", nullable: false), + From = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Md2MobInfos", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Md2MobLevelInfos", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false, defaultValueSql: "uuid_generate_v4()"), + MobInfoId = table.Column(type: "uuid", nullable: false), + MobInfoId1 = table.Column(type: "uuid", nullable: false), + MobInfoId2 = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Md2MobLevelInfos", x => x.Id); + table.ForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId", + column: x => x.MobInfoId, + principalTable: "Md2MobInfos", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId1", + column: x => x.MobInfoId1, + principalTable: "Md2MobInfos", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Md2MobLevelInfos_MobInfoId", + table: "Md2MobLevelInfos", + column: "MobInfoId"); + + migrationBuilder.CreateIndex( + name: "IX_Md2MobLevelInfos_MobInfoId1", + table: "Md2MobLevelInfos", + column: "MobInfoId1"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Md2MobLevelInfos"); + + migrationBuilder.DropTable( + name: "Md2MobInfos"); + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.Designer.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.Designer.cs new file mode 100644 index 0000000..42b633b --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.Designer.cs @@ -0,0 +1,978 @@ +// +using System; +using Church.Net.DAL.EF; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + [DbContext(typeof(ChurchNetContext))] + [Migration("20240502213603_AddMD2MobInfoUpdateId")] + partial class AddMD2MobInfoUpdateId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Church.Net.Entity.AddressInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Zip") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AddressInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplyItems"); + }); + + modelBuilder.Entity("Church.Net.Entity.Career", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Careers"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("PastoralDomainId") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PastoralDomainId"); + + b.ToTable("CellGroupRoutineEvents"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("Id") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("JoinPotluck") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("PotluckItem") + .HasColumnType("text"); + + b.HasKey("EventId", "Id"); + + b.ToTable("CellGroupRoutineEventAttendees"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.Property("EventId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("MemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Prayer") + .HasColumnType("text"); + + b.HasKey("EventId", "MemberId"); + + b.ToTable("CellGroupRoutineEventPrayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Contribution", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Contributor") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("Contributions"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("AvatarImage") + .HasColumnType("text"); + + b.Property("Baptized") + .HasColumnType("boolean"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone"); + + b.Property("CareerId") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DateOfBaptized") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfWalkIn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Married") + .HasColumnType("boolean"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CareerId"); + + b.ToTable("FamilyMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("OAuthType") + .HasColumnType("text") + .HasColumnOrder(1); + + b.Property("OAuthAccessToken") + .HasColumnType("text"); + + b.HasKey("FamilyMemberId", "OAuthType"); + + b.ToTable("FamilyMemberOAuths"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("From") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Md2MobInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("MobInfoId") + .HasColumnType("text"); + + b.Property("MobInfoId2") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("MobInfoId"); + + b.HasIndex("MobInfoId2"); + + b.ToTable("Md2MobLevelInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessBESTs"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessCost", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessCosts"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Tasker") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("WeekId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("WeekId"); + + b.ToTable("HappinessTask"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("CityAndZipCode") + .HasColumnType("text"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GroupId") + .HasColumnType("text"); + + b.Property("InvitationText") + .HasColumnType("text"); + + b.Property("SEQ") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("HappinessWeeks"); + }); + + modelBuilder.Entity("Church.Net.Entity.LineMessagingAccount", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ChatToken") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Seq") + .HasColumnType("integer"); + + b.Property("TotalUsage") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LineMessagingAccounts"); + }); + + modelBuilder.Entity("Church.Net.Entity.LogInfo", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DetailMessage") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Source") + .HasColumnType("text"); + + b.Property("StackTrace") + .HasColumnType("text"); + + b.Property("Time") + .HasColumnType("timestamp with time zone"); + + b.Property("TrackNo") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrackNo")); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LogInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Messenger.LineMessageClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("IsGroup") + .HasColumnType("boolean"); + + b.Property("IsManager") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("LineMessageClients"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ComunityAppId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("ReligionId") + .HasColumnType("integer"); + + b.Property("VisitingDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReligionId"); + + b.ToTable("NewVisitors"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Image1") + .HasColumnType("text"); + + b.Property("Image2") + .HasColumnType("text"); + + b.Property("Image3") + .HasColumnType("text"); + + b.Property("Image4") + .HasColumnType("text"); + + b.Property("Image5") + .HasColumnType("text"); + + b.Property("LeaderMemberId") + .HasColumnType("text"); + + b.Property("LineAccountId") + .HasColumnType("text"); + + b.Property("LineGroupId") + .HasColumnType("text"); + + b.Property("LogoImage") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ServiceAddressId") + .HasColumnType("text"); + + b.Property("ServiceTime") + .HasColumnType("timestamp with time zone"); + + b.Property("TimeZone") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("LeaderMemberId"); + + b.HasIndex("LineAccountId"); + + b.HasIndex("ServiceAddressId"); + + b.ToTable("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.Property("PastoralDomainCommunityAppId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("AutoReplyItemId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainCommunityAppId", "AutoReplyItemId"); + + b.HasIndex("AutoReplyItemId"); + + b.ToTable("PastoralDomainAutoReplys"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.Property("PastoralDomainId") + .HasColumnType("text") + .HasColumnOrder(0); + + b.Property("FamilyMemberId") + .HasColumnType("text") + .HasColumnOrder(1); + + b.HasKey("PastoralDomainId", "FamilyMemberId"); + + b.HasIndex("FamilyMemberId"); + + b.ToTable("PastoralDomainMembers"); + }); + + modelBuilder.Entity("Church.Net.Entity.Religion", b => + { + b.Property("ReligionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReligionId")); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("ReligionId"); + + b.ToTable("Religions"); + }); + + modelBuilder.Entity("Church.Net.Entity.Vocabulary", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefinitionCh") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionEn") + .IsRequired() + .HasColumnType("text"); + + b.Property("FlashCardTimes") + .HasColumnType("integer"); + + b.Property("ImagesUrl") + .HasColumnType("text"); + + b.Property("InsertDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NounPlural") + .HasColumnType("text"); + + b.Property("PartOfSpeech") + .HasColumnType("integer"); + + b.Property("PracticeApply") + .HasColumnType("boolean"); + + b.Property("PracticeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PracticeMemorized") + .HasColumnType("boolean"); + + b.Property("PracticeReview") + .HasColumnType("boolean"); + + b.Property("PracticeSelect") + .HasColumnType("boolean"); + + b.Property("PracticeSentence") + .HasColumnType("text"); + + b.Property("PracticeStage") + .HasColumnType("integer"); + + b.Property("PracticeVisualize") + .HasColumnType("boolean"); + + b.Property("VerbParticiple") + .HasColumnType("text"); + + b.Property("VerbPast") + .HasColumnType("text"); + + b.Property("Word") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Vocabulary"); + }); + + modelBuilder.Entity("Church.Net.Entity.WhoIsSpy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer1Chs") + .HasColumnType("text"); + + b.Property("Answer1Cht") + .HasColumnType("text"); + + b.Property("Answer1En") + .HasColumnType("text"); + + b.Property("Answer2Chs") + .HasColumnType("text"); + + b.Property("Answer2Cht") + .HasColumnType("text"); + + b.Property("Answer2En") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("WhoIsSpy"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "CellGroupInfo") + .WithMany() + .HasForeignKey("PastoralDomainId"); + + b.Navigation("CellGroupInfo"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventAttendee", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Attendees") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEventPrayer", b => + { + b.HasOne("Church.Net.Entity.CellGroupRoutineEvent", "CellGroupRoutineEvent") + .WithMany("Prayers") + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CellGroupRoutineEvent"); + }); + + modelBuilder.Entity("Church.Net.Entity.Contribution", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("Contributions") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.HasOne("Church.Net.Entity.Career", "Career") + .WithMany() + .HasForeignKey("CareerId"); + + b.Navigation("Career"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMemberOAuth", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", null) + .WithMany("OAuthInfos") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", "MobInfo") + .WithMany() + .HasForeignKey("MobInfoId"); + + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", null) + .WithMany("MobLevelInfos") + .HasForeignKey("MobInfoId2") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("MobInfo"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("Bests") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessCost", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Costs") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessTask", b => + { + b.HasOne("Church.Net.Entity.HappinessWeek", "HappinessWeek") + .WithMany("Tasks") + .HasForeignKey("WeekId"); + + b.Navigation("HappinessWeek"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") + .WithMany("HappinessWeeks") + .HasForeignKey("GroupId"); + + b.Navigation("HappinessGroup"); + }); + + modelBuilder.Entity("Church.Net.Entity.NewVisitor", b => + { + b.HasOne("Church.Net.Entity.Religion", "Religion") + .WithMany() + .HasForeignKey("ReligionId"); + + b.Navigation("Religion"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "Leader") + .WithMany() + .HasForeignKey("LeaderMemberId"); + + b.HasOne("Church.Net.Entity.LineMessagingAccount", "LineMessagingAccount") + .WithMany() + .HasForeignKey("LineAccountId"); + + b.HasOne("Church.Net.Entity.AddressInfo", "ServiceAddress") + .WithMany() + .HasForeignKey("ServiceAddressId"); + + b.Navigation("Leader"); + + b.Navigation("LineMessagingAccount"); + + b.Navigation("ServiceAddress"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainAutoReplys", b => + { + b.HasOne("Church.Net.Entity.AutoReplyItem", "FamilyMember") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("AutoReplyItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("AutoReplyItemRelations") + .HasForeignKey("PastoralDomainCommunityAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomainMembers", b => + { + b.HasOne("Church.Net.Entity.FamilyMember", "FamilyMember") + .WithMany("PastoralDomains") + .HasForeignKey("FamilyMemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Church.Net.Entity.PastoralDomain", "PastoralDomain") + .WithMany("Members") + .HasForeignKey("PastoralDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FamilyMember"); + + b.Navigation("PastoralDomain"); + }); + + modelBuilder.Entity("Church.Net.Entity.AutoReplyItem", b => + { + b.Navigation("AutoReplyItemRelations"); + }); + + modelBuilder.Entity("Church.Net.Entity.CellGroupRoutineEvent", b => + { + b.Navigation("Attendees"); + + b.Navigation("Prayers"); + }); + + modelBuilder.Entity("Church.Net.Entity.FamilyMember", b => + { + b.Navigation("OAuthInfos"); + + b.Navigation("PastoralDomains"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Navigation("MobLevelInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => + { + b.Navigation("Costs"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("Church.Net.Entity.PastoralDomain", b => + { + b.Navigation("AutoReplyItemRelations"); + + b.Navigation("Bests"); + + b.Navigation("Contributions"); + + b.Navigation("HappinessWeeks"); + + b.Navigation("Members"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.cs b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.cs new file mode 100644 index 0000000..47f90c0 --- /dev/null +++ b/Church.Net.DAL.EFCoreDBF/Migrations/20240502213603_AddMD2MobInfoUpdateId.cs @@ -0,0 +1,168 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Church.Net.DAL.EFCoreDBF.Migrations +{ + public partial class AddMD2MobInfoUpdateId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId", + table: "Md2MobLevelInfos"); + + migrationBuilder.DropForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId1", + table: "Md2MobLevelInfos"); + + migrationBuilder.DropIndex( + name: "IX_Md2MobLevelInfos_MobInfoId1", + table: "Md2MobLevelInfos"); + + migrationBuilder.DropColumn( + name: "MobInfoId1", + table: "Md2MobLevelInfos"); + + migrationBuilder.AlterColumn( + name: "MobInfoId2", + table: "Md2MobLevelInfos", + type: "text", + nullable: true, + oldClrType: typeof(Guid), + oldType: "uuid"); + + migrationBuilder.AlterColumn( + name: "MobInfoId", + table: "Md2MobLevelInfos", + type: "text", + nullable: true, + oldClrType: typeof(Guid), + oldType: "uuid"); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Md2MobLevelInfos", + type: "text", + nullable: false, + defaultValueSql: "uuid_generate_v4()", + oldClrType: typeof(Guid), + oldType: "uuid", + oldDefaultValueSql: "uuid_generate_v4()"); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Md2MobInfos", + type: "text", + nullable: false, + defaultValueSql: "uuid_generate_v4()", + oldClrType: typeof(Guid), + oldType: "uuid", + oldDefaultValueSql: "uuid_generate_v4()"); + + migrationBuilder.CreateIndex( + name: "IX_Md2MobLevelInfos_MobInfoId2", + table: "Md2MobLevelInfos", + column: "MobInfoId2"); + + migrationBuilder.AddForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId", + table: "Md2MobLevelInfos", + column: "MobInfoId", + principalTable: "Md2MobInfos", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId2", + table: "Md2MobLevelInfos", + column: "MobInfoId2", + principalTable: "Md2MobInfos", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId", + table: "Md2MobLevelInfos"); + + migrationBuilder.DropForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId2", + table: "Md2MobLevelInfos"); + + migrationBuilder.DropIndex( + name: "IX_Md2MobLevelInfos_MobInfoId2", + table: "Md2MobLevelInfos"); + + migrationBuilder.AlterColumn( + name: "MobInfoId2", + table: "Md2MobLevelInfos", + type: "uuid", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "MobInfoId", + table: "Md2MobLevelInfos", + type: "uuid", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Md2MobLevelInfos", + type: "uuid", + nullable: false, + defaultValueSql: "uuid_generate_v4()", + oldClrType: typeof(string), + oldType: "text", + oldDefaultValueSql: "uuid_generate_v4()"); + + migrationBuilder.AddColumn( + name: "MobInfoId1", + table: "Md2MobLevelInfos", + type: "uuid", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Md2MobInfos", + type: "uuid", + nullable: false, + defaultValueSql: "uuid_generate_v4()", + oldClrType: typeof(string), + oldType: "text", + oldDefaultValueSql: "uuid_generate_v4()"); + + migrationBuilder.CreateIndex( + name: "IX_Md2MobLevelInfos_MobInfoId1", + table: "Md2MobLevelInfos", + column: "MobInfoId1"); + + migrationBuilder.AddForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId", + table: "Md2MobLevelInfos", + column: "MobInfoId", + principalTable: "Md2MobInfos", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Md2MobLevelInfos_Md2MobInfos_MobInfoId1", + table: "Md2MobLevelInfos", + column: "MobInfoId1", + principalTable: "Md2MobInfos", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs b/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs index b4e9bb7..7138ac0 100644 --- a/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs +++ b/Church.Net.DAL.EFCoreDBF/Migrations/ChurchNetContextModelSnapshot.cs @@ -255,6 +255,46 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.ToTable("FamilyMemberOAuths"); }); + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("From") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Md2MobInfos"); + }); + + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("uuid_generate_v4()"); + + b.Property("MobInfoId") + .HasColumnType("text"); + + b.Property("MobInfoId2") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("MobInfoId"); + + b.HasIndex("MobInfoId2"); + + b.ToTable("Md2MobLevelInfos"); + }); + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => { b.Property("Id") @@ -769,6 +809,20 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations .IsRequired(); }); + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobLevelInfo", b => + { + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", "MobInfo") + .WithMany() + .HasForeignKey("MobInfoId"); + + b.HasOne("Church.Net.Entity.Games.MD2.MobInfo", null) + .WithMany("MobLevelInfos") + .HasForeignKey("MobInfoId2") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("MobInfo"); + }); + modelBuilder.Entity("Church.Net.Entity.HappinessBEST", b => { b.HasOne("Church.Net.Entity.PastoralDomain", "HappinessGroup") @@ -892,6 +946,11 @@ namespace Church.Net.DAL.EFCoreDBF.Migrations b.Navigation("PastoralDomains"); }); + modelBuilder.Entity("Church.Net.Entity.Games.MD2.MobInfo", b => + { + b.Navigation("MobLevelInfos"); + }); + modelBuilder.Entity("Church.Net.Entity.HappinessWeek", b => { b.Navigation("Costs"); diff --git a/Church.Net.Entity2/Games/MD2/MobInfo.cs b/Church.Net.Entity2/Games/MD2/MobInfo.cs new file mode 100644 index 0000000..e08105c --- /dev/null +++ b/Church.Net.Entity2/Games/MD2/MobInfo.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.Text; +using Newtonsoft.Json; +using Church.Net.Entity.Interface; + +namespace Church.Net.Entity.Games.MD2 +{ + public enum MobType + { + Mob, + RoamingMonster, + Boss + } + + public enum GameBundle + { + CoreGame, + HeavenFallen, + Zombiecide, + + } + public enum MobSkillType + { + Attack, + Defense, + Combat, + Passive + } + + public enum MobSkillTarget + { + LeastHp, + LeastMaxHp, + LeastMana, + LeastMaxMana, + } + public enum MD2Icon + { + Attack, + Defense, + Mana, + Shadow, + EnemySkill, + EnemyClaw, + Reroll, + Fire, + Frost, + OneHand, + TwoHand, + Helmet, + Armor, + Ring, + Foot, + Melee, + Range, + Magic, + HP, + MP, + Dice, + Arrow, + ArrowBullseye, + ArrowOverload, + SoulToken, + Rage, + RedDice, + BlueDice, + YellowDice, + OrangeDice, + BlackDice + } + public class MobInfo : IEntity + { + [Key] + public string Id { get; set; } + public MobType Type { get; set; } + public GameBundle From { get; set; } + public string Name { get; set; } + public string LeaderImgUrl { get; set; } + public string MinionImgUrl { get; set; } + public virtual ICollection MobLevelInfos { get; set; } + public virtual ICollection Skills { get; set; } + } + + + public class MobLevelInfo : IEntity + { + + [Key] + public string Id { get; set; } + [ForeignKey("MobInfo")] + public string MobInfoId { get; set; } + [JsonIgnore] + public virtual MobInfo MobInfo { get; set; } + public int RewardTokens { get; set; } + public int FixedRareTreasure { get; set; } + public int FixedEpicTreasure { get; set; } + public int FixedLegendTreasure { get; set; } + public int FixedHp { get; set; } + public int HpPerHero { get; set; } + public int Actions { get; set; } + + [ForeignKey("AttackInfo")] + public string AttackInfoId { get; set; } + public MD2DiceSet AttackInfo { get; set; } + [ForeignKey("DefenceInfo")] + public string DefenceInfoId { get; set; } + public MD2DiceSet DefenceInfo { get; set; } + public virtual ICollection Skills { get; set; } + + + } + public class MobSkill : IEntity + { + + [Key] + public string Id { get; set; } + [ForeignKey("MobLevelInfo")] + public string MobLevelInfoId { get; set; } + + [ForeignKey("MobInfo")] + public string MobInfoId { get; set; } + [JsonIgnore] + public virtual MobInfo MobInfo { get; set; } + + [JsonIgnore] + public virtual MobLevelInfo MobLevelInfo { get; set; } + + public MobSkillType Type { get; set; } + public int ClawRoll { get; set; } + public int SkillRoll { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + public class MD2DiceSet : IEntity + { + [Key] + public string Id { get; set; } + public int? Yellow { get; set; } + public int? Orange { get; set; } + public int? Red { get; set; } + public int? Blue { get; set; } + public int? Green { get; set; } + public int? Black { get; set; } + } +} diff --git a/Church.Net.Entity2/Interface/IEntity.cs b/Church.Net.Entity2/Interface/IEntity.cs index 4ff893c..e97f131 100644 --- a/Church.Net.Entity2/Interface/IEntity.cs +++ b/Church.Net.Entity2/Interface/IEntity.cs @@ -11,4 +11,8 @@ namespace Church.Net.Entity.Interface public interface ICombinedKeyEntity { } + public interface IBussinessEntity + { + Guid Id { get; set; } + } } diff --git a/WebAPI/.config/dotnet-tools.json b/Church.Net.WebAPI/.config/dotnet-tools.json similarity index 100% rename from WebAPI/.config/dotnet-tools.json rename to Church.Net.WebAPI/.config/dotnet-tools.json diff --git a/Church.Net.WebAPI/App_Data/Files/BigTresureChest-Epic.jpg b/Church.Net.WebAPI/App_Data/Files/BigTresureChest-Epic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d36befb3158eceda388ade4d35a005cc952ff617 GIT binary patch literal 33146 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.0 983731f5-925d-44ec-b4c8-a7c4ad857569 Linux + 1.0.0.2 @@ -38,9 +39,10 @@ - + - + + diff --git a/WebAPI/Controllers/ApiControllerBase.cs b/Church.Net.WebAPI/Controllers/ApiControllerBase.cs similarity index 99% rename from WebAPI/Controllers/ApiControllerBase.cs rename to Church.Net.WebAPI/Controllers/ApiControllerBase.cs index 85dadc7..eb90cc1 100644 --- a/WebAPI/Controllers/ApiControllerBase.cs +++ b/Church.Net.WebAPI/Controllers/ApiControllerBase.cs @@ -143,4 +143,6 @@ namespace WebAPI.Controllers }); } } + + } diff --git a/WebAPI/Controllers/BestController.cs b/Church.Net.WebAPI/Controllers/BestController.cs similarity index 100% rename from WebAPI/Controllers/BestController.cs rename to Church.Net.WebAPI/Controllers/BestController.cs diff --git a/WebAPI/Controllers/CellGroupRoutineEventAttendeesController.cs b/Church.Net.WebAPI/Controllers/CellGroupRoutineEventAttendeesController.cs similarity index 100% rename from WebAPI/Controllers/CellGroupRoutineEventAttendeesController.cs rename to Church.Net.WebAPI/Controllers/CellGroupRoutineEventAttendeesController.cs diff --git a/WebAPI/Controllers/CellGroupRoutineEventsController.cs b/Church.Net.WebAPI/Controllers/CellGroupRoutineEventsController.cs similarity index 100% rename from WebAPI/Controllers/CellGroupRoutineEventsController.cs rename to Church.Net.WebAPI/Controllers/CellGroupRoutineEventsController.cs diff --git a/WebAPI/Controllers/ContributionController.cs b/Church.Net.WebAPI/Controllers/ContributionController.cs similarity index 100% rename from WebAPI/Controllers/ContributionController.cs rename to Church.Net.WebAPI/Controllers/ContributionController.cs diff --git a/Church.Net.WebAPI/Controllers/FileListController.cs b/Church.Net.WebAPI/Controllers/FileListController.cs new file mode 100644 index 0000000..e52c45e --- /dev/null +++ b/Church.Net.WebAPI/Controllers/FileListController.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.IO; +using System.Linq; +using WebAPI; +using WebAPI.Services.Interfaces; + +namespace Church.Net.WebAPI.Controllers +{ + [Route("[controller]")] + [ApiController] + public class FileListController : ControllerBase + { + private readonly ILoggingService loggingService; + + public FileListController(ILoggingService loggingService) + { + this.loggingService = loggingService; + } + [HttpGet("{*filePath}")] + public ActionResult Get(string filePath) + { + string folderRootPath = ""; + string folderPath = ""; + try + { +#if DEBUG + folderRootPath = "//ArkNAS/docker/ChurchAPI/App_Data/Files"; +#else + folderRootPath = "/App_Data/Files"; +#endif + folderPath = System.IO.Path.Combine(folderRootPath, filePath); + return Directory.GetFiles(folderPath).Select(s=>s.Replace(folderRootPath,"").Replace(filePath, "").Replace("\\","/")).ToArray(); + } + catch (System.Exception ex) + { + loggingService.Error(ex); + return NotFound(); + } + } + } +} diff --git a/Church.Net.WebAPI/Controllers/FilesController.cs b/Church.Net.WebAPI/Controllers/FilesController.cs new file mode 100644 index 0000000..c7cc96d --- /dev/null +++ b/Church.Net.WebAPI/Controllers/FilesController.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.IO; +using WebAPI; +using WebAPI.Services.Interfaces; + +namespace Church.Net.WebAPI.Controllers +{ + [Route("[controller]")] + [ApiController] + public class FilesController : ControllerBase + { + private readonly ILoggingService loggingService; + + public FilesController(ILoggingService loggingService) + { + this.loggingService = loggingService; + } + [HttpGet("{*filePath}")] + public IActionResult Get(string filePath) + { + try + { + string folderRootPath = ""; +#if DEBUG + folderRootPath = "//ArkNAS/docker/ChurchAPI/App_Data/Files"; +#else + folderRootPath = "/App_Data/Files"; +#endif + + return PhysicalFile(System.IO.Path.Combine(folderRootPath, filePath), "image/jpeg"); + } + catch (System.Exception ex) + { + loggingService.Error(ex); + return NotFound(); + } + } + } +} diff --git a/Church.Net.WebAPI/Controllers/GameRoomController.cs b/Church.Net.WebAPI/Controllers/GameRoomController.cs new file mode 100644 index 0000000..604935d --- /dev/null +++ b/Church.Net.WebAPI/Controllers/GameRoomController.cs @@ -0,0 +1,57 @@ +using Church.Net.WebAPI.Models; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using WebAPI.Models.IceBreak; +using WebAPI; +using System.Linq; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace Church.Net.WebAPI.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class GameRoomController : ControllerBase + { + private readonly GameRoomLogic gameRoomLogic; + + public GameRoomController(GameRoomLogic gameRoomLogic) + { + this.gameRoomLogic = gameRoomLogic; + } + // GET: api/ + [HttpGet] + public IEnumerable Get() + { + return gameRoomLogic.GameRooms; + } + + // GET api//5 + [HttpGet("{id}")] + public IEnumerable Get(string roomId) + { + return gameRoomLogic.GameRooms.Where(r => r.Id == roomId).FirstOrDefault()?.Players; + } + + // POST api/ + [HttpPost] + public void Post([FromBody] GamePlayer gamePlayer) + { + gameRoomLogic.CreateGameRoom(gamePlayer); + } + + // PUT api//5 + [HttpPut("{roomId}")] + public bool Put(string roomId, [FromBody] GamePlayer value) + { + return gameRoomLogic.UserJoinGameRoom(roomId, value); + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(string id) + { + gameRoomLogic.UserLeave(new GamePlayer() { Id = id }); + } + } +} diff --git a/Church.Net.WebAPI/Controllers/GameRoomMessageController.cs b/Church.Net.WebAPI/Controllers/GameRoomMessageController.cs new file mode 100644 index 0000000..5e3b1d1 --- /dev/null +++ b/Church.Net.WebAPI/Controllers/GameRoomMessageController.cs @@ -0,0 +1,55 @@ +using Church.Net.WebAPI.Models; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using WebAPI; +using WebAPI.Models.IceBreak; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace Church.Net.WebAPI.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class GameRoomMessageController : ControllerBase + { + private readonly GameRoomLogic gameRoomLogic; + + public GameRoomMessageController(GameRoomLogic gameRoomLogic) + { + this.gameRoomLogic = gameRoomLogic; + } + // GET: api/ + [HttpGet] + public IEnumerable Get() + { + return gameRoomLogic.GameRooms; + } + + // GET api//5 + [HttpGet("{id}")] + public IEnumerable Get(string roomId) + { + return gameRoomLogic.GameRooms.Where(r => r.Id == roomId).FirstOrDefault()?.Players; + } + + // POST api/ + [HttpPost] + public void Post([FromBody] SignalRMessage message) + { + gameRoomLogic.SendMessage(message); + } + + // PUT api//5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/WebAPI/Controllers/HappinessCostController.cs b/Church.Net.WebAPI/Controllers/HappinessCostController.cs similarity index 100% rename from WebAPI/Controllers/HappinessCostController.cs rename to Church.Net.WebAPI/Controllers/HappinessCostController.cs diff --git a/WebAPI/Controllers/HappinessWeekTaskController.cs b/Church.Net.WebAPI/Controllers/HappinessWeekTaskController.cs similarity index 100% rename from WebAPI/Controllers/HappinessWeekTaskController.cs rename to Church.Net.WebAPI/Controllers/HappinessWeekTaskController.cs diff --git a/WebAPI/Controllers/LineMessageController.cs b/Church.Net.WebAPI/Controllers/LineMessageController.cs similarity index 99% rename from WebAPI/Controllers/LineMessageController.cs rename to Church.Net.WebAPI/Controllers/LineMessageController.cs index b007cfc..b5991f7 100644 --- a/WebAPI/Controllers/LineMessageController.cs +++ b/Church.Net.WebAPI/Controllers/LineMessageController.cs @@ -23,8 +23,8 @@ using WebAPI.Services; using Jint.Native; using WebAPI.Services.Interfaces; using Church.Net.DAL.EFCoreDBF.Migrations; -using Church.Net.DAL.EFCoreDBF; using WebAPI.Logics; +using Church.Net.DAL.EFCoreDBF.Interface; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace WebAPI.Controllers diff --git a/WebAPI/Controllers/LineMessagingAccountController.cs b/Church.Net.WebAPI/Controllers/LineMessagingAccountController.cs similarity index 100% rename from WebAPI/Controllers/LineMessagingAccountController.cs rename to Church.Net.WebAPI/Controllers/LineMessagingAccountController.cs diff --git a/WebAPI/Controllers/LogController.cs b/Church.Net.WebAPI/Controllers/LogController.cs similarity index 100% rename from WebAPI/Controllers/LogController.cs rename to Church.Net.WebAPI/Controllers/LogController.cs diff --git a/Church.Net.WebAPI/Controllers/MD2Controller.cs b/Church.Net.WebAPI/Controllers/MD2Controller.cs new file mode 100644 index 0000000..e458a26 --- /dev/null +++ b/Church.Net.WebAPI/Controllers/MD2Controller.cs @@ -0,0 +1,19 @@ +using Church.Net.Entity; +using Church.Net.Entity.Games.MD2; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Threading.Tasks; +using WebAPI.Logics.Interface; + +namespace WebAPI.Controllers +{ + [Route("[controller]/[action]")] + [ApiController] + public class MD2MobInfoController : ApiControllerBase + { + public MD2MobInfoController(ICrudLogic logic) : base(logic) + { + } + } +} diff --git a/WebAPI/Controllers/MemberController.cs b/Church.Net.WebAPI/Controllers/MemberController.cs similarity index 100% rename from WebAPI/Controllers/MemberController.cs rename to Church.Net.WebAPI/Controllers/MemberController.cs diff --git a/WebAPI/Controllers/NewVisitorController.cs b/Church.Net.WebAPI/Controllers/NewVisitorController.cs similarity index 100% rename from WebAPI/Controllers/NewVisitorController.cs rename to Church.Net.WebAPI/Controllers/NewVisitorController.cs diff --git a/WebAPI/Controllers/PasswordLoginController.cs b/Church.Net.WebAPI/Controllers/PasswordLoginController.cs similarity index 99% rename from WebAPI/Controllers/PasswordLoginController.cs rename to Church.Net.WebAPI/Controllers/PasswordLoginController.cs index d949707..03f666f 100644 --- a/WebAPI/Controllers/PasswordLoginController.cs +++ b/Church.Net.WebAPI/Controllers/PasswordLoginController.cs @@ -1,5 +1,5 @@ using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Core; using Church.Net.Entity; using Church.Net.Utility; using Microsoft.AspNetCore.Mvc; diff --git a/WebAPI/Controllers/PastoralDomainController.cs b/Church.Net.WebAPI/Controllers/PastoralDomainController.cs similarity index 100% rename from WebAPI/Controllers/PastoralDomainController.cs rename to Church.Net.WebAPI/Controllers/PastoralDomainController.cs diff --git a/WebAPI/Controllers/PingController.cs b/Church.Net.WebAPI/Controllers/PingController.cs similarity index 100% rename from WebAPI/Controllers/PingController.cs rename to Church.Net.WebAPI/Controllers/PingController.cs diff --git a/Church.Net.WebAPI/Controllers/QRCodeController.cs b/Church.Net.WebAPI/Controllers/QRCodeController.cs new file mode 100644 index 0000000..726de3d --- /dev/null +++ b/Church.Net.WebAPI/Controllers/QRCodeController.cs @@ -0,0 +1,93 @@ +using Church.Net.Utility; +using Microsoft.AspNetCore.Mvc; +using QRCoder; +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.Processing; +using System.IO; +using System.Threading.Tasks; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace Church.Net.WebAPI.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class QRCodeController : ControllerBase + { + // GET api//5 + [HttpGet] + public async Task Get(string content,int size) + { + + QRCodeGenerator gen = new QRCodeGenerator(); + QRCodeGenerator qrGenerator = new QRCodeGenerator(); + QRCodeData qrCodeData = qrGenerator.CreateQrCode(content, QRCodeGenerator.ECCLevel.Q); + QRCode qrCode = new QRCode(qrCodeData); + var qrCodeImage = qrCode.GetGraphic(size); + //string qrCodeImagePath = "/App_Data/ScaneMeQrCode.png"; + //var backgroundBitmap = SixLabors.ImageSharp.Image.Load(qrCodeImagePath); + //string qrCodeImagePath = Environment.GetEnvironmentVariable("AppData"); + //HttpContext.Current.Server.MapPath("~/App_Data/"); + //var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/ScaneMeQrCode.png"); + //System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/yourXmlFile.xml"); + + //int positionLeft = 0; + //int positionTop = 0; + //var best = logic.GetById(id); + //if (best != null) + //{ + // using (var memoryStream = new MemoryStream()) + // { + // //fileStream.CopyTo(memoryStream); + // var image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32); + // image.Scalling(75); + // image.SaveAsPng(memoryStream); + // byte[] byteImage = memoryStream.ToArray(); + // return File(byteImage, "image/png"); + // } + //} + using (var memoryStream = new MemoryStream()) + { + qrCodeImage.SaveAsJpeg(memoryStream); + return File(memoryStream.ToArray(), "image/jpeg"); + } + + } + + + private Font arialFont; + [NonAction] + public Image Superimpose(string bestName, Image largeBmp, Image smallBmp, int? x = null, int? y = null) + { + FontCollection collection = new(); + FontFamily family = collection.Add("/App_Data/arial.ttf"); + arialFont = family.CreateFont(12, FontStyle.Italic); + //Graphics g = Graphics.FromImage(largeBmp); + //g.CompositingMode = CompositingMode.SourceOver; + //smallBmp.MakeTransparent(); + int margin = 5; + if (!x.HasValue) + { + x = largeBmp.Width - smallBmp.Width - margin; + } + if (!y.HasValue) + { + y = largeBmp.Height - smallBmp.Height - margin; + } + var scale = 0.8; + var scaleWidth = (int)(smallBmp.Width * scale); + var scaleHeight = (int)(smallBmp.Height * scale); + + + largeBmp.Mutate(x => x.DrawText(bestName, arialFont, Color.Black, new PointF(10, 10))); + + smallBmp.Scalling(80); + + largeBmp.Mutate(ctx => ctx.DrawImage(smallBmp, new Point(x.Value, y.Value), 1f)); + return largeBmp; + } + + } +} diff --git a/Church.Net.WebAPI/Controllers/VersionController.cs b/Church.Net.WebAPI/Controllers/VersionController.cs new file mode 100644 index 0000000..664c664 --- /dev/null +++ b/Church.Net.WebAPI/Controllers/VersionController.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace WebAPI.Controllers +{ + [ApiController] + [Route("[controller]")] + public class VersionController : ControllerBase + { + + [HttpGet] + public string Get() + { + System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); + System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); + string version = fvi.FileVersion; + return version; + } + } +} diff --git a/WebAPI/Controllers/WeatherForecastController.cs b/Church.Net.WebAPI/Controllers/WeatherForecastController.cs similarity index 100% rename from WebAPI/Controllers/WeatherForecastController.cs rename to Church.Net.WebAPI/Controllers/WeatherForecastController.cs diff --git a/WebAPI/Controllers/WhoIsSpyController.cs b/Church.Net.WebAPI/Controllers/WhoIsSpyController.cs similarity index 100% rename from WebAPI/Controllers/WhoIsSpyController.cs rename to Church.Net.WebAPI/Controllers/WhoIsSpyController.cs diff --git a/WebAPI/Dockerfile b/Church.Net.WebAPI/Dockerfile similarity index 62% rename from WebAPI/Dockerfile rename to Church.Net.WebAPI/Dockerfile index ce0f637..af9cf8c 100644 --- a/WebAPI/Dockerfile +++ b/Church.Net.WebAPI/Dockerfile @@ -7,19 +7,19 @@ EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src -COPY ["WebAPI/WebAPI.csproj", "WebAPI/"] +COPY ["Church.Net.WebAPI/Church.Net.WebAPI.csproj", "Church.Net.WebAPI/"] COPY ["Church.Net.DAL.EFCoreDBF/Church.Net.DAL.EFCoreDBF.csproj", "Church.Net.DAL.EFCoreDBF/"] COPY ["Church.Net.Entity2/Church.Net.Entity.csproj", "Church.Net.Entity/"] COPY ["Church.Net.Utility/Church.Net.Utility.csproj", "Church.Net.Utility/"] -RUN dotnet restore "WebAPI/WebAPI.csproj" +RUN dotnet restore "Church.Net.WebAPI/Church.Net.WebAPI.csproj" COPY . . -WORKDIR "/src/WebAPI" -RUN dotnet build "WebAPI.csproj" -c Release -o /app/build +WORKDIR "/src/Church.Net.WebAPI" +RUN dotnet build "Church.Net.WebAPI.csproj" -c Release -o /app/build FROM build AS publish -RUN dotnet publish "WebAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false +RUN dotnet publish "Church.Net.WebAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "WebAPI.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "Church.Net.WebAPI.dll"] \ No newline at end of file diff --git a/Church.Net.WebAPI/GameRoomLogic.cs b/Church.Net.WebAPI/GameRoomLogic.cs new file mode 100644 index 0000000..87083da --- /dev/null +++ b/Church.Net.WebAPI/GameRoomLogic.cs @@ -0,0 +1,141 @@ +using Church.Net.WebAPI.Models; +using Jint.Native; +using Microsoft.AspNetCore.SignalR; +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WebAPI.Hubs; +using WebAPI.Models.IceBreak; +using WebAPI.Services.Interfaces; + +namespace WebAPI +{ + public class GameRoomLogic + { + public List OnlinePlayers { get; set; } + private readonly IHubContext gameHubContext; + + public GameRoomLogic( + IHubContext GameHubContext + ) + { + gameHubContext = GameHubContext; + GameRooms = new List(); + OnlinePlayers = new List(); + } + public List GameRooms { get; set; } + public void CreateGameRoom(IGamePlayer gamePlayer) + { + if (!this.GameRooms.Any(g => g.Id == gamePlayer.Id)) + { + this.GameRooms.Add(new GameRoom() + { + Id = gamePlayer.Id, + Name = gamePlayer.Name, + SignalRClientId = gamePlayer.SignalRClientId, + }); + } + else + { + var existingRoom = this.GameRooms.FirstOrDefault(g => g.Id == gamePlayer.Id); + existingRoom.SignalRClientId = gamePlayer.SignalRClientId; + } + //this.OnlinePlayers.FirstOrDefault(p => p.SignalRClientId == gamePlayer.SignalRClientId).GameRoomId = gamePlayer.Id; + //gameHubContext.Groups.AddToGroupAsync(gamePlayer.SignalRClientId, gamePlayer.Id); + } + + public bool UserJoinGameRoom(string gameRoomId, IGamePlayer gamePlayer) + { + //this.OnlinePlayers.FirstOrDefault(p => p.SignalRClientId == gamePlayer.SignalRClientId) + // .GameRoomId = gameRoomId; + //if (GameRooms.Any(g => g.Id == gameRoomId)) + //{ + // //Make sure user not exist in other room + // UserLeave(gamePlayer); + + //} + + var gameRoom = GameRooms.FirstOrDefault(r => r.Id == gameRoomId); + if (gameRoom == null) + { + CreateGameRoom(gamePlayer); + } + if (gameRoom != null) + { + //gameHubContext.Groups.AddToGroupAsync(gamePlayer.SignalRClientId, gameRoomId); + gameRoom.Players.Add(gamePlayer); + var message = new SignalRMessage(new SignalRSession(gameRoomId, "", true), "GameRoom", "Join"); + message.From = new SignalRSession(gamePlayer.SignalRClientId, gamePlayer.Name); + SendMessage(message); + return true; + } + return false; + } + public void UserLeave(IGamePlayer gamePlayer) + { + //foreach (var room in GameRooms) + //{ + // if (room.Id == gamePlayer.SignalRClientId) + // { + // GameRooms.Remove(room); + // break; + + // } + // if (room.Players.Any(p => p.Id == gamePlayer.Id)) + // { + // room.Players.Remove(room.Players.FirstOrDefault(p => p.Id == gamePlayer.Id)); + // var message = new SignalRMessage(new SignalRSession(room.Id, "", true), "GameRoom", "Leaving"); + // message.From = new SignalRSession(gamePlayer.SignalRClientId, gamePlayer.Name); + // SendMessage(message); + // break; + // } + //} + if (!string.IsNullOrWhiteSpace(gamePlayer.GameRoomId)) + { + //gameHubContext.Groups.RemoveFromGroupAsync(gamePlayer.SignalRClientId, gamePlayer.GameRoomId); + var message = new SignalRMessage(new SignalRSession(gamePlayer.GameRoomId, "", true), "GameRoom", "Leaving"); + message.From = new SignalRSession(gamePlayer.TabId, gamePlayer.Name); + SendMessage(message); + } + } + public void BrodcastMessage(GameRoom room) + { + } + + public void SendMessage(SignalRMessage message) + { + string jsonString = JsonConvert.SerializeObject(message, new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + //DateTimeZoneHandling = DateTimeZoneHandling.Local + }); + if (message.Receiver.IsGroup) + { + //this.gameHubContext.Clients.Clients( + // this.GameRooms.FirstOrDefault(g => g.Id == message.Receiver.SessionId).Players.Select(p => p.Id)) + // .SendAsync("ReceivedMessage", jsonString); + //this.gameHubContext.Clients.All.SendAsync("ReceivedMessage", jsonString); + + gameHubContext.Clients.Group(message.Receiver.SessionId).SendAsync("ReceivedMessage", jsonString); + + + } + else + { + gameHubContext.Clients.Client(message.Receiver.SessionId).SendAsync("ReceivedMessage", jsonString); + + } + + } + + public bool GetOnlinePlayerByTabId(string tabId,out IGamePlayer gamePlayer) + { + gamePlayer= this.OnlinePlayers.FirstOrDefault(p => p.TabId == tabId); + return gamePlayer != null; + } + } +} diff --git a/WebAPI/HandleExceptionFilter.cs b/Church.Net.WebAPI/HandleExceptionFilter.cs similarity index 100% rename from WebAPI/HandleExceptionFilter.cs rename to Church.Net.WebAPI/HandleExceptionFilter.cs diff --git a/WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs b/Church.Net.WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs similarity index 100% rename from WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs rename to Church.Net.WebAPI/Handlers/BasicAuthorizationMiddlewareResultHandler.cs diff --git a/WebAPI/Hubs/AvalonHub.cs b/Church.Net.WebAPI/Hubs/AvalonHub.cs similarity index 100% rename from WebAPI/Hubs/AvalonHub.cs rename to Church.Net.WebAPI/Hubs/AvalonHub.cs diff --git a/WebAPI/Hubs/BaseHub.cs b/Church.Net.WebAPI/Hubs/BaseHub.cs similarity index 100% rename from WebAPI/Hubs/BaseHub.cs rename to Church.Net.WebAPI/Hubs/BaseHub.cs diff --git a/Church.Net.WebAPI/Hubs/GameRoomHub.cs b/Church.Net.WebAPI/Hubs/GameRoomHub.cs new file mode 100644 index 0000000..7a97a24 --- /dev/null +++ b/Church.Net.WebAPI/Hubs/GameRoomHub.cs @@ -0,0 +1,121 @@ + +using Church.Net.WebAPI.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.SignalR; +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WebAPI.Models.IceBreak; +using System.Diagnostics; +using System.Text.RegularExpressions; + +namespace WebAPI.Hubs +{ + public class GameRoomHub : Hub + { + private readonly GameRoomLogic gameRoomLogic; + + public GameRoomHub(GameRoomLogic gameRoomLogic) + { + this.gameRoomLogic = gameRoomLogic; + } + + public void SendMessage(SignalRMessage message) + { + string jsonString = JsonConvert.SerializeObject(message, new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + //DateTimeZoneHandling = DateTimeZoneHandling.Local + }); + Task.Run(() => + { + if (message.Receiver.IsGroup) + { + Clients.Group(message.Receiver.SessionId).SendAsync("ReceivedMessage", jsonString); + } + else + { + Clients.Client(message.Receiver.SessionId).SendAsync("ReceivedMessage", jsonString); + + } + + }); + + } + + public override Task OnConnectedAsync() + { + var playerInfo = GetPlayerInfoFromRequest(); + //var gameHostName = Context.GetHttpContext().Request.Query["gameHostName"]; + //if (false==string.IsNullOrWhiteSpace(gameHostName)) + //{ + + //} + //var groupId = Context.GetHttpContext().Request.Query["groupId"]; + //Groups.AddToGroupAsync(Context.ConnectionId, groupId); + Debug.WriteLine($"{playerInfo.Name}({playerInfo.Id}) Conection Id:{playerInfo.SignalRClientId}"); + + if (!string.IsNullOrWhiteSpace(playerInfo.TabId)) + { + if (gameRoomLogic.GetOnlinePlayerByTabId(playerInfo.TabId, out IGamePlayer gamePlayer)) + { + gamePlayer.SignalRClientId = Context.ConnectionId; + } + else + { + gameRoomLogic.OnlinePlayers.Add(playerInfo); + } + } + + + if (!string.IsNullOrWhiteSpace(playerInfo.GameRoomId)) + { + Groups.AddToGroupAsync(Context.ConnectionId, playerInfo.GameRoomId); + } + + + this.SendMessage(new SignalRMessage(new SignalRSession(playerInfo.SignalRClientId, ""), "GameRoom", "sendJoinInfo").AddParameter("signalRConnId", Context.ConnectionId)); + + return base.OnConnectedAsync(); + } + + public override Task OnDisconnectedAsync(Exception exception) + { + + var playerInfo = GetPlayerInfoFromRequest(); + Debug.WriteLine($"{playerInfo.Name}({playerInfo.Id}) Conection Id:{playerInfo.SignalRClientId} Disconnected"); + //var groupId = Context.GetHttpContext().Request.Query["groupId"]; + //Groups.RemoveFromGroupAsync(Context.ConnectionId, groupId); + if (!string.IsNullOrWhiteSpace(playerInfo.GameRoomId)) + { + Groups.RemoveFromGroupAsync(Context.ConnectionId, playerInfo.GameRoomId); + } + + if (!string.IsNullOrWhiteSpace(playerInfo.TabId)) + { + gameRoomLogic.UserLeave(playerInfo); + gameRoomLogic.OnlinePlayers.RemoveAll(u => u.TabId == playerInfo.TabId); + } + return base.OnDisconnectedAsync(exception); + } + private GamePlayer GetPlayerInfoFromRequest() + { + var playerId = Context.GetHttpContext().Request.Query["userId"]; + var username = Context.GetHttpContext().Request.Query["username"]; + var playerTabId = Context.GetHttpContext().Request.Query["tabId"]; + var roomId = Context.GetHttpContext().Request.Query["roomId"]; + return new GamePlayer() + { + Id = playerId, + SignalRClientId = Context.ConnectionId, + Name = username, + TabId = playerTabId, + GameRoomId = roomId, + }; + } + } +} diff --git a/WebAPI/Hubs/WhoIsSpyHub.cs b/Church.Net.WebAPI/Hubs/WhoIsSpyHub.cs similarity index 100% rename from WebAPI/Hubs/WhoIsSpyHub.cs rename to Church.Net.WebAPI/Hubs/WhoIsSpyHub.cs diff --git a/WebAPI/Logics/Core/CombinedKeyLogicBase.cs b/Church.Net.WebAPI/Logics/Core/CombinedKeyLogicBase.cs similarity index 98% rename from WebAPI/Logics/Core/CombinedKeyLogicBase.cs rename to Church.Net.WebAPI/Logics/Core/CombinedKeyLogicBase.cs index 9e0510e..fcbd5ef 100644 --- a/WebAPI/Logics/Core/CombinedKeyLogicBase.cs +++ b/Church.Net.WebAPI/Logics/Core/CombinedKeyLogicBase.cs @@ -7,7 +7,7 @@ using System.Linq; using Church.Net.Utility; using System.Threading.Tasks; using WebAPI.Logics.Interface; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; namespace WebAPI.Logics.Core { diff --git a/WebAPI/Logics/Core/LogicBase.cs b/Church.Net.WebAPI/Logics/Core/LogicBase.cs similarity index 98% rename from WebAPI/Logics/Core/LogicBase.cs rename to Church.Net.WebAPI/Logics/Core/LogicBase.cs index b934590..674e141 100644 --- a/WebAPI/Logics/Core/LogicBase.cs +++ b/Church.Net.WebAPI/Logics/Core/LogicBase.cs @@ -7,7 +7,7 @@ using System.Linq; using Church.Net.Utility; using System.Threading.Tasks; using WebAPI.Logics.Interface; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; namespace WebAPI.Logics.Core { diff --git a/WebAPI/Logics/Core/LogicService.cs b/Church.Net.WebAPI/Logics/Core/LogicService.cs similarity index 100% rename from WebAPI/Logics/Core/LogicService.cs rename to Church.Net.WebAPI/Logics/Core/LogicService.cs diff --git a/WebAPI/Logics/Interface/ICrudLogic.cs b/Church.Net.WebAPI/Logics/Interface/ICrudLogic.cs similarity index 100% rename from WebAPI/Logics/Interface/ICrudLogic.cs rename to Church.Net.WebAPI/Logics/Interface/ICrudLogic.cs diff --git a/WebAPI/Logics/LineMessagingAccountLogic.cs b/Church.Net.WebAPI/Logics/LineMessagingAccountLogic.cs similarity index 96% rename from WebAPI/Logics/LineMessagingAccountLogic.cs rename to Church.Net.WebAPI/Logics/LineMessagingAccountLogic.cs index 07218af..d865f98 100644 --- a/WebAPI/Logics/LineMessagingAccountLogic.cs +++ b/Church.Net.WebAPI/Logics/LineMessagingAccountLogic.cs @@ -1,4 +1,4 @@ -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Church.Net.Entity.Interface; using System; diff --git a/WebAPI/Logics/MemberLogic.cs b/Church.Net.WebAPI/Logics/MemberLogic.cs similarity index 92% rename from WebAPI/Logics/MemberLogic.cs rename to Church.Net.WebAPI/Logics/MemberLogic.cs index a30c1cd..1cc089b 100644 --- a/WebAPI/Logics/MemberLogic.cs +++ b/Church.Net.WebAPI/Logics/MemberLogic.cs @@ -1,4 +1,4 @@ -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using WebAPI.Logics.Core; using WebAPI.Logics.Interface; diff --git a/WebAPI/Logics/PastoralDomainLogic.cs b/Church.Net.WebAPI/Logics/PastoralDomainLogic.cs similarity index 99% rename from WebAPI/Logics/PastoralDomainLogic.cs rename to Church.Net.WebAPI/Logics/PastoralDomainLogic.cs index 88500c8..21c9366 100644 --- a/WebAPI/Logics/PastoralDomainLogic.cs +++ b/Church.Net.WebAPI/Logics/PastoralDomainLogic.cs @@ -1,5 +1,4 @@ -using Church.Net.DAL.EFCoreDBF; -using Church.Net.Entity; +using Church.Net.Entity; using Church.Net.Utility; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; @@ -9,6 +8,7 @@ using WebAPI.Logics.Interface; using System.Linq; using Microsoft.Extensions.DependencyInjection; using System.Text.RegularExpressions; +using Church.Net.DAL.EFCoreDBF.Interface; namespace WebAPI.Logics { diff --git a/WebAPI/Logics/VideoDownloadLogic.cs b/Church.Net.WebAPI/Logics/VideoDownloadLogic.cs similarity index 100% rename from WebAPI/Logics/VideoDownloadLogic.cs rename to Church.Net.WebAPI/Logics/VideoDownloadLogic.cs diff --git a/WebAPI/Models/IceBreak.cs b/Church.Net.WebAPI/Models/IceBreak.cs similarity index 72% rename from WebAPI/Models/IceBreak.cs rename to Church.Net.WebAPI/Models/IceBreak.cs index c7afc57..b45379a 100644 --- a/WebAPI/Models/IceBreak.cs +++ b/Church.Net.WebAPI/Models/IceBreak.cs @@ -11,20 +11,32 @@ namespace WebAPI.Models.IceBreak WereWolf, WhoIsSpy } - public class GameRoom + + public interface IGameRoom + { + string Id { get; set; } + string Name { get; set; } + List Players { get; set; } + int TotalPlayer { get; } + string SignalRClientId { get; set; } + } + + public class GameRoom : IGameRoom { GameType Type { get; set; } public string Id { get; set; } - private List _players; + public string SignalRClientId { get; set; } + public string Name { get; set; } + private List _players; public int TotalPlayer => Players.Count; - public List Players + public List Players { get { if (_players == null) { - _players = new List(); + _players = new List(); } @@ -35,12 +47,26 @@ namespace WebAPI.Models.IceBreak } - public class GamePlayer + public interface IGamePlayer { public string Id { get; set; } + public string SignalRClientId { get; set; } + public string TabId { get; set; } [Required] public string Name { get; set; } - public string TempGameRoomId { get; set; } + public string GameRoomId { get; set; } + public bool IsPlayer { get; set; } + } + + public class GamePlayer : IGamePlayer + { + public string Id { get; set; } + public string SignalRClientId { get; set; } + public string TabId { get; set; } + [Required] + public string Name { get; set; } + public string GameRoomId { get; set; } + public bool IsPlayer { get; set; } } @@ -54,7 +80,7 @@ namespace WebAPI.Models.IceBreak Closed } - public class WhoIsSpyGameRoom : GameRoom + public class WhoIsSpyGameRoom : GameRoom, IGameRoom { public WhoIsSpyGameRoom() { @@ -76,12 +102,10 @@ namespace WebAPI.Models.IceBreak public List PlayedAnswerId { get; set; } public int VoteAmount { get; set; } } - public class WhoIsSpyPlayer + public class WhoIsSpyPlayer : GamePlayer, IGamePlayer { - public string Id { get; set; } public string RoomId { get; set; } public int Seed { get; set; } - public string Name { get; set; } public WhoIsSpyAnswer Answer { get; set; } public bool IsSpy { get; set; } public bool IsDead { get; set; } diff --git a/Church.Net.WebAPI/Models/SigmalRMessage.cs b/Church.Net.WebAPI/Models/SigmalRMessage.cs new file mode 100644 index 0000000..c31886b --- /dev/null +++ b/Church.Net.WebAPI/Models/SigmalRMessage.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Church.Net.WebAPI.Models +{ + + public class SignalRMessage + { + public SignalRSession From { get; set; } + public SignalRSession Receiver { get; set; } + public string ActionType { get; set; } + public string ActionName { get; set; } + public Dictionary Parameters { get; set; } + public string JsonValue { get; set; } + [JsonIgnore] + public object Value { get; set; } + public SignalRMessage() + { + Parameters = new Dictionary(); + + } + + public SignalRMessage(SignalRSession receiver, string actionType, string actionName = null, object value = null) + { + Parameters = new Dictionary(); + this.Receiver = receiver; + ActionType = actionType; + ActionName = actionName; + Value = value; + } + public SignalRMessage AddParameter(string key, string value) + { + if (!string.IsNullOrEmpty(key)) + { + key = key.ToLower(); + if (Parameters.ContainsKey(key)) + { + Parameters[key] = value; + } + else + { + Parameters.Add(key, value); + } + } + + return this; + } + public string GetParameter(string key) + { + return Parameters[key.ToLower()]; + } + } + + public class SignalRSession + { + public SignalRSession() + { + + } + + public SignalRSession(string sessionId, string name, bool isGroup = false) + { + SessionId = sessionId; + Name = name; + IsGroup = isGroup; + } + + public string SessionId { get; set; } + public string Name { get; set; } + public bool IsGroup { get; set; } + } +} diff --git a/Church.Net.WebAPI/Program.cs b/Church.Net.WebAPI/Program.cs new file mode 100644 index 0000000..0b41bec --- /dev/null +++ b/Church.Net.WebAPI/Program.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using DotNetTools.SharpGrabber.Grabbed; +using DotNetTools.SharpGrabber; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using DotNetTools.SharpGrabber.Converter; + +namespace WebAPI +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } + //public static class Program + //{ + // private static readonly HttpClient Client = new HttpClient(); + // private static readonly HashSet TempFiles = new HashSet(); + + // public static async Task Main(string[] args) + // { + // var grabber = GrabberBuilder.New() + // .UseDefaultServices() + // .AddYouTube() + // .Build(); + + // Console.WriteLine("Enter FFMPEG path:"); + // var ffmpegPath = Console.ReadLine().Trim(); + // FFmpeg.AutoGen.ffmpeg.RootPath = ffmpegPath; + + // Console.WriteLine("Enter a YouTube URL:"); + // var url = Console.ReadLine(); + // if (url == null) + // return; + + // var result = await grabber.GrabAsync(new Uri(url, UriKind.Absolute)); + + // var audioStream = ChooseMonoMedia(result, MediaChannels.Audio); + // //var videoStream = ChooseMonoMedia(result, MediaChannels.Video); + // if (audioStream == null) + // throw new InvalidOperationException("No audio stream detected."); + // //if (videoStream == null) + // // throw new InvalidOperationException("No video stream detected."); + + // try + // { + // var audioPath = await DownloadMedia(audioStream, result); + // //var videoPath = await DownloadMedia(videoStream, result); + // GenerateOutputFile(audioPath); + // } + // finally + // { + // foreach (var tempFile in TempFiles) + // { + // try + // { + // File.Delete(tempFile); + // } + // catch (Exception) + // { + // // ignored + // } + // } + // } + // } + + // private static void GenerateOutputFile(string audioPath) + // { + // Console.WriteLine("Output Path:"); + // var outputPath = Console.ReadLine(); + // if (string.IsNullOrWhiteSpace(outputPath)) + // throw new Exception("No output path is specified."); + // var merger = new MediaMerger(outputPath); + // merger.AddStreamSource(audioPath, MediaStreamType.Audio); + // //merger.AddStreamSource(videoPath, MediaStreamType.Video); + // merger.OutputMimeType = "audio/mp3";//videoStream.Format.Mime; + // merger.OutputShortName = "mp3";//videoStream.Format.Extension; + + // merger.Build(); + // Console.WriteLine($"Output file successfully created."); + // } + + // private static GrabbedMedia ChooseMonoMedia(GrabResult result, MediaChannels channel) + // { + // var resources = result.Resources() + // .Where(m => m.Channels == channel) + // .ToList(); + + // if (resources.Count == 0) + // return null; + + // for (var i = 0; i < resources.Count; i++) + // { + // var resource = resources[i]; + // Console.WriteLine($"{i}. {resource.Title ?? resource.FormatTitle ?? resource.Resolution}"); + // } + + // while (true) + // { + // Console.Write($"Choose the {channel} file: "); + // var choiceStr = Console.ReadLine(); + // if (!int.TryParse(choiceStr, out var choice)) + // { + // Console.WriteLine("Number expected."); + // continue; + // } + + // if (choice < 0 || choice >= resources.Count) + // { + // Console.WriteLine("Invalid number."); + // continue; + // } + + // return resources[choice]; + // } + // } + + // private static async Task DownloadMedia(GrabbedMedia media, IGrabResult grabResult) + // { + // Console.WriteLine("Downloading {0}...", media.Title ?? media.FormatTitle ?? media.Resolution); + // Console.WriteLine(media.ResourceUri); + // Client.Timeout=TimeSpan.FromSeconds(200); + // using var response = await Client.GetAsync(media.ResourceUri); + // response.EnsureSuccessStatusCode(); + // using var downloadStream = await response.Content.ReadAsStreamAsync(); + // using var resourceStream = await grabResult.WrapStreamAsync(downloadStream); + // var path = Path.GetTempFileName(); + + // using var fileStream = new FileStream(path, FileMode.Create); + // TempFiles.Add(path); + // await resourceStream.CopyToAsync(fileStream); + // return path; + // } + //} +} diff --git a/WebAPI/Properties/launchSettings.json b/Church.Net.WebAPI/Properties/launchSettings.json similarity index 100% rename from WebAPI/Properties/launchSettings.json rename to Church.Net.WebAPI/Properties/launchSettings.json diff --git a/WebAPI/ServerUtils.cs b/Church.Net.WebAPI/ServerUtils.cs similarity index 100% rename from WebAPI/ServerUtils.cs rename to Church.Net.WebAPI/ServerUtils.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupDinner.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupInfo.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupInfo.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArArkCellGroupInfo.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupInfo.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArArkCellGroupPrayer.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArChurchInfo.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArChurchInfo.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArChurchInfo.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArChurchInfo.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArHappinessBEST.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArHappinessBEST.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArHappinessBEST.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArHappinessBEST.cs diff --git a/WebAPI/Services/AutoReplyCommands/ArHappinessGroupTask.cs b/Church.Net.WebAPI/Services/AutoReplyCommands/ArHappinessGroupTask.cs similarity index 100% rename from WebAPI/Services/AutoReplyCommands/ArHappinessGroupTask.cs rename to Church.Net.WebAPI/Services/AutoReplyCommands/ArHappinessGroupTask.cs diff --git a/WebAPI/Services/DbLoggingService.cs b/Church.Net.WebAPI/Services/DbLoggingService.cs similarity index 99% rename from WebAPI/Services/DbLoggingService.cs rename to Church.Net.WebAPI/Services/DbLoggingService.cs index 7ab9ba0..dc42fb1 100644 --- a/WebAPI/Services/DbLoggingService.cs +++ b/Church.Net.WebAPI/Services/DbLoggingService.cs @@ -5,9 +5,9 @@ using WebAPI.Services.Interfaces; using System.Diagnostics; using Church.Net.Entity; using Church.Net.Entity.Interface; -using Church.Net.DAL.EFCoreDBF; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; +using Church.Net.DAL.EFCoreDBF.Interface; namespace WebAPI.Services { diff --git a/WebAPI/Services/IdentityService.cs b/Church.Net.WebAPI/Services/IdentityService.cs similarity index 100% rename from WebAPI/Services/IdentityService.cs rename to Church.Net.WebAPI/Services/IdentityService.cs diff --git a/WebAPI/Services/Interfaces/IAutoReplyCommand.cs b/Church.Net.WebAPI/Services/Interfaces/IAutoReplyCommand.cs similarity index 100% rename from WebAPI/Services/Interfaces/IAutoReplyCommand.cs rename to Church.Net.WebAPI/Services/Interfaces/IAutoReplyCommand.cs diff --git a/WebAPI/Services/Interfaces/ILoggingService.cs b/Church.Net.WebAPI/Services/Interfaces/ILoggingService.cs similarity index 100% rename from WebAPI/Services/Interfaces/ILoggingService.cs rename to Church.Net.WebAPI/Services/Interfaces/ILoggingService.cs diff --git a/WebAPI/Services/Interfaces/IScheduledTask.cs b/Church.Net.WebAPI/Services/Interfaces/IScheduledTask.cs similarity index 100% rename from WebAPI/Services/Interfaces/IScheduledTask.cs rename to Church.Net.WebAPI/Services/Interfaces/IScheduledTask.cs diff --git a/WebAPI/Services/LineAutoBotService.cs b/Church.Net.WebAPI/Services/LineAutoBotService.cs similarity index 99% rename from WebAPI/Services/LineAutoBotService.cs rename to Church.Net.WebAPI/Services/LineAutoBotService.cs index 3da4561..5ab4e88 100644 --- a/WebAPI/Services/LineAutoBotService.cs +++ b/Church.Net.WebAPI/Services/LineAutoBotService.cs @@ -1,4 +1,4 @@ -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Church.Net.Entity.Messenger; using Church.Net.Utility; diff --git a/WebAPI/Services/ScheduledTask/MorningPrayer.cs b/Church.Net.WebAPI/Services/ScheduledTask/MorningPrayer.cs similarity index 100% rename from WebAPI/Services/ScheduledTask/MorningPrayer.cs rename to Church.Net.WebAPI/Services/ScheduledTask/MorningPrayer.cs diff --git a/WebAPI/Services/WorkerService.cs b/Church.Net.WebAPI/Services/WorkerService.cs similarity index 100% rename from WebAPI/Services/WorkerService.cs rename to Church.Net.WebAPI/Services/WorkerService.cs diff --git a/WebAPI/Startup.cs b/Church.Net.WebAPI/Startup.cs similarity index 89% rename from WebAPI/Startup.cs rename to Church.Net.WebAPI/Startup.cs index c957683..74beed5 100644 --- a/WebAPI/Startup.cs +++ b/Church.Net.WebAPI/Startup.cs @@ -4,7 +4,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Core; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; @@ -64,14 +65,22 @@ namespace WebAPI services.AddSignalR(); services.AddSingleton(); - //services.AddSingleton(_ => new DatabaseOptions { ConnectionString = "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" }); - services.AddSingleton(_ => new DatabaseOptions { ConnectionString = "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" }); + + services.AddSingleton(); + + //Localted at \\ArkNAS\docker\ChurchAPI\docker-compose.yaml + string databaseConnString = Environment.GetEnvironmentVariable("DB_CONN_STRING"); +#if DEBUG + databaseConnString = "Host=192.168.68.55;Port=49154;Database=Church;Username=chris;Password=1124"; +#endif + //services.AddSingleton(_ => new DatabaseOptions { ConnectionString = databaseConnString }); + services.AddSingleton(_ => new DatabaseOptions { ConnectionString = databaseConnString }); //services.AddSingleton(new ChurchNetContext()); services.AddDbContext(options => options.UseNpgsql( //Configuration.GetConnectionString() - //"Host=192.168.86.131;Port=49154;Database=ChurchSandbox;Username=chris;Password=1124" - "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" + //"Host=192.168.68.55;Port=49154;Database=ChurchSandbox;Username=chris;Password=1124" + databaseConnString )); services.AddScoped(); @@ -82,7 +91,7 @@ namespace WebAPI services.AddScoped(); services.AddScoped(); - services.AddScoped(); + //services.AddScoped(); services.AddScoped(); @@ -155,6 +164,7 @@ namespace WebAPI endpoints.MapHub("/AvalonHub"); endpoints.MapHub("/WhoIsSpyHub"); endpoints.MapHub("/BaseHub"); + endpoints.MapHub("/GameRoomHub"); endpoints.MapControllers(); diff --git a/WebAPI/ViewModel/RegisterViewModel.cs b/Church.Net.WebAPI/ViewModel/RegisterViewModel.cs similarity index 100% rename from WebAPI/ViewModel/RegisterViewModel.cs rename to Church.Net.WebAPI/ViewModel/RegisterViewModel.cs diff --git a/WebAPI/WeatherForecast.cs b/Church.Net.WebAPI/WeatherForecast.cs similarity index 100% rename from WebAPI/WeatherForecast.cs rename to Church.Net.WebAPI/WeatherForecast.cs diff --git a/WebAPI/appsettings.Development.json b/Church.Net.WebAPI/appsettings.Development.json similarity index 100% rename from WebAPI/appsettings.Development.json rename to Church.Net.WebAPI/appsettings.Development.json diff --git a/WebAPI/appsettings.json b/Church.Net.WebAPI/appsettings.json similarity index 100% rename from WebAPI/appsettings.json rename to Church.Net.WebAPI/appsettings.json diff --git a/WebAPI/web.config b/Church.Net.WebAPI/web.config similarity index 100% rename from WebAPI/web.config rename to Church.Net.WebAPI/web.config diff --git a/Church.Net.sln b/Church.Net.sln index d2b1ba9..cc9f590 100644 --- a/Church.Net.sln +++ b/Church.Net.sln @@ -9,7 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BLL", "BLL", "{8EA076BD-086 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utility", "Utility", "{251C9BF4-223F-4D00-9BB0-9C80537D1A37}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAPI", "WebAPI\WebAPI.csproj", "{1DD6DC3F-D6E1-43E0-A2FD-2E5FF7AE20C6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Church.Net.WebAPI", "Church.Net.WebAPI\Church.Net.WebAPI.csproj", "{1DD6DC3F-D6E1-43E0-A2FD-2E5FF7AE20C6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Church.Net.Entity", "Church.Net.Entity2\Church.Net.Entity.csproj", "{FAEEA0AD-9C16-4BED-BF7D-BF74A3810D77}" EndProject diff --git a/TestProject/DateTimeTest.cs b/TestProject/DateTimeTest.cs index d9286fa..3b32540 100644 --- a/TestProject/DateTimeTest.cs +++ b/TestProject/DateTimeTest.cs @@ -1,5 +1,5 @@ using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/TestProject/FamilyMemberTest.cs b/TestProject/FamilyMemberTest.cs index 2fe50cb..7a2b7f2 100644 --- a/TestProject/FamilyMemberTest.cs +++ b/TestProject/FamilyMemberTest.cs @@ -1,5 +1,5 @@ using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/TestProject/LineMessageTest.cs b/TestProject/LineMessageTest.cs index fb91890..9b64cb7 100644 --- a/TestProject/LineMessageTest.cs +++ b/TestProject/LineMessageTest.cs @@ -1,5 +1,5 @@ using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Church.Net.Utility; using LineMessaging; diff --git a/TestProject/TestBase.cs b/TestProject/TestBase.cs index 5553746..6391bce 100644 --- a/TestProject/TestBase.cs +++ b/TestProject/TestBase.cs @@ -1,5 +1,6 @@ using Church.Net.DAL.EF; -using Church.Net.DAL.EFCoreDBF; +using Church.Net.DAL.EFCoreDBF.Core; +using Church.Net.DAL.EFCoreDBF.Interface; using Church.Net.Entity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -21,7 +22,7 @@ namespace TestProject services.AddDbContext(options => options.UseNpgsql( //Configuration.GetConnectionString() - "Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124" + "Host=192.168.68.55;Port=49154;Database=Church;Username=chris;Password=1124" )); services.AddTransient(); diff --git a/TestProject/TestProject.csproj b/TestProject/TestProject.csproj index 7f9fc86..a7c65de 100644 --- a/TestProject/TestProject.csproj +++ b/TestProject/TestProject.csproj @@ -18,7 +18,7 @@ - + diff --git a/WebAPI/GameRoomLogic.cs b/WebAPI/GameRoomLogic.cs deleted file mode 100644 index b53e394..0000000 --- a/WebAPI/GameRoomLogic.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using WebAPI.Models.IceBreak; - -namespace WebAPI -{ - public class GameRoomLogic - { - public List GameRooms { get; set; } - - public bool UserJoinGameRoom(string id,string userName,string gameRoomId) - { - if (GameRooms.Any(g => g.Id == gameRoomId)) - { - //Make sure user not exist in other room - UserLeave(id); - - } - return false; - } - public void UserLeave(string id) - { - foreach (var room in GameRooms) - { - if (room.Players.Any(p => p.Id == id)) - { - room.Players.Remove(room.Players.FirstOrDefault(p => p.Id == id)); - break; - } - } - } - } -} diff --git a/WebAPI/Program.cs b/WebAPI/Program.cs deleted file mode 100644 index 491169d..0000000 --- a/WebAPI/Program.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace WebAPI -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -}