From 62186f43974e9d076b867657297eb9637a5c851d Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:04:12 +0100 Subject: [PATCH 01/12] Initial helper classes --- src/CuteUtils/BoolExtentions.cs | 53 ++++ src/CuteUtils/Class1.cs | 6 - src/CuteUtils/CollectionExtentions.cs | 129 ++++++++ src/CuteUtils/ConsoleExtentions.cs | 148 +++++++++ src/CuteUtils/FluentMath/Shapes/Rectangle.cs | 43 +++ .../TypeExtentions/DecimalFluent.cs | 161 ++++++++++ .../FluentMath/TypeExtentions/DoubleFluent.cs | 287 ++++++++++++++++++ .../FluentMath/TypeExtentions/Int16Fluent.cs | 119 ++++++++ .../FluentMath/TypeExtentions/Int32Fluent.cs | 119 ++++++++ .../FluentMath/TypeExtentions/Int64Fluent.cs | 119 ++++++++ .../FluentMath/TypeExtentions/SingleFluent.cs | 287 ++++++++++++++++++ src/CuteUtils/Logging/LogConfig.cs | 83 +++++ src/CuteUtils/Logging/LogFormatBuilder.cs | 147 +++++++++ src/CuteUtils/Logging/LogFormatType.cs | 42 +++ src/CuteUtils/Logging/LogSeverity.cs | 32 ++ src/CuteUtils/Logging/LogTarget.cs | 23 ++ src/CuteUtils/Logging/Logger.cs | 278 +++++++++++++++++ src/CuteUtils/RandomExtentions.cs | 30 ++ src/CuteUtils/Reflection.cs | 60 ++++ src/CuteUtils/StringExtentions.cs | 169 +++++++++++ src/CuteUtils/Tasks/BlockingTaskQueue.cs | 91 ++++++ src/CuteUtils/Tasks/TaskQueue.cs | 134 ++++++++ 22 files changed, 2554 insertions(+), 6 deletions(-) create mode 100644 src/CuteUtils/BoolExtentions.cs delete mode 100644 src/CuteUtils/Class1.cs create mode 100644 src/CuteUtils/CollectionExtentions.cs create mode 100644 src/CuteUtils/ConsoleExtentions.cs create mode 100644 src/CuteUtils/FluentMath/Shapes/Rectangle.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/DecimalFluent.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/DoubleFluent.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/Int16Fluent.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/Int32Fluent.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/Int64Fluent.cs create mode 100644 src/CuteUtils/FluentMath/TypeExtentions/SingleFluent.cs create mode 100644 src/CuteUtils/Logging/LogConfig.cs create mode 100644 src/CuteUtils/Logging/LogFormatBuilder.cs create mode 100644 src/CuteUtils/Logging/LogFormatType.cs create mode 100644 src/CuteUtils/Logging/LogSeverity.cs create mode 100644 src/CuteUtils/Logging/LogTarget.cs create mode 100644 src/CuteUtils/Logging/Logger.cs create mode 100644 src/CuteUtils/RandomExtentions.cs create mode 100644 src/CuteUtils/Reflection.cs create mode 100644 src/CuteUtils/StringExtentions.cs create mode 100644 src/CuteUtils/Tasks/BlockingTaskQueue.cs create mode 100644 src/CuteUtils/Tasks/TaskQueue.cs diff --git a/src/CuteUtils/BoolExtentions.cs b/src/CuteUtils/BoolExtentions.cs new file mode 100644 index 0000000..93a9d24 --- /dev/null +++ b/src/CuteUtils/BoolExtentions.cs @@ -0,0 +1,53 @@ +namespace CuteUtils; + +/// +/// Extensions +/// +public static class BoolExt +{ + /// + /// Sets value to true if input is true. If input is false the value will not change. + /// + /// + /// + public static void OneWayTrue(this ref bool bol, bool input) + { + if (!bol && input) + { + bol = true; + } + } + + /// + /// Sets value to false if input is false. If input is true the value will not change. + /// + /// + /// + public static void OneWayFalse(this ref bool bol, bool input) + { + if (bol && !input) + { + bol = false; + } + } + + /// + /// Converts bool to int. + /// + /// + /// + public static int ToInt(this bool input) + { + return input ? 1 : 0; + } + + /// + /// Converts int to bool. + /// + /// + /// + public static void FromInt(this ref bool bol, int input) + { + bol = input == 1; + } +} \ No newline at end of file diff --git a/src/CuteUtils/Class1.cs b/src/CuteUtils/Class1.cs deleted file mode 100644 index 2f8ed95..0000000 --- a/src/CuteUtils/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace CuteUtils; - -public class Class1 -{ - -} diff --git a/src/CuteUtils/CollectionExtentions.cs b/src/CuteUtils/CollectionExtentions.cs new file mode 100644 index 0000000..a9dcb84 --- /dev/null +++ b/src/CuteUtils/CollectionExtentions.cs @@ -0,0 +1,129 @@ +using System.Diagnostics; + +namespace CuteUtils; + +/// +/// Table Style +/// +public enum TableStyle +{ + /// + /// The default representation of the table + /// + Default, + + /// + /// The minimal representation of the table + /// + Minimum, + + /// + /// The alternative representation of the table + /// + Alternative, + + /// + /// The list representation of the table + /// + List +} + +/// +/// and Extensions +/// +public static class CollectionExt +{ + /// + /// Prints all items of an + /// + /// + /// + /// + public static void Print(this IEnumerable collection, char delimiter = ',', bool printToDebugConsole = false) + { + int i = 0; + int length = collection.Count() - 1; + string split = delimiter + (delimiter == '\n' ? string.Empty : " "); + foreach (T item in collection) + { + if (item is IEnumerable ie) + { + ie.Print(delimiter, printToDebugConsole); + } + else if (printToDebugConsole) + { + Debug.Write(item?.ToString() + (i < length ? split : string.Empty)); + } + else + { + Console.Write(item?.ToString() + (i < length ? split : string.Empty)); + } + i++; + } + } + + /// + /// Creates and prints table from 2D array + /// + /// + /// + /// + public static void PrintTable(this T[,] array, TableStyle tableStyle = TableStyle.Default) + { + int[] itemLength = new int[array.GetLength(1)]; + char verticalChar = tableStyle == TableStyle.Minimum ? ' ' : '|'; + + for (int i = 0; i < array.GetLength(0); i++) + { + for (int j = 0; j < array.GetLength(1); j++) + { + itemLength[j] = Math.Max(array[i, j]!.ToString()!.Length + 2, itemLength[j]); + } + } + + PrintLine(tableStyle, itemLength, array.GetLength(1), tableStyle == TableStyle.List); + + for (int i = 0; i < array.GetLength(0); i++) + { + for (int j = 0; j < array.GetLength(1); j++) + { + string item = " " + array[i, j]?.ToString() + " "; + item = verticalChar + item + new string(' ', itemLength[j] - item.Length); + Console.Write(tableStyle == TableStyle.Minimum && j == 0 ? item.TrimStart() : item); + } + + Console.Write(verticalChar); + + PrintLine(tableStyle, itemLength, array.GetLength(1), i == 0); + } + } + + private static void PrintLine(TableStyle tableStyle, int[] itemLength, int itemCount, bool forcePrint = false) + { + char intersect = tableStyle is TableStyle.Alternative or TableStyle.List ? '+' : '-'; + + Console.WriteLine(); + if (tableStyle is TableStyle.Minimum or TableStyle.List) + { + if (tableStyle == TableStyle.List && forcePrint) + { + Console.Write(intersect); + } + + if (!forcePrint) + { + return; + } + } + else + { + Console.Write(intersect); + } + + for (int k = 0; k < itemCount; k++) + { + Console.Write(new string('-', itemLength[k] - (tableStyle == TableStyle.Minimum ? 1 : 0)) + intersect); + } + Console.WriteLine(); + } +} \ No newline at end of file diff --git a/src/CuteUtils/ConsoleExtentions.cs b/src/CuteUtils/ConsoleExtentions.cs new file mode 100644 index 0000000..347a30d --- /dev/null +++ b/src/CuteUtils/ConsoleExtentions.cs @@ -0,0 +1,148 @@ +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable S3998 // Threads should not lock on objects with weak identity + +namespace CuteUtils; + +/// +/// Extensions +/// +public static class ConsoleExt +{ + /// + /// Writes the text representation of the specified object to the standard output stream. + /// + /// + /// + public static void Write(object value, ConsoleColor color) + { + lock (Console.Out) + { + ConsoleColor oldColor = Console.ForegroundColor; + Console.ForegroundColor = color; + Console.Write(value); + Console.ForegroundColor = oldColor; + } + } + + /// + /// Writes the text representation of the specified object, followed by the current line terminator, to the standard output stream. + /// + /// + /// + public static void WriteLine(object value, ConsoleColor color) + { + lock (Console.Out) + { + ConsoleColor oldColor = Console.ForegroundColor; + Console.ForegroundColor = color; + Console.WriteLine(value); + Console.ForegroundColor = oldColor; + } + } + + /// + /// Reads the next line of characters from the standard input stream and tries to convert it to the specified type. + /// + /// + /// The input string converted to the specified type. + /// + public static T ReadLine() + { + string attemptedValue = Console.ReadLine() ?? string.Empty; + Type type = typeof(T); + TypeConverter converter = TypeDescriptor.GetConverter(type); + + return (T)converter.ConvertFromString(attemptedValue)!; + } + + /// + /// Reads the next line of characters from the standard input stream and tries to convert it to the specified type. + /// + /// + /// The input string converted to the specified type. + /// if the conversion was successful. Otherwise + public static bool TryReadLine([NotNullWhen(true)] out T? input) + { + string attemptedValue = Console.ReadLine() ?? string.Empty; + Type type = typeof(T); + TypeConverter converter = TypeDescriptor.GetConverter(type); + if (converter != null && converter.IsValid(attemptedValue)) + { + input = (T)converter.ConvertFromString(attemptedValue)!; + return true; + } + else + { + input = default; + return false; + } + } + + /// + /// Obtains the next character or function key pressed by the user and converts it to the specified type. + /// The pressed key is displayed in the console window. + /// + /// The type of the + /// The input character converted to the specified type. + /// + public static T ReadKey() + { + string attemptedValue = Console.ReadKey().KeyChar.ToString(); + Type type = typeof(T); + TypeConverter converter = TypeDescriptor.GetConverter(type); + + return (T)converter.ConvertFromString(attemptedValue)!; + } + + /// + /// Obtains the next character or function key pressed by the user and tries to convert it to the specified type. + /// The pressed key is displayed in the console window. + /// + /// The input character converted to the specified type. + /// The type of the + /// if the conversion was successful. Otherwise + public static bool TryReadKey([NotNullWhen(true)] out T? input) + { + string attemptedValue = Console.ReadKey().KeyChar.ToString(); + Type type = typeof(T); + TypeConverter converter = TypeDescriptor.GetConverter(type); + if (converter != null && converter.IsValid(attemptedValue)) + + { + input = (T)converter.ConvertFromString(attemptedValue)!; + return true; + } + else + { + input = default; + return false; + } + } + + /// + /// Suspends execution of the current method until the user presses a key + /// + /// The key that has to be pressed + /// The message that will be displayed + public static void Pause(ConsoleKey key, string? message = null) + { + Console.WriteLine(message ?? $"Press {key} to continue..."); + ConsoleKey? consoleKey = null; + while (consoleKey != key) + { + consoleKey = Console.ReadKey(true).Key; + } + } + + /// + /// Suspends execution of the current method until the user presses a key + /// + /// The message that will be displayed + public static void Pause(string message = "Press any key to continue...") + { + Console.WriteLine(message); + _ = Console.ReadKey(true); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Rectangle.cs b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs new file mode 100644 index 0000000..424424b --- /dev/null +++ b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs @@ -0,0 +1,43 @@ +namespace CuteUtils.FluentMath.Shapes; + +/// +/// Represents a rectangle +/// +public class Rectangle +{ + /// + /// The length of the + /// + public double Length { get; set; } + + /// + /// The width of the + /// + public double Width { get; set; } + + /// + /// The diagonal of the + /// + public double Diagonal => Math.Sqrt(Math.Pow(Length, 2) + Math.Pow(Width, 2)); + + /// + /// The area of the + /// + public double Area => Length * Width; + + /// + /// The perimeter of the + /// + public double Perimeter => Length * 2 + Width * 2; + + /// + /// Creates a new rectangle instance + /// + /// The length of the rectangle + /// The width of the rectangle + public Rectangle(double length, double width) + { + Length = length; + Width = width; + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/DecimalFluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/DecimalFluent.cs new file mode 100644 index 0000000..0740e68 --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/DecimalFluent.cs @@ -0,0 +1,161 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// DecimalFluent class +/// +public static class DecimalFluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static double ToDouble(this decimal num) + { + return (double)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static float ToSingle(this decimal num) + { + return (float)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static short ToInt16(this decimal num) + { + return (short)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static int ToInt32(this decimal num) + { + return (int)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static long ToInt64(this decimal num) + { + return (long)num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static decimal Add(this decimal num, decimal value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static decimal Subtract(this decimal num, decimal value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static decimal Multiply(this decimal num, decimal value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static decimal Divide(this decimal num, decimal value) + { + return num / value; + } + + /// + public static decimal Abs(this decimal num) + { + return Math.Abs(num); + } + + /// + public static decimal Ceiling(this decimal num) + { + return Math.Ceiling(num); + } + + /// + public static decimal Clamp(this decimal num, decimal min, decimal max) + { + return Math.Clamp(num, min, max); + } + + /// + public static decimal Floor(this decimal num) + { + return Math.Floor(num); + } + + /// + public static decimal Round(this decimal num) + { + return Math.Round(num); + } + + /// + public static decimal Round(this decimal num, MidpointRounding mode) + { + return Math.Round(num, mode); + } + + /// + public static decimal Round(this decimal num, int digits) + { + return Math.Round(num, digits); + } + + /// + public static decimal Round(this decimal num, int digits, MidpointRounding mode) + { + return Math.Round(num, digits, mode); + } + + /// + public static int Sign(this decimal num) + { + return Math.Sign(num); + } + + /// + public static decimal Truncate(this decimal num) + { + return Math.Truncate(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/DoubleFluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/DoubleFluent.cs new file mode 100644 index 0000000..e067c93 --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/DoubleFluent.cs @@ -0,0 +1,287 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// DoubleFluent class +/// +public static class DoubleFluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static decimal ToDecimal(this double num) + { + return (decimal)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static float ToSingle(this double num) + { + return (float)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static short ToInt16(this double num) + { + return (short)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static int ToInt32(this double num) + { + return (int)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static long ToInt64(this double num) + { + return (long)num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static double Add(this double num, double value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static double Subtract(this double num, double value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static double Multiply(this double num, double value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static double Divide(this double num, double value) + { + return num / value; + } + + /// + public static double Abs(this double num) + { + return Math.Abs(num); + } + + /// + public static double Acos(this double num) + { + return Math.Acos(num); + } + + /// + public static double Acosh(this double num) + { + return Math.Acosh(num); + } + + /// + public static double Asin(this double num) + { + return Math.Asin(num); + } + + /// + public static double Asinh(this double num) + { + return Math.Asinh(num); + } + + /// + public static double Atan(this double num) + { + return Math.Atan(num); + } + + /// + public static double Atan2(this double num, double valuee) + { + return Math.Atan2(num, valuee); + } + + /// + public static double Atanh(this double num) + { + return Math.Atanh(num); + } + + /// + public static double Cbrt(this double num) + { + return Math.Cbrt(num); + } + + /// + public static double Ceiling(this double num) + { + return Math.Ceiling(num); + } + + /// + public static double Clamp(this double num, double min, double max) + { + return Math.Clamp(num, min, max); + } + + /// + public static double Cos(this double num) + { + return Math.Cos(num); + } + + /// + public static double Cosh(this double num) + { + return Math.Cosh(num); + } + + /// + public static double Exp(this double num) + { + return Math.Exp(num); + } + + /// + public static double Floor(this double num) + { + return Math.Floor(num); + } + + /// + public static double IEEERemainder(this double num, double valuee) + { + return Math.IEEERemainder(num, valuee); + } + + /// + public static double Log(this double num) + { + return Math.Log(num); + } + + /// + public static double Log(this double num, double newBase) + { + return Math.Log(num, newBase); + } + + /// + public static double Log10(this double num) + { + return Math.Log10(num); + } + + /// + public static double Pow(this double num, double power) + { + return Math.Pow(num, power); + } + + /// + public static double Round(this double num) + { + return Math.Round(num); + } + + /// + public static double Round(this double num, MidpointRounding mode) + { + return Math.Round(num, mode); + } + + /// + public static double Round(this double num, int digits) + { + return Math.Round(num, digits); + } + + /// + public static double Round(this double num, int digits, MidpointRounding mode) + { + return Math.Round(num, digits, mode); + } + + /// + public static int Sign(this double num) + { + return Math.Sign(num); + } + + /// + public static double Sin(this double num) + { + return Math.Sin(num); + } + + /// + public static double Sinh(this double num) + { + return Math.Sinh(num); + } + + /// + public static double Sqrt(this double num) + { + return Math.Sqrt(num); + } + + /// + public static double Tan(this double num) + { + return Math.Tan(num); + } + + /// + public static double Tanh(this double num) + { + return Math.Tanh(num); + } + + /// + public static double Truncate(this double num) + { + return Math.Truncate(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/Int16Fluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/Int16Fluent.cs new file mode 100644 index 0000000..b0a53cc --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/Int16Fluent.cs @@ -0,0 +1,119 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// IntegerFluent class +/// +public static class Int16Fluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static decimal ToDecimal(this short num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static float ToSingle(this short num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static double ToDouble(this short num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static int ToInt32(this short num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static long ToInt64(this short num) + { + return num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static int Add(this short num, short value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static int Subtract(this short num, short value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static int Multiply(this short num, short value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static int Divide(this short num, short value) + { + return num / value; + } + + /// + public static short Abs(this short num) + { + return Math.Abs(num); + } + + /// + public static short Clamp(this short num, short min, short max) + { + return Math.Clamp(num, min, max); + } + + /// + public static int Sign(this short num) + { + return Math.Sign(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/Int32Fluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/Int32Fluent.cs new file mode 100644 index 0000000..754c1bb --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/Int32Fluent.cs @@ -0,0 +1,119 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// IntegerFluent class +/// +public static class Int32Fluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static decimal ToDecimal(this int num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static float ToSingle(this int num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static double ToDouble(this int num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static short ToInt16(this int num) + { + return (short)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static long ToInt64(this int num) + { + return num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static int Add(this int num, int value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static int Subtract(this int num, int value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static int Multiply(this int num, int value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static int Divide(this int num, int value) + { + return num / value; + } + + /// + public static int Abs(this int num) + { + return Math.Abs(num); + } + + /// + public static int Clamp(this int num, int min, int max) + { + return Math.Clamp(num, min, max); + } + + /// + public static int Sign(this int num) + { + return Math.Sign(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/Int64Fluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/Int64Fluent.cs new file mode 100644 index 0000000..d8c9297 --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/Int64Fluent.cs @@ -0,0 +1,119 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// IntegerFluent class +/// +public static class Int64Fluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static decimal ToDecimal(this long num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static float ToSingle(this long num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static double ToDouble(this long num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static short ToInt16(this long num) + { + return (short)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static int ToInt32(this long num) + { + return (int)num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static long Add(this long num, long value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static long Subtract(this long num, long value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static long Multiply(this long num, long value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static long Divide(this long num, long value) + { + return num / value; + } + + /// + public static long Abs(this long num) + { + return Math.Abs(num); + } + + /// + public static long Clamp(this long num, long min, long max) + { + return Math.Clamp(num, min, max); + } + + /// + public static long Sign(this long num) + { + return Math.Sign(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/TypeExtentions/SingleFluent.cs b/src/CuteUtils/FluentMath/TypeExtentions/SingleFluent.cs new file mode 100644 index 0000000..f5d2874 --- /dev/null +++ b/src/CuteUtils/FluentMath/TypeExtentions/SingleFluent.cs @@ -0,0 +1,287 @@ +namespace CuteUtils.FluentMath.TypeExtentions; + +/// +/// FloatFluent class +/// +public static class SingleFluent +{ + /// + /// Converts number to + /// + /// + /// Number as + public static decimal ToDecimal(this float num) + { + return (decimal)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static double ToDouble(this float num) + { + return num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static short ToInt16(this float num) + { + return (short)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static int ToInt32(this float num) + { + return (int)num; + } + + /// + /// Converts number to + /// + /// + /// Number as + public static long ToInt64(this float num) + { + return (long)num; + } + + /// + /// Adds the two nums + /// + /// + /// + /// + public static float Add(this float num, float value) + { + return num + value; + } + + /// + /// Subtracts the two nums + /// + /// + /// + /// + public static float Subtract(this float num, float value) + { + return num - value; + } + + /// + /// Multiples the two nums + /// + /// + /// + /// + public static float Multiply(this float num, float value) + { + return num * value; + } + + /// + /// Divides the two nums + /// + /// + /// + /// + public static float Divide(this float num, float value) + { + return num / value; + } + + /// + public static float Abs(this float num) + { + return MathF.Abs(num); + } + + /// + public static float Acos(this float num) + { + return MathF.Acos(num); + } + + /// + public static float Acosh(this float num) + { + return MathF.Acosh(num); + } + + /// + public static float Asin(this float num) + { + return MathF.Asin(num); + } + + /// + public static float Asinh(this float num) + { + return MathF.Asinh(num); + } + + /// + public static float Atan(this float num) + { + return MathF.Atan(num); + } + + /// + public static float Atan2(this float num, float value) + { + return MathF.Atan2(num, value); + } + + /// + public static float Atanh(this float num) + { + return MathF.Atanh(num); + } + + /// + public static float Cbrt(this float num) + { + return MathF.Cbrt(num); + } + + /// + public static float Ceiling(this float num) + { + return MathF.Ceiling(num); + } + + /// + public static float Clamp(this float num, float min, float max) + { + return Math.Clamp(num, min, max); + } + + /// + public static float Cos(this float num) + { + return MathF.Cos(num); + } + + /// + public static float Cosh(this float num) + { + return MathF.Cosh(num); + } + + /// + public static float Exp(this float num) + { + return MathF.Exp(num); + } + + /// + public static float Floor(this float num) + { + return MathF.Floor(num); + } + + /// + public static float IEEERemainder(this float num, float value) + { + return MathF.IEEERemainder(num, value); + } + + /// + public static float Log(this float num) + { + return MathF.Log(num); + } + + /// + public static float Log(this float num, float newBase) + { + return MathF.Log(num, newBase); + } + + /// + public static float Log10(this float num) + { + return MathF.Log10(num); + } + + /// + public static float Pow(this float num, float power) + { + return MathF.Pow(num, power); + } + + /// + public static float Round(this float num) + { + return MathF.Round(num); + } + + /// + public static float Round(this float num, MidpointRounding mode) + { + return MathF.Round(num, mode); + } + + /// + public static float Round(this float num, int digits) + { + return MathF.Round(num, digits); + } + + /// + public static float Round(this float num, int digits, MidpointRounding mode) + { + return MathF.Round(num, digits, mode); + } + + /// + public static int Sign(this float num) + { + return MathF.Sign(num); + } + + /// + public static float Sin(this float num) + { + return MathF.Sin(num); + } + + /// + public static float Sinh(this float num) + { + return MathF.Sinh(num); + } + + /// + public static float Sqrt(this float num) + { + return MathF.Sqrt(num); + } + + /// + public static float Tan(this float num) + { + return MathF.Tan(num); + } + + /// + public static float Tanh(this float num) + { + return MathF.Tanh(num); + } + + /// + public static float Truncate(this float num) + { + return MathF.Truncate(num); + } +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/LogConfig.cs b/src/CuteUtils/Logging/LogConfig.cs new file mode 100644 index 0000000..67306e6 --- /dev/null +++ b/src/CuteUtils/Logging/LogConfig.cs @@ -0,0 +1,83 @@ +using Stone_Red_C_Sharp_Utilities.Logging; + +using Stone_Red_Utilities.Logging; + +namespace CuteUtils.Logging; + +/// +/// Logging configuration. +/// +public class LogConfig +{ + /// + /// The configuration for messages. + /// + public OutputConfig DebugConfig { get; set; } = new OutputConfig(); + + /// + /// The configuration for messages. + /// + public OutputConfig InfoConfig { get; set; } = new OutputConfig(); + + /// + /// The configuration for messages. + /// + public OutputConfig WarnConfig { get; set; } = new OutputConfig(); + + /// + /// The configuration for messages. + /// + public OutputConfig ErrorConfig { get; set; } = new OutputConfig(); + + /// + /// The configuration for messages. + /// + public OutputConfig FatalConfig { get; set; } = new OutputConfig(); + + /// + /// The configuration for the message format. + /// + public FormatConfig FormatConfig { get; set; } = new FormatConfig(); +} + +/// +/// Output configuration. +/// +public class OutputConfig +{ + /// + /// The console color of the log message. + /// + public ConsoleColor ConsoleColor { get; set; } = ConsoleColor.White; + + /// + /// The target for the log message. + /// + public LogTarget LogTarget { get; set; } = LogTarget.DebugConsole; + + /// + /// The log file path. + /// + public string FilePath { get; set; } = "log.log"; +} + +/// +/// Format configuration. +/// +public class FormatConfig +{ + /// + /// The format for the debug console. + /// + public LogFormatBuilder DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; + + /// + /// The format for the console. + /// + public LogFormatBuilder ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; + + /// + /// The format for the log file. + /// + public LogFormatBuilder FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/LogFormatBuilder.cs b/src/CuteUtils/Logging/LogFormatBuilder.cs new file mode 100644 index 0000000..cfb0cd3 --- /dev/null +++ b/src/CuteUtils/Logging/LogFormatBuilder.cs @@ -0,0 +1,147 @@ +using Stone_Red_C_Sharp_Utilities.Logging; + +using System.Text; + +namespace CuteUtils.Logging; + +/// +/// A builder for +/// +public class LogFormatBuilder +{ + private readonly StringBuilder stringBuilder = new StringBuilder(); + + /// + /// Creates a new instance. + /// + public LogFormatBuilder() + { + } + + /// + /// Creates a new instance. + /// + /// The inital format. + public LogFormatBuilder(string value) + { + _ = stringBuilder.Append(value); + } + + /// + /// Converts the /> + /// + /// The to convert. + public static implicit operator string(LogFormatBuilder value) + { + return value.stringBuilder.ToString(); + } + + /// + /// Converts the /> + /// + /// The to convert. + public static implicit operator LogFormatBuilder(string value) + { + return new LogFormatBuilder(value); + } + + /// + /// Appends text to the log format. + /// + /// The text to append. + /// A reference to this instance. + public LogFormatBuilder Text(string value) + { + _ = stringBuilder.Append(value); + return this; + } + + /// + /// Appends the log datie time to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder DateTime(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.DateTime},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log severity to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder LogSeverity(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.LogSeverity},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the line number to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder LineNumber(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.LineNumber},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the file path to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder FilePath(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.FilePath},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log source to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder MemberName(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.MemberName},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log source to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder Source(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.Source},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log message to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder Message(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.Message},{padding}{GetFormat(format)}}}"); + return this; + } + + private static string GetFormat(string format) + { + return string.IsNullOrWhiteSpace(format) ? string.Empty : $":{format}"; + } +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/LogFormatType.cs b/src/CuteUtils/Logging/LogFormatType.cs new file mode 100644 index 0000000..44c3e0a --- /dev/null +++ b/src/CuteUtils/Logging/LogFormatType.cs @@ -0,0 +1,42 @@ +namespace CuteUtils.Logging; + +/// +/// Specifies the info type of the log message format. +/// +public static class LogFormatType +{ + /// + /// The of the log message. + /// + public const string DateTime = ""; + + /// + /// The of the log message. + /// + public const string LogSeverity = ""; + + /// + /// The line number of the log message. + /// + public const string LineNumber = ""; + + /// + /// The file path of the log message. + /// + public const string FilePath = ""; + + /// + /// The member name of the log message. + /// + public const string MemberName = ""; + + /// + /// The source of the log message. + /// + public const string Source = ""; + + /// + /// The message of the log message. + /// + public const string Message = ""; +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/LogSeverity.cs b/src/CuteUtils/Logging/LogSeverity.cs new file mode 100644 index 0000000..db59e64 --- /dev/null +++ b/src/CuteUtils/Logging/LogSeverity.cs @@ -0,0 +1,32 @@ +namespace CuteUtils.Logging; + +/// +/// Specifies the severity of the log message. +/// +public enum LogSeverity +{ + /// + /// Logs that contain the most detailed messages. + /// + Debug, + + /// + /// Logs that track the general flow of the application. + /// + Info, + + /// + /// Logs that highlight an abnormal activity in the flow of execution. + /// + Warn, + + /// + /// Logs that highlight when the flow of execution is stopped due to a failure. + /// + Error, + + /// + /// Logs that contain the most severe level of error. This type of error indicate that immediate attention may be required. + /// + Fatal +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/LogTarget.cs b/src/CuteUtils/Logging/LogTarget.cs new file mode 100644 index 0000000..3ac1325 --- /dev/null +++ b/src/CuteUtils/Logging/LogTarget.cs @@ -0,0 +1,23 @@ +namespace CuteUtils.Logging; + +/// +/// Specifies the target of the log message. +/// +[Flags] +public enum LogTarget +{ + /// + /// Writes log to console + /// + Console = 1, + + /// + /// Writes log to debug console + /// + DebugConsole = 2, + + /// + /// Writes log to file + /// + File = 3 +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/Logger.cs b/src/CuteUtils/Logging/Logger.cs new file mode 100644 index 0000000..7ff58f9 --- /dev/null +++ b/src/CuteUtils/Logging/Logger.cs @@ -0,0 +1,278 @@ +using Stone_Red_C_Sharp_Utilities; + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace CuteUtils.Logging; + +/// +/// Class used for logging +/// +public class Logger +{ + /// + /// The logging configuration. + /// + public LogConfig Config { get; init; } = new LogConfig(); + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + /// + public void Log(string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void Log(string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogInfo(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogWarn(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogWarn(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogError(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogFatal(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogFatal(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogDebug(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output if the condition is met + /// + /// + /// + /// + /// + /// + /// + /// + public void LogIf(bool condition, string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + if (condition) + { + WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + } + + /// + /// Log the message to the specified output if the condition is met + /// + /// + /// + /// + /// + /// + /// + public void LogIf(bool condition, string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + if (condition) + { + WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + } + + /// + /// Clears the log file + /// + public void ClearLogFile(LogSeverity logSeverity) + { + OutputConfig outputConfig = GetOutputConfig(logSeverity); + + lock (outputConfig) + { + if (File.Exists(outputConfig.FilePath)) + { + File.WriteAllText(outputConfig.FilePath, string.Empty); + } + } + } + + private static string GetFormattedString(string format, LogSeverity logSeverity, string source, string message, string memberName, string sourceFilePath, int sourceLineNumber) + { + format = format + .Replace(LogFormatType.DateTime, "0") + .Replace(LogFormatType.LogSeverity, "1") + .Replace(LogFormatType.LineNumber, "2") + .Replace(LogFormatType.FilePath, "3") + .Replace(LogFormatType.MemberName, "4") + .Replace(LogFormatType.Source, "5") + .Replace(LogFormatType.Message, "6"); + + return string.Format(format, DateTime.Now, logSeverity.ToString().ToUpper(), sourceLineNumber, sourceFilePath, memberName, source, message); + } + + private void WriteLog(string message, string source, LogSeverity logSeverity, string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0) + { + string consoleOutput = GetFormattedString(Config.FormatConfig.ConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + string debugOutput = GetFormattedString(Config.FormatConfig.DebugConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + string fileOutput = GetFormattedString(Config.FormatConfig.FileFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + + OutputConfig outputConfig = GetOutputConfig(logSeverity); + + if ((outputConfig.LogTarget & LogTarget.Console) == LogTarget.Console) + { + ConsoleExt.WriteLine(consoleOutput, outputConfig.ConsoleColor); + } + + if ((outputConfig.LogTarget & LogTarget.DebugConsole) == LogTarget.DebugConsole) + { + Trace.WriteLine(debugOutput); + } + + lock (outputConfig) + { + if ((outputConfig.LogTarget & LogTarget.File) == LogTarget.File) + { + if (!File.Exists(outputConfig.FilePath)) + { + File.Create(outputConfig.FilePath).Close(); + } + + File.AppendAllLines(outputConfig.FilePath, [fileOutput]); + } + } + } + + private OutputConfig GetOutputConfig(LogSeverity logSeverity) + { + return logSeverity switch + { + LogSeverity.Fatal => Config.FatalConfig, + LogSeverity.Error => Config.ErrorConfig, + LogSeverity.Warn => Config.WarnConfig, + LogSeverity.Info => Config.InfoConfig, + _ => Config.DebugConfig + }; + } +} \ No newline at end of file diff --git a/src/CuteUtils/RandomExtentions.cs b/src/CuteUtils/RandomExtentions.cs new file mode 100644 index 0000000..c8922a6 --- /dev/null +++ b/src/CuteUtils/RandomExtentions.cs @@ -0,0 +1,30 @@ +namespace CuteUtils; + +/// +/// Extensions +/// +public static class RandomExt +{ + public static T NextItem(this Random random, IEnumerable enumerable) + { + ArgumentNullException.ThrowIfNull(enumerable); + + return enumerable.ElementAt(random.Next(enumerable.Count())); + } + + public static bool NextBool(this Random random) + { + return random.Next(2) == 0; + } + + public static T NextEnum(this Random random) where T : struct, Enum + { + T[] values = Enum.GetValues(); + return values[random.Next(values.Length)]; + } + + public static T NextEnum(this Random random, T[] values) where T : struct, Enum + { + return values[random.Next(values.Length)]; + } +} \ No newline at end of file diff --git a/src/CuteUtils/Reflection.cs b/src/CuteUtils/Reflection.cs new file mode 100644 index 0000000..a0ab95d --- /dev/null +++ b/src/CuteUtils/Reflection.cs @@ -0,0 +1,60 @@ +using System.Reflection; + +namespace CuteUtils; + +/// +/// Reflection class +/// +public static class Reflection +{ + /// + /// Copies all properties of an object to a new one. + /// + /// + /// + /// + public static T CopyProperties(this object obj) where T : new() + { + T newObj = new T(); + + Type objType = obj.GetType(); + Type newObjType = newObj.GetType(); + + foreach (PropertyInfo propertyInfo in objType.GetProperties()) + { + PropertyInfo? newObjPropertyInfo = newObjType.GetProperty(propertyInfo.Name); + if (newObjPropertyInfo is not null && newObjPropertyInfo.PropertyType.IsAssignableFrom(propertyInfo.PropertyType)) + { + newObjPropertyInfo.SetValue(newObj, propertyInfo.GetValue(obj)); + } + } + + return newObj; + } + + /// + /// Copies all properties of an object to a different one. + /// + /// + /// + /// + /// + public static T CopyProperties(this object obj, T newObj) + { + ArgumentNullException.ThrowIfNull(newObj); + + Type objType = obj.GetType(); + Type newObjType = newObj.GetType(); + + foreach (PropertyInfo propertyInfo in objType.GetProperties()) + { + PropertyInfo? newObjPropertyInfo = newObjType.GetProperty(propertyInfo.Name); + if (newObjPropertyInfo is not null && newObjPropertyInfo.PropertyType.IsAssignableFrom(propertyInfo.PropertyType)) + { + newObjPropertyInfo.SetValue(newObj, propertyInfo.GetValue(obj)); + } + } + + return newObj; + } +} \ No newline at end of file diff --git a/src/CuteUtils/StringExtentions.cs b/src/CuteUtils/StringExtentions.cs new file mode 100644 index 0000000..ca82ea2 --- /dev/null +++ b/src/CuteUtils/StringExtentions.cs @@ -0,0 +1,169 @@ +using System.Globalization; +using System.Text; + +namespace CuteUtils; + +/// +/// Extensions +/// +public static class StringExt +{ + /// + /// Removes all invalid chars from the specified + /// + /// + /// + /// + public static string ToFileName(this string str, bool allowSpaces = false) + { + char[] invalidChars = Path.GetInvalidFileNameChars(); + + if (!allowSpaces) + { + str = str.Replace(" ", string.Empty); + } + + foreach (char item in invalidChars) + { + str = str.Replace(item.ToString(), string.Empty); + } + + string normalizedString = str.Normalize(NormalizationForm.FormD); + StringBuilder stringBuilder = new StringBuilder(); + + foreach (char c in normalizedString) + { + UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); + if (unicodeCategory != UnicodeCategory.NonSpacingMark) + { + _ = stringBuilder.Append(c); + } + } + + return stringBuilder.ToString().Normalize(NormalizationForm.FormC); + } + + /// + /// Removes all invalid chars from the specified + /// + /// + /// + /// + public static string ToPath(this string str, bool allowSpaces = false) + { + char[] invalidChars = Path.GetInvalidPathChars(); + + if (!allowSpaces) + { + str = str.Replace(" ", string.Empty); + } + + foreach (char item in invalidChars) + { + str = str.Replace(item.ToString(), string.Empty); + } + + string normalizedString = str.Normalize(NormalizationForm.FormD); + StringBuilder stringBuilder = new StringBuilder(); + + foreach (char c in normalizedString) + { + UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); + if (unicodeCategory != UnicodeCategory.NonSpacingMark) + { + _ = stringBuilder.Append(c); + } + } + + return stringBuilder.ToString().Normalize(NormalizationForm.FormC); + } + + /// + /// Truncates a to the specified length. + /// + /// + /// + /// + public static string Truncate(this string str, int length) + { + if (str.Length > length && length > 0) + { + return str[..length]; + } + + return str; + } + + /// + /// Truncates a to the specified length. + /// + /// + /// + /// + /// + public static string Truncate(this string str, int length, bool ellipsis) + { + if (str.Length > length && length > 0) + { + if (ellipsis && length > 3) + { + return $"{str[..(length - 3)]}..."; + } + else + { + return str[..length]; + } + } + + return str; + } + + /// + /// Uses the correct newline defined for this environment. + /// + /// + /// + public static string CorrectNewLine(this string str) + { + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + str = str.Replace("\r\n", "\n"); + } + else + { + str = str.Replace("\n", "\r\n"); //Ik that this can produce wrong results + } + + return str; + } + + /// + /// Removes all white spaces from the specified + /// + /// + /// + public static string RemoveWhitespaces(this string str) + { + StringBuilder result = new StringBuilder(); + foreach (char c in str) + { + if (!char.IsWhiteSpace(c)) + { + _ = result.Append(c); + } + } + return result.ToString(); + } + + /// + /// Reverses the specified + /// + /// + /// + public static string Reverse(this string str) + { + char[] array = str.ToCharArray(); + Array.Reverse(array); + return new string(array); + } +} \ No newline at end of file diff --git a/src/CuteUtils/Tasks/BlockingTaskQueue.cs b/src/CuteUtils/Tasks/BlockingTaskQueue.cs new file mode 100644 index 0000000..5a2ce71 --- /dev/null +++ b/src/CuteUtils/Tasks/BlockingTaskQueue.cs @@ -0,0 +1,91 @@ +namespace CuteUtils.Tasks; + +/// +/// Represents a blocking task queue that allows enqueueing tasks and functions. +/// +public class BlockingTaskQueue +{ + private readonly SemaphoreSlim semaphore; + + /// + /// Initializes a new instance of the class. + /// + public BlockingTaskQueue() + { + semaphore = new SemaphoreSlim(1); + } + + /// + /// Enqueues a task that returns a value. + /// + /// The type of the return value. + /// The function to execute. + /// A task representing the asynchronous operation. + public async Task Enqueue(Func function) + { + await semaphore.WaitAsync(); + try + { + return await Task.Run(function); + } + finally + { + _ = semaphore.Release(); + } + } + + /// + /// Enqueues a task that does not return a value. + /// + /// The action to execute. + /// A task representing the asynchronous operation. + public async Task Enqueue(Action function) + { + await semaphore.WaitAsync(); + try + { + await Task.Run(function); + } + finally + { + _ = semaphore.Release(); + } + } + + /// + /// Enqueues a task. + /// + /// The task to enqueue. + /// A task representing the asynchronous operation. + public async Task Enqueue(Task task) + { + await semaphore.WaitAsync(); + try + { + await task; + } + finally + { + _ = semaphore.Release(); + } + } + + /// + /// Enqueues a task that returns a value. + /// + /// The type of the return value. + /// The task to enqueue. + /// A task representing the asynchronous operation. + public async Task Enqueue(Task task) + { + await semaphore.WaitAsync(); + try + { + return await task; + } + finally + { + _ = semaphore.Release(); + } + } +} \ No newline at end of file diff --git a/src/CuteUtils/Tasks/TaskQueue.cs b/src/CuteUtils/Tasks/TaskQueue.cs new file mode 100644 index 0000000..919852b --- /dev/null +++ b/src/CuteUtils/Tasks/TaskQueue.cs @@ -0,0 +1,134 @@ +using System.Collections.Concurrent; +using System.Reactive.Linq; +using System.Reactive.Subjects; + +namespace CuteUtils.Tasks; + +/// +/// Represents a queue of tasks that can be enqueued and processed asynchronously. +/// +public class TaskQueue : IDisposable +{ + private readonly BlockingCollection<(Task Task, Action Callback)> tasks = []; + private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + private bool processing = false; + private bool disposed; + + /// + /// Enqueues a task that returns a value. + /// + /// The type of the value returned by the task. + /// The function representing the task. + /// An observable that emits the task when it completes. + public IObservable> Enqueue(Func function) + { + Subject> subject = new Subject>(); + Task task = new Task(function); + + tasks.Add((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + /// Enqueues a task that does not return a value. + /// + /// The action representing the task. + /// An observable that emits the task when it completes. + public IObservable Enqueue(Action function) + { + Subject subject = new Subject(); + Task task = new Task(function); + + tasks.Add((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + /// Enqueues a pre-created task. + /// + /// The task to enqueue. + /// An observable that emits the task when it completes. + public IObservable Enqueue(Task task) + { + Subject subject = new Subject(); + + tasks.Add((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + /// Enqueues a pre-created task that returns a value. + /// + /// The type of the value returned by the task. + /// The task to enqueue. + /// An observable that emits the task when it completes. + public IObservable> Enqueue(Task task) + { + Subject> subject = new Subject>(); + + tasks.Add((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + /// Disposes the task queue and cancels any pending tasks. + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + cancellationTokenSource.Dispose(); + tasks.Dispose(); + } + + disposed = true; + } + } + + private void ProcessTasks() + { + if (processing) + { + return; + } + + processing = true; + + _ = new TaskFactory().StartNew(async () => + { + while (!disposed) + { + (Task Task, Action Callback) container = tasks.Take(cancellationTokenSource.Token); + + if (container.Task.Status == TaskStatus.Created) + { + container.Task.Start(); + } + + await container.Task.WaitAsync(cancellationTokenSource.Token); + container.Callback?.Invoke(); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } +} \ No newline at end of file From 09512ef6db3a3151349ceba961c8325fd2386d88 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:22:36 +0100 Subject: [PATCH 02/12] Add DynDto and minor improvements --- src/CuteUtils.Tests/CuteUtils.Tests.csproj | 27 +++++ src/CuteUtils.Tests/UnitTest1.cs | 65 +++++++++++ src/CuteUtils.sln | 8 +- src/CuteUtils/BoolExtentions.cs | 16 +-- src/CuteUtils/CuteUtils.csproj | 4 + src/CuteUtils/Logging/LogConfig.cs | 6 +- src/CuteUtils/Logging/LogFormatBuilder.cs | 4 +- src/CuteUtils/Logging/Logger.cs | 4 +- src/CuteUtils/Reflection/DynDto.cs | 105 ++++++++++++++++++ .../Reflection/DynDtoNameAttribute.cs | 6 + .../ReflectionExtentions.cs} | 4 +- 11 files changed, 227 insertions(+), 22 deletions(-) create mode 100644 src/CuteUtils.Tests/CuteUtils.Tests.csproj create mode 100644 src/CuteUtils.Tests/UnitTest1.cs create mode 100644 src/CuteUtils/Reflection/DynDto.cs create mode 100644 src/CuteUtils/Reflection/DynDtoNameAttribute.cs rename src/CuteUtils/{Reflection.cs => Reflection/ReflectionExtentions.cs} (96%) diff --git a/src/CuteUtils.Tests/CuteUtils.Tests.csproj b/src/CuteUtils.Tests/CuteUtils.Tests.csproj new file mode 100644 index 0000000..95dadc8 --- /dev/null +++ b/src/CuteUtils.Tests/CuteUtils.Tests.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + diff --git a/src/CuteUtils.Tests/UnitTest1.cs b/src/CuteUtils.Tests/UnitTest1.cs new file mode 100644 index 0000000..9207c72 --- /dev/null +++ b/src/CuteUtils.Tests/UnitTest1.cs @@ -0,0 +1,65 @@ +using CuteUtils.Reflection; + +using System.Dynamic; + +namespace CuteUtils.Tests; + +[TestClass] +public class UnitTest1 +{ + [TestMethod] + public void TestMethod1() + { + TestModel testModel = new() + { + Id = 13, + Name = "test", + Value = (15, "test"), + }; + + ExpandoObject dto = testModel.ToDto(); + + Assert.IsNotNull(dto); + + Assert.IsFalse(dto.Any(p => p.Key == "Id")); + Assert.IsTrue(dto.Any(p => p.Key == "Name")); + Assert.IsTrue(dto.Any(p => p.Key == "Value")); + } + + [TestMethod] + public void TestMethod2() + { + TestModel testModel = new() + { + Id = 13, + Name = "test", + Value = (15, "test"), + }; + + TestDto dto = testModel.ToDto(); + + Assert.IsNotNull(dto); + + Assert.IsTrue(dto.Id != 0); + Assert.IsTrue(dto.Name is not null); + Assert.IsTrue(dto.Value is not null); + } + + private class TestModel + { + public required int Id { get; set; } + + [DynDtoName(nameof(Name))] + public required string Name { get; set; } + + //[DynDtoName(nameof(Value))] + public required object Value { get; set; } + } + + private class TestDto + { + public int Id { get; set; } = 0; + public string Name { get; set; } = string.Empty; + public object Value { get; set; } = (15, "test"); + } +} \ No newline at end of file diff --git a/src/CuteUtils.sln b/src/CuteUtils.sln index 5914960..53b2187 100644 --- a/src/CuteUtils.sln +++ b/src/CuteUtils.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.9.34622.214 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CuteUtils", "CuteUtils\CuteUtils.csproj", "{D640F3B6-2B09-496D-88D6-3CF57559845D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CuteUtils", "CuteUtils\CuteUtils.csproj", "{D640F3B6-2B09-496D-88D6-3CF57559845D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CuteUtils.Tests", "CuteUtils.Tests\CuteUtils.Tests.csproj", "{1468822C-92E4-4C44-93F6-DE71930F7C96}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +17,10 @@ Global {D640F3B6-2B09-496D-88D6-3CF57559845D}.Debug|Any CPU.Build.0 = Debug|Any CPU {D640F3B6-2B09-496D-88D6-3CF57559845D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D640F3B6-2B09-496D-88D6-3CF57559845D}.Release|Any CPU.Build.0 = Release|Any CPU + {1468822C-92E4-4C44-93F6-DE71930F7C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1468822C-92E4-4C44-93F6-DE71930F7C96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1468822C-92E4-4C44-93F6-DE71930F7C96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1468822C-92E4-4C44-93F6-DE71930F7C96}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/CuteUtils/BoolExtentions.cs b/src/CuteUtils/BoolExtentions.cs index 93a9d24..71e8819 100644 --- a/src/CuteUtils/BoolExtentions.cs +++ b/src/CuteUtils/BoolExtentions.cs @@ -8,26 +8,26 @@ public static class BoolExt /// /// Sets value to true if input is true. If input is false the value will not change. /// - /// + /// /// - public static void OneWayTrue(this ref bool bol, bool input) + public static void OneWayTrue(this ref bool value, bool input) { - if (!bol && input) + if (!value && input) { - bol = true; + value = true; } } /// /// Sets value to false if input is false. If input is true the value will not change. /// - /// + /// /// - public static void OneWayFalse(this ref bool bol, bool input) + public static void OneWayFalse(this ref bool value, bool input) { - if (bol && !input) + if (value && !input) { - bol = false; + value = false; } } diff --git a/src/CuteUtils/CuteUtils.csproj b/src/CuteUtils/CuteUtils.csproj index fa71b7a..b4ef780 100644 --- a/src/CuteUtils/CuteUtils.csproj +++ b/src/CuteUtils/CuteUtils.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/src/CuteUtils/Logging/LogConfig.cs b/src/CuteUtils/Logging/LogConfig.cs index 67306e6..cb7276b 100644 --- a/src/CuteUtils/Logging/LogConfig.cs +++ b/src/CuteUtils/Logging/LogConfig.cs @@ -1,8 +1,4 @@ -using Stone_Red_C_Sharp_Utilities.Logging; - -using Stone_Red_Utilities.Logging; - -namespace CuteUtils.Logging; +namespace CuteUtils.Logging; /// /// Logging configuration. diff --git a/src/CuteUtils/Logging/LogFormatBuilder.cs b/src/CuteUtils/Logging/LogFormatBuilder.cs index cfb0cd3..5ae36b1 100644 --- a/src/CuteUtils/Logging/LogFormatBuilder.cs +++ b/src/CuteUtils/Logging/LogFormatBuilder.cs @@ -1,6 +1,4 @@ -using Stone_Red_C_Sharp_Utilities.Logging; - -using System.Text; +using System.Text; namespace CuteUtils.Logging; diff --git a/src/CuteUtils/Logging/Logger.cs b/src/CuteUtils/Logging/Logger.cs index 7ff58f9..73f13b3 100644 --- a/src/CuteUtils/Logging/Logger.cs +++ b/src/CuteUtils/Logging/Logger.cs @@ -1,6 +1,4 @@ -using Stone_Red_C_Sharp_Utilities; - -using System.Diagnostics; +using System.Diagnostics; using System.Runtime.CompilerServices; namespace CuteUtils.Logging; diff --git a/src/CuteUtils/Reflection/DynDto.cs b/src/CuteUtils/Reflection/DynDto.cs new file mode 100644 index 0000000..606ce6a --- /dev/null +++ b/src/CuteUtils/Reflection/DynDto.cs @@ -0,0 +1,105 @@ +using System.Dynamic; +using System.Reflection; + +namespace CuteUtils.Reflection; +public static class DynDto +{ + public static ExpandoObject ToDto(this object data) + { + ExpandoObject dto = new ExpandoObject(); + + PropertyInfo[] properties = data.GetType().GetProperties(); + + foreach (PropertyInfo property in properties) + { + DynDtoNameAttribute? dynDtoNameAttribute = property.GetCustomAttribute(); + + if (dynDtoNameAttribute is not null) + { + _ = dto.TryAdd(dynDtoNameAttribute.Name, property.GetValue(data)); + } + } + + return dto; + } + + public static T ToDto(this object data, T dto) + { + PropertyInfo[] dataProperties = data.GetType().GetProperties(); + PropertyInfo[] dtoProperties = data.GetType().GetProperties(); + + foreach (PropertyInfo dataProperty in dataProperties) + { + DynDtoNameAttribute? dynDtoNameAttribute = dataProperty.GetCustomAttribute(); + PropertyInfo? dtoPropertyInfo = Array.Find(dtoProperties, p => p.Name == dynDtoNameAttribute?.Name); + + if (dynDtoNameAttribute is not null && dtoPropertyInfo is not null) + { + object? value = dataProperty.GetValue(data); + dtoPropertyInfo.SetValue(dto, value); + } + } + + return dto; + } + + public static T ToDto(this object data) where T : new() + { + return ToDto(data, new T()); + } + + public static T FromDto(this object dto, T data) + { + ArgumentNullException.ThrowIfNull(data); + + PropertyInfo[] dataProperties = data.GetType().GetProperties(); + PropertyInfo[] dtoProperties = dto.GetType().GetProperties(); + + foreach (PropertyInfo property in dataProperties) + { + DynDtoNameAttribute? dynDtoNameAttribute = property.GetCustomAttribute(); + if (dynDtoNameAttribute is not null) + { + PropertyInfo? propertyInfo = Array.Find(dtoProperties, x => x.Name == dynDtoNameAttribute.Name); + + if (propertyInfo is not null) + { + property.SetValue(data, propertyInfo.GetValue(dto)); + } + } + } + + return data; + } + + public static T FromDto(this ExpandoObject dto, T data) + { + ArgumentNullException.ThrowIfNull(dto); + ArgumentNullException.ThrowIfNull(data); + + IDictionary dtoProperties = dto!; + + PropertyInfo[] dataProperties = data.GetType().GetProperties(); + + foreach (PropertyInfo property in dataProperties) + { + DynDtoNameAttribute? dynDtoNameAttribute = property.GetCustomAttribute(); + if (dynDtoNameAttribute is not null && dtoProperties.TryGetValue(dynDtoNameAttribute.Name, out object? value)) + { + property.SetValue(data, value); + } + } + + return data; + } + + public static T FromDto(this object dto) where T : new() + { + return FromDto(dto, new T()); + } + + public static T FromDto(this ExpandoObject dto) where T : new() + { + return FromDto(dto, new T()); + } +} diff --git a/src/CuteUtils/Reflection/DynDtoNameAttribute.cs b/src/CuteUtils/Reflection/DynDtoNameAttribute.cs new file mode 100644 index 0000000..475350f --- /dev/null +++ b/src/CuteUtils/Reflection/DynDtoNameAttribute.cs @@ -0,0 +1,6 @@ +namespace CuteUtils.Reflection; +[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] +public class DynDtoNameAttribute(string name) : Attribute +{ + public string Name { get; set; } = name; +} diff --git a/src/CuteUtils/Reflection.cs b/src/CuteUtils/Reflection/ReflectionExtentions.cs similarity index 96% rename from src/CuteUtils/Reflection.cs rename to src/CuteUtils/Reflection/ReflectionExtentions.cs index a0ab95d..8459a45 100644 --- a/src/CuteUtils/Reflection.cs +++ b/src/CuteUtils/Reflection/ReflectionExtentions.cs @@ -1,11 +1,11 @@ using System.Reflection; -namespace CuteUtils; +namespace CuteUtils.Reflection; /// /// Reflection class /// -public static class Reflection +public static class ReflectionExtentions { /// /// Copies all properties of an object to a new one. From 5269a8d56de9884a824e7a4c84224e57f8255724 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:05:27 +0100 Subject: [PATCH 03/12] Fix DynDto --- .../{UnitTest1.cs => DynDtoTests.cs} | 18 +++++++++--------- src/CuteUtils/Reflection/DynDto.cs | 7 +++++-- 2 files changed, 14 insertions(+), 11 deletions(-) rename src/CuteUtils.Tests/{UnitTest1.cs => DynDtoTests.cs} (72%) diff --git a/src/CuteUtils.Tests/UnitTest1.cs b/src/CuteUtils.Tests/DynDtoTests.cs similarity index 72% rename from src/CuteUtils.Tests/UnitTest1.cs rename to src/CuteUtils.Tests/DynDtoTests.cs index 9207c72..6140ffb 100644 --- a/src/CuteUtils.Tests/UnitTest1.cs +++ b/src/CuteUtils.Tests/DynDtoTests.cs @@ -5,10 +5,10 @@ using System.Dynamic; namespace CuteUtils.Tests; [TestClass] -public class UnitTest1 +public class DynDtoTests { [TestMethod] - public void TestMethod1() + public void Convert_ToDto_ReturnsExpandoObject() { TestModel testModel = new() { @@ -27,7 +27,7 @@ public class UnitTest1 } [TestMethod] - public void TestMethod2() + public void Convert_ToDto_ReturnsGeneric() { TestModel testModel = new() { @@ -40,9 +40,9 @@ public class UnitTest1 Assert.IsNotNull(dto); - Assert.IsTrue(dto.Id != 0); - Assert.IsTrue(dto.Name is not null); - Assert.IsTrue(dto.Value is not null); + Assert.IsTrue(dto.Id == 0); + Assert.IsTrue(!string.IsNullOrWhiteSpace(dto.Name)); + Assert.IsTrue(dto.Value is not (0, "")); } private class TestModel @@ -52,14 +52,14 @@ public class UnitTest1 [DynDtoName(nameof(Name))] public required string Name { get; set; } - //[DynDtoName(nameof(Value))] + [DynDtoName(nameof(Value))] public required object Value { get; set; } } private class TestDto { - public int Id { get; set; } = 0; + public int Id { get; init; } = 0; public string Name { get; set; } = string.Empty; - public object Value { get; set; } = (15, "test"); + public object Value { get; init; } = (0, string.Empty); } } \ No newline at end of file diff --git a/src/CuteUtils/Reflection/DynDto.cs b/src/CuteUtils/Reflection/DynDto.cs index 606ce6a..8f3c883 100644 --- a/src/CuteUtils/Reflection/DynDto.cs +++ b/src/CuteUtils/Reflection/DynDto.cs @@ -2,6 +2,7 @@ using System.Reflection; namespace CuteUtils.Reflection; + public static class DynDto { public static ExpandoObject ToDto(this object data) @@ -25,8 +26,10 @@ public static class DynDto public static T ToDto(this object data, T dto) { + ArgumentNullException.ThrowIfNull(dto); + PropertyInfo[] dataProperties = data.GetType().GetProperties(); - PropertyInfo[] dtoProperties = data.GetType().GetProperties(); + PropertyInfo[] dtoProperties = dto.GetType().GetProperties(); foreach (PropertyInfo dataProperty in dataProperties) { @@ -102,4 +105,4 @@ public static class DynDto { return FromDto(dto, new T()); } -} +} \ No newline at end of file From 80b5cc51094661fc7c64905cb3140bffedfd2c31 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Mon, 18 Mar 2024 22:09:29 +0100 Subject: [PATCH 04/12] Add more shapes --- src/CuteUtils/FluentMath/Shapes/Circle.cs | 12 +++++++ src/CuteUtils/FluentMath/Shapes/Ellipse.cs | 12 +++++++ src/CuteUtils/FluentMath/Shapes/Rectangle.cs | 27 ++++++++------- src/CuteUtils/FluentMath/Shapes/Triangle.cs | 35 ++++++++++++++++++++ 4 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 src/CuteUtils/FluentMath/Shapes/Circle.cs create mode 100644 src/CuteUtils/FluentMath/Shapes/Ellipse.cs create mode 100644 src/CuteUtils/FluentMath/Shapes/Triangle.cs diff --git a/src/CuteUtils/FluentMath/Shapes/Circle.cs b/src/CuteUtils/FluentMath/Shapes/Circle.cs new file mode 100644 index 0000000..bb9d3c3 --- /dev/null +++ b/src/CuteUtils/FluentMath/Shapes/Circle.cs @@ -0,0 +1,12 @@ +namespace CuteUtils.FluentMath.Shapes; + +public class Circle(double radius) +{ + public double Radius { get; set; } = radius; + + public double Diameter => Radius * 2; + + public double Circumference => 2 * Math.PI * Radius; + + public double Area => Math.PI * Math.Pow(Radius, 2); +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Ellipse.cs b/src/CuteUtils/FluentMath/Shapes/Ellipse.cs new file mode 100644 index 0000000..e4963ab --- /dev/null +++ b/src/CuteUtils/FluentMath/Shapes/Ellipse.cs @@ -0,0 +1,12 @@ +namespace CuteUtils.FluentMath.Shapes; + +public class Ellipse(double majorAxis, double minorAxis) +{ + public double MajorAxis { get; set; } = majorAxis; + public double MinorAxis { get; set; } = minorAxis; + + public double Area => Math.PI * MajorAxis * MinorAxis; + public double Circumference => Math.PI * ((3 * (MajorAxis + MinorAxis)) - Math.Sqrt(((3 * MajorAxis) + MinorAxis) * (MajorAxis + (3 * MinorAxis)))); + + public bool IsCircle => MajorAxis == MinorAxis; +} \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Rectangle.cs b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs index 424424b..d67a204 100644 --- a/src/CuteUtils/FluentMath/Shapes/Rectangle.cs +++ b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs @@ -3,17 +3,22 @@ /// /// Represents a rectangle /// -public class Rectangle +/// +/// Creates a new rectangle instance +/// +/// The length of the rectangle +/// The width of the rectangle +public class Rectangle(double length, double width) { /// /// The length of the /// - public double Length { get; set; } + public double Length { get; set; } = length; /// /// The width of the /// - public double Width { get; set; } + public double Width { get; set; } = width; /// /// The diagonal of the @@ -28,16 +33,10 @@ public class Rectangle /// /// The perimeter of the /// - public double Perimeter => Length * 2 + Width * 2; + public double Perimeter => (Length * 2) + (Width * 2); - /// - /// Creates a new rectangle instance - /// - /// The length of the rectangle - /// The width of the rectangle - public Rectangle(double length, double width) - { - Length = length; - Width = width; - } + public bool IsSquare => Length == Width; + public bool IsRectangle => !IsSquare; + + public bool IsGolden => Length / Width == 1.61803398875; } \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Triangle.cs b/src/CuteUtils/FluentMath/Shapes/Triangle.cs new file mode 100644 index 0000000..4a25927 --- /dev/null +++ b/src/CuteUtils/FluentMath/Shapes/Triangle.cs @@ -0,0 +1,35 @@ +namespace CuteUtils.FluentMath.Shapes; + +public class Triangle(double sideA, double sideB, double sideC) +{ + public double SideA { get; set; } = sideA; + public double SideB { get; set; } = sideB; + public double SideC { get; set; } = sideC; + + public double Area + { + get + { + double s = (SideA + SideB + SideC) / 2; + return Math.Sqrt(s * (s - SideA) * (s - SideB) * (s - SideC)); + } + } + + public double Perimeter => SideA + SideB + SideC; + + public bool IsRightAngled + { + get + { + double[] sides = [SideA, SideB, SideC]; + Array.Sort(sides); + return Math.Pow(sides[0], 2) + Math.Pow(sides[1], 2) == Math.Pow(sides[2], 2); + } + } + + public bool IsEquilateral => SideA == SideB && SideB == SideC; + + public bool IsIsosceles => SideA == SideB || SideB == SideC || SideA == SideC; + + public bool IsScalene => !IsEquilateral && !IsIsosceles; +} \ No newline at end of file From 86b510faef119acc7e6599d8281096f94cac516d Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:54:21 +0100 Subject: [PATCH 05/12] Add missing xml docs --- src/CuteUtils/FluentMath/Shapes/Circle.cs | 19 ++++++++ src/CuteUtils/FluentMath/Shapes/Ellipse.cs | 25 ++++++++++ src/CuteUtils/FluentMath/Shapes/Rectangle.cs | 28 +++++++---- src/CuteUtils/FluentMath/Shapes/Triangle.cs | 38 +++++++++++++++ src/CuteUtils/Reflection/DynDto.cs | 47 +++++++++++++++++++ .../Reflection/DynDtoNameAttribute.cs | 13 ++++- .../Reflection/ReflectionExtentions.cs | 21 +++++---- 7 files changed, 171 insertions(+), 20 deletions(-) diff --git a/src/CuteUtils/FluentMath/Shapes/Circle.cs b/src/CuteUtils/FluentMath/Shapes/Circle.cs index bb9d3c3..151ff00 100644 --- a/src/CuteUtils/FluentMath/Shapes/Circle.cs +++ b/src/CuteUtils/FluentMath/Shapes/Circle.cs @@ -1,12 +1,31 @@ namespace CuteUtils.FluentMath.Shapes; +/// +/// Represents a circle shape. +/// +/// +/// Initializes a new instance of the class with the specified radius. +/// +/// The radius of the circle. public class Circle(double radius) { + /// + /// Gets or sets the radius of the circle. + /// public double Radius { get; set; } = radius; + /// + /// Gets the diameter of the circle. + /// public double Diameter => Radius * 2; + /// + /// Gets the circumference of the circle. + /// public double Circumference => 2 * Math.PI * Radius; + /// + /// Gets the area of the circle. + /// public double Area => Math.PI * Math.Pow(Radius, 2); } \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Ellipse.cs b/src/CuteUtils/FluentMath/Shapes/Ellipse.cs index e4963ab..f6df592 100644 --- a/src/CuteUtils/FluentMath/Shapes/Ellipse.cs +++ b/src/CuteUtils/FluentMath/Shapes/Ellipse.cs @@ -1,12 +1,37 @@ namespace CuteUtils.FluentMath.Shapes; +/// +/// Represents an ellipse shape. +/// +/// +/// Initializes a new instance of the class with the specified major and minor axes. +/// +/// The length of the major axis. +/// The length of the minor axis. public class Ellipse(double majorAxis, double minorAxis) { + /// + /// Gets or sets the length of the major axis. + /// public double MajorAxis { get; set; } = majorAxis; + + /// + /// Gets or sets the length of the minor axis. + /// public double MinorAxis { get; set; } = minorAxis; + /// + /// Gets the area of the ellipse. + /// public double Area => Math.PI * MajorAxis * MinorAxis; + + /// + /// Gets the circumference of the ellipse. + /// public double Circumference => Math.PI * ((3 * (MajorAxis + MinorAxis)) - Math.Sqrt(((3 * MajorAxis) + MinorAxis) * (MajorAxis + (3 * MinorAxis)))); + /// + /// Gets a value indicating whether the ellipse is a circle. + /// public bool IsCircle => MajorAxis == MinorAxis; } \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Rectangle.cs b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs index d67a204..d74abe7 100644 --- a/src/CuteUtils/FluentMath/Shapes/Rectangle.cs +++ b/src/CuteUtils/FluentMath/Shapes/Rectangle.cs @@ -1,42 +1,52 @@ namespace CuteUtils.FluentMath.Shapes; /// -/// Represents a rectangle +/// Represents a rectangle shape. /// /// -/// Creates a new rectangle instance +/// Initializes a new instance of the class with the specified length and width. /// -/// The length of the rectangle -/// The width of the rectangle +/// The length of the rectangle. +/// The width of the rectangle. public class Rectangle(double length, double width) { /// - /// The length of the + /// Gets or sets the length of the rectangle. /// public double Length { get; set; } = length; /// - /// The width of the + /// Gets or sets the width of the rectangle. /// public double Width { get; set; } = width; /// - /// The diagonal of the + /// Gets the diagonal length of the rectangle. /// public double Diagonal => Math.Sqrt(Math.Pow(Length, 2) + Math.Pow(Width, 2)); /// - /// The area of the + /// Gets the area of the rectangle. /// public double Area => Length * Width; /// - /// The perimeter of the + /// Gets the perimeter of the rectangle. /// public double Perimeter => (Length * 2) + (Width * 2); + /// + /// Gets a value indicating whether the rectangle is a square. + /// public bool IsSquare => Length == Width; + + /// + /// Gets a value indicating whether the rectangle is a rectangle (not a square). + /// public bool IsRectangle => !IsSquare; + /// + /// Gets a value indicating whether the rectangle has a golden ratio. + /// public bool IsGolden => Length / Width == 1.61803398875; } \ No newline at end of file diff --git a/src/CuteUtils/FluentMath/Shapes/Triangle.cs b/src/CuteUtils/FluentMath/Shapes/Triangle.cs index 4a25927..b7fbb74 100644 --- a/src/CuteUtils/FluentMath/Shapes/Triangle.cs +++ b/src/CuteUtils/FluentMath/Shapes/Triangle.cs @@ -1,11 +1,34 @@ namespace CuteUtils.FluentMath.Shapes; +/// +/// Represents a triangle with three sides. +/// +/// +/// Initializes a new instance of the class with the specified side lengths. +/// +/// The length of side A. +/// The length of side B. +/// The length of side C. public class Triangle(double sideA, double sideB, double sideC) { + /// + /// Gets or sets the length of side A. + /// public double SideA { get; set; } = sideA; + + /// + /// Gets or sets the length of side B. + /// public double SideB { get; set; } = sideB; + + /// + /// Gets or sets the length of side C. + /// public double SideC { get; set; } = sideC; + /// + /// Gets the area of the triangle. + /// public double Area { get @@ -15,8 +38,14 @@ public class Triangle(double sideA, double sideB, double sideC) } } + /// + /// Gets the perimeter of the triangle. + /// public double Perimeter => SideA + SideB + SideC; + /// + /// Gets a value indicating whether the triangle is right-angled. + /// public bool IsRightAngled { get @@ -27,9 +56,18 @@ public class Triangle(double sideA, double sideB, double sideC) } } + /// + /// Gets a value indicating whether the triangle is equilateral. + /// public bool IsEquilateral => SideA == SideB && SideB == SideC; + /// + /// Gets a value indicating whether the triangle is isosceles. + /// public bool IsIsosceles => SideA == SideB || SideB == SideC || SideA == SideC; + /// + /// Gets a value indicating whether the triangle is scalene. + /// public bool IsScalene => !IsEquilateral && !IsIsosceles; } \ No newline at end of file diff --git a/src/CuteUtils/Reflection/DynDto.cs b/src/CuteUtils/Reflection/DynDto.cs index 8f3c883..c9fe6db 100644 --- a/src/CuteUtils/Reflection/DynDto.cs +++ b/src/CuteUtils/Reflection/DynDto.cs @@ -3,8 +3,16 @@ using System.Reflection; namespace CuteUtils.Reflection; +/// +/// Provides utility methods for converting objects to and from dynamic DTOs. +/// public static class DynDto { + /// + /// Converts an object to a dynamic DTO. + /// + /// The object to convert. + /// The dynamic DTO. public static ExpandoObject ToDto(this object data) { ExpandoObject dto = new ExpandoObject(); @@ -24,6 +32,13 @@ public static class DynDto return dto; } + /// + /// Converts an object to a specified type of DTO. + /// + /// The type of DTO. + /// The object to convert. + /// The DTO instance to populate. + /// The populated DTO. public static T ToDto(this object data, T dto) { ArgumentNullException.ThrowIfNull(dto); @@ -46,11 +61,24 @@ public static class DynDto return dto; } + /// + /// Converts an object to a new instance of a specified type of DTO. + /// + /// The type of DTO. + /// The object to convert. + /// The new instance of the DTO. public static T ToDto(this object data) where T : new() { return ToDto(data, new T()); } + /// + /// Converts a dynamic DTO to an object. + /// + /// The type of object. + /// The dynamic DTO. + /// The object instance to populate. + /// The populated object. public static T FromDto(this object dto, T data) { ArgumentNullException.ThrowIfNull(data); @@ -75,6 +103,13 @@ public static class DynDto return data; } + /// + /// Converts a dynamic DTO to an object. + /// + /// The type of object. + /// The dynamic DTO. + /// The new instance of the object. + /// The populated object. public static T FromDto(this ExpandoObject dto, T data) { ArgumentNullException.ThrowIfNull(dto); @@ -96,11 +131,23 @@ public static class DynDto return data; } + /// + /// Converts a dynamic DTO to a new instance of an object. + /// + /// The type of object. + /// The dynamic DTO. + /// The new instance of the object. public static T FromDto(this object dto) where T : new() { return FromDto(dto, new T()); } + /// + /// Converts a dynamic DTO to a new instance of an object. + /// + /// The type of object. + /// The dynamic DTO. + /// The new instance of the object. public static T FromDto(this ExpandoObject dto) where T : new() { return FromDto(dto, new T()); diff --git a/src/CuteUtils/Reflection/DynDtoNameAttribute.cs b/src/CuteUtils/Reflection/DynDtoNameAttribute.cs index 475350f..4e1a84e 100644 --- a/src/CuteUtils/Reflection/DynDtoNameAttribute.cs +++ b/src/CuteUtils/Reflection/DynDtoNameAttribute.cs @@ -1,6 +1,17 @@ namespace CuteUtils.Reflection; + +/// +/// Represents an attribute that specifies the dynamic DTO name for a property. +/// +/// +/// Initializes a new instance of the class with the specified name. +/// +/// The dynamic DTO name. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class DynDtoNameAttribute(string name) : Attribute { + /// + /// Gets or sets the dynamic DTO name. + /// public string Name { get; set; } = name; -} +} \ No newline at end of file diff --git a/src/CuteUtils/Reflection/ReflectionExtentions.cs b/src/CuteUtils/Reflection/ReflectionExtentions.cs index 8459a45..4f7bb7e 100644 --- a/src/CuteUtils/Reflection/ReflectionExtentions.cs +++ b/src/CuteUtils/Reflection/ReflectionExtentions.cs @@ -3,16 +3,16 @@ namespace CuteUtils.Reflection; /// -/// Reflection class +/// Provides extension methods for reflection operations. /// public static class ReflectionExtentions { /// - /// Copies all properties of an object to a new one. + /// Creates a new instance of the specified type and copies the properties from the source object to the new instance. /// - /// - /// - /// + /// The type of the new instance. + /// The source object. + /// A new instance of the specified type with copied properties. public static T CopyProperties(this object obj) where T : new() { T newObj = new T(); @@ -33,12 +33,13 @@ public static class ReflectionExtentions } /// - /// Copies all properties of an object to a different one. + /// Copies the properties from the source object to the specified target object. /// - /// - /// - /// - /// + /// The type of the target object. + /// The source object. + /// The target object. + /// The target object with copied properties. + /// Thrown when the target object is null. public static T CopyProperties(this object obj, T newObj) { ArgumentNullException.ThrowIfNull(newObj); From 3bd8a283041181f17c45bf9d44d37393ab48d3c5 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Tue, 19 Mar 2024 22:42:28 +0100 Subject: [PATCH 06/12] Add Vsxmd --- src/CuteUtils/CuteUtils.csproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CuteUtils/CuteUtils.csproj b/src/CuteUtils/CuteUtils.csproj index b4ef780..30470d5 100644 --- a/src/CuteUtils/CuteUtils.csproj +++ b/src/CuteUtils/CuteUtils.csproj @@ -4,10 +4,19 @@ net8.0 enable enable + True + CuteUtils + Stone_Red + https://github.com/Stone-Red-Code/CuteUtils + True + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From e2c3e6e2af1907cc94b9481f024fd23f131b5531 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Thu, 21 Mar 2024 08:19:20 +0100 Subject: [PATCH 07/12] Update old xml docs --- src/CuteUtils/CollectionExtentions.cs | 19 +-- src/CuteUtils/ConsoleExtentions.cs | 41 +++--- src/CuteUtils/CuteUtils.csproj | 47 ++++--- src/CuteUtils/Logging/Logger.cs | 175 +++++++++++++------------- src/CuteUtils/RandomExtentions.cs | 27 +++- 5 files changed, 174 insertions(+), 135 deletions(-) diff --git a/src/CuteUtils/CollectionExtentions.cs b/src/CuteUtils/CollectionExtentions.cs index a9dcb84..a9cb784 100644 --- a/src/CuteUtils/CollectionExtentions.cs +++ b/src/CuteUtils/CollectionExtentions.cs @@ -34,11 +34,12 @@ public enum TableStyle public static class CollectionExt { /// - /// Prints all items of an + /// Prints the elements of the collection. /// - /// - /// - /// + /// The type of the elements in the collection. + /// The collection to print. + /// The delimiter character to use between elements. Default is ','. + /// Indicates whether to print to the debug console. Default is false. public static void Print(this IEnumerable collection, char delimiter = ',', bool printToDebugConsole = false) { int i = 0; @@ -63,11 +64,11 @@ public static class CollectionExt } /// - /// Creates and prints table from 2D array + /// Prints the elements of the 2D array in a table format. /// - /// - /// - /// + /// The type of the elements in the array. + /// The 2D array to print. + /// The style of the table. Default is TableStyle.Default. public static void PrintTable(this T[,] array, TableStyle tableStyle = TableStyle.Default) { int[] itemLength = new int[array.GetLength(1)]; @@ -126,4 +127,4 @@ public static class CollectionExt } Console.WriteLine(); } -} \ No newline at end of file +} diff --git a/src/CuteUtils/ConsoleExtentions.cs b/src/CuteUtils/ConsoleExtentions.cs index 347a30d..5ca80d1 100644 --- a/src/CuteUtils/ConsoleExtentions.cs +++ b/src/CuteUtils/ConsoleExtentions.cs @@ -11,10 +11,10 @@ namespace CuteUtils; public static class ConsoleExt { /// - /// Writes the text representation of the specified object to the standard output stream. + /// Writes the specified value to the console with the specified color. /// - /// - /// + /// The value to write. + /// The color of the text. public static void Write(object value, ConsoleColor color) { lock (Console.Out) @@ -27,10 +27,10 @@ public static class ConsoleExt } /// - /// Writes the text representation of the specified object, followed by the current line terminator, to the standard output stream. + /// Writes the specified value to the console with the specified color and appends a new line. /// - /// - /// + /// The value to write. + /// The color of the text. public static void WriteLine(object value, ConsoleColor color) { lock (Console.Out) @@ -45,9 +45,9 @@ public static class ConsoleExt /// /// Reads the next line of characters from the standard input stream and tries to convert it to the specified type. /// - /// + /// The type to convert the input string to. /// The input string converted to the specified type. - /// + /// Thrown if the conversion is not supported. public static T ReadLine() { string attemptedValue = Console.ReadLine() ?? string.Empty; @@ -60,9 +60,9 @@ public static class ConsoleExt /// /// Reads the next line of characters from the standard input stream and tries to convert it to the specified type. /// - /// + /// The type to convert the input string to. /// The input string converted to the specified type. - /// if the conversion was successful. Otherwise + /// if the conversion was successful. Otherwise . public static bool TryReadLine([NotNullWhen(true)] out T? input) { string attemptedValue = Console.ReadLine() ?? string.Empty; @@ -84,9 +84,9 @@ public static class ConsoleExt /// Obtains the next character or function key pressed by the user and converts it to the specified type. /// The pressed key is displayed in the console window. /// - /// The type of the + /// The type to convert the input character to. /// The input character converted to the specified type. - /// + /// Thrown if the conversion is not supported. public static T ReadKey() { string attemptedValue = Console.ReadKey().KeyChar.ToString(); @@ -101,15 +101,14 @@ public static class ConsoleExt /// The pressed key is displayed in the console window. /// /// The input character converted to the specified type. - /// The type of the - /// if the conversion was successful. Otherwise + /// The type to convert the input character to. + /// if the conversion was successful. Otherwise . public static bool TryReadKey([NotNullWhen(true)] out T? input) { string attemptedValue = Console.ReadKey().KeyChar.ToString(); Type type = typeof(T); TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.IsValid(attemptedValue)) - { input = (T)converter.ConvertFromString(attemptedValue)!; return true; @@ -122,10 +121,10 @@ public static class ConsoleExt } /// - /// Suspends execution of the current method until the user presses a key + /// Suspends execution of the current method until the user presses a key. /// - /// The key that has to be pressed - /// The message that will be displayed + /// The key that has to be pressed. + /// The message that will be displayed. public static void Pause(ConsoleKey key, string? message = null) { Console.WriteLine(message ?? $"Press {key} to continue..."); @@ -137,12 +136,12 @@ public static class ConsoleExt } /// - /// Suspends execution of the current method until the user presses a key + /// Suspends execution of the current method until the user presses a key. /// - /// The message that will be displayed + /// The message that will be displayed. public static void Pause(string message = "Press any key to continue...") { Console.WriteLine(message); _ = Console.ReadKey(true); } -} \ No newline at end of file +} diff --git a/src/CuteUtils/CuteUtils.csproj b/src/CuteUtils/CuteUtils.csproj index 30470d5..804a56e 100644 --- a/src/CuteUtils/CuteUtils.csproj +++ b/src/CuteUtils/CuteUtils.csproj @@ -1,22 +1,35 @@  - - net8.0 - enable - enable - True - CuteUtils - Stone_Red - https://github.com/Stone-Red-Code/CuteUtils - True - + + net8.0 + enable + enable + True + CuteUtils + Stone_Red + https://github.com/Stone-Red-Code/CuteUtils + True + README.md + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + False + False + + + + + True + \ + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/CuteUtils/Logging/Logger.cs b/src/CuteUtils/Logging/Logger.cs index 73f13b3..ce43d68 100644 --- a/src/CuteUtils/Logging/Logger.cs +++ b/src/CuteUtils/Logging/Logger.cs @@ -9,172 +9,172 @@ namespace CuteUtils.Logging; public class Logger { /// - /// The logging configuration. + /// Gets or sets the log configuration. /// public LogConfig Config { get; init; } = new LogConfig(); /// - /// Log the message to the specified output + /// Logs a message with the specified source, log severity, and additional caller information. /// - /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The severity level of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void Log(string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a message with the specified log severity and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The severity level of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void Log(string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs an informational message with the specified source and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogInfo(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs an informational message with additional caller information. /// - /// - /// - /// - /// + /// The message to log. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a warning message with the specified source and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogWarn(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a warning message with additional caller information. /// - /// - /// - /// - /// + /// The message to log. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogWarn(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs an error message with additional caller information. /// - /// - /// - /// - /// + /// The message to log. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs an error message with the specified source and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogError(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a fatal error message with additional caller information. /// - /// - /// - /// - /// + /// The message to log. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogFatal(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a fatal error message with the specified source and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogFatal(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a debug message with additional caller information. /// - /// - /// - /// - /// + /// The message to log. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, string.Empty, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output + /// Logs a debug message with the specified source and additional caller information. /// - /// - /// - /// - /// - /// + /// The message to log. + /// The source of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogDebug(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { WriteLog(message, source, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); } /// - /// Log the message to the specified output if the condition is met + /// Logs a message with the specified source, log severity, and additional caller information if the condition is met. /// - /// - /// - /// - /// - /// - /// - /// + /// The condition to check. + /// The message to log. + /// The source of the log message. + /// The severity level of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogIf(bool condition, string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (condition) @@ -184,14 +184,14 @@ public class Logger } /// - /// Log the message to the specified output if the condition is met + /// Logs a message with the specified log severity and additional caller information if the condition is met. /// - /// - /// - /// - /// - /// - /// + /// The condition to check. + /// The message to log. + /// The severity level of the log message. + /// The name of the calling member. + /// The path of the source file. + /// The line number in the source file. public void LogIf(bool condition, string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (condition) @@ -201,8 +201,9 @@ public class Logger } /// - /// Clears the log file + /// Clears the log file for the specified log severity. /// + /// The severity level of the log messages to clear. public void ClearLogFile(LogSeverity logSeverity) { OutputConfig outputConfig = GetOutputConfig(logSeverity); @@ -257,7 +258,7 @@ public class Logger File.Create(outputConfig.FilePath).Close(); } - File.AppendAllLines(outputConfig.FilePath, [fileOutput]); + File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput }); } } } @@ -273,4 +274,4 @@ public class Logger _ => Config.DebugConfig }; } -} \ No newline at end of file +} diff --git a/src/CuteUtils/RandomExtentions.cs b/src/CuteUtils/RandomExtentions.cs index c8922a6..36fc0d8 100644 --- a/src/CuteUtils/RandomExtentions.cs +++ b/src/CuteUtils/RandomExtentions.cs @@ -5,6 +5,13 @@ /// public static class RandomExt { + /// + /// Returns a random item from the specified enumerable. + /// + /// The type of the items in the enumerable. + /// The random number generator. + /// The enumerable to select a random item from. + /// A random item from the enumerable. public static T NextItem(this Random random, IEnumerable enumerable) { ArgumentNullException.ThrowIfNull(enumerable); @@ -12,19 +19,37 @@ public static class RandomExt return enumerable.ElementAt(random.Next(enumerable.Count())); } + /// + /// Returns a random boolean value. + /// + /// The random number generator. + /// A random boolean value. public static bool NextBool(this Random random) { return random.Next(2) == 0; } + /// + /// Returns a random value from the specified enum type. + /// + /// The enum type. + /// The random number generator. + /// A random value from the enum type. public static T NextEnum(this Random random) where T : struct, Enum { T[] values = Enum.GetValues(); return values[random.Next(values.Length)]; } + /// + /// Returns a random value from the specified array of enum values. + /// + /// The enum type. + /// The random number generator. + /// The array of enum values. + /// A random value from the array of enum values. public static T NextEnum(this Random random, T[] values) where T : struct, Enum { return values[random.Next(values.Length)]; } -} \ No newline at end of file +} From 9e1d9098a74e3de34f69ccf31847b0bc8ee2bd82 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:58:53 +0200 Subject: [PATCH 08/12] Fix xml docs mistakes --- src/CuteUtils/Logging/LogFormatBuilder.cs | 4 ++-- src/CuteUtils/Tasks/TaskQueue.cs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CuteUtils/Logging/LogFormatBuilder.cs b/src/CuteUtils/Logging/LogFormatBuilder.cs index 5ae36b1..7ce6888 100644 --- a/src/CuteUtils/Logging/LogFormatBuilder.cs +++ b/src/CuteUtils/Logging/LogFormatBuilder.cs @@ -26,7 +26,7 @@ public class LogFormatBuilder } /// - /// Converts the /> + /// Converts the to /// /// The to convert. public static implicit operator string(LogFormatBuilder value) @@ -35,7 +35,7 @@ public class LogFormatBuilder } /// - /// Converts the /> + /// Converts the to /// /// The to convert. public static implicit operator LogFormatBuilder(string value) diff --git a/src/CuteUtils/Tasks/TaskQueue.cs b/src/CuteUtils/Tasks/TaskQueue.cs index 919852b..9a78cae 100644 --- a/src/CuteUtils/Tasks/TaskQueue.cs +++ b/src/CuteUtils/Tasks/TaskQueue.cs @@ -92,6 +92,7 @@ public class TaskQueue : IDisposable GC.SuppressFinalize(this); } + /// protected virtual void Dispose(bool disposing) { if (!disposed) From a759e09c6715c033a2524bbf47077ff5284d3e79 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:59:24 +0200 Subject: [PATCH 09/12] Fix vsxmd error --- src/CuteUtils/CuteUtils.csproj | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/CuteUtils/CuteUtils.csproj b/src/CuteUtils/CuteUtils.csproj index 804a56e..fe76f91 100644 --- a/src/CuteUtils/CuteUtils.csproj +++ b/src/CuteUtils/CuteUtils.csproj @@ -18,6 +18,10 @@ + + True + \ + True \ @@ -27,9 +31,32 @@ - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + $([System.IO.Path]::GetTempPath()) + 1.0.0.0 + A "cute" utility library for C# + https://github.com/Stone-Red-Code/CuteUtils + Utility, Helper + LICENSE + + + + + + + + + + From fde63845f51cad4d8291169f43ee601ecea612c7 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:59:37 +0200 Subject: [PATCH 10/12] Finalize DynDto tests --- src/CuteUtils.Tests/DynDtoTests.cs | 146 +++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 31 deletions(-) diff --git a/src/CuteUtils.Tests/DynDtoTests.cs b/src/CuteUtils.Tests/DynDtoTests.cs index 6140ffb..7ed1394 100644 --- a/src/CuteUtils.Tests/DynDtoTests.cs +++ b/src/CuteUtils.Tests/DynDtoTests.cs @@ -8,58 +8,142 @@ namespace CuteUtils.Tests; public class DynDtoTests { [TestMethod] - public void Convert_ToDto_ReturnsExpandoObject() + public void ToDto_ShouldConvertObjectToDynamicDto() { - TestModel testModel = new() + // Arrange + TestData data = new TestData { - Id = 13, - Name = "test", - Value = (15, "test"), + Name = "John", + Age = 30 }; - ExpandoObject dto = testModel.ToDto(); + // Act + dynamic dto = data.ToDto(); - Assert.IsNotNull(dto); - - Assert.IsFalse(dto.Any(p => p.Key == "Id")); - Assert.IsTrue(dto.Any(p => p.Key == "Name")); - Assert.IsTrue(dto.Any(p => p.Key == "Value")); + // Assert + Assert.AreEqual("John", dto.Name); + Assert.AreEqual(30, dto.Age); } [TestMethod] - public void Convert_ToDto_ReturnsGeneric() + public void ToDto_ShouldConvertObjectToSpecifiedDtoType() { - TestModel testModel = new() + // Arrange + TestData data = new TestData { - Id = 13, - Name = "test", - Value = (15, "test"), + Name = "John", + Age = 30 + }; + TestDataDto dto = new TestDataDto(); + + // Act + dto = data.ToDto(dto); + + // Assert + Assert.AreEqual("John", dto.Name); + Assert.AreEqual(30, dto.Age); + } + + [TestMethod] + public void ToDto_ShouldConvertObjectToNewInstanceDto() + { + // Arrange + TestData data = new TestData + { + Name = "John", + Age = 30 }; - TestDto dto = testModel.ToDto(); + // Act + TestDataDto dto = data.ToDto(); - Assert.IsNotNull(dto); - - Assert.IsTrue(dto.Id == 0); - Assert.IsTrue(!string.IsNullOrWhiteSpace(dto.Name)); - Assert.IsTrue(dto.Value is not (0, "")); + // Assert + Assert.AreEqual("John", dto.Name); + Assert.AreEqual(30, dto.Age); } - private class TestModel + [TestMethod] + public void FromDto_ShouldConvertDynamicDtoToObject() { - public required int Id { get; set; } + // Arrange + ExpandoObject dto = new ExpandoObject(); + _ = dto.TryAdd("Name", "John"); + _ = dto.TryAdd("Age", 30); + TestData data = new TestData(); - [DynDtoName(nameof(Name))] - public required string Name { get; set; } + // Act + data = dto.FromDto(data); - [DynDtoName(nameof(Value))] - public required object Value { get; set; } + // Assert + Assert.AreEqual("John", data.Name); + Assert.AreEqual(30, data.Age); } - private class TestDto + [TestMethod] + public void FromDto_ShouldConvertDynamicDtoToNewInstanceObject() { - public int Id { get; init; } = 0; + // Arrange + ExpandoObject dto = new ExpandoObject(); + _ = dto.TryAdd("Name", "John"); + _ = dto.TryAdd("Age", 30); + + // Act + TestData data = dto.FromDto(); + + // Assert + Assert.AreEqual("John", data.Name); + Assert.AreEqual(30, data.Age); + } + + [TestMethod] + public void FromDto_ShouldConvertDtoToObject() + { + // Arrange + TestDataDto dto = new TestDataDto + { + Name = "John", + Age = 30 + }; + TestData data = new TestData(); + + // Act + data = dto.FromDto(data); + + // Assert + Assert.AreEqual("John", data.Name); + Assert.AreEqual(30, data.Age); + } + + [TestMethod] + public void FromDto_ShouldConvertDtoToNewInstanceObject() + { + // Arrange + TestDataDto dto = new TestDataDto + { + Name = "John", + Age = 30 + }; + + // Act + TestData data = dto.FromDto(); + + // Assert + Assert.AreEqual("John", data.Name); + Assert.AreEqual(30, data.Age); + } + + public class TestData + { + [DynDtoName("Name")] public string Name { get; set; } = string.Empty; - public object Value { get; init; } = (0, string.Empty); + + [DynDtoName("Age")] + public int Age { get; set; } + } + + public class TestDataDto + { + public string Name { get; set; } = string.Empty; + public int Age { get; set; } } } \ No newline at end of file From f0f727117abcfa82aca7ce53a96921655e1d01b2 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:23:24 +0200 Subject: [PATCH 11/12] Add more unit tests and improve existing ones --- .../{ => DynDto}/DynDtoTests.cs | 0 .../Misc/BoolExtentionsTests.cs | 117 +++++++++++++++ .../Misc/CollectionExtentionsTests.cs | 133 ++++++++++++++++++ src/CuteUtils/Logging/Logger.cs | 8 +- src/CuteUtils/{ => Misc}/BoolExtentions.cs | 2 +- .../{ => Misc}/CollectionExtentions.cs | 2 +- src/CuteUtils/{ => Misc}/ConsoleExtentions.cs | 2 +- src/CuteUtils/{ => Misc}/RandomExtentions.cs | 2 +- 8 files changed, 259 insertions(+), 7 deletions(-) rename src/CuteUtils.Tests/{ => DynDto}/DynDtoTests.cs (100%) create mode 100644 src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs create mode 100644 src/CuteUtils.Tests/Misc/CollectionExtentionsTests.cs rename src/CuteUtils/{ => Misc}/BoolExtentions.cs (97%) rename src/CuteUtils/{ => Misc}/CollectionExtentions.cs (99%) rename src/CuteUtils/{ => Misc}/ConsoleExtentions.cs (99%) rename src/CuteUtils/{ => Misc}/RandomExtentions.cs (98%) diff --git a/src/CuteUtils.Tests/DynDtoTests.cs b/src/CuteUtils.Tests/DynDto/DynDtoTests.cs similarity index 100% rename from src/CuteUtils.Tests/DynDtoTests.cs rename to src/CuteUtils.Tests/DynDto/DynDtoTests.cs diff --git a/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs b/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs new file mode 100644 index 0000000..f2e0302 --- /dev/null +++ b/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs @@ -0,0 +1,117 @@ +using CuteUtils.Misc; + +namespace CuteUtils.Tests; + +[TestClass] +public class BoolExtentionsTests +{ + [TestMethod] + public void OneWayTrue_ShouldSetValueToTrue_WhenInputIsTrue() + { + // Arrange + bool value = false; + bool input = true; + + // Act + value.OneWayTrue(input); + + // Assert + Assert.IsTrue(value); + } + + [TestMethod] + public void OneWayTrue_ShouldNotChangeValue_WhenInputIsFalse() + { + // Arrange + bool value = true; + bool input = false; + + // Act + value.OneWayTrue(input); + + // Assert + Assert.IsTrue(value); + } + + [TestMethod] + public void OneWayFalse_ShouldSetValueToFalse_WhenInputIsFalse() + { + // Arrange + bool value = true; + bool input = false; + + // Act + value.OneWayFalse(input); + + // Assert + Assert.IsFalse(value); + } + + [TestMethod] + public void OneWayFalse_ShouldNotChangeValue_WhenInputIsTrue() + { + // Arrange + bool value = false; + bool input = true; + + // Act + value.OneWayFalse(input); + + // Assert + Assert.IsFalse(value); + } + + [TestMethod] + public void ToInt_ShouldReturn1_WhenInputIsTrue() + { + // Arrange + bool input = true; + + // Act + int result = input.ToInt(); + + // Assert + Assert.AreEqual(1, result); + } + + [TestMethod] + public void ToInt_ShouldReturn0_WhenInputIsFalse() + { + // Arrange + bool input = false; + + // Act + int result = input.ToInt(); + + // Assert + Assert.AreEqual(0, result); + } + + [TestMethod] + public void FromInt_ShouldSetValueToTrue_WhenInputIs1() + { + // Arrange + bool value = false; + int input = 1; + + // Act + value.FromInt(input); + + // Assert + Assert.IsTrue(value); + } + + [TestMethod] + public void FromInt_ShouldSetValueToFalse_WhenInputIs0() + { + // Arrange + bool value = true; + int input = 0; + + // Act + value.FromInt(input); + + // Assert + Assert.IsFalse(value); + } +} \ No newline at end of file diff --git a/src/CuteUtils.Tests/Misc/CollectionExtentionsTests.cs b/src/CuteUtils.Tests/Misc/CollectionExtentionsTests.cs new file mode 100644 index 0000000..9a3aff8 --- /dev/null +++ b/src/CuteUtils.Tests/Misc/CollectionExtentionsTests.cs @@ -0,0 +1,133 @@ +using CuteUtils.Misc; + +using System.Text; + +namespace CuteUtils.Tests.Misc; + +[TestClass] +public class CollectionExtentionsTests +{ + private StringBuilder consoleOutput = null!; + + [TestInitialize] + public void Initialize() + { + consoleOutput = new StringBuilder(); + Console.SetOut(new StringWriter(consoleOutput)); + } + + [TestMethod] + public void Print_ShouldPrintCollectionElements() + { + // Arrange + List collection = [1, 2, 3, 4, 5]; + string expectedOutput = "1, 2, 3, 4, 5"; + + // Act + collection.Print(); + string actualOutput = consoleOutput.ToString(); + + // Assert + Assert.AreEqual(expectedOutput, actualOutput); + } + + [TestMethod] + public void Print_ShouldPrintCollectionElementsWithCustomDelimiter() + { + // Arrange + List collection = ["apple", "banana", "cherry"]; + string expectedOutput = "apple, banana, cherry"; + + // Act + collection.Print(','); + string actualOutput = consoleOutput.ToString(); + + // Assert + Assert.AreEqual(expectedOutput, actualOutput); + } + + [TestMethod] + public void Print_ShouldPrintCollectionElementsToDebugConsole() + { + Assert.Inconclusive("Need to find a way to test this."); + } + + [TestMethod] + public void PrintTable_ShouldPrint2DArrayInTableFormat() + { + // Arrange + int[,] array = new int[,] + { + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } + }; + string expectedOutput = Environment.NewLine + + $"-------------{Environment.NewLine}" + + $"| 1 | 2 | 3 |{Environment.NewLine}" + + $"-------------{Environment.NewLine}" + + $"| 4 | 5 | 6 |{Environment.NewLine}" + + $"-------------{Environment.NewLine}" + + $"| 7 | 8 | 9 |{Environment.NewLine}" + + $"-------------{Environment.NewLine}"; + + // Act + array.PrintTable(); + string actualOutput = consoleOutput.ToString(); + + // Assert + Assert.AreEqual(expectedOutput, actualOutput); + } + + [TestMethod] + public void PrintTable_ShouldPrint2DArrayInTableFormatWithAlternativeStyle() + { + // Arrange + int[,] array = new int[,] + { + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } + }; + string expectedOutput = Environment.NewLine + + $"+---+---+---+{Environment.NewLine}" + + $"| 1 | 2 | 3 |{Environment.NewLine}" + + $"+---+---+---+{Environment.NewLine}" + + $"| 4 | 5 | 6 |{Environment.NewLine}" + + $"+---+---+---+{Environment.NewLine}" + + $"| 7 | 8 | 9 |{Environment.NewLine}" + + $"+---+---+---+{Environment.NewLine}"; + + // Act + array.PrintTable(TableStyle.Alternative); + string actualOutput = consoleOutput.ToString(); + + // Assert + Assert.AreEqual(expectedOutput, actualOutput); + } + + [TestMethod] + public void PrintTable_ShouldPrint2DArrayInTableFormatWithListStyle() + { + // Arrange + int[,] array = new int[,] + { + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } + }; + string expectedOutput = Environment.NewLine + + $"+---+---+---+{Environment.NewLine}" + + $"| 1 | 2 | 3 |{Environment.NewLine}" + + $"+---+---+---+{Environment.NewLine}" + + $"| 4 | 5 | 6 |{Environment.NewLine}" + + $"| 7 | 8 | 9 |{Environment.NewLine}"; + + // Act + array.PrintTable(TableStyle.List); + string actualOutput = consoleOutput.ToString(); + + // Assert + Assert.AreEqual(expectedOutput, actualOutput); + } +} \ No newline at end of file diff --git a/src/CuteUtils/Logging/Logger.cs b/src/CuteUtils/Logging/Logger.cs index ce43d68..37da229 100644 --- a/src/CuteUtils/Logging/Logger.cs +++ b/src/CuteUtils/Logging/Logger.cs @@ -1,4 +1,6 @@ -using System.Diagnostics; +using CuteUtils.Misc; + +using System.Diagnostics; using System.Runtime.CompilerServices; namespace CuteUtils.Logging; @@ -258,7 +260,7 @@ public class Logger File.Create(outputConfig.FilePath).Close(); } - File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput }); + File.AppendAllLines(outputConfig.FilePath, [fileOutput]); } } } @@ -274,4 +276,4 @@ public class Logger _ => Config.DebugConfig }; } -} +} \ No newline at end of file diff --git a/src/CuteUtils/BoolExtentions.cs b/src/CuteUtils/Misc/BoolExtentions.cs similarity index 97% rename from src/CuteUtils/BoolExtentions.cs rename to src/CuteUtils/Misc/BoolExtentions.cs index 71e8819..cc9f3a9 100644 --- a/src/CuteUtils/BoolExtentions.cs +++ b/src/CuteUtils/Misc/BoolExtentions.cs @@ -1,4 +1,4 @@ -namespace CuteUtils; +namespace CuteUtils.Misc; /// /// Extensions diff --git a/src/CuteUtils/CollectionExtentions.cs b/src/CuteUtils/Misc/CollectionExtentions.cs similarity index 99% rename from src/CuteUtils/CollectionExtentions.cs rename to src/CuteUtils/Misc/CollectionExtentions.cs index a9cb784..b418f12 100644 --- a/src/CuteUtils/CollectionExtentions.cs +++ b/src/CuteUtils/Misc/CollectionExtentions.cs @@ -1,6 +1,6 @@ using System.Diagnostics; -namespace CuteUtils; +namespace CuteUtils.Misc; /// /// Table Style diff --git a/src/CuteUtils/ConsoleExtentions.cs b/src/CuteUtils/Misc/ConsoleExtentions.cs similarity index 99% rename from src/CuteUtils/ConsoleExtentions.cs rename to src/CuteUtils/Misc/ConsoleExtentions.cs index 5ca80d1..683b5bc 100644 --- a/src/CuteUtils/ConsoleExtentions.cs +++ b/src/CuteUtils/Misc/ConsoleExtentions.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; #pragma warning disable S3998 // Threads should not lock on objects with weak identity -namespace CuteUtils; +namespace CuteUtils.Misc; /// /// Extensions diff --git a/src/CuteUtils/RandomExtentions.cs b/src/CuteUtils/Misc/RandomExtentions.cs similarity index 98% rename from src/CuteUtils/RandomExtentions.cs rename to src/CuteUtils/Misc/RandomExtentions.cs index 36fc0d8..22337f9 100644 --- a/src/CuteUtils/RandomExtentions.cs +++ b/src/CuteUtils/Misc/RandomExtentions.cs @@ -1,4 +1,4 @@ -namespace CuteUtils; +namespace CuteUtils.Misc; /// /// Extensions From 9a8725564fab2939cf8774a12ff62997ac9bc2ef Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:27:06 +0200 Subject: [PATCH 12/12] Move unit tests to their respective directory --- src/CuteUtils.Tests/DynDto/DynDtoTests.cs | 2 +- src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CuteUtils.Tests/DynDto/DynDtoTests.cs b/src/CuteUtils.Tests/DynDto/DynDtoTests.cs index 7ed1394..c21fb29 100644 --- a/src/CuteUtils.Tests/DynDto/DynDtoTests.cs +++ b/src/CuteUtils.Tests/DynDto/DynDtoTests.cs @@ -2,7 +2,7 @@ using CuteUtils.Reflection; using System.Dynamic; -namespace CuteUtils.Tests; +namespace CuteUtils.Tests.DynDto; [TestClass] public class DynDtoTests diff --git a/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs b/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs index f2e0302..566895a 100644 --- a/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs +++ b/src/CuteUtils.Tests/Misc/BoolExtentionsTests.cs @@ -1,6 +1,6 @@ using CuteUtils.Misc; -namespace CuteUtils.Tests; +namespace CuteUtils.Tests.Misc; [TestClass] public class BoolExtentionsTests