diff --git a/SiteManagementService/SiteManagementService.py b/SiteManagementService/SiteManagementService.py new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/SiteManagementService/SiteManagementService.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SiteManagementService/SiteManagementService.pyproj b/SiteManagementService/SiteManagementService.pyproj new file mode 100644 index 0000000..e23e3b6 --- /dev/null +++ b/SiteManagementService/SiteManagementService.pyproj @@ -0,0 +1,35 @@ + + + Debug + 2.0 + 2c74bf2c-c988-45c5-8f7e-1822c7358818 + . + SiteManagementService.py + + + . + . + SiteManagementService + SiteManagementService + + + true + false + + + true + false + + + + + + + + + + + + \ No newline at end of file diff --git a/SiteManagementSystem(SoftwareEngineering).sln b/SiteManagementSystem(SoftwareEngineering).sln index 3b0481b..9404c54 100644 --- a/SiteManagementSystem(SoftwareEngineering).sln +++ b/SiteManagementSystem(SoftwareEngineering).sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.11.35327.3 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SiteManagementSystem(SoftwareEngineering)", "SiteManagementSystem(SoftwareEngineering)\SiteManagementSystem(SoftwareEngineering).csproj", "{CB0750D4-7BC3-4D7D-B9E1-AADA28283DFB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SiteManagementSystem(SoftwareEngineering)", "SiteManagementSystem(SoftwareEngineering)\SiteManagementSystem(SoftwareEngineering).csproj", "{CB0750D4-7BC3-4D7D-B9E1-AADA28283DFB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/SiteManagementSystem(SoftwareEngineering)/Model/SecretConfig.cs b/SiteManagementSystem(SoftwareEngineering)/Configuration/SecretConfig.cs similarity index 59% rename from SiteManagementSystem(SoftwareEngineering)/Model/SecretConfig.cs rename to SiteManagementSystem(SoftwareEngineering)/Configuration/SecretConfig.cs index 6c19824..085594f 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Model/SecretConfig.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Configuration/SecretConfig.cs @@ -1,4 +1,4 @@ -namespace IwutMail.Model +namespace SiteManagementSystem_SoftwareEngineering_.Configuration { public class SecretConfig { diff --git a/SiteManagementSystem(SoftwareEngineering)/Model/TokenFactoryConfiguration.cs b/SiteManagementSystem(SoftwareEngineering)/Configuration/TokenFactoryConfiguration.cs similarity index 90% rename from SiteManagementSystem(SoftwareEngineering)/Model/TokenFactoryConfiguration.cs rename to SiteManagementSystem(SoftwareEngineering)/Configuration/TokenFactoryConfiguration.cs index f60c17c..45d288f 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Model/TokenFactoryConfiguration.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Configuration/TokenFactoryConfiguration.cs @@ -1,4 +1,4 @@ -namespace SiteManagementSystem_SoftwareEngineering_.Model +namespace SiteManagementSystem_SoftwareEngineering_.Configuration { public class TokenFactoryConfiguration { diff --git a/SiteManagementSystem(SoftwareEngineering)/Controllers/FieldController.cs b/SiteManagementSystem(SoftwareEngineering)/Controllers/FieldController.cs index 0f87bc0..0e15ac4 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Controllers/FieldController.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Controllers/FieldController.cs @@ -1,8 +1,30 @@ using Microsoft.AspNetCore.Mvc; +using SiteManagementSystem_SoftwareEngineering_.Entity; +using SiteManagementSystem_SoftwareEngineering_.Extension; +using SiteManagementSystem_SoftwareEngineering_.Interface; +using SiteManagementSystem_SoftwareEngineering_.Service; namespace SiteManagementSystem_SoftwareEngineering_.Controllers { + [Route("Field")] public class FieldController : ControllerBase { + IFieldService _fieldService; + SQLService _sql; + public FieldController(IFieldService fieldService,SQLService sql) { _fieldService = fieldService; _sql = sql; } + [HttpPost("AddField")] + public IActionResult AddField() + { + _sql.Fields.Add(new Field()); + _sql.SaveChanges(); + return Ok(); + } + [HttpGet("test")] + public IActionResult test() + { + _fieldService.AddField("", ""); + return this.Success(); + } + } } diff --git a/SiteManagementSystem(SoftwareEngineering)/Entity/Field.cs b/SiteManagementSystem(SoftwareEngineering)/Entity/Field.cs new file mode 100644 index 0000000..64ac58b --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Entity/Field.cs @@ -0,0 +1,15 @@ +using SiteManagementSystem_SoftwareEngineering_.Service; +using System.ComponentModel.DataAnnotations; + +namespace SiteManagementSystem_SoftwareEngineering_.Entity +{ + public class Field + { + [Key] + public Guid Id { get; set; } = Guid.NewGuid(); + public string Name { get; set; } = null!; + public string Position { get; set; } = null!; + public string OpenTime { get; set; } = null!; + public FieldType Type { get; set; } = FieldType.Unspecified; + } +} diff --git a/SiteManagementSystem(SoftwareEngineering)/Entity/User.cs b/SiteManagementSystem(SoftwareEngineering)/Entity/User.cs index 92a9397..5b8c9db 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Entity/User.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Entity/User.cs @@ -1,11 +1,8 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Data; -using System.Security.Claims; -using System.Xml.Linq; -using Microsoft.AspNetCore.DataProtection; -using SiteManagementSystem_SoftwareEngineering_.Model; +using SiteManagementSystem_SoftwareEngineering_.Model; using SiteManagementSystem_SoftwareEngineering_.Service; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Security.Claims; namespace SiteManagementSystem_SoftwareEngineering_.Entity { diff --git a/SiteManagementSystem(SoftwareEngineering)/Entity/UserField.cs b/SiteManagementSystem(SoftwareEngineering)/Entity/UserField.cs new file mode 100644 index 0000000..e44b393 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Entity/UserField.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace SiteManagementSystem_SoftwareEngineering_.Entity +{ + public class UserField + { + [Key] + public Guid Uid { get; set; } + //[Key] + public Guid Fid { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + // other properties + } +} diff --git a/SiteManagementSystem(SoftwareEngineering)/Extension/IServiceCollectionExtension.cs b/SiteManagementSystem(SoftwareEngineering)/Extension/IServiceCollectionExtension.cs index 0cc37ba..634b761 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Extension/IServiceCollectionExtension.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Extension/IServiceCollectionExtension.cs @@ -1,7 +1,6 @@ -using IwutMail.Model; +using SiteManagementSystem_SoftwareEngineering_.Configuration; using SiteManagementSystem_SoftwareEngineering_.Factory; using SiteManagementSystem_SoftwareEngineering_.Interface; -using SiteManagementSystem_SoftwareEngineering_.Model; using SiteManagementSystem_SoftwareEngineering_.Service; using static SiteManagementSystem_SoftwareEngineering_.Service.UserManagerService; diff --git a/SiteManagementSystem(SoftwareEngineering)/Factory/TokenFactory.cs b/SiteManagementSystem(SoftwareEngineering)/Factory/TokenFactory.cs index 3e81744..42639f7 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Factory/TokenFactory.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Factory/TokenFactory.cs @@ -4,9 +4,9 @@ using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; +using SiteManagementSystem_SoftwareEngineering_.Configuration; using SiteManagementSystem_SoftwareEngineering_.Entity; using SiteManagementSystem_SoftwareEngineering_.Interface; -using SiteManagementSystem_SoftwareEngineering_.Model; namespace SiteManagementSystem_SoftwareEngineering_.Factory { diff --git a/SiteManagementSystem(SoftwareEngineering)/Interface/IFieldService.cs b/SiteManagementSystem(SoftwareEngineering)/Interface/IFieldService.cs new file mode 100644 index 0000000..fac6cb0 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Interface/IFieldService.cs @@ -0,0 +1,8 @@ +namespace SiteManagementSystem_SoftwareEngineering_.Interface +{ + public interface IFieldService + { + public void AddField(string name, string value); + public void RentField(); + } +} diff --git a/SiteManagementSystem(SoftwareEngineering)/Program.cs b/SiteManagementSystem(SoftwareEngineering)/Program.cs index 568832d..76f1414 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Program.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Program.cs @@ -1,8 +1,10 @@ -using System.Text; +using System.Runtime.Serialization.Formatters; +using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using SiteManagementSystem_SoftwareEngineering_.Extension; +using SiteManagementSystem_SoftwareEngineering_.Interface; using SiteManagementSystem_SoftwareEngineering_.Service; var builder = WebApplication.CreateBuilder(args); @@ -50,7 +52,7 @@ builder }) .AddUserManager(options => options.HashSalt = builder.Configuration.GetValue("SecretSalt")! - ); + ).AddScoped(); var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/FieldService.cs b/SiteManagementSystem(SoftwareEngineering)/Service/FieldService.cs new file mode 100644 index 0000000..d993585 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/FieldService.cs @@ -0,0 +1,214 @@ +using System.Linq.Dynamic.Core; +using IronPython.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.Scripting.Hosting; +using SiteManagementSystem_SoftwareEngineering_.Entity; +using SiteManagementSystem_SoftwareEngineering_.Interface; + +namespace SiteManagementSystem_SoftwareEngineering_.Service +{ + public enum FieldType + { + Unspecified, + Tennis, + Basketball, + Badminton + } + + public class FieldService : IFieldService + { + private readonly EntityFrameworkPythonCompatibilityAndInterpretationLayer _layer; + private readonly ScriptEngine _engine = Python.CreateEngine(); + private readonly dynamic _service; + + public FieldService(SQLService storageService) + { + _layer = new EntityFrameworkPythonCompatibilityAndInterpretationLayer(storageService); + var _engine = Python.CreateEngine(); + var searchPaths = _engine.GetSearchPaths(); + searchPaths.Add(@"./Service/PythonServiceFile/"); + _engine.SetSearchPaths(searchPaths); + var source = _engine.CreateScriptSourceFromFile(@"./Service/PythonServiceFile/demo.py"); + var scope = _engine.CreateScope(); + scope.SetVariable("LAYER", _layer); + source.Execute(scope); + _service = scope.GetVariable("Service")(); + } + + public void AddField(string name, string value) + { + var t = (Field) + _service.AddField( + new Field + { + Name = "t1", + Position = "t2", + OpenTime = "t3" + } + ); + Console.WriteLine( + $"{t.Id},{t.Name},{t.Type}" + ); + //t(); + //Console.WriteLine(_service.AddField()); + throw new NotImplementedException(); + } + + public void RentField() + { + throw new NotImplementedException(); + } + } + + public class EntityFrameworkPythonCompatibilityAndInterpretationLayer + { + public readonly SQLHelperService FieldDb; + public readonly SQLHelperService RecordDb; + + public EntityFrameworkPythonCompatibilityAndInterpretationLayer(SQLService storageService) + { + FieldDb = new SQLHelperService(storageService, nameof(storageService.Fields)); + RecordDb = new SQLHelperService( + storageService, + nameof(storageService.UserFieldRecords) + ); + } + } + + public class SQLHelperService + where TEntity : class, new() + { + private readonly SQLService _sqlService; + private readonly DbSet _dbSet; + + public SQLHelperService(SQLService sqlService, string dbName) + { + _sqlService = sqlService; + if (dbName.IsNullOrEmpty()) + dbName = typeof(TEntity).Name; + _dbSet = + _sqlService.GetType().GetProperty(dbName)?.GetValue(_sqlService) as DbSet + ?? throw new InvalidOperationException( + $"SQLHelper don't have DbSet which named {dbName}." + ); + } + + public SQLHelperService Add(TEntity entity) => + Process((dbSet) => dbSet.Add(entity)); + + private SQLHelperService Update(TEntity oldEntity, TEntity newEntity) => + Process( + (dbSet) => + { + dbSet.Remove(oldEntity); + dbSet.Add(newEntity); + } + ); + + public SQLHelperService Update(TEntity entity, string key, TValue value) + { + var t = FindAll(key, value); + switch (t.Count()) + { + case 0: + throw new InvalidOperationException("No values match the criteria!"); + case 1: + Update(t.First(), entity); + break; + default: + throw new InvalidOperationException("Multiple values match the criteria!"); + } + return this; + } + + public SQLHelperService AddOrUpdate( + TEntity entity, + string key, + TValue value + ) + { + var t = FindAll(key, value); + switch (t.Count()) + { + case 0: + Add(entity); + break; + case 1: + Update(t.First(), entity); + break; + default: + throw new InvalidOperationException("Multiple values match the criteria!"); + } + return this; + } + + public TEntity? FindFirst(string key, TValue value) + { + TEntity? ans = null; + if (value is null) + Process(key, (dbSet) => ans = dbSet.Where($"{key} == null").FirstOrDefault()); + else + Process(key, (dbSet) => ans = dbSet.Where($"{key} == @0", value).FirstOrDefault()); + return ans; + } + + public IEnumerable FindAll(string key, TValue value) + { + IEnumerable ans = null!; + var y = typeof(TEntity).GetType().GetProperty(key); + if (value is null) + Process(key, (dbSet) => ans = dbSet.Where($"{key} == null").ToList()); + else + Process(key, (dbSet) => ans = dbSet.Where($"{key} == @0", value).ToList()); + return ans; + } + + public IEnumerable GetFirstNElements(int n) + { + List ans = null!; + Process((dbSet) => ans = dbSet.Take(n).ToList()); + return ans; + } + + public SQLHelperService Delete(TEntity entity) => + Process((dbSet) => dbSet.Remove(entity)); + + public SQLHelperService TryDelete(string key, TValue value) + { + var t = FindFirst(key, value); + if (t is null) + return this; + return Process((dbSet) => dbSet.Remove(t)); + } + + public SQLHelperService Save() + { + _sqlService.SaveChanges(); + return this; + } + + public SQLHelperService DeleteAll(string key, TValue value) => + Process((dbSet) => dbSet.RemoveRange(FindAll(key, value))); + + public SQLHelperService Process(Action> action) + { + action(_dbSet); + _sqlService.SaveChanges(); + return this; + } + + public TEntity GetDefaultEntity() => new(); + + public SQLHelperService Process(string key, Action> action) + { + if (typeof(TEntity).GetProperty(key) is null) + throw new InvalidOperationException( + $"{typeof(TEntity).Name} does not have the property key: {key}" + ); + action(_dbSet); + _sqlService.SaveChanges(); + return this; + } + } +} diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/demo.py b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/demo.py new file mode 100644 index 0000000..d213d77 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/demo.py @@ -0,0 +1,17 @@ +from layer import Layer +from field import Field +from user import User +from user_field import UserFieldRecord + + + + + +class Service: + layer = Layer(LAYER) + x = 16 + + def AddField(self, cs_field) -> str: + field = Field(cs_field) + self.layer.add_field(field) + return "" diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/field.py b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/field.py new file mode 100644 index 0000000..f447910 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/field.py @@ -0,0 +1,45 @@ +import clr +clr.AddReference('System') +from System import Guid + +class FieldType: + UNSPECIFIED = 0 + TENNIS = 1 + BASKETBALL = 2 + BADMINTON = 3 + + +class Field: + id = "" + name = "" + position = "" + open_time = "" + type = FieldType.UNSPECIFIED + + def __init__(self, *args, **kwargs): + if len(args) == 0: + pass + elif len(args) == 1: + field = args[0] + self.id = field.Id.ToString() + self.name = field.Name + self.position = field.Position + self.open_time = field.OpenTime + self.type = field.Type + elif len(args) == 4: + self.id, self.name, self.position, self.type = args + else: + raise ValueError("Invalid arguments for Field initialization") + + def __str__(self): + return f"Field: Id: {self.id}, Name: {self.name}, Position: {self.position}, Type: {self.type}" + + def parse_to_csharp_object(self, empty_field): + empty_field.Id = Guid.Parse(self.id) + empty_field.Name = self.name + empty_field.Position = self.position + empty_field.OpenTime = self.open_time + print(FieldType.UNSPECIFIED) + print(self.type) + empty_field.Type = self.type + return empty_field diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/layer.py b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/layer.py new file mode 100644 index 0000000..b2e853e --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/layer.py @@ -0,0 +1,37 @@ +import clr +from user import User +from field import Field +from user_field import UserFieldRecord + +clr.AddReference('System') +from System import Guid, DateTime + + +class Layer: + def __init__(self, layer): + self._field_db = layer.FieldDb + self._record_db = layer.RecordDb + + def add_field(self, field: Field) -> 'Layer': + self._field_db.Add(field.parse_to_csharp_object(self._field_db.GetDefaultEntity())) + return self + + # The value property will + def find_field(self, key: str, value: str) -> [Field]: + return [Field(t) for t in self._field_db.FindAll(key, Guid.Parse(value))] + + def remove_field(self, field: Field) -> 'Layer': + self._field_db.TryDelete(field.id, field.parse_to_csharp_object(self._field_db.GetDefaultEntity()).Id) + return self + + def add_record(self, record: UserFieldRecord) -> 'Layer': + self._record_db.Add(record.parse_to_csharp_object(self._record_db.GetDefaultEntity())) + return self + + def find_record(self, key: str, value: str) -> [UserFieldRecord]: + return [UserFieldRecord(t) for t in self._record_db.FindAll(key, Guid.Parse(value))] + + # One User only allowed to book one field at a time + def remove_record(self, record: UserFieldRecord) -> 'Layer': + self._record_db.TryDelete("Uid", record.parse_to_csharp_object(self._record_db.GetDefaultEntity()).Uid) + return self diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user.py b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user.py new file mode 100644 index 0000000..6d169b8 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user.py @@ -0,0 +1,18 @@ + + +class RoleNames: + NOT_SUPPORT = 0 + COMMON_USER = 1 + ADMINISTRATOR = 2 + + +class User: + id = "" + role = RoleNames.NOT_SUPPORT + name = "" + + # x: + def __init__(self, user): + self.id = user.Id.ToString() + self.role = user.Role + self.role = user.Name diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user_field.py b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user_field.py new file mode 100644 index 0000000..eb6ce01 --- /dev/null +++ b/SiteManagementSystem(SoftwareEngineering)/Service/PythonServiceFile/user_field.py @@ -0,0 +1,41 @@ +from field import * +from user import * +import time +import clr + +clr.AddReference('System') +from System import Guid, Convert + + +class UserFieldRecord: + fid = "" + uid = "" + start_time: time.struct_time + end_time: time.struct_time + + def __init__(self, *args, **kwargs): + if len(args) == 0: + pass + if len(args) == 1: + field_record = args[0] + self.fid = field_record.Fid.ToString() + self.uid = field_record.Uid.ToString() + self.start_time = time.strptime(field_record.StartTime.ToString(), "%Y-%m-%d %H:%M:%S") + self.end_time = time.strptime(field_record.EndTime.ToString(), "%Y-%m-%d %H:%M:%S") + elif len(args) == 4 and isinstance(args[0], User) and isinstance(args[1], Field) and isinstance(args[2], + time.struct_time) and isinstance( + args[3], time.struct_time): + user, field, start_time, end_time = args + self.fid = field.id + self.uid = user.id + self.start_time = start_time + self.end_time = end_time + else: + raise ValueError("Invalid arguments for UserFieldRecord initialization") + + def parse_to_csharp_object(self, empty_field_record): + empty_field_record.Fid = Guid.Parse(self.fid) + empty_field_record.Uid = Guid.Parse(self.uid) + empty_field_record.StartTime = Convert.ToDateTime(time.strftime("%Y-%m-%d %H:%M:%S", self.start_time)) + empty_field_record.EndTime = Convert.ToDateTime(time.strftime("%Y-%m-%d %H:%M:%S", self.end_time)) + return empty_field_record diff --git a/SiteManagementSystem(SoftwareEngineering)/Service/SQLService.cs b/SiteManagementSystem(SoftwareEngineering)/Service/SQLService.cs index f27b7c5..b8dfd16 100644 --- a/SiteManagementSystem(SoftwareEngineering)/Service/SQLService.cs +++ b/SiteManagementSystem(SoftwareEngineering)/Service/SQLService.cs @@ -12,5 +12,7 @@ namespace SiteManagementSystem_SoftwareEngineering_.Service Database.EnsureCreated(); } public DbSet Users { get; set; } + public DbSet Fields { get; set; } + public DbSet UserFieldRecords{get;set;} } } diff --git a/SiteManagementSystem(SoftwareEngineering)/SiteManagementSystem(SoftwareEngineering).csproj b/SiteManagementSystem(SoftwareEngineering)/SiteManagementSystem(SoftwareEngineering).csproj index 9f1b7cc..d88f9e9 100644 --- a/SiteManagementSystem(SoftwareEngineering)/SiteManagementSystem(SoftwareEngineering).csproj +++ b/SiteManagementSystem(SoftwareEngineering)/SiteManagementSystem(SoftwareEngineering).csproj @@ -15,6 +15,11 @@ + + + + +