diff --git a/.gitignore b/.gitignore index 5e4cc56..fd076d2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /.idea/ /bin/ /obj/ +*.DotSettings +*.DotSettings.user diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 4674690..dffd18e 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -1,5 +1,8 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using fxl.codes.kisekae.Models; +using fxl.codes.kisekae.Services; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -8,17 +11,30 @@ namespace fxl.codes.kisekae.Controllers public class HomeController : Controller { private readonly ILogger _logger; + private readonly ConfigurationReaderService _readerService; - public HomeController(ILogger logger) + public HomeController(ILogger logger, ConfigurationReaderService readerService) { _logger = logger; + _readerService = readerService; } + [HttpGet] public IActionResult Index() { return View(); } + [HttpPost] + public IActionResult LoadConfiguration(IFormFile file) + { + if (!(file?.FileName.EndsWith("cnf", StringComparison.InvariantCultureIgnoreCase) ?? false)) + throw new Exception("Please select a *.cnf file"); + + var model = _readerService.ReadCnf(file); + return View("Index"); + } + public IActionResult Privacy() { return View(); diff --git a/Models/CelModel.cs b/Models/CelModel.cs new file mode 100644 index 0000000..be2a314 --- /dev/null +++ b/Models/CelModel.cs @@ -0,0 +1,60 @@ +using System; +using System.Text.RegularExpressions; + +namespace fxl.codes.kisekae.Models +{ + public class CelModel + { + public const string Regex = "#([0-9]*)[\\.]?([0-9]*?)\\s([a-zA-Z\\-0-9]*\\.[cCeElL]+)\\s[\\*]?([0-9]*)?\\s?:([0-9\\s]*);(.*)"; + + public CelModel(string line) + { + var matcher = new Regex(Regex); + var match = matcher.Match(line); + + foreach (var group in matcher.GetGroupNames()) + { + if (group == "0") continue; + + match.Groups.TryGetValue(group, out var value); + if (string.IsNullOrEmpty(value?.Value)) continue; + + switch (group) + { + case "1": + Id = int.Parse(value.Value); + break; + case "2": + Fix = int.Parse(value.Value); + break; + case "3": + FileName = value.Value; + break; + case "4": + PaletteId = int.Parse(value.Value); + break; + case "5": + foreach (var id in value.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries)) + { + Sets[int.Parse(id)] = true; + } + break; + case "6": + Comment = value.Value; + break; + } + } + } + + public int Id { get; } + public int Fix { get; } + public string FileName { get; } + public int PaletteId { get; } + public bool[] Sets { get; } = new bool[10]; + public string Comment { get; } + + public int CurrentPaletteId { get; set; } + public Point[] InitialPositions { get; set; } = new Point[10]; + public Point[] CurrentPositions { get; set; } = new Point[10]; + } +} \ No newline at end of file diff --git a/Models/ConfigurationModel.cs b/Models/ConfigurationModel.cs new file mode 100644 index 0000000..60cae5f --- /dev/null +++ b/Models/ConfigurationModel.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace fxl.codes.kisekae.Models +{ + public class ConfigurationModel + { + private readonly string _originalDirectory; + + public ConfigurationModel(string originalDirectory) + { + _originalDirectory = originalDirectory; + } + + public int Height { get; set; } + public int Width { get; set; } + public int BorderColorIndex { get; set; } + + public List Palettes { get; } = new(); + public List Cels { get; } = new(); + } +} \ No newline at end of file diff --git a/Models/PaletteModel.cs b/Models/PaletteModel.cs new file mode 100644 index 0000000..64ffc44 --- /dev/null +++ b/Models/PaletteModel.cs @@ -0,0 +1,36 @@ +using System.Text.RegularExpressions; + +namespace fxl.codes.kisekae.Models +{ + public class PaletteModel + { + private const string Regex = "%([a-zA-Z0-9\\-]*\\.[kKcCfF]+)[\\s]*;(.*)"; + + public string FileName { get; } + public string Comment { get; } + + public PaletteModel(string line) + { + var matcher = new Regex(Regex); + var match = matcher.Match(line); + + foreach (var group in matcher.GetGroupNames()) + { + if (group == "0") continue; + + match.Groups.TryGetValue(group, out var value); + if (string.IsNullOrEmpty(value?.Value)) continue; + + switch (group) + { + case "1": + FileName = value.Value; + break; + case "2": + Comment = value.Value; + break; + } + } + } + } +} \ No newline at end of file diff --git a/Models/Point.cs b/Models/Point.cs new file mode 100644 index 0000000..9b956b3 --- /dev/null +++ b/Models/Point.cs @@ -0,0 +1,8 @@ +namespace fxl.codes.kisekae.Models +{ + public class Point + { + public int X { get; set; } + public int Y { get; set; } + } +} \ No newline at end of file diff --git a/Services/ConfigurationReaderService.cs b/Services/ConfigurationReaderService.cs new file mode 100644 index 0000000..9d1981f --- /dev/null +++ b/Services/ConfigurationReaderService.cs @@ -0,0 +1,53 @@ +using System.IO; +using System.Text.RegularExpressions; +using fxl.codes.kisekae.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; + +namespace fxl.codes.kisekae.Services +{ + public class ConfigurationReaderService + { + private readonly ILogger _logger; + + public ConfigurationReaderService(ILogger logger) + { + _logger = logger; + } + + public ConfigurationModel ReadCnf(IFormFile file) + { + _logger.LogTrace($"Reading filename {file.FileName}"); + + var model = new ConfigurationModel(""); + + using var reader = new StreamReader(file.OpenReadStream()); + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + if (string.IsNullOrEmpty(line)) continue; + + switch (line.ToCharArray()[0]) + { + case '(': + var resolutionRegex = new Regex("\\(([0-9]*),([0-9]*)\\)"); + var resolutionMatch = resolutionRegex.Match(line); + model.Width = int.Parse(resolutionMatch.Groups[1].Value); + model.Height = int.Parse(resolutionMatch.Groups[2].Value); + break; + case '[': + model.BorderColorIndex = int.Parse(line.Replace("[", "")); + break; + case '%': + model.Palettes.Add(new PaletteModel(line)); + break; + case '#': + model.Cels.Add(new CelModel(line)); + break; + } + } + + return model; + } + } +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index af75aa5..6428811 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using fxl.codes.kisekae.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -23,7 +19,10 @@ namespace fxl.codes.kisekae // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddControllersWithViews(); + services.AddControllersWithViews() + .AddRazorRuntimeCompilation(); + + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -50,8 +49,8 @@ namespace fxl.codes.kisekae app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); + "default", + "{controller=Home}/{action=Index}/{id?}"); }); } } diff --git a/Styles/main.scss b/Styles/main.scss index e69de29..1843faf 100644 --- a/Styles/main.scss +++ b/Styles/main.scss @@ -0,0 +1,23 @@ +$fxl-gray: #263238; +$fxl-orange: #ff6e40; + +@use "@material/theme" with ( + $primary: $fxl-orange, + $on-primary: $fxl-gray +); + +@use "@material/icon-button"; +@use "@material/top-app-bar/mdc-top-app-bar"; +@use "@material/typography/mdc-typography"; + +html, body { + height: 100vh; + margin: 0; + padding: 0; +} + +body { + footer { + font-size: smaller; + } +} \ No newline at end of file diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index 378bcad..d561f08 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -2,7 +2,7 @@ ViewData["Title"] = "Home Page"; } -
-

Welcome

-

Learn about building Web apps with ASP.NET Core.

-
\ No newline at end of file +
+ + +
\ No newline at end of file diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 4ab4d7d..0106385 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -3,43 +3,33 @@ - @ViewData["Title"] - fxl.codes.kisekae - + Kisekae Online - @ViewData["Title"] + + + + -
- -
-
-
- @RenderBody() -
-
- -