diff --git a/.gitignore b/.gitignore index 00022acfc..3716c2a5a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,22 +6,29 @@ *.exe *.dll *.bak +*.user +*.bak /.svn /.vs /bin +/obj +/obj.net /*/.vs -/CSharpBible/*/.vs /*/obj /*/bin /*/TestResults /*/*/TestResults +/*/*/.vs /*/*/obj /*/*/bin /*/*/*/.vs /*/*/*/obj /*/*/*/bin +/*/*/*/TestResults /CSharpBible/Help /CSharpBible/Mobile +/CSharpBible/Web +/CSharpBible/WinUI /CSharpBible/AboutEx/obj /CSharpBible/AboutEx/publish /CSharpBible/AboutExTests/bin @@ -42,9 +49,12 @@ /CSharpBible/CSV_ViewerTest/obj /CSharpBible/ConsoleMouseApp/obj /CSharpBible/ConsoleLib/obj +/CSharpBible/DB/ADO_Test /CSharpBible/DataGridEx/obj /CSharpBible/DataGridExWPF/obj /CSharpBible/packages +/CSharpBible/Basics/.vs +/CSharpBible/Basics/.vs /NUnitTestProject1/NUnitTestProject1/obj /TestStatements/.vs /TestStatements/AsyncExample/obj @@ -66,21 +76,6 @@ /CSharpProgrammierHandbuch/Fibonacci2 /TestStatements/AsyncExampleWPF /TestStatements/Tutorials/obj/Debug -/CSharpBible/Basics/.vs -/CSharpBible/Basics/.vs -*.user -*.bak -/CSharpBible/Calc/.vs -/CSharpBible/DB/.vs -/CSharpBible/Mobile -/CSharpBible/MVVM_Tutorial/.vs -/CSharpBible/Calc/Help -/CSharpBible/DependencyInjection/.vs -/CSharpBible/CSharpBibleTest/.vs -/CSharpBible/Games/.vs -/CSharpBible/Graphics/.vs -/GenFreeWin/.vs -/JC-AMS/.vs /obj /obj.net /TestStatements/Help diff --git a/CSharpBible/ConsoleDisplay/View/ITileDef.cs b/CSharpBible/ConsoleDisplay/View/ITileDef.cs new file mode 100644 index 000000000..835b61148 --- /dev/null +++ b/CSharpBible/ConsoleDisplay/View/ITileDef.cs @@ -0,0 +1,25 @@ +// *********************************************************************** +// Assembly : ConsoleDisplay +// Author : Mir +// Created : 08-19-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-27-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Drawing; + +namespace ConsoleDisplay.View +{ + public interface ITileDef + { + Size TileSize { get; } + + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile); + } +} \ No newline at end of file diff --git a/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs b/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs new file mode 100644 index 000000000..ac7df635c --- /dev/null +++ b/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs @@ -0,0 +1,39 @@ +// *********************************************************************** +// Assembly : ConsoleDisplay +// Author : Mir +// Created : 07-16-2022 +// +// Last Modified By : Mir +// Last Modified On : 07-24-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; + +namespace ConsoleDisplay.View +{ + public interface IConsole + { + ConsoleColor ForegroundColor { get; set; } + ConsoleColor BackgroundColor { get; set; } + bool IsOutputRedirected { get; } + bool KeyAvailable { get; } + int LargestWindowHeight { get; } + string Title { get; set; } + int WindowHeight { get; set; } + int WindowWidth { get; set; } + + void Beep(int freq, int len); + void Clear(); + (int Left, int Top) GetCursorPosition(); + ConsoleKeyInfo? ReadKey(); + string ReadLine(); + void SetCursorPosition(int left, int top); + void Write(char ch); + void Write(string? st); + void WriteLine(string? st = ""); + } +} \ No newline at end of file diff --git a/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs b/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs new file mode 100644 index 000000000..faa64df4a --- /dev/null +++ b/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Assembly : ConsoleDisplay +// Author : Mir +// Created : 08-19-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-27-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Drawing; + +namespace ConsoleDisplay.View +{ + public interface ITileDisplay + { + T? this[Point Idx] { get; set; } + + Point Position { get; } + Size DispSize { get; } + Size TileSize { get; } + IConsole console { get; } + Point DispOffset { get; set; } + Func? FncGetTile { get; set; } + Func? FncOldPos { get; set; } + + void FullRedraw(); + void SetDispSize(Size size); + void Update(bool e); + void WriteTile(PointF p, T tile); + } +} \ No newline at end of file diff --git a/CSharpBible/ConsoleDisplay/View/TileDefBase.cs b/CSharpBible/ConsoleDisplay/View/TileDefBase.cs index 46c2fb1a2..f3539e4ab 100644 --- a/CSharpBible/ConsoleDisplay/View/TileDefBase.cs +++ b/CSharpBible/ConsoleDisplay/View/TileDefBase.cs @@ -19,7 +19,7 @@ namespace ConsoleDisplay.View { /// Class TileDef. /// /// The type of the enum. - public abstract class TileDefBase + public abstract class TileDefBase : ITileDef { /// /// Gets the tile definition. diff --git a/CSharpBible/ConsoleDisplay/View/TileDisplay.cs b/CSharpBible/ConsoleDisplay/View/TileDisplay.cs index 4ce2ccf71..efbe8db75 100644 --- a/CSharpBible/ConsoleDisplay/View/TileDisplay.cs +++ b/CSharpBible/ConsoleDisplay/View/TileDisplay.cs @@ -63,7 +63,7 @@ public class TileDisplay: ITileDisplay /// it returns the default-tileDef when the local tileDef isn't set. /// /// The tile definition. - public TileDefBase? TileDef { get => _tileDef ?? tileDef; set => _tileDef = value; } + public ITileDef? TileDef { get => _tileDef ?? tileDef; set => _tileDef = value; } public Point DispOffset { get; set; } = Point.Empty; public Func? FncGetTile { get; set; } @@ -96,7 +96,7 @@ public class TileDisplay: ITileDisplay /// /// The (local) tile-definition /// - private TileDefBase? _tileDef; + private ITileDef? _tileDef; #endregion #endregion @@ -154,29 +154,20 @@ private static void WriteTileChunk(IConsole console,Point Offset, PointF p, (str /// /// Initializes a new instance of the class. /// - public TileDisplay() : this(new MyConsole(),Point.Empty,Size.Empty){} + public TileDisplay() : this(new MyConsole(),tileDef!,Point.Empty,Size.Empty){} /// /// Initializes a new instance of the class. /// - public TileDisplay(IConsole console) : this(console, Point.Empty, Size.Empty) { } + public TileDisplay(IConsole console,ITileDef tileDef) : this(console, tileDef, Point.Empty, Size.Empty) { } /// /// Initializes a new instance of the class. /// /// The position. /// The size. - public TileDisplay(IConsole console,Point position, Size size) : this(console, position, size,tileDef?.TileSize ?? new Size(4,2)) { } + public TileDisplay(IConsole console, ITileDef tileDef, Point position, Size size) : this(console, tileDef, position, size,tileDef?.TileSize ?? new Size(4,2)) { } - /// - /// Initializes a new instance of the class. - /// - /// The position. - /// The size. - /// The tile-definition. - public TileDisplay(IConsole console,Point position, Size size, TileDefBase aTileDef) : this(console,position, size, aTileDef.TileSize ) { - TileDef = aTileDef; - } /// /// Initializes a new instance of the class. @@ -184,16 +175,23 @@ public TileDisplay(IConsole console,Point position, Size size, TileDefBase aTile /// The position. /// The size. /// Size of the tile. - public TileDisplay(IConsole console,Point position,Size size, Size tileSize) + public TileDisplay(IConsole console, ITileDef tileDef, Point position,Size size, Size tileSize) { this.console = console; + _tileDef = tileDef; _rect.Location = position; _tileSize = tileSize != Size.Empty ? tileSize : new Size(4, 2); + SetDispSize(size); + } + + public void SetDispSize(Size size) + { if (size == Size.Empty) - _size = new Size(console.WindowWidth / _tileSize.Width,console.WindowHeight/_tileSize.Height); + _size = new Size(console.WindowWidth / _tileSize.Width, console.WindowHeight / _tileSize.Height); else _size = size; - _rect.Size = new Size(_size.Width * _tileSize.Width,_size.Height * _tileSize.Height); + _rect.Size = new Size(_size.Width * _tileSize.Width, _size.Height * _tileSize.Height); + _changed = true; } #region private Methods @@ -332,22 +330,15 @@ public TileDisplay() : base() { } /// /// Initializes a new instance of the class. /// - public TileDisplay(IConsole console) : base(console) { } + public TileDisplay(IConsole console, ITileDef tileDef) : base(console,tileDef) { } /// /// Initializes a new instance of the class. /// /// The position. /// The size. - public TileDisplay(IConsole console,Point position, Size size) : base(console, position, size) { } + public TileDisplay(IConsole console,ITileDef tileDef, Point position, Size size) : base(console, tileDef, position, size) { } - /// - /// Initializes a new instance of the class. - /// - /// The position. - /// The size. - /// The tile-definition. - public TileDisplay(IConsole console, Point position, Size size, TileDefBase aTileDef) : base(console, position, size, aTileDef) { } /// /// Initializes a new instance of the class. @@ -355,5 +346,5 @@ public TileDisplay(IConsole console, Point position, Size size, TileDefBase aTil /// The position. /// The size. /// Size of the tile. - public TileDisplay(IConsole console, Point position, Size size, Size tileSize) : base(console, position, size, tileSize) { } + public TileDisplay(IConsole console, ITileDef tileDef, Point position, Size size, Size tileSize) : base(console, tileDef, position, size, tileSize) { } } diff --git a/CSharpBible/Games/CsEpiphany/Model/Direction.cs b/CSharpBible/Games/CsEpiphany/Model/Direction.cs new file mode 100644 index 000000000..242ca2ade --- /dev/null +++ b/CSharpBible/Games/CsEpiphany/Model/Direction.cs @@ -0,0 +1,10 @@ +namespace CsEpiphany.Model +{ + public enum Direction + { + UP, + DOWN, + RIGHT, + LEFT + } +} \ No newline at end of file diff --git a/CSharpBible/Games/Game_Base/Helper/CRandom.cs b/CSharpBible/Games/Game_Base/Helper/CRandom.cs new file mode 100644 index 000000000..5d2cfa3b7 --- /dev/null +++ b/CSharpBible/Games/Game_Base/Helper/CRandom.cs @@ -0,0 +1,22 @@ +using BaseLib.Interfaces; +using System; + +namespace BaseLib.Helper; + +public class CRandom :IRandom +{ + private Random _random; + + public CRandom() + { + _random = new Random(); + } + + public int Next(int v1, int v2) => v2 !=-1 || v1 _random.NextDouble(); + + public int NextInt() => _random.Next(); + + public void Seed(int value) => _random = new Random(value); +} diff --git a/CSharpBible/Games/Game_Base/Helper/SysTime.cs b/CSharpBible/Games/Game_Base/Helper/SysTime.cs new file mode 100644 index 000000000..f580bbe9f --- /dev/null +++ b/CSharpBible/Games/Game_Base/Helper/SysTime.cs @@ -0,0 +1,12 @@ +using BaseLib.Interfaces; +using System; + +namespace BaseLib.Helper; + +public class SysTime : ISysTime +{ + public static Func GetNow {get; set;} = () => DateTime.Now; + public DateTime Now => GetNow(); + public DateTime Today => GetNow().Date; + +} diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs new file mode 100644 index 000000000..55e76295e --- /dev/null +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs @@ -0,0 +1,6 @@ +namespace BaseLib.Interfaces; + +public interface IHasValue +{ + object? Value { get; } +} diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs new file mode 100644 index 000000000..2f9c1cb91 --- /dev/null +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs @@ -0,0 +1,10 @@ +using System; + +namespace BaseLib.Interfaces; + +public interface ILog +{ + public void Log(string message); + + public void Log(string message, Exception exception); +} diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs index caa665b35..d2b22b030 100644 --- a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs @@ -29,7 +29,7 @@ public interface IPlacedObject /// /// Occurs when [on place change]. /// - event EventHandler<(Point oP, Point nP)> OnPlaceChange; + event EventHandler<(Point oP, Point nP)>? OnPlaceChange; #if NET6_0_OR_GREATER /// /// Gets or sets the place. diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs new file mode 100644 index 000000000..159a6d68d --- /dev/null +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs @@ -0,0 +1,31 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-24-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace Game_Base.Model; + +public interface IPlayfield2D where T : class +{ + T? this[Point p] { get;set; } + + Size PfSize { get; set; } + Rectangle Rect { get; } + IEnumerable Items { get; } + + event EventHandler<(string prop, object? oldVal, object? newVal)>? OnDataChanged; + + bool IsInside(Point P); +} \ No newline at end of file diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs new file mode 100644 index 000000000..fcb45ab39 --- /dev/null +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs @@ -0,0 +1,46 @@ +// *********************************************************************** +// Assembly : MVVM_BaseLib +// Author : Mir +// Created : 07-01-2024 +// +// Last Modified By : Mir +// Last Modified On : 07-01-2024 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +/// +/// The Interfaces namespace. +/// +namespace BaseLib.Interfaces; + +/// +/// Interface IRandom +/// +public interface IRandom +{ + /// + /// Gets the next random number between v1 and v2 if v2 is set, between 0 and v1 if v2 is not set. + /// + /// The first boarder + /// The second boarder + /// System.Int32. + int Next(int v1, int v2=-1); + /// + /// Gets the next random number as double between ]0 and 1[. + /// + /// System.Double. + double NextDouble(); + /// + /// Gets the next random number as int. + /// + /// System.Int32. + int NextInt(); + /// + /// Specifies the seed-value. + /// + /// The value. + void Seed(int value); +} diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs new file mode 100644 index 000000000..d74e68f63 --- /dev/null +++ b/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs @@ -0,0 +1,9 @@ +using System; + +namespace BaseLib.Interfaces; + +public interface ISysTime +{ + DateTime Now { get; } + DateTime Today { get; } +} diff --git a/CSharpBible/Games/Games.sln b/CSharpBible/Games/Games.sln index 0cd342ca4..b1ce1766e 100644 --- a/CSharpBible/Games/Games.sln +++ b/CSharpBible/Games/Games.sln @@ -113,6 +113,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTileEdit", "VTileEdit\VTil EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Werner_Flaschbier_ConsoleTests", "Werner_Flaschbier_BaseTests\Werner_Flaschbier_ConsoleTests.csproj", "{2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTileEditTests", "VTileEditTests\VTileEditTests.csproj", "{AC41269E-DFCB-4656-BE50-AB6A7FABFB37}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -299,6 +301,10 @@ Global {2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Release|Any CPU.ActiveCfg = Release|Any CPU {2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Release|Any CPU.Build.0 = Release|Any CPU + {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CSharpBible/Games/Snake_Base/Models/Apple.cs b/CSharpBible/Games/Snake_Base/Models/Apple.cs new file mode 100644 index 000000000..fb7c3e772 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Apple.cs @@ -0,0 +1,47 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using Game_Base.Model; +using Snake_Base.Models.Interfaces; +using System.Drawing; + +/// +/// The Models namespace. +/// +/// +namespace Snake_Base.Models +{ + /// + /// Class Apple. + /// Implements the + /// + /// + public class Apple : SnakeGameObject + { + /// + /// Initializes a new instance of the class. + /// + public Apple():base() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The point. + /// The PLF. + public Apple(Point point, IPlayfield2D? plf = null) : base(point, plf) + { + } + } +} diff --git a/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs b/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs new file mode 100644 index 000000000..0c5538fda --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs @@ -0,0 +1,95 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-26-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +/// +/// The ViewModel namespace. +/// +/// +namespace Snake_Base.Models.Data +{ + /// + /// Enum SnakeTiles + /// + public enum SnakeTiles + { + /// + /// The empty field + /// + Empty, //0 + /// + /// The wall + /// + Wall, //1 + /// + /// The apple + /// + Apple, //2 + /// + /// The snake head north + /// + SnakeHead_N,//3 + /// + /// The snake tail north + /// + SnakeTail_N,//4 + /// + /// The snake body north-south + /// + SnakeBody_NS,//5 + /// + /// The snake head west + /// + SnakeHead_W, + /// + /// The snake head south + /// + SnakeHead_S, + /// + /// The snake head east + /// + SnakeHead_E, + /// + /// The snake tail west + /// + SnakeTail_W, + /// + /// The snake tail south + /// + SnakeTail_S, + /// + /// The snake tail east + /// + SnakeTail_E, + /// + /// The snake body north-west + /// + SnakeBody_NW, + /// + /// The snake body south-west + /// + SnakeBody_SW, + /// + /// The snake body south-east + /// + SnakeBody_SE, + /// + /// The snake body north-east + /// + SnakeBody_NE, + /// + /// The snake body west-east + /// + SnakeBody_WE, + }; + +} diff --git a/CSharpBible/Games/Snake_Base/Models/Direction.cs b/CSharpBible/Games/Snake_Base/Models/Direction.cs new file mode 100644 index 000000000..93240d5a4 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Direction.cs @@ -0,0 +1,76 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System.Drawing; + +/// +/// The Models namespace. +/// +/// +namespace Snake_Base.Models +{ + /// + /// Enum Direction + /// + public enum Direction + { + /// + /// The north + /// + North, + /// + /// The west + /// + West, + /// + /// The south + /// + South, + /// + /// The east + /// + East + } + + /// + /// Class Offsets. + /// + public static class Offsets + { + /// + /// The dir offsets + /// + /// + static Point[] DirOffsets = { new Point(0, -1), new Point(-1, 0), new Point(0, 1), new Point(1, 0) }; + /// + /// Dirs the offset. + /// + /// The d. + /// Point. + public static Point DirOffset(Direction d) => DirOffsets[(int)d]; + + /// + /// Dirs the offset. + /// + /// The dir. + /// The position. + /// Point. + public static Point DirOffset(Direction? dir, Point position) + { + var p = new Point(position.X,position.Y); + if (dir.HasValue) + p.Offset(DirOffset((Direction)dir)); + return p; + } + } +} \ No newline at end of file diff --git a/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs new file mode 100644 index 000000000..38c615b67 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs @@ -0,0 +1,41 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using Game_Base.Model; +using Snake_Base.Models.Data; +using System; +using System.Drawing; + +namespace Snake_Base.Models.Interfaces; + +public interface ISnakeGame +{ + IPlayfield2D Playfield { get; } + int Level { get; } + bool IsRunning { get; } + int Score { get; } + int Lives { get; } + int MaxLives { get; } + Size size { get; } + bool UserQuit { set; } + + SnakeTiles this[Point p] { get; } + + event EventHandler? visUpdate; + event EventHandler? visFullRedraw; + + Point GetOldPos(Point p); + void SetSnakeDir(Direction action); + int GameStep(); + void Setup(int v); +} \ No newline at end of file diff --git a/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs new file mode 100644 index 000000000..ecca3b703 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs @@ -0,0 +1,23 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System.Drawing; + +namespace Snake_Base.Models.Interfaces; + +public interface ISnakeGameObject +{ + Point OldPlace { get; } + + void ResetOldPlace(); +} \ No newline at end of file diff --git a/CSharpBible/Games/Snake_Base/Models/Snake.cs b/CSharpBible/Games/Snake_Base/Models/Snake.cs new file mode 100644 index 000000000..ef2843503 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/Snake.cs @@ -0,0 +1,263 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using BaseLib.Model; +using BaseLib.Helper; +using BaseLib.Interfaces; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Runtime.CompilerServices; +using Snake_Base.Models.Interfaces; +using Game_Base.Model; + +/// +/// The Models namespace. +/// +/// +namespace Snake_Base.Models +{ + /// + /// Class SnakeBodyPart. + /// Implements the + /// Implements the + /// + /// + /// + public class SnakeBodyPart : SnakeGameObject, IParentedObject + { + #region Properties + #region private Properties + /// + /// The sn parent + /// + /// + private Snake? _snParent; + #endregion + /// + /// Gets or sets the snake. + /// + /// The snake. + public Snake? Snake { get => _snParent; set => SetParent(value); } + /// + /// Sets the parent. + /// + /// The value. + /// The caller member. + public void SetParent(Snake? value, [CallerMemberName] string CallerMember = "") => value.SetProperty(ref _snParent, null, CallerMember); + + /// + /// Gets or sets the next part. + /// + /// The next part. + public SnakeBodyPart? NextPart { get; set; } = null; + + /// + /// Gets or sets the previous part. + /// + /// The next part. + public SnakeBodyPart? PrevPart { get; set; }= null; + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + public SnakeBodyPart() : this(null) { } + + /// + /// Gets the parent. + /// + /// System.Nullable<Snake>. + /// + Snake? IParentedObject.GetParent() => _snParent; + /// + /// Initializes a new instance of the class. + /// + /// The snake. + public SnakeBodyPart(Snake? snake):base() + { + _snParent = snake; + } + + /// + /// Initializes a new instance of the class. + /// + /// The place. + /// The snake. + /// The playfield. + public SnakeBodyPart(Point place,Snake? snake, IPlayfield2D? playfield = null) :base(place,playfield) + { + _snParent = snake; + } + #endregion + } + + /// + /// Class SnakeHead. + /// Implements the + /// + /// + public class SnakeHead : SnakeBodyPart + { + /// + /// Initializes a new instance of the class. + /// + /// The snake. + public SnakeHead(Snake? snake = null) : base(snake) { } + /// + /// Initializes a new instance of the class. + /// + /// The place. + /// The snake. + /// The playfield. + public SnakeHead(Point place, Snake? snake, IPlayfield2D? playfield = null):base(place,snake,playfield) { } + } + + /// + /// Class SnakeTail. + /// Implements the + /// + /// + public class SnakeTail : SnakeBodyPart + { + /// + /// Initializes a new instance of the class. + /// + /// The snake. + public SnakeTail(Snake? snake = null) : base(snake) { } + /// + /// Initializes a new instance of the class. + /// + /// The place. + /// The snake. + /// The playfield. + public SnakeTail(Point place, Snake? snake, IPlayfield2D? playfield = null) : base(place, snake, playfield) { } + } + + /// + /// Class Snake. + /// + public class Snake : NotificationObjectAdv + { + #region Properties + #region private Properties + /// + /// The playfield + /// + /// + private IPlayfield2D? _playfield; + /// + /// The sn head + /// + /// + private SnakeHead _snHead; + /// + /// The sn body + /// + /// + private List _snBody = new List(); + /// + /// The sn tail + /// + /// + private SnakeTail _snTail; + /// + /// The sn length + /// + /// + private int _snLength; + #endregion + /// + /// The alive + /// + public bool alive; + + /// + /// Gets the length. + /// + /// The length. + public int Length { get => _snLength; private set => SetProperty(ref _snLength,value); } + /// + /// Gets the head position. + /// + /// The head position. + public Point HeadPos { get => _snHead.Place; } + + public event EventHandler OnSnakeEatsApple; + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + /// The start. + /// The playfield. + public Snake(Point start, IPlayfield2D? playfield=null) { + playfield ??= SnakeGameObject.DefaultParent; + _playfield = playfield; + _snTail = new SnakeTail(start,this); + _snHead = new SnakeHead(start,this); + _snHead.NextPart = _snTail; + _snTail.PrevPart = _snHead; + Length = 2; // Head & Tail; + alive = true; + } + + /// + /// Snakes the move. + /// + /// The dir. + public void SnakeMove(Direction dir) + { + var nextPlace = Offsets.DirOffset(dir, _snHead.Place); + if (!_playfield?.Rect.Contains(nextPlace) ?? false) { alive = false;return; } + if (_playfield?[nextPlace] is SnakeBodyPart) { alive = false; return; } + if (_playfield?[nextPlace] is Apple) { + OnSnakeEatsApple?.Invoke(this, new EventArgs()); + _playfield[nextPlace] = null; + Length++; + } + SnakeBodyPart? _mRun = _snHead; + var _nxtPlace = nextPlace; + var bCount = 1; + while ((_mRun != null) && (_mRun.NextPart != _snTail)) + { + (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place); + if (bCount==1) + RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos)); + _mRun = _mRun.NextPart; + bCount++; + } + if (bCount++ < _snLength && _mRun != null) { + (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place); + if (bCount == 2) + RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos)); + var _snBody = new SnakeBodyPart(_nxtPlace,this,_playfield); + _snBody.ResetOldPlace(); + _snBody.NextPart = _mRun.NextPart; + _snBody.PrevPart = _mRun; + _mRun.NextPart!.PrevPart = _snBody; + _mRun.NextPart= _snBody; + } + else if (_mRun != null) + { + (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place); + if (bCount == 2) + RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos)); + _snTail.Place = _nxtPlace; + } + } + #endregion + } +} diff --git a/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs b/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs new file mode 100644 index 000000000..1bd40bda9 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs @@ -0,0 +1,225 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using BaseLib.Interfaces; +using Game_Base.Model; +using Snake_Base.Models.Data; +using Snake_Base.Models.Interfaces; +using System; +using System.Drawing; + +/// +/// The ViewModel namespace. +/// +/// +namespace Snake_Base.Models +{ + /// + /// Class SnakeGame. + /// + public class SnakeGame: ISnakeGame + { + #region Properties + #region private Properties + /// + /// The random + /// + /// + private static IRandom? _rnd; + + private Direction sDir; + private bool _userQuit = false; + private bool xHalfStep; + + #endregion + /// + /// Gets or sets the playfield. + /// + /// The playfield. + public IPlayfield2D Playfield { get; } + /// + /// Gets or sets the snake. + /// + /// The snake. + public Snake Snake { get; set; } + /// + /// The get next random + /// + public int Level { get; } + public event EventHandler? visUpdate; + public event EventHandler? visFullRedraw; + public static readonly int MaxLives; + + /// + /// Gets the with the specified p. + /// + /// The p. + /// SnakeTiles. + public SnakeTiles this[Point p] => GetTile(p); + + /// + /// Gets a value indicating whether this instance is running. + /// + /// true if this instance is running; otherwise, false. + public bool IsRunning => Snake.alive && !_userQuit; + + public int Score { get; private set; } + public int Lives { get; private set; } + public Size size { get => new Size(Playfield.PfSize.Width+2,Playfield.PfSize.Height+2); } + + int ISnakeGame.MaxLives => MaxLives; + + public bool UserQuit { set => _userQuit=value; } + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + public SnakeGame(IRandom random, IPlayfield2D playfield2D) + { + _rnd = random; + Playfield = playfield2D; + Playfield.PfSize = new Size(20, 20); + Playfield.OnDataChanged += PfDataChange; + SnakeGameObject.DefaultParent = Playfield; + Snake = new Snake(new Point(10,10)); + Snake.OnSnakeEatsApple += OnSnakeEatsApple; + } + + private void OnSnakeEatsApple(object? sender, EventArgs e) + { + NewApple(); + } + + private void NewApple() + { + // Getplace for apple + Point p; + // Get Random Startplace + var w = Playfield.PfSize.Width; + var sp = _rnd?.Next(Playfield.PfSize.Height * w)??0; + while (Playfield[p=new Point(sp % w,sp / w)]!=null) + sp++; + // + var a=new Apple(p, Playfield); + a.ResetOldPlace(); + } + + /// + /// Pfs the data change. + /// + /// The sender. + /// The e. + /// + /// + private void PfDataChange(object? sender, (string prop, object? oldVal, object? newVal) e) + { + // throw new NotImplementedException(); + } + + /// + /// Games the step. + /// + /// System.Int32. + public int GameStep() + { + xHalfStep = !xHalfStep; + if (xHalfStep) + { + foreach (var i in Playfield.Items) + i.ResetOldPlace(); + Snake.SnakeMove(sDir); + } + visUpdate?.Invoke(this, xHalfStep); + return 150; + } + + /// + /// Gets the tile. + /// + /// The p. + /// SnakeTiles. + public SnakeTiles GetTile(Point p) + { + SnakeTiles result = SnakeTiles.Empty; + var field = Playfield[p]; + switch(field) + { + case Apple: + result = SnakeTiles.Apple; break; + case SnakeHead sh: + { + var np = Point.Subtract(sh.Place, (Size?)sh.NextPart?.Place??Size.Empty); + switch ((np.X, np.Y)) + { + case (1, 0): result = SnakeTiles.SnakeHead_E; break; + case (-1, 0): result = SnakeTiles.SnakeHead_W; break; + case (0, 1): result = SnakeTiles.SnakeHead_S; break; + case (0, -1): result = SnakeTiles.SnakeHead_N; break; + } + break; + } + case SnakeTail st: { + var np = Point.Subtract(st.Place, (Size?)st.PrevPart?.Place??Size.Empty); + switch ((np.X, np.Y)) + { + case (1, 0): result = SnakeTiles.SnakeTail_W; break; + case (-1, 0): result = SnakeTiles.SnakeTail_E; break; + case (0, 1): result = SnakeTiles.SnakeTail_N; break; + case (0, -1): result = SnakeTiles.SnakeTail_S; break; + } + break; } + case SnakeBodyPart sb: { + var nx = Point.Subtract(sb.Place, (Size?)sb.NextPart?.Place ?? Size.Empty); + var np = Point.Subtract(sb.Place, (Size?)sb.PrevPart?.Place ?? Size.Empty); + switch ((np.X+nx.X, np.Y+nx.Y)) + { + case (0, 0) when nx.Y==0: result = SnakeTiles.SnakeBody_WE; break; + case (0, 0) when nx.X == 0: result = SnakeTiles.SnakeBody_NS; break; + case (1, 1): result = SnakeTiles.SnakeBody_NE; break; + case (-1, 1): result = SnakeTiles.SnakeBody_NW; break; + case (-1, -1): result = SnakeTiles.SnakeBody_SW; break; + case (1, -1): result = SnakeTiles.SnakeBody_SE; break; + } + break; + } + default: + if (Playfield.IsInside(p)) + result = SnakeTiles.Empty; + else + result = SnakeTiles.Wall; + break; + } + return result; + } + + public Point GetOldPos(Point arg) + { + return Playfield[arg]?.OldPlace ?? arg; + } + + public void Setup(int v) + { + NewApple(); + //throw new NotImplementedException(); + } + + public void SetSnakeDir(Direction action) + { + sDir = action; + } + + #endregion + } +} diff --git a/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs b/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs new file mode 100644 index 000000000..978d73677 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs @@ -0,0 +1,183 @@ +// *********************************************************************** +// Assembly : Snake_Base +// Author : Mir +// Created : 08-25-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using BaseLib.Helper; +using BaseLib.Interfaces; +using Game_Base.Model; +using Game_Base.Model.Interfaces; +using Snake_Base.Models.Interfaces; +using System; +using System.Drawing; +using System.Runtime.CompilerServices; + +/// +/// The Models namespace. +/// +/// +namespace Snake_Base.Models +{ + /// + /// Class SnakeGameObject. + /// Implements the + /// Implements the + /// + /// + /// + public abstract class SnakeGameObject :ISnakeGameObject, IPlacedObject, IParentedObject> + { + #region Properties + #region private Properties + /// + /// The place + /// + /// + private Point _place=Point.Empty; + /// + /// The old place + /// + /// + private Point _oldPlace; + /// + /// The pf parent + /// + /// + private IPlayfield2D? _pfParent; + #endregion + #region static Properties + /// + /// Gets or sets the default parent. + /// + /// The default parent. + public static IPlayfield2D? DefaultParent { get; set; } = null; + #endregion + + /// + /// Occurs when [data change event]. + /// + public event EventHandler<(string sender, object? oldVal, object? newVal)>? DataChangeEvent; + /// + /// Occurs when [on place change]. + /// + public event EventHandler<(Point oP, Point nP)>? OnPlaceChange; + + /// + /// Gets the old place. + /// + /// The old place. + public Point OldPlace { get => GetOldPlace(); } + #region interface Properties + /// + /// Gets or sets the place. + /// + /// The place. + public Point Place { get => GetPlace();set=> SetPlace(value); } + /// + /// Gets or sets the parent. + /// + /// The parent. + public IPlayfield2D? Parent { get => GetParent(); set => SetParent(value); } + #endregion + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + public SnakeGameObject() : this(Point.Empty) { } + + /// + /// Initializes a new instance of the class. + /// + /// The place. + /// The parent. + public SnakeGameObject(Point place, IPlayfield2D? parent=null) { + Place= place; + if (parent!=null) + Parent = parent; + else if (DefaultParent!=null) + Parent= DefaultParent; + } + + #region interface Methods + /// + /// Gets the old place. + /// + /// Point. + public virtual Point GetOldPlace() => _oldPlace; + /// + /// Gets the place. + /// + /// Point. + public virtual Point GetPlace() => _place; + /// + /// Sets the place. + /// + /// The value. + /// The name. + public virtual void SetPlace(Point value, [CallerMemberName] string Name = "") => value.SetProperty(ref _place, NtfyPlaceChange, Name); + + /// + /// Gets the parent. + /// + /// System.Nullable<Playfield2D<SnakeGameObject>>. + public virtual IPlayfield2D? GetParent() => _pfParent; + /// + /// Sets the parent. + /// + /// The value. + /// The caller member. + public virtual void SetParent(IPlayfield2D? value, [CallerMemberName] string CallerMember = "") => + value.SetProperty(ref _pfParent, NtfyParentChange, CallerMember); + #endregion + + /// + /// Ntfies the parent change. + /// + /// The arg1. + /// The arg2. + /// The arg3. + /// + protected virtual void NtfyParentChange(string arg1, IPlayfield2D? arg2, IPlayfield2D? arg3) + { + if (arg2 is IHasChildren hc) + hc.RemoveItem(this); + if (arg3 is IHasChildren hc2) + hc2.AddItem(this); + if (arg3 is IHasChildren hc3) + hc3.AddItem(this); + DataChangeEvent?.Invoke(this, (arg1, arg2, arg3)); + } + + /// + /// Ntfies the place change. + /// + /// The arg1. + /// The arg2. + /// The arg3. + /// + protected virtual void NtfyPlaceChange(string arg1, Point arg2, Point arg3) + { + _oldPlace = arg2; + if (_pfParent is IHasChildren hc) + hc.NotifyChildChange(this, arg2, arg3); + OnPlaceChange?.Invoke(this, (arg2, arg3)); + DataChangeEvent?.Invoke(this, (arg1, arg2, arg3)); + } + + public void ResetOldPlace() + { + _oldPlace = _place; + } + #endregion + } +} diff --git a/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs b/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs new file mode 100644 index 000000000..c3883003d --- /dev/null +++ b/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs @@ -0,0 +1,38 @@ +// *********************************************************************** +// Assembly : Snake_Console +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using Snake_Base.Models.Data; +using System; +using System.ComponentModel; +using System.Drawing; + +namespace Snake_Base.ViewModels; + +public interface ISnakeViewModel: INotifyPropertyChanged +{ + public interface ITileProxy + { + public T this[Point p] { get; } + } + + UserAction UserAction { get; set; } + ITileProxy Tiles { get; } + + Func GetOldPos { get; } + Size size { get; } + int Level { get; } + int Score { get; } + int Lives { get; } + int MaxLives { get; } + bool HalfStep { get; } +} \ No newline at end of file diff --git a/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs b/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs new file mode 100644 index 000000000..13a267874 --- /dev/null +++ b/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BaseLib.Helper; +using CommunityToolkit.Mvvm.ComponentModel; +using Snake_Base.Models; +using Snake_Base.Models.Data; +using Snake_Base.Models.Interfaces; + +namespace Snake_Base.ViewModels; + +public partial class SnakeViewModel : ObservableObject, ISnakeViewModel +{ + ISnakeGame _game; + + [ObservableProperty] + private UserAction _userAction; + private bool _halfStep; + + public SnakeViewModel(ISnakeGame game) + { + _game = game; + Tiles = new _TileProxy(game); + _game.visUpdate += (s, e) => + { + _halfStep = e; + OnPropertyChanged(nameof(Tiles)); + }; + _game.visFullRedraw += (s, e) => OnPropertyChanged(nameof(Level)); + } + + public class _TileProxy(ISnakeGame game) : ISnakeViewModel.ITileProxy + { + ISnakeGame _game = game; + public SnakeTiles this[Point p] + { get => _game[p]; } + } + + public ISnakeViewModel.ITileProxy Tiles { get; } + + public Size size => _game.size; + public int Level => _game.Level; + public int Score => _game.Score; + public int Lives => _game.Lives; + public int MaxLives => _game.MaxLives; + + public Func GetOldPos { get => _game.GetOldPos; } + + public bool HalfStep => _halfStep; + + partial void OnUserActionChanged(UserAction value) + { + if ((int)value < typeof(Direction).GetEnumValues().Length) + _game.SetSnakeDir((Direction)value); + else if (value <= UserAction.Quit) + _game.UserQuit = true; + } + +} diff --git a/CSharpBible/Games/Snake_Console/Program.cs b/CSharpBible/Games/Snake_Console/Program.cs index 877419a57..e22f3b881 100644 --- a/CSharpBible/Games/Snake_Console/Program.cs +++ b/CSharpBible/Games/Snake_Console/Program.cs @@ -9,15 +9,17 @@ using Snake_Console.View; using System; using System.Threading; +using Game_Base.Model; namespace Snake_Console { public static class Program { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fgen Sie ggf. den erforderlichen Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. private static ISnakeGame _game; - private static UserAction action; - private static int iDelay; private static IVisual _visual; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fgen Sie ggf. den erforderlichen Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. + private static int iDelay; private static void OnStartUp() { @@ -25,8 +27,10 @@ private static void OnStartUp() .AddTransient() .AddTransient() .AddSingleton() + .AddSingleton, Playfield2D>() .AddSingleton() - .AddSingleton, TileDisplay>() + .AddTransient, TileDisplay>() + .AddTransient() .AddSingleton(); var sp = sc.BuildServiceProvider(); diff --git a/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj b/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj index f953daa23..90acc3fee 100644 --- a/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj +++ b/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,6 +8,8 @@ + + diff --git a/CSharpBible/Games/Snake_Console/View/IVisual.cs b/CSharpBible/Games/Snake_Console/View/IVisual.cs new file mode 100644 index 000000000..7b125d82b --- /dev/null +++ b/CSharpBible/Games/Snake_Console/View/IVisual.cs @@ -0,0 +1,23 @@ +// *********************************************************************** +// Assembly : Snake_Console +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; + +namespace Snake_Console.View +{ + public interface IVisual + { + bool CheckUserAction(); + void FullRedraw(object? sender = null, EventArgs? e = null); + } +} \ No newline at end of file diff --git a/CSharpBible/Games/Snake_Console/View/TileDef.cs b/CSharpBible/Games/Snake_Console/View/TileDef.cs index 19cfc19d8..b6dded0b7 100644 --- a/CSharpBible/Games/Snake_Console/View/TileDef.cs +++ b/CSharpBible/Games/Snake_Console/View/TileDef.cs @@ -11,83 +11,82 @@ // // // *********************************************************************** -using ConsoleDisplay.View; using System; +using ConsoleDisplay.View; using System.Drawing; /// /// The View namespace. /// /// -namespace Snake_Console.View +namespace Snake_Console.View; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase { /// - /// Class TileDef. - /// Implements the - /// - public class TileDef : TileDefBase - { - /// - /// The v tile definition string - /// - /// - private static string[][] _vTileDefStr = new string[][]{ - new string[]{ " " }, //Empty - new string[]{ "|_" }, //Wall - new string[]{ "##" }, //Apple - new string[]{ "/\\" }, //Head_N - new string[]{ "''" }, //Tail_N - new string[]{ "||" }, //Boby_NS - new string[]{ "<}" }, //Head_W - new string[]{ "\\/" }, //Head_S - new string[]{ "{>" }, //Head_E - new string[]{ "=-" }, //Tail_W - new string[]{ ",," }, //Tail_S - new string[]{ "-=" }, //Tail_E - new string[]{ "++" }, - new string[]{ "++" }, - new string[]{ "++" }, - new string[]{ "++" }, - new string[]{ "==" }, //Body_WE - }; + /// The v tile definition string + /// + /// + private string[][] _vTileDefStr = [ + [" "], //Empty + ["|_"], //Wall + ["##"], //Apple + ["/\\"], //Head_N + ["''"], //Tail_N + ["||"], //Boby_NS + ["<}"], //Head_W + ["\\/"], //Head_S + ["{>"], //Head_E + ["=-"], //Tail_W + [",,"], //Tail_S + ["-="], //Tail_E + ["++"], + ["++"], + ["++"], + ["++"], + ["=="], //Body_WE + ]; - /// - /// The v tile colors - /// - /// - private static byte[][] _vTileColors = new byte[][]{ - new byte [] { 0x07 }, //Empty - new byte [] { 0x4F }, //Wall - new byte [] { 0x0C }, //Apple - new byte [] { 0xAE }, //Head_N - new byte [] { 0x0E }, - new byte [] { 0x0E }, - new byte [] { 0xAE }, - new byte [] { 0xAE }, - new byte [] { 0xAE }, - new byte [] { 0x0E } //Rest ... - }; + /// + /// The v tile colors + /// + /// + private byte[][] _vTileColors = [ + [0x07], //Empty + [0x4F], //Wall + [0x0C], //Apple + [0xAE], //Head_N + [0x0E], + [0x0E], + [0xAE], + [0xAE], + [0xAE], + [0x0E] //Rest ... + ]; - /// - /// Gets the tile definition. - /// - /// The tile. - /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). - /// - public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum tile) - { - (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; - result.lines = GetArrayElement(_vTileDefStr, tile); + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); - result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; - byte[] colDef = GetArrayElement(_vTileColors, tile); - for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) - result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); - return result; - } + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + } - public TileDef():base() { - TileSize = new Size(2, 1); - } + public TileDef():base() { + TileSize = new Size(2, 1); } } diff --git a/CSharpBible/Games/Snake_Console/View/Visual.cs b/CSharpBible/Games/Snake_Console/View/Visual.cs index 7259174ed..072fdebcf 100644 --- a/CSharpBible/Games/Snake_Console/View/Visual.cs +++ b/CSharpBible/Games/Snake_Console/View/Visual.cs @@ -17,6 +17,7 @@ using System.Drawing; using Snake_Base.ViewModels; using System.ComponentModel; +using Snake_Base.Models.Data; namespace Snake_Console.View { @@ -29,14 +30,14 @@ public class Visual : IVisual { /// The game /// - private ISnakeViewModel? _game; + private ISnakeViewModel _viewModel; /// /// My console /// public IConsole myConsole; - private ITileDisplay _tileDisplay; + private ITileDisplay _tileDisplay; /// /// The key action /// @@ -55,45 +56,37 @@ public class Visual : IVisual { #endregion #region Methods - public Visual(ISnakeViewModel viewModel, ITileDisplay tileDisplay) + public Visual(ISnakeViewModel viewModel, ITileDisplay tileDisplay) { + _viewModel = viewModel; + _viewModel.PropertyChanged += OnPropertyChanged; + myConsole = tileDisplay.console; _tileDisplay = tileDisplay; _tileDisplay.DispOffset = new Point(-1, -1); - _tileDisplay.FncGetTile = (p) => (Enum)_game.Tiles[(Point)p]; - _tileDisplay.FncOldPos = _game.GetOldPos; + _tileDisplay.SetDispSize ( new Size(22, 22)); + _tileDisplay.FncGetTile = (p) => _viewModel.Tiles[(Point)p]; + _tileDisplay.FncOldPos = _viewModel.GetOldPos; - _game = viewModel; - _game.PropertyChanged += OnPropertyChanged; FullRedraw(); } - private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(_game.Tiles)) + if (e.PropertyName == nameof(_viewModel.Tiles)) { - _tileDisplay.Update(_game.HalfStep); + _tileDisplay.Update(_viewModel.HalfStep); ShowStatistics(); } - else if (e.PropertyName == nameof(_game.Level)) + else if (e.PropertyName == nameof(_viewModel.Level)) { FullRedraw(); } } - - /// - /// gs the vis update. - /// - /// The sender. - /// if set to true [e]. - private static void G_visUpdate(object? sender, bool e) - { - } - /// /// Fulls the redraw. /// @@ -102,7 +95,7 @@ private static void G_visUpdate(object? sender, bool e) public void FullRedraw(object? sender=null,EventArgs? e=null) { // basic Checks - if (_game == null) return; + if (_viewModel == null) return; _tileDisplay.FullRedraw(); // Draw statistics @@ -114,11 +107,11 @@ public void FullRedraw(object? sender=null,EventArgs? e=null) /// private void ShowStatistics() { - if (_game == null) return; + if (_viewModel == null) return; myConsole.SetCursorPosition(0, 24); myConsole.BackgroundColor = ConsoleColor.Black; myConsole.ForegroundColor = ConsoleColor.Yellow; - myConsole.Write($"\t{_game.Level + 1}\t\t{_game.Score}\t\t{_game.Lives}/{_game.MaxLives}\t\x08"); + myConsole.Write($"\t{_viewModel.Level + 1}\t\t{_viewModel.Score}\t\t{_viewModel.Lives}/{_viewModel.MaxLives}\t\x08"); } @@ -163,8 +156,8 @@ public bool CheckUserAction() result = true; } } - if (_game != null) - _game.UserAction = action; + if (_viewModel != null) + _viewModel.UserAction = action; return result; } diff --git a/CSharpBible/Games/Sokoban_Base/View/Visuals.cs b/CSharpBible/Games/Sokoban_Base/View/Visuals.cs index 9aceb09fb..f2b39c952 100644 --- a/CSharpBible/Games/Sokoban_Base/View/Visuals.cs +++ b/CSharpBible/Games/Sokoban_Base/View/Visuals.cs @@ -53,6 +53,8 @@ public static class Visuals { 'Q', UserAction.Quit }, { '\u001b', UserAction.Quit } }; + private static ITileDef _visualDef; + /// /// Gets or sets the message. /// @@ -72,6 +74,8 @@ static Visuals() KeyAction.Add(dir.ToString()?[0] ?? '\0', (UserAction)dir); } catch { } + + _visualDef = new VisualsDef(); } /// @@ -200,13 +204,13 @@ private static void ShowHelp() var sDirs = ""; foreach (string d in typeof(Direction).GetEnumNames()) sDirs += $", {MarkFirst(d)}"; - myConsole.WriteLine(String.Format(Resource1.InfoText, + myConsole.WriteLine(string.Format(Resource1.InfoText, Resource1.stone, sDirs.TrimStart(','), - $"{VisualsDef.GetTileStr(TileDef.Stone)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Stone)[1]}", - $"{VisualsDef.GetTileStr(TileDef.Player)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Player)[1]}", - $"{VisualsDef.GetTileStr(TileDef.Wall)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Wall)[1]}", - $"{VisualsDef.GetTileStr(TileDef.Destination)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Destination)[1]}" + $"{_visualDef.GetTileDef(TileDef.Stone).lines[0]}\r\n{_visualDef.GetTileDef(TileDef.Stone).lines[1]}", + $"{_visualDef.GetTileDef(TileDef.Player).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Player).lines[1]}", + $"{_visualDef.GetTileDef(TileDef.Wall).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Wall).lines[1]}", + $"{_visualDef.GetTileDef(TileDef.Destination).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Destination).lines[1]}" )); var cp = myConsole.GetCursorPosition(); WriteTile(new PointF(0, (cp.Top - 3) * 0.5f), TileDef.Destination); @@ -269,14 +273,13 @@ private static void ShowStatistics() #endif static void WriteTile(PointF p, TileDef td) { - var colors = VisualsDef.GetTileColors(td); - var sTileStr=VisualsDef.GetTileStr(td); - myConsole.ForegroundColor = colors[0]; - myConsole.BackgroundColor = colors[1]; - for (int i = 0; i < sTileStr.Length; i++) + var tld = _visualDef.GetTileDef(td); + myConsole.ForegroundColor = tld.colors[0].fgr; + myConsole.BackgroundColor = tld.colors[0].bgr; + for (int i = 0; i < tld.lines.Length; i++) { myConsole.SetCursorPosition((int)(p.X * 4), (int)(p.Y * 2) + i); - myConsole.Write(sTileStr[i]); + myConsole.Write(tld.lines[i]); } } diff --git a/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs b/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs index 415e31cac..5c52b0c6e 100644 --- a/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs +++ b/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs @@ -11,14 +11,16 @@ // // // *********************************************************************** +using ConsoleDisplay.View; using Sokoban_Base.ViewModel; using System; +using System.Drawing; namespace Sokoban_Base.View { /// /// Class VisualsDef. /// - public static class VisualsDef { + public class VisualsDef: ITileDef { /// /// The g STR1 @@ -42,12 +44,14 @@ public static class VisualsDef { static string[] pStr1 = { "|()|", @" <°)", "(°°)", @"(°> ", "(__)", @">-||", "|^^|", @"||-<" }; - /// - /// Gets the tile string. - /// - /// The tile definition. - /// System.String[]. - public static string[] GetTileStr(TileDef tileDef) { + public Size TileSize => new Size(4, 2); + + /// + /// Gets the tile string. + /// + /// The tile definition. + /// System.String[]. + public static string[] GetTileStr(TileDef tileDef) { String[] result ={ "","" }; if ((int)tileDef < gStr1.Length / 2 && tileDef != TileDef.Player) (result[0], result[1]) = (gStr1[(int)tileDef], gStr1[(int)tileDef + gStr1.Length / 2]); @@ -106,21 +110,26 @@ public static string[] GetTileStr(TileDef tileDef) { /// /// The tile definition. /// ConsoleColor[]. - public static ConsoleColor[] GetTileColors(TileDef tileDef) + public static (ConsoleColor fgr,ConsoleColor bgr) GetTileColors(TileDef tileDef) { - ConsoleColor[] result = new ConsoleColor[2] { ConsoleColor.Gray, ConsoleColor.Black }; + var result = ( ConsoleColor.Gray, ConsoleColor.Black ); if ((int)tileDef < gColors.Length / 2) - (result[0], result[1]) = (gColors[(int)tileDef], gColors[(int)tileDef + gColors.Length / 2]); + result = (gColors[(int)tileDef], gColors[(int)tileDef + gColors.Length / 2]); else if (tileDef == TileDef.Floor_Marked) - (result[0], result[1]) = (gColors[(int)TileDef.Floor], gColors[(int)TileDef.Floor + gColors.Length / 2]); + result = (gColors[(int)TileDef.Floor], gColors[(int)TileDef.Floor + gColors.Length / 2]); else if (tileDef >= TileDef.Player_W && tileDef <= TileDef.PlayerOverDest_E) { var td = (int)tileDef % 2 + (int)TileDef.Player; - (result[0], result[1]) = (gColors[td], gColors[td + gColors.Length / 2]); + result = (gColors[td], gColors[td + gColors.Length / 2]); } else - (result[0], result[1]) = (gColors[(int)TileDef.Wall], gColors[(int)TileDef.Wall + gColors.Length / 2]); + result = (gColors[(int)TileDef.Wall], gColors[(int)TileDef.Wall + gColors.Length / 2]); return result; } - } + + public (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + return (GetTileStr((TileDef)tile), [GetTileColors((TileDef)tile)]); + } + } } diff --git a/CSharpBible/Games/VTileEdit/Models/EStreamType.cs b/CSharpBible/Games/VTileEdit/Models/EStreamType.cs new file mode 100644 index 000000000..2fa72fefb --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Models/EStreamType.cs @@ -0,0 +1,11 @@ +namespace VTileEdit.Models +{ + public enum EStreamType + { + Binary, + Text, + Json, + Code, + Xml + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs b/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs new file mode 100644 index 000000000..eda21af00 --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Drawing; +using System.IO; + +namespace VTileEdit.Models; + +public interface IVTEModel +{ + void LoadFromStream(Stream stream, EStreamType eStreamType); + void SaveToStream(Stream stream, EStreamType eStreamType); + void Clear(); + void SetTileSize(Size size); + Size TileSize { get; } + SingleTile GetTileDef(Enum? tile); + void SetTileDef(Enum tile, string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors); + } \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/Models/VisTileData.cs b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs new file mode 100644 index 000000000..59e47a386 --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs @@ -0,0 +1,443 @@ +using ConsoleDisplay.View; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel.DataAnnotations; +using System.Data; +using System.Data.SqlTypes; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.PortableExecutable; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Shapes; +using System.Xml.Serialization; + +namespace VTileEdit.Models; + +public class VisTileData : ITileDef +{ + private Size _size; + private Dictionary _storage = new(); + + public Size TileSize => _size; + + public static bool EqualTo(IEnumerable a, IEnumerable b) + { + return a.Zip(b).All((t) => t.First!.Equals(t.Second)); + } + + + + public SingleTile GetTileDef(Enum? tile) + { + if (_storage.TryGetValue(tile, out var result)) + { + return result; + } + else + if (_storage.TryGetValue(_storage.Keys.FirstOrDefault((t) => (int)(object)t == (int)(object)tile), out result)) + { + return result; + } + else + return (new string[0], new (ConsoleColor fgr, ConsoleColor bgr)[0]); + } + + + public void SetTileDefs(ITileDef tiledef) where T : Enum + { + Clear(); + _size = tiledef.TileSize; + foreach (T e in Enum.GetValues(typeof(T))) + { + var tile = tiledef.GetTileDef(e); + _storage.Add(e, tile); + } + for (var i = _storage.Count - 2; i > 0; i--) + { + var e0 = _storage.ElementAt(i).Value; + var e1 = _storage.ElementAt(i + 1).Value; + if (e0.lines.Length == e1.lines.Length + && EqualTo(e0.lines, e1.lines) + && e0.colors.Length == e1.colors.Length + && EqualTo(e0.colors.Select((c) => (int)c.fgr + (int)c.bgr * 256), e1.colors.Select((c) => (int)c.fgr + (int)c.bgr * 256))) + _storage.Remove(_storage.ElementAt(i + 1).Key); + else + break; + } + } + + public bool LoadFromStream(Stream stream, EStreamType eStreamType) + { + switch (eStreamType) + { + case EStreamType.Binary: + { + _storage.Clear(); + using (BinaryReader reader = new BinaryReader(stream)) + { + Type _keyType = typeof(object); + int count = reader.ReadInt32(); + if (count > 0) + { + _size = new Size(reader.ReadInt32(), reader.ReadInt32()); + _keyType = Type.GetType(reader.ReadString()) ?? Assembly.GetExecutingAssembly().GetType(); + } + for (int i = 0; i < count; i++) + { + Enum key = (Enum)Enum.ToObject(_keyType, reader.ReadInt32()); + int lineCount = reader.ReadInt32(); + string[] lines = new string[lineCount]; + for (int j = 0; j < lineCount; j++) + { + lines[j] = reader.ReadString(); + } + int colorCount = reader.ReadInt32(); + FullColor[] colors = new FullColor[colorCount]; + for (int j = 0; j < colorCount; j++) + { + colors[j] = ((ConsoleColor)reader.ReadByte(), (ConsoleColor)reader.ReadByte()); + } + _storage.Add(key, new SingleTile(lines, colors)); + } + } + return true; + } + case EStreamType.Text: + { + int iSplPos; + (string key, string Value) kv(string line) + => (line.Substring(0, iSplPos = line.IndexOf(':')), line.Substring(iSplPos + 1)); + + Dictionary? data = new(); + using (TextReader reader = new StreamReader(stream)) + { + string? line; + while ((line = reader.ReadLine()) != null) + { + var (key, value) = kv(line); + if (key == "Count") + { + data = new(); + Type KeyType; + int count = int.Parse(value); + if (count > 0) + { + (key, value) = kv(reader.ReadLine() ?? ":"); + var size = value.Split(','); + _size = new Size(int.Parse(size[0]), int.Parse(size[1])); + (key, value) = kv(reader.ReadLine() ?? ":"); + KeyType = Type.GetType(value); + + for (int i = 0; i < count; i++) + { + (key, value) = kv(reader.ReadLine() ?? ":"); + var keyE = (Enum)Enum.Parse(KeyType, value.Substring(0, value.IndexOf(' ') - 0)); + (key, value) = kv(reader.ReadLine() ?? ":"); + var lineCount = int.Parse(value); + string[] lines = new string[lineCount]; + for (int j = 0; j < lineCount; j++) + { + (key, value) = kv(reader.ReadLine() ?? ":"); + lines[j] = value; + } + + (key, value) = kv(reader.ReadLine() ?? ":"); + var colorCount = int.Parse(value); + FullColor[] colors = new FullColor[colorCount]; + for (int j = 0; j < colorCount; j++) + { + (key, value) = kv(reader.ReadLine() ?? ":"); + var color = Convert.FromHexString(value.Substring(2)); + colors[j] = ((ConsoleColor)(color[0] >> 4), (ConsoleColor)(color[0] & 0xf)); + } + data.Add(keyE, new SingleTile(lines, colors)); + + } + } + } + } + } + _storage = data ?? _storage; + return data != null; + } + case EStreamType.Xml: + { + Dictionary? data = new(); + + using (TextReader reader = new StreamReader(stream)) + { + var xml = new XmlSerializer(typeof(List), extraTypes: [typeof(SingleTile)]); + var xdata = ((string KeyType, List Data)?)xml.Deserialize(reader); + var _keyType = Type.GetType(xdata.Value.KeyType) ?? Assembly.GetExecutingAssembly().GetType(); + + foreach (var itm in xdata.Value.Data) + { + data.Add((Enum)Enum.ToObject(_keyType, (int)itm[0]), (SingleTile)itm[1]); + } + } + _storage = data ?? _storage; + return data != null; + } + case EStreamType.Json: + { + Dictionary? data = new(); + var lst = JsonSerializer.Deserialize<(string, List)>(new StreamReader(stream).ReadToEnd()); + var _keyType = Type.GetType(lst.Item1) ?? Assembly.GetExecutingAssembly().GetType(); + foreach (var itm in lst.Item2) + { + data.Add((Enum)Enum.ToObject(_keyType, itm[0]), (SingleTile)itm[1]); + } + _storage = data ?? _storage; + return data != null; + } + default: + return false; + } + } + + public bool WriteToStream(Stream stream, EStreamType eStreamType) + { + string Quoted(string s) => $"@\"{s.Replace("\"", "\"\"")}\""; + string ToNibble(ConsoleColor[] c) => $"0x{(byte)c[1] & 0xf:X1}{(byte)c[0] & 0xf:X1}"; + + switch (eStreamType) + { + case EStreamType.Binary: + { + using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) + { + writer.Write(_storage.Count); + if (_storage.Count > 0) + { + writer.Write(_size.Width); + writer.Write(_size.Height); + writer.Write(_storage.First().Key.GetType().AssemblyQualifiedName); + } + foreach (var item in _storage) + { + writer.Write(Convert.ToInt32(item.Key)); + writer.Write(item.Value.lines.Length); + foreach (var line in item.Value.lines) + { + writer.Write(line); + } + writer.Write(item.Value.colors.Length); + foreach (var color in item.Value.colors) + { + writer.Write((byte)color.fgr); + writer.Write((byte)color.bgr); + } + } + } + return true; + } + case EStreamType.Xml: + { + using (TextWriter writer = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true)) + { + Type _keyType = _storage.Count > 0 ? _storage.First().Key.GetType() : typeof(object); + (string KeyType, List Data) data = (_keyType.AssemblyQualifiedName, _storage.Select(v => new object[] { v.Key, v.Value }).ToList()); + var xml = new XmlSerializer(data.GetType(), [typeof(SingleTile)]); + xml.Serialize(writer, data); + } + return true; + } + case EStreamType.Text: + { + using (TextWriter writer = new StreamWriter(stream, leaveOpen: true)) + { + writer.WriteLine($"Count:{_storage.Count}"); + writer.WriteLine($"Size:{_size.Width},{_size.Height}"); + if (_storage.Count > 0) + { + writer.WriteLine($"KeyType:{_storage.First().Key.GetType().AssemblyQualifiedName}"); + } + for (int i = 0; i < _storage.Count; i++) + { + var item = _storage.ElementAt(i); + writer.WriteLine($"Key{i}:{item.Key} ({item.Key.GetType().Name})"); + writer.WriteLine($"Lines{i}:{item.Value.lines.Length}"); + for (var j = 0; j < item.Value.lines.Length; j++) + { + writer.WriteLine($"L{i}_{j}:{Quoted(item.Value.lines[j])}"); + } + writer.WriteLine($"Colors:{item.Value.colors.Length}"); + for (var j = 0; j < item.Value.colors.Length; j++) + { + var color = item.Value.colors[j]; + writer.WriteLine($"L{i}_{j}:{ToNibble([color.fgr, color.bgr])}"); + } + } + } + return true; + } + case EStreamType.Json: + { + var json = JsonSerializer.Serialize(_storage.Select(v => new object[] { v.Key, v.Value })); + using (TextWriter writer = new StreamWriter(stream, leaveOpen: true)) + { + writer.Write(json); + } + return true; + } + case EStreamType.Code: + { + const string code = @"//*************************************************************** +// Assembly : SomeGame_Base +// Author : Mir +// Created : 01-01-2025 +// +// Last Modified By : Mir +// Last Modified On : 01-01-2025 +// *********************************************************************** +// +// Copyright (c) {0}. All rights reserved. +// +// +// *********************************************************************** +using System; +using ConsoleDisplay.View; +using System.Drawing; + +/// +/// The View namespace. +/// +/// +namespace Console.Views; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase +{{ + /// + /// The tile definition string + /// + private readonly string[][] _vTileDefStr = [ + {1} + ]; + + + /// + /// The tile colors + /// + private readonly byte[][] _vTileColors = [ + {2} + ]; + + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + {{ + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); + + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + }} + + public TileDef():base() => TileSize = new Size({3}); +}}"; + using (TextWriter writer = new StreamWriter(stream, leaveOpen: true)) + { + string Brackeded(IEnumerable @as, Func Quoted) => $"[{Compress(string.Join(", ", @as.Select(Quoted)))}]"; + + var sLines = _storage.Select(v => Brackeded(v.Value.lines, Quoted) + $", //{v.Key}"); + var sColors = _storage.Select(v => Brackeded( + v.Value.colors.Select(c => ToNibble([c.fgr, c.bgr])), (s) => s) + $", //{v.Key}"); + + writer.Write(string.Format(code, [ + "JC-Soft", + string.Join($"{Environment.NewLine.PadRight(10,' ')}",sLines), + string.Join($"{Environment.NewLine.PadRight(10,' ')}",sColors), + $"{_size.Width},{_size.Height}" + ])); + } + return true; + } + default: + return false; + } + } + + public override bool Equals(object? obj) + { + return obj is VisTileData ot + && _size == ot._size + && _storage.Count == ot._storage.Count + && _storage.All((t) => ot._storage.TryGetValue(t.Key, out var v) && t.Value.Equals(v)); + } + + private string Compress(string s) + { + while (s.Length > 3 + && s.Substring(s.Length / 2 - 1, 2) == ", " + && s.Substring(0, s.Length / 2 - 1) == s.Substring(s.Length / 2 + 1, s.Length / 2 - 1)) + { + s = s.Substring(0, s.Length / 2 - 1); + } + return s; + } + + private void Clear() + { + _storage.Clear(); + } + + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) ITileDef.GetTileDef(Enum? tile) + => GetTileDef(tile); +} + +public record struct SingleTile(string[] lines, FullColor[] colors) +{ + public static implicit operator (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors)(SingleTile value) + { + return (value.lines, value.colors.Select(fc => (fc.fgr, fc.bgr)).ToArray()); + } + + public static implicit operator SingleTile((string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) value) + { + return new SingleTile(value.lines, value.colors.Select(fc => new FullColor(fc.fgr, fc.bgr)).ToArray()); + } + + public bool Equals(SingleTile other) + { + return lines.Length == other.lines.Length + && lines.Zip(other.lines).All((t) => t.First!.Equals(t.Second)) + && colors.Length == other.colors.Length + && colors.Zip(other.colors).All((t) => t.First!.Equals(t.Second)); + } +} + +public record struct FullColor(ConsoleColor fgr, ConsoleColor bgr) +{ + public static implicit operator (ConsoleColor fgr, ConsoleColor bgr)(FullColor value) + { + return (value.fgr, value.bgr); + } + + public static implicit operator FullColor((ConsoleColor fgr, ConsoleColor bgr) value) + { + return new FullColor(value.fgr, value.bgr); + } + + public bool Equals(FullColor other) + { + return fgr == other.fgr && bgr == other.bgr; + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/Program.cs b/CSharpBible/Games/VTileEdit/Program.cs index 06b9b62b7..275cf3ed6 100644 --- a/CSharpBible/Games/VTileEdit/Program.cs +++ b/CSharpBible/Games/VTileEdit/Program.cs @@ -1,17 +1,51 @@ -using System; +using BaseLib.Helper; +using ConsoleDisplay.View; +using Microsoft.Extensions.DependencyInjection; +using System; +using VTileEdit.ViewModels; +using VTileEdit.Views; namespace VTileEdit { /// /// Class Program. /// - public static class Program + public class Program { + private void OnStartUp() + { + var sc = new ServiceCollection() + .AddTransient() + // .AddTransient() +// .AddSingleton() + // .AddSingleton, Playfield2D>() + .AddSingleton() + .AddTransient, TileDisplay>() + // .AddTransient() + .AddSingleton(); + var sp = sc.BuildServiceProvider(); + + IoC.Configure(sp); + } + + /// Defines the entry point of the application. /// The arguments. static void Main(string[] args) { - Console.WriteLine("Hello, World!"); + var _program = new Program(); + _program.Init(args); + _program.Run(); + } + + private void Run() + { + throw new NotImplementedException(); + } + + private void Init(string[] args) + { + OnStartUp(); } } } \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/VTileEdit.csproj b/CSharpBible/Games/VTileEdit/VTileEdit.csproj index a3c582b37..004d588e9 100644 --- a/CSharpBible/Games/VTileEdit/VTileEdit.csproj +++ b/CSharpBible/Games/VTileEdit/VTileEdit.csproj @@ -1,16 +1,23 @@ + Exe - net6.0 + net6.0;net7.0;net8.0;net9.0 disable enable - ..\..\..\obj.net\$(MSBuildProjectName)\ - ..\..\..\obj.net\$(MSBuildProjectName)\ - ..\..\..\bin\$(MSBuildProjectName) - - + + + + + + + + + ..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\PresentationFramework.dll + + diff --git a/CSharpBible/Games/VTileEdit/ViewModels/IVTEViewModel.cs b/CSharpBible/Games/VTileEdit/ViewModels/IVTEViewModel.cs new file mode 100644 index 000000000..2f24d7881 --- /dev/null +++ b/CSharpBible/Games/VTileEdit/ViewModels/IVTEViewModel.cs @@ -0,0 +1,8 @@ +using System.ComponentModel; + +namespace VTileEdit.ViewModels +{ + public interface IVTEViewModel : INotifyPropertyChanged + { + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/ViewModels/VTEViewModel.cs b/CSharpBible/Games/VTileEdit/ViewModels/VTEViewModel.cs new file mode 100644 index 000000000..50713e8ed --- /dev/null +++ b/CSharpBible/Games/VTileEdit/ViewModels/VTEViewModel.cs @@ -0,0 +1,112 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +#if linux +#else +using Microsoft.Win32; +#endif +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using VTileEdit.Models; +using VTileEdit.ViewModels; + +namespace VTileEdit; + +public partial class VTEViewModel : ObservableObject, IVTEViewModel +{ + private IVTEModel _model; + + public Func ShowFileDialog { get; set; } + public VTEViewModel(IVTEModel model) + { + _model = model; + } + + [RelayCommand] + private void LoadTileDefs() + { + FileDialog ofd = new OpenFileDialog(); + ofd.Filter = FileDialogFilter.Build([ + ("TileDef Files", [ "tdf","tdt","tdj","tdx" ]), + ("All Files", ["*"]), + ("TileDef Files", ["tdf"]) ]); + + if (ShowFileDialog?.Invoke(ofd) ?? false) + { + using (var fs = new FileStream(ofd.FileName, FileMode.Open)) + { + switch (Path.GetExtension(ofd.FileName)) + { + case ".txt": + _model.LoadFromStream(fs, EStreamType.Text); + break; + case ".tdf": + _model.LoadFromStream(fs, EStreamType.Binary); + break; + case ".tdj": + _model.LoadFromStream(fs, EStreamType.Json); + break; + case ".tdx": + _model.LoadFromStream(fs, EStreamType.Xml); + break; + case ".cs": + _model.LoadFromStream(fs, EStreamType.Code); + break; + }; + } + } + } + + [RelayCommand] + private void SaveTileDefs() + { + FileDialog sfd = new SaveFileDialog(); + sfd.Filter = FileDialogFilter.Build([ + ("TileDef Files", [ "tdf","tdt","tdj","tdx" ]), + ("All Files", ["*"]), + ("TileDef Files", ["tdf"]) ]); + if (ShowFileDialog?.Invoke(sfd) ?? false) + { + using (var fs = new FileStream(sfd.FileName, FileMode.Create)) + { + switch (Path.GetExtension(sfd.FileName)) + { + case ".txt": + _model.SaveToStream(fs, EStreamType.Text); + break; + case ".tdf": + _model.SaveToStream(fs, EStreamType.Binary); + break; + case ".tdj": + _model.SaveToStream(fs, EStreamType.Json); + break; + case ".tdx": + _model.SaveToStream(fs, EStreamType.Xml); + break; + case ".cs": + _model.SaveToStream(fs, EStreamType.Code); + break; + }; + } + } + } +} +public static class FileDialogFilter +{ + public static string Build(IEnumerable<(string, IEnumerable)> filters) + { + var sb = new StringBuilder(); + foreach (var filter in filters) + { + sb.Append(filter.Item1); + sb.Append("|"); + sb.Append(string.Join(";", filter.Item2.Select(e => $"*.{e}"))); + sb.Append("|"); + } + sb.Append("|"); + return sb.ToString(); + } +} diff --git a/CSharpBible/Games/VTileEdit/Views/IFileDialogData.cs b/CSharpBible/Games/VTileEdit/Views/IFileDialogData.cs new file mode 100644 index 000000000..075a99fd8 --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Views/IFileDialogData.cs @@ -0,0 +1,13 @@ +namespace VTileEdit.Views +{ + public interface IFileDialogData + { + string Title { get; set; } + string Filter { get; set; } + string FileName { get; set; } + string InitialDirectory { get; set; } + bool Multiselect { get; set; } + bool CheckFileExists { get; set; } + bool CheckPathExists { get; set; } + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/Views/IVisual.cs b/CSharpBible/Games/VTileEdit/Views/IVisual.cs new file mode 100644 index 000000000..0e24db4f5 --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Views/IVisual.cs @@ -0,0 +1,8 @@ +namespace VTileEdit.Views +{ + public interface IVisual + { + bool ShowFileDialog(IFileDialogData fileDialog); + void HandleUserInput(); + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEdit/Views/VTEVisual.cs b/CSharpBible/Games/VTileEdit/Views/VTEVisual.cs new file mode 100644 index 000000000..222d0757a --- /dev/null +++ b/CSharpBible/Games/VTileEdit/Views/VTEVisual.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VTileEdit.ViewModels; + +namespace VTileEdit.Views; + +public class VTEVisual : IVisual +{ + private IVTEViewModel _viewModel; + + public VTEVisual(IVTEViewModel viewModel) + { + _viewModel = viewModel; + _viewModel.PropertyChanged += OnPropertyChanged; + } + + public void HandleUserInput() + { + throw new NotImplementedException(); + } + + public bool ShowFileDialog(IFileDialogData fileDialog) + { + throw new NotImplementedException(); + } + + private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + // Find bound properties + } +} diff --git a/CSharpBible/Games/VTileEditTests/Models/.info b/CSharpBible/Games/VTileEditTests/Models/.info new file mode 100644 index 000000000..e69de29bb diff --git a/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs b/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs new file mode 100644 index 000000000..22c620fcd --- /dev/null +++ b/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs @@ -0,0 +1,564 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using VTileEdit.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ConsoleDisplay.View; +using System.IO; +using System.Diagnostics; +using static BaseLib.Helper.TestHelper; +using System.IO.Compression; +using System.Buffers.Text; + +namespace VTileEdit.Models.Tests +{ + [TestClass()] + public class VisTileDataTests + { + private const string csExp0CodeC = "H4sIAAAAAAACCqxXwW7bRhC9G/A/bAgUkGxZpIW0h1hyrUhM0MJGi8qODrIg0NRKJkByhV1KNmsY8KGHosghbWyn195awEB88KnoSZ/CL+lwl5S4lEg7SgiBXO68NzM7MztaqurG513ra6qK6oxh58T2UXy9QC3i4NeGg3svDYYFaOydEopQAnRgUS5qUGx4uJ8Uadtb8Ktola9DBEftG8xDB6RvDSzAvvQTCmTRD+6CArTxZS6uq2qSkU+t4amHBpaNa8qbQ3g08aBsMgWZxBkZrl9Tvm9stcjAU3Y5KbwaM17BLKJIXkZ120Z8miGKGaYT3C8LQ+rMklBSZWPHMai/W1Xj0Zdd3ZhZ7hC1fOZhZyd+bRCXEVigxUa24ZffWPhsR4aWm9Q4g1eYDv1JOCpeD08xCmnIhZJgI8PE5QinysCqMfbIELuYhgVBTKSCYEaKPeEusCxjDdtgDMUpEXPfOSMbO9iFEHvgS5VhjEyKBzUlwl2ET3apgMEFnwBs2IxkEtbXRuMT2zKRmbQMNRiNxBa4WF8LayDlcDwVRsgDOOrjgeVankVcxDwKMU3QVJk3otYEwgRFY/SJC9tPEDrdThf1JpHxlkdRDXUEI7w6e0r4ULolUKo7I8+XZLWt2pZSQnsKPGsC1LSoJ2GC66vg+iG4voMBx/KJOz53JThtw7Zlm8HN++DmFgn87fvg9vfg9g8YRDYw8yzXCNctm3r7bnq/V+QsFLz9K/xd/Sc4P0I1YirB1enH6cdjjj7u9VSBa3nExRKsO72f3nc4rPfsWS+KhYsdv3c0ku1/+AXsz6DHSehP4caU9RKyXGvzTF5Wd296H9z+y7FqCruPB7JWNbj5G35Ll3VAJrMaiSO9uRH8+o+I882fwc274MNve8mINaFeMuqhCQXmZ+X6ISfXvaMU6y5dIQ/LWO0s1kMe66j9ZGN3CVrzycaSrKPmSsbaK1pb4D1pq/X01ZKmr5Y1fcW06avlTV8xcfqKmdNXTV1E7PK/pqf1e5PYhLJPaPInvocTLb7B+akWr51r2tL+rp1/oy/r6dr581fL+jYo0kto2b1S5/cKn6mIcU4nB8OvljftmUvpNq2db3MbdW1+365ntepH0elu/ShB7tmPwlNtW17WQptOxSPVkudpSvVjKU9Sz5Ul7WxOtqiZTcoWtXNYOTI9m5UtauewcmTNHFqOrJ3HS+31nJ3+GkeHztTxrpy95/ncyKCGww/MNSWkKrtxzyhXVS5Moin2xtRlu4X4DIhsy8WshArRCT06OvN2gQZDWkLLBCdDWgSuaEpFMBTrTZhadkTnnUocgskEU2r1MVp0ZdGHHONh4KIzbEF3x863fO1FYetinpnPNQOfXGPbgwYKqTFgtDNXLURlrhcA4FCdUsPXxadEIXnGLgnvZsWQoJtxh3bhA+hJziXtlvexO/RO0YbkTUfrRoJuwl/x1xCuLPz+yHJY/GPMHY7ZAzBfmBgUWUDVduBRRZ/iCTA2N4tzfQsh6Fhd0PwSnDwklXDV3JOCcLdjoa8iz+OVFaVUhHUY6YvmL+NgR5UXV0vxxQl8cRWKqLbL51rWzzgKfzgsPC9VQtWX/wMAAP//AwByNfB7/RAAAA=="; + private const string csExp1CodeC = "H4sIAAAAAAACCqxVXW/TMBR9n7T/cBWESLcuSbuNAWsKWxkTCMRDJ15KNbmp21lK4spOu4Wx/86NHXfx6iIQWJGSnPt1rnNyHYZ7/7Z2d8IQzqSk2SQtwaw3MOQZvSQZvT4nkmqnZXHDBUDD6QsTyjQQlBR02jRFnQO8ulH3uPJQXp+JLOALn7IZQ9/zspHANn3NNxLA3v9ZKlcv4YtSsPlNATOW0tj7doW393QWJNKDhGcLkpex92lwMOSzwuuroGoN1nF+0oLaHsBZmoKCJQgqqVjRaaALhetKOklPLrOMiLLfC83T/+1uKVk+h2EpC5qdmtcBzyXHBplcpKQMvjF6e2q7Bu8FucVXhCs+DaL69eqGQhUGOUpCLkhCg9ovtB17ZFnwOc2pqATBEwjRsA4yTBQFua3YICVSgvkkGvuYLVKa0Ry3uEAuPUkpJILOYq/2u6/u8sHDghuc0Jmkkm8N2N1ZLCcpSyBpVkYN1k/6F7jf3ak08ISwgaodKtAdpnTGclYwnoMsBO5pIyy04xaCrXCbUDRkynP8/XTAaDwaw/WqLj4sBMQw0hHVGr3zALxxG1NeR5GF/7w2eMfCnz0zeNfCw+8GP7TwFy8MfmTn/2nwYwvvPRj8pYV/Dw1+YuH3fYO/svD4wOCvLbzdrvGO3e9BbHC73/19g3e34Idb8KMtuN1vvK5b9ztWWv4zgSQ85UL+hSomZUEbmhio+CeaiO6iE4ckorujDw5FoPfAIYjo7uzCoQf0vnDIoQEfu5O8dMMnbviVO/drJ9yJ3HDHDXfdsLvLjrvLzrEbtiTwGwFc0np4PRkTwXYpKGxBBMnU4I29KtTrGykFvVAZm96CFkuRy75vZgmkLKeyDX496esRrFQEs7log8swmYsWxmqttrCQydso5Rr1SsB6mPIVFYJNKWxS2eTwm+LVxtWz0L/Il9lb1XtL17p//Cb/WgaP7mVa4H+Fn4bg0+ljam0KVF50QEJnQpDyQh9JfnNWtzW7tRga4Yn5cXM8SP+IXLNu8Jnm8+IG9iw2o2hcG8YNvnpiVJ1V59g2wnqQPBI20TMs76+IAIah0SneevA3TDBif7/1mG9jC0ZsjJnPkeQV71ZdKya+pjti8LxmbjprWZ+i0mGdr8YfzGbXyjNqab2Z4MnttyDuK2zIftB6+6tHv9vuVKkffgEAAP//AwAjWdJIRQsAAA=="; + private const string csExp2CodeC = "H4sIAAAAAAACCqxX/26bSBD+P1LeYYV0EqQ2+KzeVWqw7xLHqXpq0kpE9R+ugzZ47aDjh7WL3XAh79Rn6JN1dhccFgxH1KJI4J3vm/l2mJ0MlnXyc9fxkWWhM8ZIeBekqLjeIicOyTscEvccMyJB2+Q+pgiVQFc+FaYJJTghy7Jp8Hsf/oaD4R8cIVAfMEvQVbz0Vz5gz9OSA9X0Mao5QCe/5hK+bC/epNRf3ydo5QdkpH2+gdsFWZke05AXhxscpSPtn0nfiVeJNhYkfk32PN0zUG430VkQILHMECWM0B1ZmjKQtY8kndhsG4aYpmPbKp5+7e62zI/WyElZQsLT4uckjlgMG/TZJsCp+dknX09VqHlB8Vf4CctcT0mo/HlzTxCnoQhKgm2wR8wcZ6lAG2+TeE0iQnlBxB6ywLAnFUqEBNYUbBJgxlDxSuTa+3ATkJBEkOIEtNiMEORRshppOe6R39mTBgFrmgCMAxY3Eo6PNtu7wPeQV44MNZg/ySPweHzEa6AiuFjiGUoAjpZk5Ud+4scRYgmFnJZolsrbUH8HaYKiwcs4guMnCfPFfIHcXR7cSSgaoblk8Gv+t8Zv2qIHTqfhJkkV29zNFloPwUPmLiRohoNAwZjIRAIDd1NiLoM4pvUgHGSPRmMJuiAs8SPMN6dAM93IBFR3XUNCP0GlkYpD+/s3Q8DGbuaWYR93hHLfCty6vf0i0F9c15JoJ4kjooB6/X5PgDLXzUqg91HNX9Om3StM/yXLLkl0r9VtFyhXRc06oa5nnUI63YQ53ZQ5HaXVorpF1KyEm3ZCXU+rQd0iaBk26wa7nnWL6nQU53RU53SVVwGWqr6fZeWqr9TJ/x+PCkH//q1gZLe3qmvnpa6dquuxPCxZ1rcVz9OXes4JC9Huu/VQLw5iyl7QOO/ShJTa5kTwK21z8DB4c7BnDh5evznUJwcPw7ODvREMly39cG+u9cCK5UDbGzz8OT3Y6sBw2dLeVK31lqbsUWljqmXWzGk2Oc2kZtOshdVimzazmk2zFlaLzWmhtdhmbbyqUSmISvoPFksbpvImDvNbMO60A185zy2n+R3Jh7XKWGQ2n2uxtsEUh2LQHGmcqo2LvmDaljCW0ZQkWxqxsV7MTijwI8J6SM8n23zkFC0Brda0hw4Z7tbUAK5sPAYEKvyWQh0abUU3ksNjDAmi/pKgupS6hpbgPHH57KdPo234l9i7IWM9Pr+gnw0DnyrbIIEmCa8Gw9Pps2tpMoVfAICgM0pxOpUjuF6eTXtS3b4YSnSv6MIRfDh0EleOa34g0Tq5RyeKmvlgkRsWJb2y/fOd8bm9SbD8r/AsuGCvILy+wxT5QB2cws1GL1ECjFevjGd/tRTM/QV4PgeRN/GQ71oo0aXcuY9+y5UXOzOUV8HrMPeXrz8Vyc4rr6gW4+0dfKnoBhqNxZrj/0fy9PNH/XVvyF0//QAAAP//AwBpvTAoNRAAAA=="; + private const string csExp3CodeC = ""; + + private const string csExp0Code = @"//*************************************************************** +// Assembly : SomeGame_Base +// Author : Mir +// Created : 01-01-2025 +// +// Last Modified By : Mir +// Last Modified On : 01-01-2025 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using ConsoleDisplay.View; +using System.Drawing; + +/// +/// The View namespace. +/// +/// +namespace Console.Views; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase +{ + /// + /// The tile definition string + /// + private readonly string[][] _vTileDefStr = [ + [@"" ""], //Empty + [@""=-=-"", @""-=-=""], //Dirt + [@""─┴┬─"", @""─┬┴─""], //Wall + [@"" ╓╖ "", @""▓░▒▓""], //Destination + [@""⌐°@)"", @"" ⌡⌡‼""], //Player + [@""/¯¯\"", @""\__/""], //Stone + [@""]°°["", @""_!!_""], //Enemy_Up + [@""◄°@["", @""_!!\""], //Enemy_Right + [@""]oo["", @""_!!_""], //Enemy_Dwn + [@""]@°►"", @""/!!_""], //Enemy_Left + [@""/╨╨\"", @""\__/""], //StoneMoving + [@"" +*∩"", @""╘═◊@""], //PlayerDead + [@"" ""], //Dummy + [@""─┴┬┴"", @""─┬┴─""], //Wall_U + [@""┬┴┬─"", @""┴┬┴─""], //Wall_W + [@""┬┴┬┴"", @""┴┬┴─""], //Wall_UW + [@""┬┴┬─"", @""┴┬┴┬""], //Wall_D + [@""┬┴┬┴"", @""┴┬┴┬""], //Wall_UD + [@""┬┴┬─"", @""┴┬┴┬""], //Wall_WD + [@""┬┴┬┴"", @""┴┬┴┬""], //Wall_UWD + [@""─┴┬─"", @""─┬┴─""], //Wall_E + [@""─┴┬┴"", @""─┬┴─""], //Wall_UE + [@""┬┴┬─"", @""┴┬┴─""], //Wall_WE + [@""┬┴┬┴"", @""┴┬┴─""], //Wall_UWE + [@""┬┴┬─"", @""┴┬┴┬""], //Wall_DE + [@""┬┴┬┴"", @""┴┬┴┬""], //Wall_UDE + [@""┬┴┬─"", @""┴┬┴┬""], //Wall_WDE + [@""┬┴┬┴"", @""┴┬┴┬""], //Wall_UWDE + ]; + + + /// + /// The tile colors + /// + private readonly byte[][] _vTileColors = [ + [0x00], //Empty + [0x6E], //Dirt + [0x4F], //Wall + [0x0E, 0x0E, 0x0E, 0x0E, 0x2A, 0x22, 0x02, 0x22], //Destination + [0x6F], //Player + [0x6E], //Stone + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Up + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Right + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Dwn + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Left + [0x6E], //StoneMoving + [0x6F], //PlayerDead + [0x6E], //Dummy + [0x4F], //Wall_U + [0x4F], //Wall_W + [0x4F], //Wall_UW + [0x4F], //Wall_D + [0x4F], //Wall_UD + [0x4F], //Wall_WD + [0x4F], //Wall_UWD + [0x4F], //Wall_E + [0x4F], //Wall_UE + [0x4F], //Wall_WE + [0x4F], //Wall_UWE + [0x4F], //Wall_DE + [0x4F], //Wall_UDE + [0x4F], //Wall_WDE + [0x4F], //Wall_UWDE + ]; + + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); + + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + } + + public TileDef():base() => TileSize = new Size(4,2); +}"; + private const string csExp1Code = @"//*************************************************************** +// Assembly : SomeGame_Base +// Author : Mir +// Created : 01-01-2025 +// +// Last Modified By : Mir +// Last Modified On : 01-01-2025 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using ConsoleDisplay.View; +using System.Drawing; + +/// +/// The View namespace. +/// +/// +namespace Console.Views; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase +{ + /// + /// The tile definition string + /// + private readonly string[][] _vTileDefStr = [ + [@"" ""], //_00 + [@""|_""], //_01 + [@""##""], //_02 + [@""/\""], //_03 + [@""''""], //_04 + [@""||""], //_05 + [@""<}""], //_06 + [@""\/""], //_07 + [@""{>""], //_08 + [@""=-""], //_09 + [@"",,""], //_10 + [@""-=""], //_11 + [@""++""], //_12 + [@""++""], //_13 + [@""++""], //_14 + [@""++""], //_15 + [@""==""], //_16 + ]; + + + /// + /// The tile colors + /// + private readonly byte[][] _vTileColors = [ + [0x07], //_00 + [0x4F], //_01 + [0x0C], //_02 + [0xAE], //_03 + [0x0E], //_04 + [0x0E], //_05 + [0xAE], //_06 + [0xAE], //_07 + [0xAE], //_08 + [0x0E], //_09 + [0x0E], //_10 + [0x0E], //_11 + [0x0E], //_12 + [0x0E], //_13 + [0x0E], //_14 + [0x0E], //_15 + [0x0E], //_16 + ]; + + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); + + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + } + + public TileDef():base() => TileSize = new Size(2,1); +}"; + + private const string csExp2Code = @"//*************************************************************** +// Assembly : SomeGame_Base +// Author : Mir +// Created : 01-01-2025 +// +// Last Modified By : Mir +// Last Modified On : 01-01-2025 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using ConsoleDisplay.View; +using System.Drawing; + +/// +/// The View namespace. +/// +/// +namespace Console.Views; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase +{ + /// + /// The tile definition string + /// + private readonly string[][] _vTileDefStr = [ + [@"" ""], //Empty + [@""[_|]"", @""[|_]""], //Wall + [@"". . "", @"" . .""], //Floor + [@"" "", @""<==>""], //Destination + [@""|()|"", @""(__)""], //Player + [@"" <°)"", @"">_|_""], //PlayerOverDest + [@""/^^\"", @""\__/""], //Stone + [@"",--,"", @""|__|""], //StoneInDest + [@"". . "", @"" . .""], //Floor_Marked + [@""[_|]"", @""[|_]""], //Wall_N + [@""|_|]"", @""_|_]""], //Wall_W + [@""|_|]"", @""_|_]""], //Wall_NW + [@""[_|]"", @""[|_]""], //Wall_S + [@""[_|]"", @""[|_]""], //Wall_NS + [@""|_|]"", @""_|_]""], //Wall_WS + [@""|_|]"", @""_|_]""], //Wall_NWS + [@""[_|_"", @""[|_|""], //Wall_E + [@""[_|_"", @""[|_|""], //Wall_NE + [@""|_|_"", @""_|_|""], //Wall_WE + [@""|_|_"", @""_|_|""], //Wall_NWE + [@""[_|_"", @""[|_|""], //Wall_SE + [@""[_|_"", @""[|_|""], //Wall_NSE + [@""|_|_"", @""_|_|""], //Wall_WSE + [@""|_|_"", @""_|_|""], //Wall_NWSE + [@"" <°)"", @"">-||""], //Player_W + [@"" <°)"", @"">_|_""], //PlayerOverDest_W + [@""(°°)"", @""|^^|""], //Player_S + [@"" <°)"", @"">_|_""], //PlayerOverDest_S + [@""(°> "", @""||-<""], //Player_E + [@"" <°)"", @"">_|_""], //PlayerOverDest_E + ]; + + + /// + /// The tile colors + /// + private readonly byte[][] _vTileColors = [ + [0x07], //Empty + [0x47], //Wall + [0x2A], //Floor + [0x2F], //Destination + [0x2F], //Player + [0x2F], //PlayerOverDest + [0x6E], //Stone + [0x6F], //StoneInDest + [0x2A], //Floor_Marked + [0x47], //Wall_N + [0x47], //Wall_W + [0x47], //Wall_NW + [0x47], //Wall_S + [0x47], //Wall_NS + [0x47], //Wall_WS + [0x47], //Wall_NWS + [0x47], //Wall_E + [0x47], //Wall_NE + [0x47], //Wall_WE + [0x47], //Wall_NWE + [0x47], //Wall_SE + [0x47], //Wall_NSE + [0x47], //Wall_WSE + [0x47], //Wall_NWSE + [0x2F], //Player_W + [0x2F], //PlayerOverDest_W + [0x2F], //Player_S + [0x2F], //PlayerOverDest_S + [0x2F], //Player_E + [0x2F], //PlayerOverDest_E + ]; + + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); + + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + } + + public TileDef():base() => TileSize = new Size(4,2); +}"; + private const string csExp0Json = @"[[0,{""lines"":["" "","" ""],""colors"":[{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0}]}],[1,{""lines"":[""=-=-"",""-=-=""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[2,{""lines"":[""\u2500\u2534\u252C\u2500"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[3,{""lines"":["" \u2553\u2556 "",""\u2593\u2591\u2592\u2593""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":10,""bgr"":2},{""fgr"":2,""bgr"":2},{""fgr"":2,""bgr"":0},{""fgr"":2,""bgr"":2}]}],[4,{""lines"":[""\u2310\u00B0@)"","" \u2321\u2321\u203C""],""colors"":[{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6}]}],[5,{""lines"":[""/\u00AF\u00AF\\"",""\\__/""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[6,{""lines"":[""]\u00B0\u00B0["",""_!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[7,{""lines"":[""\u25C4\u00B0@["",""_!!\\""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[8,{""lines"":[""]oo["",""_!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[9,{""lines"":[""]@\u00B0\u25BA"",""/!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[10,{""lines"":[""/\u2568\u2568\\"",""\\__/""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[11,{""lines"":["" \u002B*\u2229"",""\u2558\u2550\u25CA@""],""colors"":[{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6}]}],[12,{""lines"":["" "","" ""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[13,{""lines"":[""\u2500\u2534\u252C\u2534"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[14,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[15,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[16,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[17,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[18,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[19,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[20,{""lines"":[""\u2500\u2534\u252C\u2500"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[21,{""lines"":[""\u2500\u2534\u252C\u2534"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[22,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[23,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[24,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[25,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[26,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[27,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}]]"; + private const string csExp1Json = @"[[0,{""lines"":["" ""],""colors"":[{""fgr"":7,""bgr"":0},{""fgr"":7,""bgr"":0}]}],[1,{""lines"":[""|_""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[2,{""lines"":[""##""],""colors"":[{""fgr"":12,""bgr"":0},{""fgr"":12,""bgr"":0}]}],[3,{""lines"":[""/\\""],""colors"":[{""fgr"":14,""bgr"":10},{""fgr"":14,""bgr"":10}]}],[4,{""lines"":[""\u0027\u0027""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[5,{""lines"":[""||""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[6,{""lines"":[""\u003C}""],""colors"":[{""fgr"":14,""bgr"":10},{""fgr"":14,""bgr"":10}]}],[7,{""lines"":[""\\/""],""colors"":[{""fgr"":14,""bgr"":10},{""fgr"":14,""bgr"":10}]}],[8,{""lines"":[""{\u003E""],""colors"":[{""fgr"":14,""bgr"":10},{""fgr"":14,""bgr"":10}]}],[9,{""lines"":[""=-""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[10,{""lines"":["",,""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[11,{""lines"":[""-=""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[12,{""lines"":[""\u002B\u002B""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[13,{""lines"":[""\u002B\u002B""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[14,{""lines"":[""\u002B\u002B""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[15,{""lines"":[""\u002B\u002B""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}],[16,{""lines"":[""==""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0}]}]]"; + private const string csExp2Json = @"[[0,{""lines"":["" "","" ""],""colors"":[{""fgr"":7,""bgr"":0}]}],[1,{""lines"":[""[_|]"",""[|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[2,{""lines"":["". . "","" . .""],""colors"":[{""fgr"":10,""bgr"":2}]}],[3,{""lines"":["" "",""\u003C==\u003E""],""colors"":[{""fgr"":15,""bgr"":2}]}],[4,{""lines"":[""|()|"",""(__)""],""colors"":[{""fgr"":15,""bgr"":2}]}],[5,{""lines"":["" \u003C\u00B0)"",""\u003E_|_""],""colors"":[{""fgr"":15,""bgr"":2}]}],[6,{""lines"":[""/^^\\"",""\\__/""],""colors"":[{""fgr"":14,""bgr"":6}]}],[7,{""lines"":["",--,"",""|__|""],""colors"":[{""fgr"":15,""bgr"":6}]}],[8,{""lines"":["". . "","" . .""],""colors"":[{""fgr"":10,""bgr"":2}]}],[9,{""lines"":[""[_|]"",""[|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[10,{""lines"":[""|_|]"",""_|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[11,{""lines"":[""|_|]"",""_|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[12,{""lines"":[""[_|]"",""[|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[13,{""lines"":[""[_|]"",""[|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[14,{""lines"":[""|_|]"",""_|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[15,{""lines"":[""|_|]"",""_|_]""],""colors"":[{""fgr"":7,""bgr"":4}]}],[16,{""lines"":[""[_|_"",""[|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[17,{""lines"":[""[_|_"",""[|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[18,{""lines"":[""|_|_"",""_|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[19,{""lines"":[""|_|_"",""_|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[20,{""lines"":[""[_|_"",""[|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[21,{""lines"":[""[_|_"",""[|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[22,{""lines"":[""|_|_"",""_|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[23,{""lines"":[""|_|_"",""_|_|""],""colors"":[{""fgr"":7,""bgr"":4}]}],[24,{""lines"":["" \u003C\u00B0)"",""\u003E-||""],""colors"":[{""fgr"":15,""bgr"":2}]}],[25,{""lines"":["" \u003C\u00B0)"",""\u003E_|_""],""colors"":[{""fgr"":15,""bgr"":2}]}],[26,{""lines"":[""(\u00B0\u00B0)"",""|^^|""],""colors"":[{""fgr"":15,""bgr"":2}]}],[27,{""lines"":["" \u003C\u00B0)"",""\u003E_|_""],""colors"":[{""fgr"":15,""bgr"":2}]}],[28,{""lines"":[""(\u00B0\u003E "",""||-\u003C""],""colors"":[{""fgr"":15,""bgr"":2}]}],[29,{""lines"":["" \u003C\u00B0)"",""\u003E_|_""],""colors"":[{""fgr"":15,""bgr"":2}]}]]"; + private const string csExp3Json = @"[[0,{""lines"":["" ""],""colors"":[{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0},{""fgr"":0,""bgr"":0}]}],[1,{""lines"":[""=-=-"",""-=-=""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[2,{""lines"":[""\u2500\u2534\u252C\u2500"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[3,{""lines"":["" \u2553\u2556 "",""\u2593\u2591\u2592\u2593""],""colors"":[{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":14,""bgr"":0},{""fgr"":10,""bgr"":2},{""fgr"":2,""bgr"":2},{""fgr"":2,""bgr"":0},{""fgr"":2,""bgr"":2}]}],[4,{""lines"":[""\u2310\u00B0@)"","" \u2321\u2321\u203C""],""colors"":[{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6}]}],[5,{""lines"":[""/\u00AF\u00AF\\"",""\\__/""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[6,{""lines"":[""]\u00B0\u00B0["",""_!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[7,{""lines"":[""\u25C4\u00B0@["",""_!!\\""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[8,{""lines"":[""]oo["",""_!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[9,{""lines"":[""]@\u00B0\u25BA"",""/!!_""],""colors"":[{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1},{""fgr"":10,""bgr"":1},{""fgr"":0,""bgr"":10},{""fgr"":0,""bgr"":10},{""fgr"":10,""bgr"":1}]}],[10,{""lines"":[""/\u2568\u2568\\"",""\\__/""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[11,{""lines"":["" \u002B*\u2229"",""\u2558\u2550\u25CA@""],""colors"":[{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6},{""fgr"":15,""bgr"":6}]}],[12,{""lines"":["" ""],""colors"":[{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6},{""fgr"":14,""bgr"":6}]}],[13,{""lines"":[""\u2500\u2534\u252C\u2534"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[14,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[15,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[16,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[17,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[18,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[19,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[20,{""lines"":[""\u2500\u2534\u252C\u2500"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[21,{""lines"":[""\u2500\u2534\u252C\u2534"",""\u2500\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[22,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[23,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u2500""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[24,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[25,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[26,{""lines"":[""\u252C\u2534\u252C\u2500"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}],[27,{""lines"":[""\u252C\u2534\u252C\u2534"",""\u2534\u252C\u2534\u252C""],""colors"":[{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4},{""fgr"":15,""bgr"":4}]}]]"; + private const string csExp0JsonC = "H4sIAAAAAAACCuSX32rCMBTG7wd7B83dRsWTk6RaQVALe4laCo5tDGQFx67Ed1/SHGtb64o46LJ4cUq/9E9++dJzjkkCwZ5t3z9ePtksYQP9Y4E9pMH9HXvOt/nODO3Z69uOzSBgm+J4CHpV0oOZXsKrk5+P5iM9eR3n7ZPnku4Pyyf2KhEEViHWX6gATBTSRIytosFOQ1a0F+ihdlhF75GnV/cpEayobTcDoEQRwwEhRsV5xIuIVunwE85X92rpuLewlPCiAi3XEJ9smCm4dgxgBYsH82EZBXkZQcQd7oXna9mHRHSqSjc2YMsnimtj3zrLxk59e2EVKLVO2Zhonmw4zC7gHLcLP0tOHH6SWm78jWcRzqSZSmJJu49wtE0u8Uxr9uS5k6ZENYjFcZOhWi01ztg1HA6NJIAqnFJ0Mwlw3ihKALh61EiIERUlVRCqwrZ4uXAqaXO8qsX7qyaJ7jZJyP/SJvFmH1GDaTSF9SVwkVZ105beuk8b3uQtxm7RTm7y1jXaqVfeRj55i+DTH3XkPtVbRJ/qLQqf6i1Kn3IyKq9ysle9FHrTS6XfAAAA//8DAFaB8smZGAAA"; + private const string csExp1JsonC = "H4sIAAAAAAACCrTT3QqCMBQH8Pugd5Dj7cJtzizBm6Kn2CQoKgJJMLpS3z3MIWepBB282eAP58fZx9Gaswry++PyhESD50HGlgs4F3lRtkkF11sJSczg1O68YYMka9oSLbBTH8cdEdky1UMospLEku9PSHLQEoqsFGIpMGaCUrZOIAtlFlMYMy/OZdytP9QRtDcj59JqgrT+7i7cN6Tjxg5oAhK2wVj1ae9AArcYTFeEixPOADBGoZwZWKUUSg5+265bKWg4B6rmQKM5UGdG0n+fJ3sDAAD//wMAEDG8jDQFAAA="; + private const string csExp2JsonC = "H4sIAAAAAAACCqyUTWuDQBBA74X+h7AnhTVZ1+9ALi3+ilUHGtpSCAkk9JTJf+9uNrarxHbL6ME56Hs+cBmlBD+z3cf+9cTWii30xbgdLX98YNvD7nA0j87s7f3I1gVnL2aKS3sxL6jYxRVgq3GF0P6Opz0uXXy5WF6/rud9PBY3XvZ8cqe++RQied5srrOeMGVjU+qaMAhRmwKA0JfPBiW2wdyfRNg31YDgq8td3arrmsZYGoDVhCG9GfLeULgGHkVcCxAA/yj45kvir6loJyMeHEy0PPyDj4m8JPYnRD4l9mdEPh/1g+1HX74g8uWoH2y/N1/ReClo/TIm8pLYnxD51GOhRYi+C03OvCDl4HwG1vTjw67zTytmTisn0pLaLFHEyH7C21fN19d+AQAA//8DADTfrvXyBwAA"; + private const string csExp3JsonC = "H4sIAAAAAAACCuSXUWvCMBDH3wf7Dpq3jYp3l6S2gmBb2JeopbCxjYGs4NiT+N2XtLG2ta7bFCSLDyf+2yb88j/vrmkK3pat396fP9g8ZSP1YZl3e8OeinWx0dqWvbxu2Bw89lh+77w/KdlOL5tic7fFZDFhHlNx0b8pCvO8X694VclAUBNi9UkSQEcudKSkUhTY4VIlVjeoS/2w0uwjDltfUzKwvJUfGkDyMvojgxiWv0MsI1XKgJ9wfLq/lva5RbVEJxXoucfwiY6ZHJVjADEs7xSfBuaEdQSeDLjnH5/lNSRDJ5t0Uw0WPZi40vat8nxq1X/PbwJllVNVTBVPPh7nJ3D26YJHxQnhO6nnwUusZXBm3VKSCJN9BkfZZBNP0LKnKKw0JWxBLPdJRjKOFM7UNhyEThEg6Qcm2lkEEDtNCYDie4VEFJqmJEtCWdqWREurijbSz2ayS54oH55puPgvMw12m34LpjPBtY/ARlo5TFt7az+tf5a3lNhFOzvLW9toA6e8DV3ylsClt2pCl/otkUv9lrhL/ZaESzWZpFM12alZipyZpbIvAAAA//8DAM4Z33L3FwAA"; + + private const string csExp0XmlC = "H4sIAAAAAAACCuycPU/bQBjH90r9DsFbW4WDdqmQHSi12wVExYtoVVBkkkticbEj2yFkY+hQVQy0kNC1WytFIkOmqlM+yn2SXlzeLFGHyheD3b8UCefu7B/xnX88fvwEdX6/znJ71PUsx9aU2ekZJUftklO27KqmNP1K/rkyX3j4QH3humZ7pXLxw26vtxs0J3a2vbl9z9KUmu835ghptVrTrWfTjlslT2dmZsnb5aW1Uo3Wzbxle75pl6hyuVd5/F6KYOdyahgbtIlW8+K38Kw5X2xoyrrFqKcUjHrDb6vEHDd8TXxKRkc7KeeDxDBm2dS7fCsaPN8V4wrBNjl/c8tulYSPppYc5riho79qMvZy1HqtUTRXqm5hkZmlXZWMNkN9O1d9O6E+ldx0NCCASBlCJaELJXwpq+QGHfyrInTL9WUbQstr+QhDiF5NsiHeUcac1l/Otm66uxcD4s4qQAClGjR5o2yajMk2Cj854CcDftITGxFmCYb1gpEHkg2zWbN8GjEDq7Qcf54BAeTeQxKISajnW7bpi1sx6TcvvHPMO92oGxjePebdz7z7RWwkGaZIijvBuD3jtUupHXFFnPfHxVw71F2jJJ04qZ9o8kJ5w8w2daUHJYdHw/7Co6hcCD/8Nnod/Eo4GpEVeIIDTjo5k5fKmu/YVLZTyPBseLYVoZStYpEgeQIQQJlMnhg2rbeLGw3ZXtke9of99xFeKU5NFSV7ZVyAuMiadLJ5dklBdQKIZM4VZiT5c5WUM1atak36kxx++kHc4ozxxha8AW9gRlLqDb0lPcm67TgINaAMzEhGlbFEK9Ijje2FYZ93f0Zog0Ab0AZmJI3aCFKly86euHKlJ0x557t4IWUKEED/Zcr0z8NdnZpl6cUiTx7zjz+iSkU6X3nniJ9+WsDzXXDAydTzXb1Zr2fgyzP46wQQQPenNL64McHi+AGK4wEBJMvF8YFDNuU7pHe7L9gM4BBAAMmAQzYmKZEBJAIIIJmXiH73gUgPDgEEkBQHIvrdByKQCCCApDkjgkgECxYQSCReSgShCFYsILBIHIsY+O9nWK+AwCFxIhEDVSJYsIBAInFyIgbKRLBgAYFEYuVEDNSJYMUCAovEqRMx8HgGCxYQSCRWoYiBxzNYsYDAIrEqRRCLYMUCAovELBVBMIIlCwg0EjReNYV7fgMAAP//AwCw+aV5WXgAAA=="; + private const string csExp1XmlC = "H4sIAAAAAAACCuzYW2vCMBQA4PfB/kOJsD3MGp27OE2VXZgvG4MpbANh1Bo1mKWSxlWZ+++LQ90KihueFIQ8NT056Wny0VZDauM37rxTGbFQeKiQyyOHiiDsMNHz0Eh13RKqVff3yKWU/uShuziISXMypI4eLKLyOGIe6is1LGMcx3EuLuZC2cPH+XwBP9/fNYI+ffNdJiLli4Ci5ajO5lFI13Yckiz7HdNRf3EXESsr3fCQvmaZCYWqeYL9TckNPUdOm4xTNE/SaZwJGi1PdSBSUudVdQvPm8tcnEwmQchDmRh8O+L8ehb9FdThbk9W63pGBM9aia62DlxxPxgQ3E70EbzqYqYrEJyYVHJVCV7h8n+rArTV9BXY6qnPFF2zlDe+HDzSzvZcQEXSEDuGFstkgMW+F8vkwwVQIA2pIrQUbgFLvVDOw3jNWtYlpWJ7LJgaaXidQHsdHqbpBfRwwdRIw+sU/Ns1tV4Gvc6gvQ64qnzaV6JBsnNosha2Xga9StBeHwc9VbFkBskuoMk8137FTP5jBt/eyGYtmEkw8D0O17NgJsHAtziOjiyYSbCiBdstsBMLtltgpxZst8DANzs8+6Pjr2A/oWTPFwAAAP//AwATlI94cR0AAA=="; + private const string csExp2XmlC = "H4sIAAAAAAACCuzZ3WrbMBQA4PvB3sHooiRQW7aTNj+VU/ZDd7NRWAvbaBvhOkpiqsrFVucG9FB9hj5Z5ZJ0MxvqxhQlw7qKfCRL9pfDwULo8O6aOt9JXqQZi0Dg+cAhLMkmKZtF4JZP3T44HL1+hd7kebw4nq5+2OJ0cUMceTMrhndFGoE55zdDCMuy9MqOl+UzGPp+AL9++niSzMl17Kas4DFLCHi+a/LyXUCu7TiovuxTTEbj1VMU6ZDLRgTknMOUcTDyEYxfGnwi35GS05QSsBwkh9GUkeL5UgYKnstxo6c2XF78YTeC9dlQktEsr81+dEvpuyr6U1CGp7N89EG+MoJVq9Z1KQNvaZxcIXhZ60Pw18kQrC1ZR0HwN6x/Tx3opj7D4kJBfSbwhTnq93F+9ZlMtgU71I3tOZ4yr2W/dmxCmEJ72b8d3h3DdWSH8oMo2pnxA83qX+YpJ/+Lele3umi1hUK9hXG7yd572rO8yuOH+7Yq02WOY4GbzL6vmx2Ox+cK8nOMoWbvb4TSrFSArwZsh3hPt/iu6+4qxAXGwnCGbxd4336vGPUe2I9xgzsf7btModbGjdYOrLZB7dBWEoPaHattULtrK4lB7T2rbVB7fw2VBKsriWiuds9qG9Tur6GSYHUlabD2wGobPNjxbSUxqB1YbYPaoa0kBrU7VtugdndDZ2euEE0+OwvtmeVm3LXvL1sP92p1MR43O9V7NtU34t5fQ6pXrqoDTCHc6s9ptPvA5vu/uv8I1XseAQAA//8DADuPYn7wKwAA"; + private const string csExp3XmlC = "H4sIAAAAAAACCuycz2/SYBjH7yb+D11vauClMPaDtGxOoxeNiVuiRgzp4B1r1rVLW2TcOHgwZofpgHn1pgnJOHAynvqnvH+JL4SNNc4yu3edZd+EhPK+b/uBvg8fHt4+oK7s75rSe+q4hm1pspLOyBK1KnbVsGqaXPe2UkvySvHuHfWh4+jNF1und1Zzo7lHJb6z5Rb2XUOTtz1vr0BIo9FIN3Jp26mRbCajkNfPn61XtumunjIs19OtCpXP9qpO30vmbElSg9hRG2/VT5+FaxQ8vqHJ/JgFw/LkYkYl+rTB6/w1mnTDMKk8HsSHmYZF3bOHvMH1HD6uONom4wdno0lwuFqxTdsJ7P6kbpqPhq3nGnnzVs0prpl6ZUclw81A3+akbzPQp5KLjgbEpRAqCUxOMD5UckGE/XvUKaKjTktpqT+ibtLNezXBQfmGmqbd+MvJfqw7O6cDrjqpAAGUaFAcQsmKFgprt1h7wNo9vhEiltGw3mhkS7BgXm0bHg2ZgJe0evVpBgSQ/x4Sh0BywvNg1jlina4UJo/uEet+Zt0vfCPO7ERQtgnG5RlPHUqtkHfCuP+qmHOHummUoBMn9BXFIZJ54ZnIwaHfX70X4hGJHXwb3lq/Yk5BRCWb4ICTTE4cRsmLNgrxT/yTUohQSuUywXIJQADN6HLJgmilvPP7fv9tiFLKc3NlwUqZlhaumXV6vWvqglLpGBDxnCvMSPznKg5dLAr/TnP8gX+nmeKLEnwBX2BGEuiLJeHphW0juYAsMCMzKItl4bJY9fus+zPEFwS+gC8wI8n0hSK8ZJGwznd+w4ooQADd0hVRRXhJqvTgPvv4I6z8o/OVdQ7Z8adVXLYFB5wZu2yrZBPw0wp87tyaD7jcNZZID1AiDQggs10irYgvbRx7YeqPLAYwCCCAJN4g+Ws0yAAGAQSQGTfIws3nID0YBBBAkmqQxZvPQWAQQABJrEGWkIMgWgGBQSIbZBk5CKIVEBgk8v9dZfCHV4hWQGCQyAZRUA+CaAUEBolskCzqQRCtgMAgkQ2SQz0IohUQGCSyQeZxLQbRCggMEtkgeVyLQbQCAoNENghqUhGtgMAg0Q2CmlREKyAwyKhx0hTs+Q0AAP//AwBCDfCDg3QAAA=="; + + private const string csExp0TextC = "H4sIAAAAAAACCoTXv2/bRhQH8D1A/gdFU9M69r1HHu9IQIDdyF6aAEGT1ENdCErCJkJlKdCPNO6UoUNRZEgb2+narQUMxEOmopP/FP4lpe5Oel9SdGV7eKQP4AePx/fF3R3PR7OM7c0bDwc/5Vm8xTdvfJWfPDp5mWeH+WSUT3oHw/706Ysng7L8sj/Nt++Pn+XD7UeDYT7dajWv2Wp9k0+mg/GoQ9tq8bvVujsfzuaTvDPK57NJf7jVejB/Mhw8XTxr/EM+6ozmw6F7tMr2j1/OTlqfuSfcvnnj3mCUT1VWwu6pnsp2263yp+2uSK7ujofjyTSzYZV6rVRYsipZykjKWEotZSKlCWVpo6w7mMxqNHI0crTOnc6dtrta0MqLTpVGjpbshyWrkqWMpIyl1FImUppQljTODvvDYY3GjsaOVpy+KU4/FacXZdF2d2l598L9402Vyo4aH4Slq5KljKSMpdRSJlKaUJbUKOvm09lg1J+VO6Qmjpw48u+5OHtfnJ27dx157fn74vy34vz3sqhqI//O98PSVclSRlIutLznyoWW/TPdO/elCXdLbZw9GPZP8kkNGjto7Fv79t3V5e7ttrvh9mTx9s/F35t/q8rYv/6DsHBVspSRlLGUWspEShPKUqmzh7PxKK8htUNqh9y5+nj18ajtrhfGo15vp6rTsjm1bE4tm1PL5tSyObVsTi2bU+PmTLL9UX580nv8sgZMHDBxwO+uLq8uv2276wWwd+tWrwpMHJD2whL1ek+5kqWMZEEspZYFiZQmLCiBJgC/Hjx/Uf++jTMa/6Y//Fy+aYc0S+RRFWkEaQRpBGkEaQRpBGkEaRBpA7L7Y/2rsY5ofRvHY+ez1zTRis+Kz4rPis+Kz4rPis+iLw2+e/n39R6mDph64O7VZXH+T9vdWBh31oypGFMxpmJMxZiKMRVjKsYUjaT8h3J//Gowel6f5D5lyMfMTnH2V/nnPhlS13wzpGCiKxjpCma6gqGuYKorGOsK5rrCb4coDKBu3n9WB4fs8eHT+uLz4pe/2/6GG5dnfxRn74oPv+7W0CRziEgGEZFMIiIZRUQyi4hkGBHJNCLCcUScdefHx/UUJx9IxJUcJ74myImhuQzNZWguQ3MZmsvQXIbmcqW5kYvN3uM61OcQRfXo/NT2t/8/OymS8KRI0pMiiU+KJD8pkgClSBKUIolQijBDKfbwwzrc5xKFYAq8ZeZTHOCfroPHAI8BHgM8BngM8BjgMcDjClyHjq/JfViRrst9y/UmuQa5BrkGuQa5BrkGuQa5rsgTL+/W4T7EKGlueVKHX9TgCcATgCcATwCeADwBeALwpAI3oeVrch9tZJpbbjbJDcgNyA3IDcgNyA3IDchNRW7DLl+T+8Qj29xzu0luQW5BbkFuQW5BbkFuQW4r8nS5zdfoPgspbW56uomeAj0Fegr0FOgp0FOgp0BPkc7K0/frhwmfjqyajxNq03lCwYFCwYlCwZFCwZlCwaFCwalCwbFCVeAUer4m9zHJ1DjNmTbJCeQEcgI5gZxATiAnkFNFzmGfr8nDCY4b9znzhqHIeIjDUxwe4/Achwc5PMnhUa5yluNlgK7TfYRy1LjPOdpEhwhliFCGCGWIUIYIZYhQhgjlSoRyiNDumtxnKDdnKMcbvlCGDGXIUIYMZchQhgxlyFCGDOVKhvIyQ9fpPkS5OURZb6JDiDKEKEOIMoQoQ4gyhChDiHIlRDlZTvQ1uo9Rbo5R3hSjDDHKEKMMMcoQowwxyhCjDDHKlRhlsxrpa3YfpNwcpLwpSBmClCFIGYKUIUgZgpQhSBmClCVI/wMAAP//AwA9YL725BMAAA=="; + private const string csExp1TextC = "H4sIAAAAAAACCmzSS2vbQBSG4b3B/0EkizRYceYb3UVVWlx30wQCMVkFjJPMQlSViiVBc/vvOT4jopmR8eZ4JB6NRu+q6esuRzKf3ZYvKpc+5rPf6nnz/E/ld5uyUuunslteN0+qapcb1Xbt8q5sDxd+7rodLyzWdf9XZr73eT8v03+1b8umLrAUh5/vrfqq6/eqqFXf7XeV7930D1X5eHhe80fVRd1XFT9e5FshvC8aPp/PrspatSKnvV2Jrci/n3jeyXy2aqpm3+ZyWBX/RcIjhpEgEAQXAkNg6G1rQ2Ao/MUjhpEgSZB0IcmQZOj01Iak3tGKRwwjQQFBgQsFDAUMXd7bUMDQjzWPGEaCQoJCFwoZChk6O7OhUO9ozSOGkaCIoMiFIoYifUZvNhSNUGRCMUGxC8UMxQx9fbeheHy12Hy1hKDEhRKGEobuL20oGaHEhFKCUhdKGUoZev1mQ+kIpSaUEZS5UMZQxlBxYUPZeEaZeUagtDFJG7pt6Lh932lSjBiEpVHfmPY9BK4LvygcDYYGS6PIMYkcunLozBcLR5OGJi2NSsekdOjUERzXAkMLLI1yxyR36N4RHteM4mElD2oek+aho0d0XDOyh9U9KHxMwocuHzr9wv0KsaHFn9oHAAAA//8DAOesOI+PBQAA"; + private const string csExp2TextC = "H4sIAAAAAAACCnTW207bQBAG4Hsk3sHKVZCS4B2frSRqy0GqCi1SEFwAWYWylSxcG+XQNpUfimfgyRrP2DTj3YWrFejbn2F+lpNyU6xTzz08mGV/VeoP4PDgi9peb19UOiufy8dFIT8tVmp0k6nfl+WTykfXWa5O1Y+Bs//1gXOjlqusLCZi5NafA+dkk683SzUp1Ga9XOQD52rzmGffa718VsWk2OQ5XuamZz9f1lun38hHhwcXWaFWbroLc+FKN/3Qc3YfPTyJ/6eTMi+Xq1Q03+X+cSMERXq7yHPNE+gJ9O5k9dDDU+3dVfKBewI9nzxIz/OyXGogIAgIjpwRBgQKuDtyEBCEjwh66alarbNisd5NTGM9ZD32c3vIjieTKWc9Ys+R9dOrfLFVelAfRR/Fqn9U9fBUi30pj7jo74tBI377pZZ1ZE0OUA4o6/jttcZ2x5qeykpyOtinw3S2LguliSGKIYrH8/l9D081eC/lMQdDBMMzBCMCPxfGoBGyEbKD4XDQw1PNVlJWnI2IpZwx/fLl5WL5rJ40N0Y3ZjsQW3Yg3t+BBJdUftXEBMWErWliWdNkf02FS+StvvlUJUFdqtrdpzJJffldxoomqcFtKiW4K2wua5UAcmc6S8USwKsKtq4CY70mrsGlZgmPu57N9ZjrN9M1uNQv4fMx+LYx+MwN2vEaYKqXCDgc2OCAwSHBZzpLHRNhOwfZo2Mzh04dRMjYqMlrcKlkIuJuZHMj5sbNfA0ulUzE7RjIjdsxdN2YuW3RTDB1TSQcTmwwqxs0dZvpLlDfwGWDANcyCGB9g7ZvJpgKB4LDwgbzZwzaDTbAzVsGbBIAlkkAqxx47ytskKl04HHZs8msdNA+aYY/akCtA58/PkC1mw6rrsxeNug+baYbqH7Qed7A9r4Be+AgbLPrxQZqIFAD+2+vLU0drObzbviQ0VE3vOEKKiNEnfCRLXzEbojb8IbfKNUR4jb8lP7zoT5W1XDckWMmJ93shhuol5B0sie27Mn7Df8AAAD//wMAuoivtdEKAAA="; + + private const string csExp0BinC = "H4sIAAAAAAACCpJhYGBgAWImIC4MTy3KSy2Kd8tJLE7OSMoEMp0Si1P1fPNTUnP0QjJzUot1FLCr0VEISy0qzszPszXUMwBBHQXn0pyS0qJU27zU0pKixBwdhYDSpJzMZO/UypD87NQ827zSnBwGqM0sCkAAJjgYMAEjTJWtrq0uCxDbglTxsaFCJqgqnkdTGh5N2fJoyhogA8JZA+Y3gHTxs6BCZqguDoVHUyc/mjpNgefRtMmPpk18NG0SkAG2Bwq5mICAgYkJFlrsj3omHNrgoMml8KhnIQg17AFbwIYKWaHK2fQPrT+0PoYlJj5eH5vz2WDqYg9tOLQhmiVeUTEepI6LkYGLgYuLEUazw62f3gK0HqwwBptCDlioxebn4zaOE2ZcrMOhDY+m7WLRx6GQCxZQ+o+mrgAi3D7hhvlEQVvrUcdKrkdTZzyaOuHR9C4HbOHDgzUJoJvJiyVytxCMXD6ErjXISWILXl38WHRtIahLgJBda7DpEiRkF1ZdQmTZJUyWXSJkZStRsuJLjKz4EicrviTICkNJssJQiiy7pMmyCwAAAP//AwCEr84E0QUAAA=="; + private const string csExp1BinC = "H4sIAAAAAAACCmTOT2vCMBgG8Np1/ulc675BwIOHxrrtJhgvmycZeCiehFFnDmFZCk1yGOp3Nyk+vZSHF5JfkjfvSxAEoaueK7svhOSbkzD5V3XiUucF10bne6H9wWdpygayjbJ/70tK2vsNuz2vtagUe8tffSj5sNLYmjPFralLScnOHqX42fL/ovrliikrZXD/PSTEDzJw6YEu357SKI0wYzid+uXY5QG0OHhK4iSOQLNZQy6Pba8LqA9aXfFwADosQEPQeQ0agdgcvWIQpaAn0JyBxqAsAz13KelS2qVJO0Tb/gYAAP//AwAfetHlxQEAAA=="; + private const string csExp2BinC = "H4sIAAAAAAACCnSRXUvDMBSGu5p1OnWb39+SyxbaTu/bXah3IgiO3WzroZsRykIL3YoI+VH7DftlJv0YVTgJCeR5z/sm4dxrmkbk0uWafySLZBbG8BQumTuK2Pdb8sm4O4w4e2FfNq3rNh2xdBklsf/oPqhp0+eMr7KU+THLVmnIbfqezXg0f2U/w2TBYj/OONfKuwiVI98a8tTSGhUfg5iSsYBpzolecZe6sl7uirf1nT85nu8PFO/q1V+IMC1BTACr4M2SN6m3WVtkAAIKwagM/SCYkAlAX/GO0aq47Tg2EQAirzd2kQftIR9obx+kOGz5PsIPkJxDhHeQnC7Ce7UcUDmi4EcIP67lgMop+QnCT5GcM4SfIzkXCL/810hHFI3Rr7AOX5eCYW7WShFBUFpuMMttJUjLgBIhHK8Q7jDHLwAAAP//AwBX8XAjSAMAAA=="; +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. + private VisTileData testClass; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. + private Dictionary, int)> _testDefs = new(); + + [TestInitialize] + public void TestInitialize() + { + // Arrange + testClass = new VisTileData(); + + _testDefs.Add(0, ((t) => t.SetTileDefs(new Werner_Flaschbier_Base.View.VTileDef()), 29)); + _testDefs.Add(1, ((t) => t.SetTileDefs(new Snake_Console.View.TileDef()), 16)); + _testDefs.Add(2, ((t) => t.SetTileDefs(new Sokoban_Base.View.VisualsDef()), 23)); + _testDefs.Add(3, ((t) => t.SetTileDefs(new Console.Views.TileDef()), 29)); + } + + [TestMethod()] + public void GetTileDefTest() + { + Assert.Fail(); + } + + [TestMethod()] + [DataRow(0, 0, new[] { " ", " " })] + [DataRow(0, 1, new[] { "=-=-", "-=-=" })] + [DataRow(0, 2, new[] { "─┴┬─", "─┬┴─" })] + [DataRow(0, 3, new[] { " ╓╖ ", "▓░▒▓" })] + [DataRow(0, 4, new[] { "⌐°@)", " ⌡⌡‼" })] + [DataRow(1, 0, new[] { " " })] + [DataRow(1, 1, new[] { "|_" })] + [DataRow(1, 2, new[] { "##" })] + [DataRow(1, 3, new[] { "/\\" })] + [DataRow(1, 4, new[] { "''" })] + [DataRow(2, 0, new[] { " ", " " })] + [DataRow(2, 1, new[] { "[_|]", "[|_]" })] + [DataRow(2, 2, new[] { ". . ", " . ." })] + [DataRow(2, 3, new[] { " ", "<==>" })] + [DataRow(2, 4, new[] { "|()|", "(__)" })] + [DataRow(3, 0, new[] { " ", " " })] + [DataRow(3, 1, new[] { "=-=-", "-=-=" })] + [DataRow(3, 2, new[] { "─┴┬─", "─┬┴─" })] + [DataRow(3, 3, new[] { " ╓╖ ", "▓░▒▓" })] + [DataRow(3, 4, new[] { "⌐°@)", " ⌡⌡‼" })] + public void SetTileDefsTest(int iAct1, int iAct2, string[] asExp) + { + _testDefs[iAct1].Item1(testClass); + var act = testClass.GetTileDef((Enum)(Enum29)iAct2).lines; + Assert.IsNotNull(act); + for (int i = 0; i < asExp.Length; i++) + Assert.AreEqual(asExp[i], act[i]); + } + + [TestMethod()] + [DataRow(0, EStreamType.Code, new[] { csExp0CodeC })] + [DataRow(1, EStreamType.Code, new[] { csExp1CodeC })] + [DataRow(2, EStreamType.Code, new[] { csExp2CodeC })] + [DataRow(3, EStreamType.Code, new[] { csExp0CodeC })] + [DataRow(0, EStreamType.Json, new[] { csExp0JsonC })] + [DataRow(1, EStreamType.Json, new[] { csExp1JsonC })] + [DataRow(2, EStreamType.Json, new[] { csExp2JsonC })] + [DataRow(3, EStreamType.Json, new[] { csExp3JsonC })] + [DataRow(0, EStreamType.Xml, new[] { csExp0XmlC })] + [DataRow(1, EStreamType.Xml, new[] { csExp1XmlC })] + [DataRow(2, EStreamType.Xml, new[] { csExp2XmlC })] + [DataRow(3, EStreamType.Xml, new[] { csExp3XmlC })] + [DataRow(0, EStreamType.Text, new[] { csExp0TextC })] + [DataRow(0, EStreamType.Binary, new[] { csExp0BinC })] + [DataRow(1, EStreamType.Text, new[] { csExp1TextC })] + [DataRow(1, EStreamType.Binary, new[] { csExp1BinC })] + [DataRow(2, EStreamType.Text, new[] { csExp2TextC })] + [DataRow(2, EStreamType.Binary, new[] { csExp2BinC })] + [DataRow(1, EStreamType.Xml, new[] { csExp1XmlC })] + [DataRow(2, EStreamType.Xml, new[] { csExp2XmlC })] + [DataRow(3, EStreamType.Xml, new[] { csExp3XmlC })] + public void LoadFromStreamTest(int iAct1, EStreamType iAct2, string[] asExp) + { + var sAct = Decompress(asExp[0]); + + var ms = new MemoryStream(); + ms.Write(Encoding.UTF8.GetBytes(sAct)); + ms.Position = 0L; + var act = testClass.LoadFromStream(ms, iAct2); + Assert.IsTrue(act); + + var cExp = new VisTileData(); + _testDefs[iAct1].Item1(cExp); + + if (!cExp.Equals(testClass)) + { + AssertAreEqual(cExp, testClass, []); + } + else + Assert.AreEqual(cExp, testClass); + } + + [TestMethod()] + [DataRow(0, EStreamType.Code, new[] { csExp0CodeC })] + [DataRow(1, EStreamType.Code, new[] { csExp1CodeC })] + [DataRow(2, EStreamType.Code, new[] { csExp2CodeC })] + [DataRow(3, EStreamType.Code, new[] { csExp0CodeC })] + [DataRow(0, EStreamType.Json, new[] { csExp0JsonC })] + [DataRow(1, EStreamType.Json, new[] { csExp1JsonC })] + [DataRow(2, EStreamType.Json, new[] { csExp2JsonC })] + [DataRow(3, EStreamType.Json, new[] { csExp3JsonC })] + [DataRow(0, EStreamType.Xml, new[] { csExp0XmlC })] + [DataRow(1, EStreamType.Xml, new[] { csExp1XmlC })] + [DataRow(2, EStreamType.Xml, new[] { csExp2XmlC })] + [DataRow(3, EStreamType.Xml, new[] { csExp3XmlC })] + [DataRow(0, EStreamType.Text, new[] { csExp0TextC })] + [DataRow(0, EStreamType.Binary, new[] { csExp0BinC })] + [DataRow(1, EStreamType.Text, new[] { csExp1TextC })] + [DataRow(1, EStreamType.Binary, new[] { csExp1BinC })] + [DataRow(2, EStreamType.Text, new[] { csExp2TextC })] + [DataRow(2, EStreamType.Binary, new[] { csExp2BinC })] + [DataRow(1, EStreamType.Xml, new[] { csExp1XmlC })] + [DataRow(2, EStreamType.Xml, new[] { csExp2XmlC })] + [DataRow(3, EStreamType.Xml, new[] { csExp3XmlC })] + public void WriteToStreamTest(int iAct1, EStreamType iAct2, string[] asExp) + { + _testDefs[iAct1].Item1(testClass); + var ms = new MemoryStream(); + var act = testClass.WriteToStream(ms, iAct2); + Assert.IsTrue(act); + + ms.Position = 0L; + var sr = new StreamReader(ms).ReadToEnd(); + if (iAct2 == EStreamType.Json) + sr = sr.Replace("],", "],\r\n"); + var sExp = Decompress(asExp[0]); + if (sExp != sr) + { + Debug.WriteLine("Result:"); + Debug.WriteLine(sr); + Debug.WriteLine("Packed:"); + Debug.WriteLine(Compress(sr)); + AssertAreEqual(sExp, sr); + } + else + Assert.AreEqual(sExp, sr); + + } + + private static string Compress(string input) + { + using (var memoryStream = new MemoryStream()) + { + using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.SmallestSize)) + using (var writer = new StreamWriter(gzipStream)) + { + writer.Write(input); + } + return Convert.ToBase64String(memoryStream.ToArray()); + } + } + + private static string Decompress(string input) + { + try + { + using (var memoryStream = new MemoryStream(Convert.FromBase64String(input))) + using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) + using (var reader = new StreamReader(gzipStream)) + { + return reader.ReadToEnd(); + } + } + catch (Exception ex) + { + return input; + } + } + private enum Enum29 + { + _00 = 0, + _01, _02, _03, _04, _05, _06, _07, _08, _09, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, + + } + } +} \ No newline at end of file diff --git a/CSharpBible/Games/VTileEditTests/VTileEditTests.csproj b/CSharpBible/Games/VTileEditTests/VTileEditTests.csproj new file mode 100644 index 000000000..08bf69bdf --- /dev/null +++ b/CSharpBible/Games/VTileEditTests/VTileEditTests.csproj @@ -0,0 +1,33 @@ + + + + Library + net6.0;net7.0;net8.0;net9.0 + disable + enable + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + diff --git a/CSharpBible/Games/VTileEditTests/Views/TileDef.cs b/CSharpBible/Games/VTileEditTests/Views/TileDef.cs new file mode 100644 index 000000000..b07cf9f69 --- /dev/null +++ b/CSharpBible/Games/VTileEditTests/Views/TileDef.cs @@ -0,0 +1,118 @@ +//*************************************************************** +// Assembly : SomeGame_Base +// Author : Mir +// Created : 01-01-2025 +// +// Last Modified By : Mir +// Last Modified On : 01-01-2025 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using ConsoleDisplay.View; +using System.Drawing; + +/// +/// The View namespace. +/// +/// +namespace Console.Views; + +/// +/// Class TileDef. +/// Implements the +/// +public class TileDef : TileDefBase +{ + /// + /// The tile definition string + /// + private readonly string[][] _vTileDefStr = [ + [@" "], //Empty + [@"=-=-", @"-=-="], //Dirt + [@"─┴┬─", @"─┬┴─"], //Wall + [@" ╓╖ ", @"▓░▒▓"], //Destination + [@"⌐°@)", @" ⌡⌡‼"], //Player + [@"/¯¯\", @"\__/"], //Stone + [@"]°°[", @"_!!_"], //Enemy_Up + [@"◄°@[", @"_!!\"], //Enemy_Right + [@"]oo[", @"_!!_"], //Enemy_Dwn + [@"]@°►", @"/!!_"], //Enemy_Left + [@"/╨╨\", @"\__/"], //StoneMoving + [@" +*∩", @"╘═◊@"], //PlayerDead + [@" "], //Dummy + [@"─┴┬┴", @"─┬┴─"], //Wall_U + [@"┬┴┬─", @"┴┬┴─"], //Wall_W + [@"┬┴┬┴", @"┴┬┴─"], //Wall_UW + [@"┬┴┬─", @"┴┬┴┬"], //Wall_D + [@"┬┴┬┴", @"┴┬┴┬"], //Wall_UD + [@"┬┴┬─", @"┴┬┴┬"], //Wall_WD + [@"┬┴┬┴", @"┴┬┴┬"], //Wall_UWD + [@"─┴┬─", @"─┬┴─"], //Wall_E + [@"─┴┬┴", @"─┬┴─"], //Wall_UE + [@"┬┴┬─", @"┴┬┴─"], //Wall_WE + [@"┬┴┬┴", @"┴┬┴─"], //Wall_UWE + [@"┬┴┬─", @"┴┬┴┬"], //Wall_DE + [@"┬┴┬┴", @"┴┬┴┬"], //Wall_UDE + [@"┬┴┬─", @"┴┬┴┬"], //Wall_WDE + [@"┬┴┬┴", @"┴┬┴┬"], //Wall_UWDE + ]; + + + /// + /// The tile colors + /// + private readonly byte[][] _vTileColors = [ + [0x00], //Empty + [0x6E], //Dirt + [0x4F], //Wall + [0x0E, 0x0E, 0x0E, 0x0E, 0x2A, 0x22, 0x02, 0x22], //Destination + [0x6F], //Player + [0x6E], //Stone + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Up + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Right + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Dwn + [0x1A, 0xA0, 0xA0, 0x1A], //Enemy_Left + [0x6E], //StoneMoving + [0x6F], //PlayerDead + [0x6E], //Dummy + [0x4F], //Wall_U + [0x4F], //Wall_W + [0x4F], //Wall_UW + [0x4F], //Wall_D + [0x4F], //Wall_UD + [0x4F], //Wall_WD + [0x4F], //Wall_UWD + [0x4F], //Wall_E + [0x4F], //Wall_UE + [0x4F], //Wall_WE + [0x4F], //Wall_UWE + [0x4F], //Wall_DE + [0x4F], //Wall_UDE + [0x4F], //Wall_WDE + [0x4F], //Wall_UWDE + ]; + + /// + /// Gets the tile definition. + /// + /// The tile. + /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors). + /// + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + { + (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default; + result.lines = GetArrayElement(_vTileDefStr, tile); + + result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++) + result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]); + return result; + } + + public TileDef() : base() => TileSize = new Size(4, 2); +} \ No newline at end of file diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Enemy.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Enemy.cs index 15ade7c24..3cdcce19f 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/Enemy.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Enemy.cs @@ -49,7 +49,7 @@ public override bool TestMove(Direction? dir = null) if (dir == null) dir = _direction; var result = false; - var dest = field?.Parent?[Offsets.DirOffset(dir, Position)]; + var dest = field?.Parent?[Offsets.DirOffset(dir, Place)]; if (dest is Space s ) { result = s.Item == null || s.Item is Player; @@ -70,7 +70,7 @@ public override bool TryMove(Direction? dir = null) foreach (int dd in new int[] { 0, 3, 1, 2 }) { var dir2 = (Direction)(((int)dir + dd) % 4); - if (field?.Parent?[Offsets.DirOffset(dir2, Position)] is Space s && s is not Destination) + if (field?.Parent?[Offsets.DirOffset(dir2, Place)] is Space s && s is not Destination) { result = s.Item == null || s.Item is Player || (s.Item is Enemy e && !e.Handled && e.TryMove()); if (s.Item == null) diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/IWernerGame.cs b/CSharpBible/Games/Werner_Flaschbier/Model/IWernerGame.cs new file mode 100644 index 000000000..c05647cb9 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/Model/IWernerGame.cs @@ -0,0 +1,46 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Drawing; + +namespace Werner_Flaschbier_Base.Model +{ + public interface IWernerGame + { + Size size { get; } + int Level { get; } + int Lives { get; } + float TimeLeft { get; } + bool isRunning { get; } + int Score { get; } + int MaxLives { get; } + + Enum this[Point p] { get; } + + event EventHandler? visUpdate; + event EventHandler? visFullRedraw; + event EventHandler? visShowHelp; + + void Setup(int? newLevel = null); + void ReqQuit(); + void ReqHelp(); + void ReqRestart(); + void NextLvl(); + void PrevLvl(); + void MovePlayer(Direction action); + void HandleGameLogic(); + int GameStep(); + Point OldPos(Point p); + } +} \ No newline at end of file diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/PlayObject.cs b/CSharpBible/Games/Werner_Flaschbier/Model/PlayObject.cs index 089b88e00..fa0f5223d 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/PlayObject.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/PlayObject.cs @@ -11,21 +11,38 @@ // // // *********************************************************************** +using Game_Base.Model.Interfaces; +using System; using System.Drawing; +using System.Runtime.CompilerServices; namespace Werner_Flaschbier_Base.Model { /// /// Class PlayObject. /// - public abstract class PlayObject + public abstract class PlayObject : IPlacedObject { + private Point _place = Point.Empty; + + public event EventHandler<(Point oP, Point nP)>? OnPlaceChange; /// /// Gets or sets the position. /// /// The position of the player on the playfield - public Point Position { get; set; } + public Point Place { get=>GetPlace(); set=>SetPlace(value); } + + public void SetPlace(Point value, [CallerMemberName] string Name = "") + { + if (_place == value) return; + var _o = _place; + _place = value; + OnPlaceChange?.Invoke(this,(_o, _place)); + } + + public Point GetPlace() => _place; + /// /// Gets or sets the old position. /// @@ -57,6 +74,11 @@ public abstract class PlayObject /// true: if the object has moveed in the direction public abstract bool TryMove(Direction? dir=null); + public Point GetOldPlace() + { + throw new NotImplementedException(); + } + /// /// Initializes a new instance of the class. /// diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Player.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Player.cs index 44877304c..0bd3d3d7a 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/Player.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Player.cs @@ -55,7 +55,7 @@ public bool Go(Direction? aDir) { /// true: if the object can move in the direction public override bool TestMove(Direction? dir) { - var newfield = field?.Parent?[Offsets.DirOffset(dir,Position)]; + var newfield = field?.Parent?[Offsets.DirOffset(dir,Place)]; if (newfield == null || newfield is not Space s) return false; else @@ -73,7 +73,7 @@ public override bool TestMove(Direction? dir) public override bool TryMove(Direction? dir) { if (dir == null) return false; - var newfield = field?.Parent?[Offsets.DirOffset(dir, Position)]; + var newfield = field?.Parent?[Offsets.DirOffset(dir, Place)]; if (newfield == null || newfield is not Space f ) { if (newfield is Destination) diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Playfield.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Playfield.cs index f5b6f1239..ed882bc5f 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/Playfield.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Playfield.cs @@ -143,11 +143,11 @@ public void Setup(FieldDef[]? SFDef) case FieldDef.Stone: result.Item = CreateStone(); - result.Item.OldPosition = result.Item.Position; + result.Item.OldPosition = result.Item.Place; break; case FieldDef.Enemy: result.Item = CreateEnemy(); - result.Item.OldPosition = result.Item.Position; + result.Item.OldPosition = result.Item.Place; break; case FieldDef.Dirt: result.Item = new Dirt(null); ; diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Space.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Space.cs index 0af052c6b..acaf6bf90 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/Space.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Space.cs @@ -63,8 +63,8 @@ protected override void SetItem(PlayObject? value) { if (Item != null) { - Item.OldPosition = Item.Position; - Item.Position = new Point(0, 0); + Item.OldPosition = Item.Place; + Item.Place = new Point(0, 0); Item.field = null; OldItem = Item; _item = null; @@ -77,8 +77,8 @@ protected override void SetItem(PlayObject? value) var f = value.field; f.Item = null; } -// value.OldPosition = value.Position; - value.Position = Position; +// value.OldPosition = value.Place; + value.Place = Position; value.field = this; OldItem = Item; _item = value; diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Stone.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Stone.cs index 13dd4c5e2..17666de81 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/Stone.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Stone.cs @@ -38,19 +38,19 @@ public override bool TestMove(Direction? dir = null) { var result = false; - var dest = field?.Parent?[Offsets.DirOffset(Direction.Down, Position)]; + var dest = field?.Parent?[Offsets.DirOffset(Direction.Down, Place)]; if (dest is Space @s && @s.Item == null && dest is not Destination) result = true; else if (dest is Space @s2 && @s2.Item is Stone || dest is Wall) { - var zwd= field?.Parent?[Offsets.DirOffset(Direction.West, Position)]; - var dest2= field?.Parent?[Offsets.DirOffset(Direction.WestDown, Position)]; + var zwd= field?.Parent?[Offsets.DirOffset(Direction.West, Place)]; + var dest2= field?.Parent?[Offsets.DirOffset(Direction.WestDown, Place)]; if (zwd is Space @zs && @zs.Item==null && @zs.OldItem == null && dest2 is Space @ds2 && @ds2.Item == null) result =true; else { - zwd = field?.Parent?[Offsets.DirOffset(Direction.East, Position)]; - dest2 = field?.Parent?[Offsets.DirOffset(Direction.EastDown, Position)]; + zwd = field?.Parent?[Offsets.DirOffset(Direction.East, Place)]; + dest2 = field?.Parent?[Offsets.DirOffset(Direction.EastDown, Place)]; if (zwd is Space @zs2 && @zs2.Item == null && @zs2.OldItem == null && dest2 is Space @ds3 && @ds3.Item == null) result = true; } @@ -66,33 +66,33 @@ public override bool TestMove(Direction? dir = null) public override bool TryMove(Direction? dir=null) { Handled=true; - var dest= field?.Parent?[Offsets.DirOffset(Direction.Down, Position)]; + var dest= field?.Parent?[Offsets.DirOffset(Direction.Down, Place)]; if (dest is Space @s && dest is not Destination && (s.Item == null && s.OldItem == null || s.Item is Player)) if (@s.Item == null) @s.Item = this; - else if (@s.Item is Player @p && (OldPosition != Position)) + else if (@s.Item is Player @p && (OldPosition != Place)) p.IsAlive = false; - else { OldPosition = Position; return false; } + else { OldPosition = Place; return false; } else if (dest is Space @s2 && @s2.Item is Stone || dest is Wall) { - var zwd = field?.Parent?[Offsets.DirOffset(Direction.West, Position)]; - var dest2 = field?.Parent?[Offsets.DirOffset(Direction.WestDown, Position)]; + var zwd = field?.Parent?[Offsets.DirOffset(Direction.West, Place)]; + var dest2 = field?.Parent?[Offsets.DirOffset(Direction.WestDown, Place)]; if (zwd is Space @zs && zwd is not Destination && @zs.Item == null && dest2 is Space @ds2 && dest2 is not Destination && @ds2.Item == null && @ds2.OldItem == null) @ds2.Item = this; else { - zwd = field?.Parent?[Offsets.DirOffset(Direction.East, Position)]; - dest2 = field?.Parent?[Offsets.DirOffset(Direction.EastDown, Position)]; + zwd = field?.Parent?[Offsets.DirOffset(Direction.East, Place)]; + dest2 = field?.Parent?[Offsets.DirOffset(Direction.EastDown, Place)]; if (zwd is Space @zs2 && zwd is not Destination && @zs2.Item == null && dest2 is Space @ds3 && dest2 is not Destination && @ds3.Item == null && @ds3.OldItem == null) @ds3.Item = this; else - { OldPosition = Position; return false; } + { OldPosition = Place; return false; } } } else - { OldPosition = Position; return false; } + { OldPosition = Place; return false; } return true; } } diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/Tiles.cs b/CSharpBible/Games/Werner_Flaschbier/Model/Tiles.cs new file mode 100644 index 000000000..b1866b046 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/Model/Tiles.cs @@ -0,0 +1,137 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using Werner_Flaschbier_Base.Model; + +namespace Werner_Flaschbier_Base.Model +{ + /// + /// Enum Tiles + /// + public enum Tiles + { + /// + /// The empty + /// + Empty = FieldDef.Empty, + /// + /// The dirt + /// + Dirt = FieldDef.Dirt, + /// + /// The wall + /// + Wall = FieldDef.Wall, + /// + /// The destination + /// + Destination = FieldDef.Destination, + /// + /// The player + /// + Player = FieldDef.Player, + /// + /// The stone + /// + Stone = FieldDef.Stone, + /// + /// The enemy up + /// + Enemy_Up = FieldDef.Enemy, + /// + /// The enemy right + /// + Enemy_Right = 7, + /// + /// The enemy DWN + /// + Enemy_Dwn = 8, + /// + /// The enemy left + /// + Enemy_Left = 9, + /// + /// The stone moving + /// + StoneMoving = 10, + /// + /// The player dead + /// + PlayerDead = 11, + /// + /// The dummy + /// + Dummy = 12, + /// + /// The wall u + /// + Wall_U, + /// + /// The wall w + /// + Wall_W, + /// + /// The wall uw + /// + Wall_UW, + /// + /// The wall d + /// + Wall_D, + /// + /// The wall ud + /// + Wall_UD, + /// + /// The wall wd + /// + Wall_WD, + /// + /// The wall uwd + /// + Wall_UWD, + /// + /// The wall e + /// + Wall_E, + /// + /// The wall ue + /// + Wall_UE, + /// + /// The wall we + /// + Wall_WE, + /// + /// The wall uwe + /// + Wall_UWE, + /// + /// The wall de + /// + Wall_DE, + /// + /// The wall ude + /// + Wall_UDE, + /// + /// The wall wde + /// + Wall_WDE, + /// + /// The wall uwde + /// + Wall_UWDE + }; + +} diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs b/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs new file mode 100644 index 000000000..02f8a94c1 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs @@ -0,0 +1,265 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Drawing; +using Werner_Flaschbier_Base.Model; + +namespace Werner_Flaschbier_Base.Model +{ + /// + /// Class WernerGame. + /// + public class WernerGame : IWernerGame + { + #region Properties + #region private Properties & Fields + + #endregion + /// + /// Gets the size. + /// + /// The size. + public Size size => playfield.size; + /// + /// Gets the lives. + /// + /// The lives. + public int Lives { get; private set; } + /// + /// Gets the time left. + /// + /// The time left. + public float TimeLeft { get; private set; } + /// + /// Gets a value indicating whether this instance is running. + /// + /// true if this instance is running; otherwise, false. + public bool isRunning { get => !_userQuit && (Lives > 0); } + + /// + /// Occurs when [vis update]. + /// + public event EventHandler? visUpdate; + /// + /// Occurs when [vis full redraw]. + /// + public event EventHandler? visFullRedraw; + /// + /// Occurs when [vis show help]. + /// + public event EventHandler? visShowHelp; + + /// + /// Gets the with the specified p. + /// + /// The p. + /// Tiles. + public Enum this[Point p]=>GetTile(p); + /// + /// The level + /// + private int level = 0; + /// + /// The maximum lives + /// + private readonly int maxLives = 10; + /// + /// Gets or sets the score. + /// + /// The score. + public int Score { get; set; } = 0; + + public int MaxLives => maxLives; + + public int Level { get => level; set => level = value; } + + #region private Properties + /// + /// The playfield + /// + private readonly Playfield playfield = new(); + /// + /// The half step + /// + private bool halfStep=false; + /// + /// The act dir + /// + private Direction? actDir; + /// + /// The next dir + /// + private Direction? nextDir; + /// + /// The next dir2 + /// + private Direction? nextDir2; + /// + /// The user quit + /// + private bool _userQuit=false; + #endregion + #endregion + + #region Methods + /// + /// Gets the tile. + /// + /// The p. + /// Tiles. + public Tiles GetTile(Point p) + { + var field = playfield[p]; + Tiles result; + switch (field?.fieldDef) + { + case FieldDef.Enemy: + result = Tiles.Enemy_Up; + if (field?.Item is Enemy e) + result = (Tiles)((int)result + (int)(e.direction)); + break; + case FieldDef.Wall: + int w = 0; + result = Tiles.Wall; + for (var d = (Direction)0; (int)d < 4; d++) + w += ((playfield[Offsets.DirOffset(d, p)] is Wall) ? 1 << (int)d : 0); + if (w > 0) + result = (Tiles)(w - 1 + (int)Tiles.Wall_U); + break; + case FieldDef.Player: + if ((field.Item is Player plr) && (plr.IsAlive)) + result = Tiles.Player; + else + result = Tiles.PlayerDead; + break; + case FieldDef.Stone: + if ((field.Item is Stone stn) && (stn.Place == stn.OldPosition)) + result = Tiles.Stone; + else + result = Tiles.StoneMoving; + break; + default: + result = (Tiles?)field?.fieldDef ?? Tiles.Empty; + break; + } + return result; + } + + /// + /// Olds the position. + /// + /// The p. + /// Point. + public Point OldPos(Point p) + { + var field = playfield[p]; + if (field is Space s && s.Item != null) + return s.Item.OldPosition; + else + return p; + } + + /// + /// Initializes a new instance of the class. + /// + public WernerGame() + { + Setup(); + Lives = maxLives; + } + + /// + /// Setups the specified new level. + /// + /// The new level. + public void Setup(int? newLevel=null) + { + Level = newLevel ?? Level; + playfield.Setup(LevelDefs.GetLevel(Level)); + TimeLeft = 99f; + visFullRedraw?.Invoke(this,new EventArgs()); + } + + public void HandleGameLogic() + { + if (!playfield.player?.IsAlive ?? false && Lives > 0) + { + Lives--; + if (Lives > 0) Setup(); + } + if (playfield.player?.field is Destination) + { + Score += (int)TimeLeft; + Setup(Level + 1); + } + } + + public void MovePlayer(Direction dir) + { + if (actDir == null) actDir = dir; + else if (nextDir == null) nextDir = dir; + else if (nextDir2 == null) nextDir2 = dir; + else { actDir = nextDir; nextDir = nextDir2; nextDir2 = dir; } + } + + public void PrevLvl() => Setup(Math.Max(Level - 1, 0)); + + public void NextLvl() => Setup(Level + 1); + + public void ReqRestart() + { + Lives--; + if (Lives > 0) Setup(); + } + + public void ReqHelp() => visShowHelp?.Invoke(this, new EventArgs()); + + public void ReqQuit() => _userQuit = true; + + /// + /// Games the step. + /// + /// System.Int32. + public int GameStep() + { + halfStep = !halfStep; + if (TimeLeft > 0.1) + TimeLeft -= 0.06f; + else if (playfield.player!=null) + playfield.player.IsAlive = false; + if (halfStep) + { + foreach (PlayObject po in playfield.ActiveObjects) + po.Handled = false; + foreach (Space sp in playfield.Spaces) + sp.OldItem = sp.Item; + playfield.player?.TryMove(actDir); + actDir = nextDir; + nextDir = nextDir2; + nextDir2 = null; + foreach (PlayObject po in playfield.ActiveObjects) + if (!po.Handled) + { + if (po is not Player) + po.TryMove(); + } + } + + visUpdate?.Invoke(this, halfStep); + + return 60; + } + #endregion + } +} diff --git a/CSharpBible/Games/Werner_Flaschbier/Program.cs b/CSharpBible/Games/Werner_Flaschbier/Program.cs index ed598edbc..bb7085043 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Program.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Program.cs @@ -32,16 +32,18 @@ public class Programm /// /// The game /// - private IWernerGame game; - private IVisual visual; + private IWernerGame? game; + private IVisual? visual; - private static void OnStartUp() + private void OnStartUp() { var sc = new ServiceCollection() .AddSingleton() .AddTransient() + .AddSingleton() .AddSingleton() .AddSingleton(); + var sp = sc.BuildServiceProvider(); IoC.Configure(sp); @@ -61,10 +63,9 @@ public static void Main(params string[] args) public void Run() { - while (game.isRunning) + while (game!.isRunning) { - UserAction action; - visual.CheckUserAction(); + visual?.CheckUserAction(); var delay = game.GameStep(); Thread.Sleep(delay); } diff --git a/CSharpBible/Games/Werner_Flaschbier/View/IVisual.cs b/CSharpBible/Games/Werner_Flaschbier/View/IVisual.cs new file mode 100644 index 000000000..82fa9cd57 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/View/IVisual.cs @@ -0,0 +1,19 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +namespace Werner_Flaschbier_Base.View; + +public interface IVisual +{ + bool CheckUserAction(); +} \ No newline at end of file diff --git a/CSharpBible/Games/Werner_Flaschbier/View/VTileDef.cs b/CSharpBible/Games/Werner_Flaschbier/View/VTileDef.cs index d0387d663..ad4d86331 100644 --- a/CSharpBible/Games/Werner_Flaschbier/View/VTileDef.cs +++ b/CSharpBible/Games/Werner_Flaschbier/View/VTileDef.cs @@ -12,91 +12,85 @@ // // *********************************************************************** using System; +using System.Drawing; +using ConsoleDisplay.View; using Werner_Flaschbier_Base.Model; namespace Werner_Flaschbier_Base.View { - /// - /// Struct FullColor - /// - public struct FullColor - { - /// - /// The fore ground - /// - public ConsoleColor foreGround, backGround; - } /// /// Class VTileDef. /// - public static class VTileDef { + public class VTileDef :ITileDef { /// /// The v tile definition string /// - private static string[][] _vTileDefStr = new string[][]{ - new string[]{" ", " " }, - new string[]{"=-=-", "-=-=" }, - new string[]{ "─┴┬─", "─┬┴─"}, - new string[]{ " ╓╖ ", "▓░▒▓" }, - new string[]{ "⌐°@)", " ⌡⌡‼" }, - new string[]{ @"/¯¯\", @"\__/" }, - new string[]{ "]°°[", "_!!_" }, - new string[]{ "◄°@[",@"_!!\" }, - new string[]{ "]oo[", "_!!_" }, - new string[]{ "]@°►", "/!!_" }, - new string[]{ @"/╨╨\", @"\__/" }, - new string[]{ " +*∩", "╘═◊@" }, - new string[]{ " ", " "}, - new string[]{ "─┴┬┴", "─┬┴─"}, - new string[]{ "┬┴┬─", "┴┬┴─"}, - new string[]{ "┬┴┬┴", "┴┬┴─"}, + private string[][] _vTileDefStr = [ + [" ", " "], + ["=-=-", "-=-="], + ["─┴┬─", "─┬┴─"], + [" ╓╖ ", "▓░▒▓"], + ["⌐°@)", " ⌡⌡‼"], + [@"/¯¯\", @"\__/"], + ["]°°[", "_!!_"], + ["◄°@[",@"_!!\"], + ["]oo[", "_!!_"], + ["]@°►", "/!!_"], + [@"/╨╨\", @"\__/"], + [" +*∩", "╘═◊@"], + [" ", " "], + ["─┴┬┴", "─┬┴─"], + ["┬┴┬─", "┴┬┴─"], + ["┬┴┬┴", "┴┬┴─"], - new string[]{ "┬┴┬─", "┴┬┴┬"}, - new string[]{ "┬┴┬┴", "┴┬┴┬"}, - new string[]{ "┬┴┬─", "┴┬┴┬"}, - new string[]{ "┬┴┬┴", "┴┬┴┬"}, + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], - new string[]{ "─┴┬─", "─┬┴─"}, - new string[]{ "─┴┬┴", "─┬┴─"}, - new string[]{ "┬┴┬─", "┴┬┴─"}, - new string[]{ "┬┴┬┴", "┴┬┴─"}, + ["─┴┬─", "─┬┴─"], + ["─┴┬┴", "─┬┴─"], + ["┬┴┬─", "┴┬┴─"], + ["┬┴┬┴", "┴┬┴─"], - new string[]{ "┬┴┬─", "┴┬┴┬"}, - new string[]{ "┬┴┬┴", "┴┬┴┬"}, - new string[]{ "┬┴┬─", "┴┬┴┬"}, - new string[]{ "┬┴┬┴", "┴┬┴┬"} - }; + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"] + ]; /// /// The v tile colors /// - private static byte[][] _vTileColors = new byte[][] - { - new byte [] {0x00 }, - new byte [] {0x6E }, - new byte [] { 0x4F }, - new byte [] { 0x0E, 0x0E, 0x0E, 0x0E, 0x2A, 0x22, 0x02, 0x22 }, - new byte [] { 0x6F }, - new byte [] { 0x6E }, - new byte [] { 0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A }, - new byte [] { 0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A }, - new byte [] { 0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A }, - new byte [] { 0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A }, - new byte [] { 0x6E }, - new byte [] { 0x6F }, - new byte [] { 0x6E }, - new byte [] { 0x4F }, + private byte[][] _vTileColors = + [ + [0x00], + [0x6E], + [0x4F], + [0x0E, 0x0E, 0x0E, 0x0E, 0x2A, 0x22, 0x02, 0x22], + [0x6F], + [0x6E], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x6E], + [0x6F], + [0x6E], + [0x4F], - }; + ]; - /// - /// Gets the tile string. - /// - /// The tile. - /// System.String[]. - public static string[] GetTileStr(Tiles tile) { - if ((int)tile < _vTileDefStr.Length) + public Size TileSize => new Size(4,2); + + /// + /// Gets the tile string. + /// + /// The tile. + /// System.String[]. + private string[] GetTileStr(Tiles? tile) { + if ((int?)tile < _vTileDefStr.Length) return _vTileDefStr[(int)tile]; else return _vTileDefStr[_vTileDefStr.Length-1]; @@ -107,21 +101,23 @@ public static string[] GetTileStr(Tiles tile) { /// /// The tile. /// FullColor[]. - public static FullColor[] GetTileColors(Tiles tile) + private (ConsoleColor fgr, ConsoleColor bgr)[] GetTileColors(Tiles? tile) { - var result = new FullColor[8]; + var result = new (ConsoleColor fgr, ConsoleColor bgr)[8]; byte[] colDef; - if ((int)tile < _vTileColors.Length) + if ((int?)tile < _vTileColors.Length) colDef = _vTileColors[(int)tile]; else colDef = _vTileColors[_vTileColors.Length - 1]; for (var i =0;i> 4)); } return result; } - } + public (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + => (GetTileStr((Tiles?)tile), GetTileColors((Tiles?)tile)); + } } diff --git a/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs b/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs index 21df70349..baf8a8533 100644 --- a/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs +++ b/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs @@ -34,12 +34,13 @@ public class Visual : IVisual { /// /// The game /// - private IWernerViewModel? _game; + private IWernerViewModel _viewModel; + private readonly ITileDef _tileDef; - /// - /// My console - /// - private IConsole _console ; + /// + /// My console + /// + private IConsole _console ; /// /// The key action @@ -61,18 +62,19 @@ public class Visual : IVisual { #endregion #region Methods - public Visual(IWernerViewModel viewModel,IConsole console) + public Visual(IWernerViewModel viewModel,IConsole console, ITileDef tileDef) { - _game = viewModel; - _game.PropertyChanged += OnPropertyChanged; - _console = console; + _viewModel = viewModel; + _viewModel.PropertyChanged += OnPropertyChanged; + _tileDef = tileDef; + _console = console; FullRedraw(); } - private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Tiles") - G_visUpdate(sender, _game.HalfStep); + G_visUpdate(sender, _viewModel!.HalfStep); else if (e.PropertyName == "Level") FullRedraw(); } @@ -96,20 +98,20 @@ private void G_visUpdate(object? sender, bool e) { List<(Point, Tiles, Point)> diffFields = new(); var p = new Point(); - if (_game==null) return; + if (_viewModel==null) return; - for (p.Y = 0; p.Y < _game.size.Height; p.Y++) - for (p.X = 0; p.X < _game.size.Width; p.X++) + for (p.Y = 0; p.Y < _viewModel.size.Height; p.Y++) + for (p.X = 0; p.X < _viewModel.size.Width; p.X++) { - var td = _game.Tiles[p]; - if ((Tiles)td != _buffer[p.X + p.Y * _game.size.Width] || (IsEnemy((Tiles)td) && _game.OldPos(p)!=p)) + var td = _viewModel.Tiles[p]; + if ((Tiles)td != _buffer[p.X + p.Y * _viewModel.size.Width] || (IsEnemy((Tiles)td) && _viewModel.OldPos(p)!=p)) { Point pp = new Point(p.X,p.Y); #pragma warning disable CS8604 // Mgliches Nullverweisargument. - diffFields.Add((pp, (Tiles)td, _game.OldPos(p))); + diffFields.Add((pp, (Tiles)td, _viewModel.OldPos(p))); #pragma warning restore CS8604 // Mgliches Nullverweisargument. if (!e) - _buffer[p.X + p.Y * _game.size.Width] = (Tiles)td; + _buffer[p.X + p.Y * _viewModel.size.Width] = (Tiles)td; } } if (e) @@ -132,9 +134,9 @@ private void G_visUpdate(object? sender, bool e) if (f.Item1.X != f.Item3.X && f.Item1.Y != f.Item3.Y) { var p1 = new Point(f.Item1.X, f.Item3.Y); - WriteTile(p1, (Tiles)_game.Tiles[p1]); + WriteTile(p1, (Tiles)_viewModel.Tiles[p1]); var p2 = new Point(f.Item3.X, f.Item1.Y); - WriteTile(p2, (Tiles)_game.Tiles[p2]); + WriteTile(p2, (Tiles)_viewModel.Tiles[p2]); } WriteTile(f.Item1, f.Item2); } @@ -150,13 +152,13 @@ private void G_visUpdate(object? sender, bool e) public void FullRedraw(object? sender=null,EventArgs? e=null) { // basic Checks - if (_game == null) return; + if (_viewModel == null) return; // Draw playfield Point p = new Point(); - for (p.Y = 0; p.Y < _game.size.Height; p.Y++) - for (p.X = 0; p.X < _game.size.Width; p.X++) - WriteTile(p, _buffer[p.X + p.Y * _game.size.Width] = (Tiles)_game.Tiles[p]); + for (p.Y = 0; p.Y < _viewModel.size.Height; p.Y++) + for (p.X = 0; p.X < _viewModel.size.Width; p.X++) + WriteTile(p, _buffer[p.X + p.Y * _viewModel.size.Width] = (Tiles)_viewModel.Tiles[p]); // Draw statistics ShowStatistics(); @@ -167,11 +169,11 @@ public void FullRedraw(object? sender=null,EventArgs? e=null) /// private void ShowStatistics() { - if (_game == null) return; + if (_viewModel == null) return; _console.SetCursorPosition(0, 24); _console.BackgroundColor = ConsoleColor.Black; _console.ForegroundColor = ConsoleColor.Yellow; - _console.Write($"\t{_game.Level + 1}\t\t{_game.Score}\t\t{_game.Lives}/{_game.MaxLives} \t\t{Math.Floor(_game.TimeLeft)}\t\x08"); + _console.Write($"\t{_viewModel.Level + 1}\t\t{_viewModel.Score}\t\t{_viewModel.Lives}/{_viewModel.MaxLives} \t\t{Math.Floor(_viewModel.TimeLeft)}\t\x08"); } /// @@ -182,15 +184,14 @@ private void ShowStatistics() public void WriteTile(PointF p, Tiles tile) { Size s = new Size(4, 2); - var colors = VTileDef.GetTileColors(tile); - var sTileStr = VTileDef.GetTileStr(tile); - for (int i = 0; i < sTileStr.Length; i++) - for (int x = 0; x < sTileStr[i].Length; x++) + var tDef = _tileDef.GetTileDef(tile); + for (int i = 0; i < tDef.lines.Length; i++) + for (int x = 0; x < tDef.lines[i].Length; x++) { - _console.ForegroundColor = colors[x + i * s.Width].foreGround; - _console.BackgroundColor = colors[x + i * s.Width].backGround; + _console.ForegroundColor = tDef.colors[x + i * s.Width].fgr; + _console.BackgroundColor = tDef.colors[x + i * s.Width].bgr; _console.SetCursorPosition((int)(p.X * s.Width) + x, (int)(p.Y * s.Height) + i); - _console.Write(sTileStr[i][x]); + _console.Write(tDef.lines[i][x]); } } @@ -235,7 +236,7 @@ public bool CheckUserAction() result = true; } } - _game?.HandleUserAction(action); + _viewModel?.HandleUserAction(action); return result; } diff --git a/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs b/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs new file mode 100644 index 000000000..b6ae1f93b --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; +using System.Drawing; + +namespace Werner_Flaschbier_Base.ViewModels; + +public interface IWernerViewModel : INotifyPropertyChanged, INotifyPropertyChanging +{ + public interface ITileProxy + { + System.Enum this[Point p] { get; } + } + ITileProxy Tiles { get; } + Size size { get; } + int Level { get; } + int Score { get; } + int Lives { get; } + int MaxLives { get; } + float TimeLeft { get; } + bool HalfStep { get; } + + void HandleUserAction(UserAction action); + Point OldPos(Point p); +} \ No newline at end of file diff --git a/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs b/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs new file mode 100644 index 000000000..3ef28bd40 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs @@ -0,0 +1,94 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Werner_Flaschbier_Base.Model; + +namespace Werner_Flaschbier_Base.ViewModels; + +public partial class WernerViewModel : ObservableObject, IWernerViewModel +{ + public class _TileProxy(IWernerGame game) : IWernerViewModel.ITileProxy + { + IWernerGame _game = game; + public Enum this[Point p] + { get => _game[p]; } + } + #region + private IWernerGame _game; + private bool _halfStep; + + public IWernerViewModel.ITileProxy Tiles { get; } + + public Size size => _game.size; + + public int Level => _game.Level; + + public int Score => _game.Score; + + public int Lives => _game.Lives; + + public int MaxLives => _game.MaxLives; + + public float TimeLeft => _game.TimeLeft; + + public bool HalfStep => _halfStep; + #endregion + + #region Methods + public WernerViewModel(IWernerGame game) { + _game = game; + Tiles = new _TileProxy(game); + _game.visUpdate += (s, e) => + { + _halfStep = e; + OnPropertyChanged(nameof(Tiles)); + }; + _game.visFullRedraw += (s, e) => OnPropertyChanged(nameof(Level)); + } + + /// + /// Handles the user action. + /// + /// The action. + public void HandleUserAction(UserAction action) + { + switch (action) + { + case UserAction.Quit: + _game.ReqQuit(); + break; + case UserAction.Help: + _game.ReqHelp(); + break; + case UserAction.Restart: + _game.ReqRestart(); + break; + case UserAction.Nop: + break; + case UserAction.NextLvl: + _game.NextLvl(); + break; + case UserAction.PrevLvl: + _game.PrevLvl(); + break; + default: + if ((int)action < typeof(Direction).GetEnumValues().Length) + { + _game.MovePlayer((Direction)action); + } + break; + } + _game.HandleGameLogic(); + } + + public Point OldPos(Point p) + { + return _game.OldPos(p); + } + + #endregion +} diff --git a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj index 2ffe1b7dd..517785552 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj +++ b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj @@ -18,6 +18,9 @@ + + + diff --git a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj index 0bfb35753..ae96d7f86 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj +++ b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj @@ -18,6 +18,9 @@ + + + diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs b/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs index 73d17a654..3b850b536 100644 --- a/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs +++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs @@ -76,8 +76,11 @@ public class VisualTests \c0E\t2\t\t0\t\t10/10\t\t99\t\c00"; TstConsole? _testConsole; +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. private IWernerViewModel _model; + private VTileDef _tileDef; private Visual testClass; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. /// /// Initializes this instance. @@ -87,7 +90,8 @@ public void Init() { _testConsole ??= new TstConsole(); _model = Substitute.For(); - testClass = new Visual(_model,_testConsole); + _tileDef = new VTileDef(); + testClass = new Visual(_model,_testConsole,_tileDef); } /// diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj new file mode 100644 index 000000000..8082484f4 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj @@ -0,0 +1,31 @@ + + + + net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows + false + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj new file mode 100644 index 000000000..35751d907 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj @@ -0,0 +1,26 @@ + + + + net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows + false + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + diff --git a/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj b/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj index cffdfcc5c..94a815635 100644 --- a/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj +++ b/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj @@ -2,7 +2,7 @@ Library - net6.0;net7.0;net8.0;net481-windows;net48-windows;net472-windows;net462-windows + net6.0;net7.0;net8.0;net9.0;net481-windows;net48-windows;net472-windows;net462-windows True @@ -13,7 +13,6 @@ - @@ -21,5 +20,6 @@ - - + + + \ No newline at end of file diff --git a/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs b/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs new file mode 100644 index 000000000..b52be079c --- /dev/null +++ b/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs @@ -0,0 +1,22 @@ +using BaseLib.Interfaces; +using System; + +namespace BaseLib.Helper; + +public class CRandom : IRandom +{ + private Random _random; + + public CRandom() + { + _random = new Random(); + } + + public int Next(int v1, int v2) => v2 != -1 || v1 < v2 ? _random.Next(v1, v2) : _random.Next(v1); + + public double NextDouble() => _random.NextDouble(); + + public int NextInt() => _random.Next(); + + public void Seed(int value) => _random = new Random(value); +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln new file mode 100644 index 000000000..0dd5f5ee8 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln @@ -0,0 +1,67 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projektmappenelemente", "Projektmappenelemente", "{658BD492-33FF-4995-AAE7-4F6894E92F0C}" + ProjectSection(SolutionItems) = preProject + MVVM_Tutorial.props = MVVM_Tutorial.props + MVVM_Tutorial_net.props = MVVM_Tutorial_net.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_BaseLib", "..\Libraries\MVVM_BaseLib\MVVM_BaseLib.csproj", "{890CF504-3814-443B-9EE6-E8BCACF68203}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{AF041458-CF94-4D6D-BB0F-8BC50F4F099C}" + ProjectSection(SolutionItems) = preProject + ..\Libraries\Libraries_net.props = ..\Libraries\Libraries_net.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_BaseLibTests", "..\Libraries\MVVM_BaseLibTests\MVVM_BaseLibTests.csproj", "{66EB60F2-523D-47C8-95EA-C7E10759E239}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue", "MVVM_99_SomeIssue\MVVM_99_SomeIssue.csproj", "{16A3E367-674C-4959-8B31-7681B0E8258C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue_net", "MVVM_99_SomeIssue\MVVM_99_SomeIssue_net.csproj", "{D6BFC652-822A-4E7D-9846-7F529C584BAC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue_netTests", "MVVM_99_SomeIssueTests\MVVM_99_SomeIssue_netTests.csproj", "{A7844F45-74D9-4A81-9C27-D0E17ED0F851}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssueTests", "MVVM_99_SomeIssueTests\MVVM_99_SomeIssueTests.csproj", "{7FF12BBB-AA2E-48C1-B283-0665570902F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {890CF504-3814-443B-9EE6-E8BCACF68203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {890CF504-3814-443B-9EE6-E8BCACF68203}.Debug|Any CPU.Build.0 = Debug|Any CPU + {890CF504-3814-443B-9EE6-E8BCACF68203}.Release|Any CPU.ActiveCfg = Release|Any CPU + {890CF504-3814-443B-9EE6-E8BCACF68203}.Release|Any CPU.Build.0 = Release|Any CPU + {66EB60F2-523D-47C8-95EA-C7E10759E239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66EB60F2-523D-47C8-95EA-C7E10759E239}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66EB60F2-523D-47C8-95EA-C7E10759E239}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66EB60F2-523D-47C8-95EA-C7E10759E239}.Release|Any CPU.Build.0 = Release|Any CPU + {16A3E367-674C-4959-8B31-7681B0E8258C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16A3E367-674C-4959-8B31-7681B0E8258C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16A3E367-674C-4959-8B31-7681B0E8258C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16A3E367-674C-4959-8B31-7681B0E8258C}.Release|Any CPU.Build.0 = Release|Any CPU + {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Release|Any CPU.Build.0 = Release|Any CPU + {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Release|Any CPU.Build.0 = Release|Any CPU + {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {890CF504-3814-443B-9EE6-E8BCACF68203} = {AF041458-CF94-4D6D-BB0F-8BC50F4F099C} + {66EB60F2-523D-47C8-95EA-C7E10759E239} = {AF041458-CF94-4D6D-BB0F-8BC50F4F099C} + EndGlobalSection +EndGlobal diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml new file mode 100644 index 000000000..de9b986e0 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs new file mode 100644 index 000000000..5c01749b0 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs @@ -0,0 +1,43 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 08-11-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-24-2022 +// *********************************************************************** +// +// Copyright © JC-Soft 2022 +// +// +// *********************************************************************** +using BaseLib.Helper; +using BaseLib.Interfaces; +using Microsoft.Extensions.DependencyInjection; +using MVVM.View.Extension; +using MVVM_99_SomeIssue.Models; +using System.Windows; + +namespace MVVM_99_SomeIssue +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + protected override void OnStartup(StartupEventArgs e) + { + var sc = new ServiceCollection() + .AddTransient() + .AddTransient() + .AddSingleton(); + + var bc = sc.BuildServiceProvider(); + + IoC.Configure(bc); + } + } +} +namespace MVVM_99_SomeIssue.Models { } +namespace MVVM_99_SomeIssue.ValueConverter { } +namespace MVVM_99_SomeIssue.Services { } diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs new file mode 100644 index 000000000..f60efc019 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj new file mode 100644 index 000000000..5d87bdcae --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj @@ -0,0 +1,40 @@ + + + + WinExe + net462-windows;net472-windows;net48-windows;net481-windows + true + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + PublicSettingsSingleFileGenerator + Settings.Designer.cs + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj new file mode 100644 index 000000000..977e7a83b --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj @@ -0,0 +1,40 @@ + + + + WinExe + net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows + true + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + PublicSettingsSingleFileGenerator + Settings.Designer.cs + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml new file mode 100644 index 000000000..1a157ed14 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs new file mode 100644 index 000000000..6438f00f9 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs @@ -0,0 +1,31 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 08-11-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-24-2022 +// *********************************************************************** +// +// Copyright © JC-Soft 2022 +// +// +// *********************************************************************** +using System.Windows; + +namespace MVVM_99_SomeIssue +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + /// + /// Initializes a new instance of the class. + /// + public MainWindow() + { + InitializeComponent(); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info new file mode 100644 index 000000000..62f215ed0 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info @@ -0,0 +1 @@ +Folder for Models diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs new file mode 100644 index 000000000..ecc73970d --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs @@ -0,0 +1,41 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 05-19-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using System; +using System.ComponentModel; + +/// +/// The Models namespace. +/// +/// +namespace MVVM_99_SomeIssue.Models +{ + /// + /// Interface ISomeIssueModel + /// + /// + public interface ISomeIssueModel + { + /// + /// Gets the now. + /// + /// The now. + /// + DateTime Now { get; } + /// + /// Occurs when [property changed]. + /// + /// + event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs new file mode 100644 index 000000000..a227287ac --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs @@ -0,0 +1,30 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 08-11-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-24-2022 +// *********************************************************************** +// +// Copyright © JC-Soft 2022 +// +// +// *********************************************************************** +using BaseLib.Interfaces; +using System; +using System.Diagnostics; +using System.Globalization; + +namespace MVVM_99_SomeIssue; + +public class SimpleLog(ISysTime sysTime):ILog +{ + public static Action LogAction { get; set; } = (message) => Debug.WriteLine(message); + ISysTime _sysTime { get; } = sysTime; + + public void Log(string message) + => LogAction($"{_sysTime.Now.ToString(CultureInfo.InvariantCulture)}: Msg: {message}"); + public void Log(string message, Exception exception) + => LogAction($"{_sysTime.Now.ToString(CultureInfo.InvariantCulture)}: Err: {message}, {exception}"); +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs new file mode 100644 index 000000000..95f458e31 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs @@ -0,0 +1,84 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 05-19-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using BaseLib.Interfaces; +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Timers; + +/// +/// The Models namespace. +/// +/// +namespace MVVM_99_SomeIssue.Models +{ + /// + /// Class SomeIssueModel. + /// Implements the + /// Implements the + /// + /// + /// + /// + public partial class SomeIssueModel :ObservableObject, ISomeIssueModel + { + private const string csApplStart = "Application startet"; +#if !NET5_0_OR_GREATER + private const string csApplEnded = "Application ended"; +#endif + #region Properties + /// + /// The timer + /// + /// + private readonly Timer _timer; + private readonly ISysTime _systime; + private readonly ILog _log; + + /// + /// Gets the now. + /// + /// The now. + /// + public DateTime Now { get => _systime.Now; } + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + /// + public SomeIssueModel(ISysTime sysTime,ILog log) + { + _systime = sysTime; + _log = log; + _log.Log(csApplStart); + _timer = new(250d); + _timer.Elapsed += (s, e) => OnPropertyChanged(nameof(Now)); + _timer.Start(); + } + +#if !NET5_0_OR_GREATER + /// + /// Finalizes an instance of the class. + /// + ~SomeIssueModel() + { + _timer.Stop(); + _log.Log(csApplEnded); + return; + } +#endif + #endregion + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs new file mode 100644 index 000000000..dedf68853 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace MVVM_99_SomeIssue.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MVVM_99_SomeIssue.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die MVVM-SomeIssue using Community-Toolkit ähnelt. + /// + public static string Description { + get { + return ResourceManager.GetString("Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die <Page + /// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + /// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + /// xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + /// xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + /// xmlns:local="clr-namespace:MVVM_99_SomeIssue.Views" + /// xmlns:p="clr-namespace:MVVM_99_SomeIssue.Properties" + /// xmlns:vc="clr-namespace:MVVM_99_SomeIssue.ValueConverter" + /// xmlns:mvvm="clr-namespace: [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. + /// + public static string SomeIssueView { + get { + return ResourceManager.GetString("SomeIssueView", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die // *********************************************************************** + ///// Assembly : MVVM_99_SomeIssue + ///// Author : Mir + ///// Created : 08-11-2022 + ///// + ///// Last Modified By : Mir + ///// Last Modified On : 08-24-2022 + ///// *********************************************************************** + ///// <copyright file="MainWindowViewModel.cs" company="JC-Soft"> + ///// Copyright © JC-Soft 2022 + ///// </copyright> + ///// <summary></summary> + ///// ************************************************** [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. + /// + public static string SomeIssueViewModel { + get { + return ResourceManager.GetString("SomeIssueViewModel", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die CT-SomeIssue-View ähnelt. + /// + public static string Title { + get { + return ResourceManager.GetString("Title", resourceCulture); + } + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx new file mode 100644 index 000000000..17780c00a --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + MVVM-SomeIssue using Community-Toolkit + + + + ..\Views\SomeIssueView.xaml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + ..\ViewModels\SomeIssueViewModel.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + CT-SomeIssue-View + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs new file mode 100644 index 000000000..b9e5e754f --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace MVVM_99_SomeIssue.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")] + public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings new file mode 100644 index 000000000..049245f40 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info new file mode 100644 index 000000000..b4bc464df --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info @@ -0,0 +1 @@ +Folder for ValueConverters diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs new file mode 100644 index 000000000..7fd3bcbee --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs @@ -0,0 +1,63 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 07-03-2022 +// +// Last Modified By : Mir +// Last Modified On : 07-04-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Globalization; +using System.Windows.Data; + +namespace MVVM_99_SomeIssue.ValueConverter +{ + /// + /// Class CurrencyValueConverter. + /// Implements the + /// + /// + public class DateTimeValueConverter : IValueConverter + { + /// + /// Converts a value. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns , the valid null value is used. + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is DateTime dt) + if (parameter is string spar) + return dt.ToString(spar); + else + return dt.ToString(culture); + else + return value?.ToString() ?? ""; + + } + + /// + /// Converts a value. + /// + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns , the valid null value is used. + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is string sval && DateTime.TryParse(sval.Trim(),culture, DateTimeStyles.AssumeLocal, out var dt)) + return dt; + else + return DateTime.MinValue; + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info new file mode 100644 index 000000000..a3ed848fb --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info @@ -0,0 +1 @@ +Folder for ViewModels diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs new file mode 100644 index 000000000..e874122f4 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,47 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 08-11-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-24-2022 +// *********************************************************************** +// +// Copyright © JC-Soft 2022 +// +// +// *********************************************************************** +using MVVM.ViewModel; + +namespace MVVM_99_SomeIssue.ViewModels +{ + /// + /// Class MainWindowViewModel. + /// Implements the + /// + /// + public class MainWindowViewModel : BaseViewModelCT + { + #region Properties + #endregion + #region Methods + /// + /// Initializes a new instance of the class. + /// + public MainWindowViewModel() + { + + } + +#if !NET5_0_OR_GREATER + /// + /// Finalizes an instance of the class. + /// + ~MainWindowViewModel() + { + return; + } +#endif + #endregion + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs new file mode 100644 index 000000000..24f83d50a --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue +// Author : Mir +// Created : 08-11-2022 +// +// Last Modified By : Mir +// Last Modified On : 08-24-2022 +// *********************************************************************** +// +// Copyright © JC-Soft 2022 +// +// +// *********************************************************************** +using MVVM.View.Extension; +using MVVM.ViewModel; +using MVVM_99_SomeIssue.Models; +using System; +using System.ComponentModel; + +namespace MVVM_99_SomeIssue.ViewModels; + +/// +/// Class MainWindowViewModel. +/// Implements the +/// +/// +public partial class SomeIssueViewModel : BaseViewModelCT +{ + #region Properties + private readonly ISomeIssueModel _model; + + public DateTime Now => _model.Now; + #endregion + + #region Methods + /// + /// Initializes a new instance of the class. + /// + public SomeIssueViewModel():this(IoC.GetRequiredService()) + { + } + + public SomeIssueViewModel(ISomeIssueModel model) + { + _model = model; + _model.PropertyChanged += OnMPropertyChanged; + } + + private void OnMPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + OnPropertyChanged(e.PropertyName); + } + + #endregion +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info new file mode 100644 index 000000000..65a00d680 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info @@ -0,0 +1 @@ +Folder for Views diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml new file mode 100644 index 000000000..8d86d8941 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs new file mode 100644 index 000000000..25b9c440b --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows.Controls; + +namespace MVVM_99_SomeIssue.Views +{ + /// + /// Interaktionslogik für SomeIssueView.xaml + /// + public partial class SomeIssueView : Page + { + public SomeIssueView() + { + InitializeComponent(); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs new file mode 100644 index 000000000..695996c10 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs @@ -0,0 +1,65 @@ +using BaseLib.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using MVVM.View.Extension; +using MVVM_99_SomeIssue.Models; +using NSubstitute; +using System; + +namespace MVVM_99_SomeIssue.Tests +{ + internal class TestApp : App + { + public void DoStartUp() + { + OnStartup(null); + } + } + [TestClass()] + public class AppTests + { + static TestApp app = new(); +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + private Func _gsold; + private Func _grsold; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + private ISysTime? _sysTime; + private ILog? _log; + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + _gsold = IoC.GetSrv; + _grsold = IoC.GetReqSrv; + IoC.GetReqSrv = (t) =>t switch { + _ when t == typeof(ILog) => _log ??= Substitute.For(), + _ when t == typeof(ISysTime) => _sysTime ??= Substitute.For(), + _ when t == typeof(ISomeIssueModel) => new SomeIssueModel(IoC.GetRequiredService(),IoC.GetRequiredService()), + _ => throw new ArgumentException() }; + } + + [TestCleanup] + public void CleanUp() + { + IoC.GetSrv = _gsold; + IoC.GetReqSrv = _grsold; + } + + [TestMethod] + public void AppTest() + { + Assert.IsNotNull(app); + } + + [TestMethod] + public void AppTest2() + { + app.DoStartUp(); + Assert.IsNotNull(IoC.GetReqSrv(typeof(ISomeIssueModel))); + Assert.IsNull(IoC.GetSrv(typeof(App))); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj new file mode 100644 index 000000000..a1e06aeb1 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj @@ -0,0 +1,27 @@ + + + + net462-windows;net472-windows;net48-windows;net481-windows + true + false + true + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj new file mode 100644 index 000000000..776439cce --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj @@ -0,0 +1,24 @@ + + + + net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows + true + false + true + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs new file mode 100644 index 000000000..7e7393948 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs @@ -0,0 +1,71 @@ +using BaseLib.Interfaces; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using MVVM.ViewModel; +using MVVM.ViewModel.Tests; +using NSubstitute; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVVM_99_SomeIssue.Models.Tests; + +[TestClass] +public class SimpleLogTests:BaseTestViewModel +{ +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. + private Action _gsOld; + private SimpleLog simpleLog; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend. + private ISysTime? _sysTime; + + + [TestInitialize] + public void TestInitialize() + { + _gsOld= SimpleLog.LogAction; + _gsOld("Test message"); + SimpleLog.LogAction = DoLog; + _sysTime = Substitute.For(); + _sysTime.Now.Returns(new DateTime(2022, 08, 24, 12, 0, 0)); + simpleLog = new SimpleLog(_sysTime); + } + + [TestCleanup] + public void TestCleanup() + { + SimpleLog.LogAction = _gsOld; + } + + [DataTestMethod] + [DataRow("Test message",new[] { "08/24/2022 12:00:00: Msg: Test message\r\n" })] + [DataRow(null, new[] { "08/24/2022 12:00:00: Msg: \r\n" })] + [DataRow("Some other test", new[] { "08/24/2022 12:00:00: Msg: Some other test\r\n" })] + + public void LogTest(string message, string[] asExp) + { + + // Act + simpleLog.Log(message); + + // Assert + Assert.AreEqual(1, _sysTime.ReceivedCalls().Count()); + Assert.AreEqual(asExp[0],DebugLog); + } + + [TestMethod] + public void LogTest1() + { + // Arrange + var message = "Test message"; + var exception = new Exception("Test exception"); + + // Act + simpleLog.Log(message, exception); + + // Assert + Assert.AreEqual(1, _sysTime.ReceivedCalls().Count()); + Assert.AreEqual("08/24/2022 12:00:00: Err: Test message, System.Exception: Test exception\r\n", DebugLog); + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs new file mode 100644 index 000000000..d28ef186d --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssueTests +// Author : Mir +// Created : 05-19-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using CommunityToolkit.Mvvm.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using BaseLib.Interfaces; +using MVVM.ViewModel; +using NSubstitute; +using System.ComponentModel; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.Models.Tests +{ + /// + /// Defines test class SomeIssueModelTests. + /// Implements the + /// + /// + /// + [TestClass()] + public class SomeIssueModelTests : BaseTestViewModel + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test model + /// + /// + SomeIssueModel testModel; + ISysTime _sysTime; + ILog _log; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + [TestInitialize] + public void Init() + { + _sysTime = Substitute.For(); + _log = Substitute.For(); + testModel = new(_sysTime,_log); + testModel.PropertyChanged += OnVMPropertyChanged; + if (testModel is INotifyPropertyChanging npchgn) + npchgn.PropertyChanging += OnVMPropertyChanging; + ClearLog(); + } + + /// + /// Defines the test method SetupTest. + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testModel); + Assert.IsInstanceOfType(testModel, typeof(SomeIssueModel)); + Assert.IsInstanceOfType(testModel, typeof(ObservableObject)); + Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs new file mode 100644 index 000000000..ff7cd0142 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Configuration; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.Properties.Tests +{ + /// + /// Defines test class SettingsTests. + /// + /// + [TestClass()] + public class SettingsTests + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test item + /// + /// + Settings testItem; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + testItem = new(); + } + + /// + /// Defines the test method SetupTest. + /// + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testItem); + Assert.IsInstanceOfType(testItem, typeof(Settings)); + Assert.IsInstanceOfType(testItem, typeof(ApplicationSettingsBase)); + } + /// + /// Defines the test method DefaultInstanceTest. + /// + /// + [TestMethod()] + public void DefaultInstanceTest() + { + Assert.IsNotNull(Settings.Default); + Assert.IsInstanceOfType(Settings.Default, typeof(Settings)); + Assert.IsInstanceOfType(Settings.Default, typeof(ApplicationSettingsBase)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs new file mode 100644 index 000000000..0e9b16ad4 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssueTests +// Author : Mir +// Created : 05-11-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-11-2023 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Globalization; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.ValueConverter.Tests +{ + + /// + /// Defines test class CurrencyValueConverterTests. + /// + /// + [TestClass()] + public class DateTimeValueConverterTests + { + /// + /// The converter + /// + /// + readonly DateTimeValueConverter testConv = new(); + + /// + /// Converts the correctly formats value. + /// + /// The value. + /// The expected. + /// + [DataTestMethod] + [DataRow("2023-01-01 22:00",null, "01/01/2023 23:00:00")] + [DataRow("2023-05-02 12:30","MM/dd/yyyy", "05.02.2023")] + [DataRow("Hallo",null, "Hallo")] + [DataRow(null,null, "")] + public void ConvertTest(object? value, string? param, string expected) + { + if (value is string s && DateTime.TryParse(s, CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal,out var dt)) value = dt; + var result = testConv.Convert(value, typeof(string), param, CultureInfo.InvariantCulture); + Assert.AreEqual(expected, result); + } + + /// + /// Defines the test method ConvertBackTest. + /// + /// + [DataTestMethod] + [DataRow("2023-01-01 22:30", null, "01/01/2023 22:30:00")] + [DataRow("2023-05-02", "MM/dd/yyyy", "05.02.2023")] + [DataRow("01.01.0001 00:00:00", null, "Hallo")] + [DataRow("01.01.0001 00:00:00", "", 100)] + [DataRow("01.01.0001 00:00:00", "", null)] + public void ConvertBackTest(object? value, string? param, object? expected) + { + if (value is string s && DateTime.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var dt)) value = dt; + var result = testConv.ConvertBack(expected, typeof(DateTime), param, CultureInfo.InvariantCulture); + Assert.AreEqual(value, result); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs new file mode 100644 index 000000000..5e90b2bc0 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs @@ -0,0 +1,58 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.ComponentModel; +using MVVM.ViewModel; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.ViewModels.Tests +{ + /// + /// Defines test class MainWindowViewModelTests. + /// + /// + [TestClass()] + public class MainWindowViewModelTests : BaseTestViewModel + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public override void Init() + { + base.Init(); + } + + /// + /// Defines the test method SetupTest. + /// + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testModel); + Assert.IsInstanceOfType(testModel, typeof(MainWindowViewModel)); + Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT)); + Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs new file mode 100644 index 000000000..50a049cd4 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs @@ -0,0 +1,80 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using System; +using System.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; +using MVVM.ViewModel; +using MVVM.View.Extension; +using MVVM_99_SomeIssue.Models; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.ViewModels.Tests +{ + /// + /// Defines test class SomeIssueViewModelTests. + /// + /// + [TestClass()] + public class SomeIssueViewModelTests : BaseTestViewModel + { + /// The model + private ISomeIssueModel? _model; + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public override void Init() + { + IoC.GetReqSrv = (t) => t switch + { + Type _t when _t == typeof(ISomeIssueModel) => _model ??= Substitute.For(), + _ => throw new System.NotImplementedException($"No code for {t}") + }; + base.Init(); + _model.Now.Returns(new DateTime(2022, 08, 24, 12, 0, 0)); + } + + /// + /// Defines the test method SetupTest. + /// + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testModel); + Assert.IsInstanceOfType(testModel, typeof(SomeIssueViewModel)); + Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT)); + Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged)); + Assert.IsNotNull(_model); + } + + [DataTestMethod()] + [DataRow(nameof(ISomeIssueModel.Now), new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,Now)=24.08.2022 12:00:00\r\n" })] + [DataRow("HasErrors", new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,HasErrors)=False\r\n" })] + [DataRow("Dummy", new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,Dummy)=\r\n" })] + public void PropertyChangedTest(string prop, string[] asExp) + { + _model.PropertyChanged += Raise.Event(_model, new PropertyChangedEventArgs(prop)); + if (prop == nameof(ISomeIssueModel.Now)) + _ = _model.Received(2).Now; + Assert.AreEqual(asExp[0], DebugLog); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs new file mode 100644 index 000000000..1ae34a0d6 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Threading; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.Views.Tests +{ + /// + /// Defines test class MainWindowTests. + /// + /// + [TestClass()] + public class MainWindowTests + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test view + /// + /// + MainWindow testView; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + var t = new Thread(() => testView = new()); + t.SetApartmentState(ApartmentState.STA); //Set the thread to STA + t.Start(); + t.Join(); //Wait for the thread to end + } + + /// + /// Defines the test method MainWindowTest. + /// + /// + [TestMethod()] + public void MainWindowTest() + { + Assert.IsNotNull(testView); + Assert.IsInstanceOfType(testView, typeof(MainWindow)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs new file mode 100644 index 000000000..7b6c3f602 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Assembly : MVVM_99_SomeIssue_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Threading; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_99_SomeIssue.Views.Tests +{ + /// + /// Defines test class SomeIssueViewTests. + /// + /// + [TestClass()] + public class SomeIssueViewTests + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test view + /// + /// + SomeIssueView testView; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + var t = new Thread(() => testView = new()); + t.SetApartmentState(ApartmentState.STA); //Set the thread to STA + t.Start(); + t.Join(); //Wait for the thread to end + } + + /// + /// Defines the test method MainWindowTest. + /// + /// + [TestMethod()] + public void MainWindowTest() + { + Assert.IsNotNull(testView); + Assert.IsInstanceOfType(testView, typeof(SomeIssueView)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs new file mode 100644 index 000000000..58cb6debb --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs @@ -0,0 +1,44 @@ +// *********************************************************************** +// Assembly : MVVM_AllExamples +// Author : Mir +// Created : 05-19-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using System; +using System.Collections.Generic; +using System.ComponentModel; + +/// +/// The Models namespace. +/// +/// +namespace MVVM_AllExamples.Models +{ + /// + /// Interface ITemplateModel + /// + /// + public interface IAllExampleModel + { + /// + /// Gets the now. + /// + /// The now. + /// + DateTime Now { get; } + List Examples { get; } + + /// + /// Occurs when [property changed]. + /// + /// + event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs new file mode 100644 index 000000000..c081284c9 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs @@ -0,0 +1,67 @@ +// *********************************************************************** +// Assembly : MVVM_AllExamplesTests +// Author : Mir +// Created : 05-19-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-19-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using CommunityToolkit.Mvvm.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using MVVM.ViewModel; +using System.ComponentModel; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_AllExamples.Models.Tests +{ + /// + /// Defines test class AllExampleModelTests. + /// Implements the + /// + /// + /// + [TestClass()] + public class AllExampleModelTests : BaseTestViewModel + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test model + /// + /// + AllExampleModel testModel; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + [TestInitialize] + public void Init() + { + testModel = new(); + testModel.PropertyChanged += OnVMPropertyChanged; + if (testModel is INotifyPropertyChanging npchgn) + npchgn.PropertyChanging += OnVMPropertyChanging; + ClearLog(); + } + + /// + /// Defines the test method SetupTest. + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testModel); + Assert.IsInstanceOfType(testModel, typeof(AllExampleModel)); + Assert.IsInstanceOfType(testModel, typeof(ObservableObject)); + Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs new file mode 100644 index 000000000..2f761f0d5 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs @@ -0,0 +1,66 @@ +// *********************************************************************** +// Assembly : MVVM_AllExamples_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.ComponentModel; +using MVVM.ViewModel; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_AllExamples.ViewModels.Tests +{ + /// + /// Defines test class AllExampleViewModelTests. + /// + /// + [TestClass()] + public class AllExamplesViewModelTests:BaseTestViewModel + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test model + /// + /// + AllExamplesViewModel testModel; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + testModel = new(); + testModel.PropertyChanged += OnVMPropertyChanged; + if (testModel is INotifyPropertyChanging npchgn) + npchgn.PropertyChanging += OnVMPropertyChanging; + ClearLog(); + } + + /// + /// Defines the test method SetupTest. + /// + /// + [TestMethod()] + public void SetupTest() + { + Assert.IsNotNull(testModel); + Assert.IsInstanceOfType(testModel, typeof(AllExamplesViewModel)); + Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT)); + Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged)); + } + } +} diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs new file mode 100644 index 000000000..abfa25636 --- /dev/null +++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Assembly : MVVM_AllExamples_netTests +// Author : Mir +// Created : 05-14-2023 +// +// Last Modified By : Mir +// Last Modified On : 05-14-2023 +// *********************************************************************** +// +// Copyright © JC-Soft 2023 +// +// +// *********************************************************************** +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Threading; + +/// +/// The Tests namespace. +/// +/// +namespace MVVM_AllExamples.Views.Tests +{ + /// + /// Defines test class AllExampleViewTests. + /// + /// + [TestClass()] + public class AllExampleViewTests + { +#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + /// + /// The test view + /// + /// + AllExamplesView testView; +#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable. + + /// + /// Initializes this instance. + /// + /// + [TestInitialize] + public void Init() + { + var t = new Thread(() => testView = new()); + t.SetApartmentState(ApartmentState.STA); //Set the thread to STA + t.Start(); + t.Join(); //Wait for the thread to end + } + + /// + /// Defines the test method MainWindowTest. + /// + /// + [TestMethod()] + public void MainWindowTest() + { + Assert.IsNotNull(testView); + Assert.IsInstanceOfType(testView, typeof(AllExamplesView)); + } + } +} diff --git a/CSharpBible/TestConsole/View/TestConsoleForm.cs b/CSharpBible/TestConsole/View/TestConsoleForm.cs index c78ef30d6..379cab730 100644 --- a/CSharpBible/TestConsole/View/TestConsoleForm.cs +++ b/CSharpBible/TestConsole/View/TestConsoleForm.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Threading; using System.Windows.Forms; @@ -143,16 +144,20 @@ public void Write(string? st) /// The foreground color /// private ConsoleColor foregroundColor = ConsoleColor.Gray; + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] + public ConsoleColor ForegroundColor { get => foregroundColor; set => foregroundColor = value; } /// /// The background color /// private ConsoleColor backgroundColor = ConsoleColor.Black; + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public ConsoleColor BackgroundColor { get => backgroundColor; set => backgroundColor = value; } /// /// Gets or sets the width of the window. /// /// The width of the window. + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public int WindowWidth { get => ConsoleSize.Width; @@ -166,6 +171,7 @@ public int WindowWidth /// Gets or sets the height of the window. /// /// The height of the window. + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public int WindowHeight { get => ConsoleSize.Height; @@ -234,8 +240,11 @@ public string Content { get } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ConsoleCharInfo[] ScreenBuffer { get => screenBuffer; set => screenBuffer = value; } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ConsoleCharInfo[] OutBuffer { get => outBuffer; set => outBuffer = value; } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public Size ConsoleSize { get => consoleSize; set => consoleSize = value; } ///