From 211b3722191fad8d4ba017807aef5b0a4324fdb4 Mon Sep 17 00:00:00 2001 From: "Serg A. Verevkin" Date: Sat, 1 Mar 2025 11:47:14 +0700 Subject: [PATCH] initial commit --- .gitignore | 3 ++ Controllers/Field2Controller.cs | 60 +++++++++++++++++++++++ Controllers/FieldController.cs | 53 ++++++++++++++++++++ Controllers/WeatherForecastController.cs | 39 +++++++++++++++ Model/Field.cs | 19 ++++++++ Model/FieldManager.cs | 34 +++++++++++++ Model/Figure.cs | 10 ++++ Model/FigureMover.cs | 41 ++++++++++++++++ Model/IFieldManager.cs | 9 ++++ Model/RandomField.cs | 22 +++++++++ Program.cs | 28 +++++++++++ Properties/launchSettings.json | 30 ++++++++++++ Startup.cs | 62 ++++++++++++++++++++++++ TextFile.md | 11 +++++ WeatherForecast.cs | 15 ++++++ WebApplication1.csproj | 11 +++++ WebApplication1.csproj.user | 7 +++ WebApplication1.sln | 31 ++++++++++++ appsettings.Development.json | 9 ++++ appsettings.json | 10 ++++ 20 files changed, 504 insertions(+) create mode 100644 .gitignore create mode 100644 Controllers/Field2Controller.cs create mode 100644 Controllers/FieldController.cs create mode 100644 Controllers/WeatherForecastController.cs create mode 100644 Model/Field.cs create mode 100644 Model/FieldManager.cs create mode 100644 Model/Figure.cs create mode 100644 Model/FigureMover.cs create mode 100644 Model/IFieldManager.cs create mode 100644 Model/RandomField.cs create mode 100644 Program.cs create mode 100644 Properties/launchSettings.json create mode 100644 Startup.cs create mode 100644 TextFile.md create mode 100644 WeatherForecast.cs create mode 100644 WebApplication1.csproj create mode 100644 WebApplication1.csproj.user create mode 100644 WebApplication1.sln create mode 100644 appsettings.Development.json create mode 100644 appsettings.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e16852 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/ +obj/ +.vs/ \ No newline at end of file diff --git a/Controllers/Field2Controller.cs b/Controllers/Field2Controller.cs new file mode 100644 index 0000000..4da2c20 --- /dev/null +++ b/Controllers/Field2Controller.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1.Controllers +{ + [Route("api/v2/[controller]")] + [ApiController] + public class Field2Controller : ControllerBase + { + private IFieldManager _fm; + private ILogger _lg; + + /// + /// .ctor + /// + /// + public Field2Controller( + IFieldManager fm, + ILogger lg) + { + _fm = fm; + _lg = lg; + } + + + + [HttpPost(Name = "new")] + [Route("new")] + public Field StartNewGame() + { + return _fm.StartNewGame(); + } + [HttpPost(Name = "move")] + [Route("move")] + public Field Move(string identifier) + { + return _fm.Move(identifier); + } + + [HttpPost(Name = "move2")] + [Route("move2")] + public Field Move2(string identifier) + { + return _fm.Move(identifier); + } + + [HttpGet(Name = "list")] + [Route("list")] + public Field List(string identifier) + { + return _fm.List(identifier); + } + + } +} diff --git a/Controllers/FieldController.cs b/Controllers/FieldController.cs new file mode 100644 index 0000000..5f162c5 --- /dev/null +++ b/Controllers/FieldController.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1.Controllers +{ + [Route("api/v1/[controller]")] + [ApiController] + public class FieldController : ControllerBase + { + private IFieldManager _fm; + private ILogger _lg; + + /// + /// .ctor + /// + /// + public FieldController( + IFieldManager fm, + ILogger lg) + { + _fm = fm; + _lg = lg; + } + + + + [HttpPost(Name = "new")] + [Route("new")] + public Field StartNewGame() + { + return _fm.StartNewGame(); + } + [HttpPost(Name = "move")] + [Route("move")] + public Field Move(string identifier) + { + return _fm.Move(identifier); + } + + [HttpGet(Name = "list")] + [Route("list")] + public Field List(string identifier) + { + return _fm.List(identifier); + } + + } +} diff --git a/Controllers/WeatherForecastController.cs b/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..895da7f --- /dev/null +++ b/Controllers/WeatherForecastController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + SummaryWeather = Summaries[rng.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/Model/Field.cs b/Model/Field.cs new file mode 100644 index 0000000..acd9d41 --- /dev/null +++ b/Model/Field.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WebApplication1 +{ + + public class Field + { + public string identifier { get; } = Guid.NewGuid().ToString("N"); + public List
Figures { get; } = new List
(); + public bool MoveRandomFigure() + { + Random rr = new Random(); + int iPos = rr.Next(Figures.Count()); + return FigureMover.Move(Figures[iPos]); + } + } +} diff --git a/Model/FieldManager.cs b/Model/FieldManager.cs new file mode 100644 index 0000000..6614ff7 --- /dev/null +++ b/Model/FieldManager.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1 +{ + + public class FieldManager : IFieldManager + { + private List _fields = new List(); + + public Field StartNewGame() + { + var ff = new RandomField(2); + _fields.Add(ff); + return ff; + } + public Field Move(string identifier) + { + var ff = _fields.FirstOrDefault(f => f.identifier.Equals(identifier)); + if (ff == null) return null; + ff.MoveRandomFigure(); + return ff; + } + + public Field List(string identifier) + { + var ff = _fields.FirstOrDefault(f => f.identifier.Equals(identifier)); + if (ff == null) return null; + return ff; + } + } +} \ No newline at end of file diff --git a/Model/Figure.cs b/Model/Figure.cs new file mode 100644 index 0000000..2b064a6 --- /dev/null +++ b/Model/Figure.cs @@ -0,0 +1,10 @@ +namespace WebApplication1 +{ + public class Figure + { + public int FigureColor { get; set; } + public int FigureType { get; set; } + public int PosX { get; set; } + public int PosY { get; set; } + } +} diff --git a/Model/FigureMover.cs b/Model/FigureMover.cs new file mode 100644 index 0000000..33f60d2 --- /dev/null +++ b/Model/FigureMover.cs @@ -0,0 +1,41 @@ +namespace WebApplication1 +{ + public static class FigureMover + { + public static readonly int FieldYMin = 0; + public static readonly int FieldYMax = 7; + public static readonly int FieldXMin = 0; + public static readonly int FieldXMax = 7; + + public static bool Move(Figure figure) + { + if (figure.FigureType == 1) + { + return h_MoveSimple(figure); + } + return false; + } + + private static bool h_MoveSimple(Figure figure) + { + bool bDirectionUp = false; + if (figure.FigureColor == 1) + { + bDirectionUp = true; + } + int iInc = bDirectionUp ? 1 : -1; + figure.PosY += iInc; + if (figure.PosY < FieldYMin) + { + figure.PosY = FieldYMin; + return false; + } + if (figure.PosY > FieldYMax) + { + figure.PosY = FieldYMax; + return false; + } + return true; + } + } +} diff --git a/Model/IFieldManager.cs b/Model/IFieldManager.cs new file mode 100644 index 0000000..6b0ccdb --- /dev/null +++ b/Model/IFieldManager.cs @@ -0,0 +1,9 @@ +namespace WebApplication1 +{ + public interface IFieldManager + { + public Field StartNewGame(); + Field Move(string identifier); + Field List(string identifier); + } +} \ No newline at end of file diff --git a/Model/RandomField.cs b/Model/RandomField.cs new file mode 100644 index 0000000..29ebd09 --- /dev/null +++ b/Model/RandomField.cs @@ -0,0 +1,22 @@ +using System; + +namespace WebApplication1 +{ + public class RandomField : Field + { + public RandomField(int iCount) + { + Random rr = new Random(); + for (int ii = 0; ii < iCount; ii++) + { + this.Figures.Add(new Figure() + { + FigureColor = rr.Next(2), + FigureType = rr.Next(1), + PosX = rr.Next(FigureMover.FieldXMin, FigureMover.FieldXMax), + PosY = rr.Next(FigureMover.FieldYMin, FigureMover.FieldYMax), + }); + } + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..d3f224d --- /dev/null +++ b/Program.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1 +{ + 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(); + }); + } +} diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..6708034 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49746" + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WebApplication1": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Startup.cs b/Startup.cs new file mode 100644 index 0000000..2fd1b19 --- /dev/null +++ b/Startup.cs @@ -0,0 +1,62 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WebApplication1 +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + + services.AddControllers(); + + services.AddSingleton(new FieldManager()); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" }); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseSwagger(); + app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication1 v1")); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/TextFile.md b/TextFile.md new file mode 100644 index 0000000..ecc2326 --- /dev/null +++ b/TextFile.md @@ -0,0 +1,11 @@ +# Задача +Продемонстрировать работающий сервис с реализацией логики вне контроллера + +# Алгоритм решения задачи +- Создать пустое веб-апи сервис на основе шаблона +- Создать класс, осуществляющий прогноз погоды на следующий день по предыдущему +- Встроить класс в сервисную коллекцию (Singleton) +- Получить класс через Dependency Injection (конструктор) +- Использовать класс для выдачи результата + +-- SET PATH=%PATH%;"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\mingw32\bin" \ No newline at end of file diff --git a/WeatherForecast.cs b/WeatherForecast.cs new file mode 100644 index 0000000..d7653e7 --- /dev/null +++ b/WeatherForecast.cs @@ -0,0 +1,15 @@ +using System; + +namespace WebApplication1 +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string SummaryWeather { get; set; } + } +} diff --git a/WebApplication1.csproj b/WebApplication1.csproj new file mode 100644 index 0000000..2884716 --- /dev/null +++ b/WebApplication1.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/WebApplication1.csproj.user b/WebApplication1.csproj.user new file mode 100644 index 0000000..efbdd2d --- /dev/null +++ b/WebApplication1.csproj.user @@ -0,0 +1,7 @@ + + + + ApiControllerEmptyScaffolder + root/Common/Api + + \ No newline at end of file diff --git a/WebApplication1.sln b/WebApplication1.sln new file mode 100644 index 0000000..286708b --- /dev/null +++ b/WebApplication1.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30709.132 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplication1", "WebApplication1.csproj", "{1E41DB1E-938D-4030-B8C7-B90C64A7B6CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp2", "..\ConsoleApp2\ConsoleApp2.csproj", "{95D5C921-BDC7-4A88-AAAD-EF09B81221EF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E41DB1E-938D-4030-B8C7-B90C64A7B6CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E41DB1E-938D-4030-B8C7-B90C64A7B6CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E41DB1E-938D-4030-B8C7-B90C64A7B6CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E41DB1E-938D-4030-B8C7-B90C64A7B6CC}.Release|Any CPU.Build.0 = Release|Any CPU + {95D5C921-BDC7-4A88-AAAD-EF09B81221EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95D5C921-BDC7-4A88-AAAD-EF09B81221EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95D5C921-BDC7-4A88-AAAD-EF09B81221EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95D5C921-BDC7-4A88-AAAD-EF09B81221EF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F485B05F-F662-4D8B-8E28-EB57AA152B44} + EndGlobalSection +EndGlobal diff --git a/appsettings.Development.json b/appsettings.Development.json new file mode 100644 index 0000000..8983e0f --- /dev/null +++ b/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ b/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}