mirror of
https://github.com/Stone-Red-Code/CuteUtils.git
synced 2026-09-04 00:46:11 +02:00
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CuteUtils\CuteUtils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,149 @@
|
||||
using CuteUtils.Reflection;
|
||||
|
||||
using System.Dynamic;
|
||||
|
||||
namespace CuteUtils.Tests.DynDto;
|
||||
|
||||
[TestClass]
|
||||
public class DynDtoTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ToDto_ShouldConvertObjectToDynamicDto()
|
||||
{
|
||||
// Arrange
|
||||
TestData data = new TestData
|
||||
{
|
||||
Name = "John",
|
||||
Age = 30
|
||||
};
|
||||
|
||||
// Act
|
||||
dynamic dto = data.ToDto();
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("John", dto.Name);
|
||||
Assert.AreEqual(30, dto.Age);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ToDto_ShouldConvertObjectToSpecifiedDtoType()
|
||||
{
|
||||
// Arrange
|
||||
TestData data = new TestData
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
// Act
|
||||
TestDataDto dto = data.ToDto<TestDataDto>();
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("John", dto.Name);
|
||||
Assert.AreEqual(30, dto.Age);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FromDto_ShouldConvertDynamicDtoToObject()
|
||||
{
|
||||
// Arrange
|
||||
ExpandoObject dto = new ExpandoObject();
|
||||
_ = dto.TryAdd("Name", "John");
|
||||
_ = dto.TryAdd("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_ShouldConvertDynamicDtoToNewInstanceObject()
|
||||
{
|
||||
// Arrange
|
||||
ExpandoObject dto = new ExpandoObject();
|
||||
_ = dto.TryAdd("Name", "John");
|
||||
_ = dto.TryAdd("Age", 30);
|
||||
|
||||
// Act
|
||||
TestData data = dto.FromDto<TestData>();
|
||||
|
||||
// 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<TestData>();
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("John", data.Name);
|
||||
Assert.AreEqual(30, data.Age);
|
||||
}
|
||||
|
||||
public class TestData
|
||||
{
|
||||
[DynDtoName("Name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[DynDtoName("Age")]
|
||||
public int Age { get; set; }
|
||||
}
|
||||
|
||||
public class TestDataDto
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int Age { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using CuteUtils.Misc;
|
||||
|
||||
namespace CuteUtils.Tests.Misc;
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
@@ -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<int> 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<string> 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);
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -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
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace CuteUtils;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -4,6 +4,59 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Title>CuteUtils</Title>
|
||||
<Authors>Stone_Red</Authors>
|
||||
<PackageProjectUrl>https://github.com/Stone-Red-Code/CuteUtils</PackageProjectUrl>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
||||
<Deterministic>False</Deterministic>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
<None Include="..\..\README.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive.Linq" Version="6.0.0" />
|
||||
<PackageReference Include="Vsxmd" Version="1.4.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
FIXES:
|
||||
An assembly specified in the application dependencies manifest (Vsxmd.deps.json) was not found:
|
||||
package: 'runtimepack.Microsoft.NETCore.App.Runtime.win-x64', version: '3.1.1'
|
||||
path: 'Microsoft.Win32.Primitives.dll'
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<UserTempFolder>$([System.IO.Path]::GetTempPath())</UserTempFolder>
|
||||
<Version>1.0.0.0</Version>
|
||||
<Description>A "cute" utility library for C#</Description>
|
||||
<RepositoryUrl>https://github.com/Stone-Red-Code/CuteUtils</RepositoryUrl>
|
||||
<PackageTags>Utility, Helper</PackageTags>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<FilesToDelete Include="$(UserTempFolder).net\Vsxmd\**\*" />
|
||||
</ItemGroup>
|
||||
<Target Name="CustomCleanVsxmd" AfterTargets="Clean" Condition="$([MSBuild]::IsOsPlatform('Windows'))">
|
||||
<Message Importance="high" Text="Cleaning up Vsxmd temporary files in $(UserTempFolder).net\Vsxmd" />
|
||||
<Delete Files="@(FilesToDelete)" ContinueOnError="true" />
|
||||
<RemoveDir Directories="$(UserTempFolder).net\Vsxmd\" ContinueOnError="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace CuteUtils.FluentMath.Shapes;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a circle shape.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="Circle"/> class with the specified radius.
|
||||
/// </remarks>
|
||||
/// <param name="radius">The radius of the circle.</param>
|
||||
public class Circle(double radius)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the radius of the circle.
|
||||
/// </summary>
|
||||
public double Radius { get; set; } = radius;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the diameter of the circle.
|
||||
/// </summary>
|
||||
public double Diameter => Radius * 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the circumference of the circle.
|
||||
/// </summary>
|
||||
public double Circumference => 2 * Math.PI * Radius;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the area of the circle.
|
||||
/// </summary>
|
||||
public double Area => Math.PI * Math.Pow(Radius, 2);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace CuteUtils.FluentMath.Shapes;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an ellipse shape.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="Ellipse"/> class with the specified major and minor axes.
|
||||
/// </remarks>
|
||||
/// <param name="majorAxis">The length of the major axis.</param>
|
||||
/// <param name="minorAxis">The length of the minor axis.</param>
|
||||
public class Ellipse(double majorAxis, double minorAxis)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the major axis.
|
||||
/// </summary>
|
||||
public double MajorAxis { get; set; } = majorAxis;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the minor axis.
|
||||
/// </summary>
|
||||
public double MinorAxis { get; set; } = minorAxis;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the area of the ellipse.
|
||||
/// </summary>
|
||||
public double Area => Math.PI * MajorAxis * MinorAxis;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the circumference of the ellipse.
|
||||
/// </summary>
|
||||
public double Circumference => Math.PI * ((3 * (MajorAxis + MinorAxis)) - Math.Sqrt(((3 * MajorAxis) + MinorAxis) * (MajorAxis + (3 * MinorAxis))));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the ellipse is a circle.
|
||||
/// </summary>
|
||||
public bool IsCircle => MajorAxis == MinorAxis;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace CuteUtils.FluentMath.Shapes;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle shape.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="Rectangle"/> class with the specified length and width.
|
||||
/// </remarks>
|
||||
/// <param name="length">The length of the rectangle.</param>
|
||||
/// <param name="width">The width of the rectangle.</param>
|
||||
public class Rectangle(double length, double width)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the rectangle.
|
||||
/// </summary>
|
||||
public double Length { get; set; } = length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the rectangle.
|
||||
/// </summary>
|
||||
public double Width { get; set; } = width;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the diagonal length of the rectangle.
|
||||
/// </summary>
|
||||
public double Diagonal => Math.Sqrt(Math.Pow(Length, 2) + Math.Pow(Width, 2));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the area of the rectangle.
|
||||
/// </summary>
|
||||
public double Area => Length * Width;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the perimeter of the rectangle.
|
||||
/// </summary>
|
||||
public double Perimeter => (Length * 2) + (Width * 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the rectangle is a square.
|
||||
/// </summary>
|
||||
public bool IsSquare => Length == Width;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the rectangle is a rectangle (not a square).
|
||||
/// </summary>
|
||||
public bool IsRectangle => !IsSquare;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the rectangle has a golden ratio.
|
||||
/// </summary>
|
||||
public bool IsGolden => Length / Width == 1.61803398875;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
namespace CuteUtils.FluentMath.Shapes;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a triangle with three sides.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="Triangle"/> class with the specified side lengths.
|
||||
/// </remarks>
|
||||
/// <param name="sideA">The length of side A.</param>
|
||||
/// <param name="sideB">The length of side B.</param>
|
||||
/// <param name="sideC">The length of side C.</param>
|
||||
public class Triangle(double sideA, double sideB, double sideC)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the length of side A.
|
||||
/// </summary>
|
||||
public double SideA { get; set; } = sideA;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of side B.
|
||||
/// </summary>
|
||||
public double SideB { get; set; } = sideB;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of side C.
|
||||
/// </summary>
|
||||
public double SideC { get; set; } = sideC;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the area of the triangle.
|
||||
/// </summary>
|
||||
public double Area
|
||||
{
|
||||
get
|
||||
{
|
||||
double s = (SideA + SideB + SideC) / 2;
|
||||
return Math.Sqrt(s * (s - SideA) * (s - SideB) * (s - SideC));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the perimeter of the triangle.
|
||||
/// </summary>
|
||||
public double Perimeter => SideA + SideB + SideC;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the triangle is right-angled.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the triangle is equilateral.
|
||||
/// </summary>
|
||||
public bool IsEquilateral => SideA == SideB && SideB == SideC;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the triangle is isosceles.
|
||||
/// </summary>
|
||||
public bool IsIsosceles => SideA == SideB || SideB == SideC || SideA == SideC;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the triangle is scalene.
|
||||
/// </summary>
|
||||
public bool IsScalene => !IsEquilateral && !IsIsosceles;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// DecimalFluent class
|
||||
/// </summary>
|
||||
public static class DecimalFluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static double ToDouble(this decimal num)
|
||||
{
|
||||
return (double)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="float"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="float"/></returns>
|
||||
public static float ToSingle(this decimal num)
|
||||
{
|
||||
return (float)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="short"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="short"/></returns>
|
||||
public static short ToInt16(this decimal num)
|
||||
{
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="int"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="int"/></returns>
|
||||
public static int ToInt32(this decimal num)
|
||||
{
|
||||
return (int)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="long"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="long"/></returns>
|
||||
public static long ToInt64(this decimal num)
|
||||
{
|
||||
return (long)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal Add(this decimal num, decimal value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal Subtract(this decimal num, decimal value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal Multiply(this decimal num, decimal value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal Divide(this decimal num, decimal value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Abs(decimal)"/>
|
||||
public static decimal Abs(this decimal num)
|
||||
{
|
||||
return Math.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Ceiling(decimal)"/>
|
||||
public static decimal Ceiling(this decimal num)
|
||||
{
|
||||
return Math.Ceiling(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(decimal,decimal,decimal)"/>
|
||||
public static decimal Clamp(this decimal num, decimal min, decimal max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Floor(decimal)"/>
|
||||
public static decimal Floor(this decimal num)
|
||||
{
|
||||
return Math.Floor(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(decimal)"/>
|
||||
public static decimal Round(this decimal num)
|
||||
{
|
||||
return Math.Round(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(decimal,MidpointRounding)"/>
|
||||
public static decimal Round(this decimal num, MidpointRounding mode)
|
||||
{
|
||||
return Math.Round(num, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(decimal,int)"/>
|
||||
public static decimal Round(this decimal num, int digits)
|
||||
{
|
||||
return Math.Round(num, digits);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(decimal,int,MidpointRounding)"/>
|
||||
public static decimal Round(this decimal num, int digits, MidpointRounding mode)
|
||||
{
|
||||
return Math.Round(num, digits, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sign(decimal)"/>
|
||||
public static int Sign(this decimal num)
|
||||
{
|
||||
return Math.Sign(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Truncate(decimal)"/>
|
||||
public static decimal Truncate(this decimal num)
|
||||
{
|
||||
return Math.Truncate(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// DoubleFluent class
|
||||
/// </summary>
|
||||
public static class DoubleFluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static decimal ToDecimal(this double num)
|
||||
{
|
||||
return (decimal)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="float"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="float"/></returns>
|
||||
public static float ToSingle(this double num)
|
||||
{
|
||||
return (float)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="short"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="short"/></returns>
|
||||
public static short ToInt16(this double num)
|
||||
{
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="int"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="int"/></returns>
|
||||
public static int ToInt32(this double num)
|
||||
{
|
||||
return (int)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="long"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="long"/></returns>
|
||||
public static long ToInt64(this double num)
|
||||
{
|
||||
return (long)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double Add(this double num, double value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double Subtract(this double num, double value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double Multiply(this double num, double value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double Divide(this double num, double value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Abs(double)"/>
|
||||
public static double Abs(this double num)
|
||||
{
|
||||
return Math.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Acos(double)"/>
|
||||
public static double Acos(this double num)
|
||||
{
|
||||
return Math.Acos(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Acosh(double)"/>
|
||||
public static double Acosh(this double num)
|
||||
{
|
||||
return Math.Acosh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Asin(double)"/>
|
||||
public static double Asin(this double num)
|
||||
{
|
||||
return Math.Asin(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Asinh(double)"/>
|
||||
public static double Asinh(this double num)
|
||||
{
|
||||
return Math.Asinh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Atan(double)"/>
|
||||
public static double Atan(this double num)
|
||||
{
|
||||
return Math.Atan(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Atan2(double,double)"/>
|
||||
public static double Atan2(this double num, double valuee)
|
||||
{
|
||||
return Math.Atan2(num, valuee);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Atanh(double)"/>
|
||||
public static double Atanh(this double num)
|
||||
{
|
||||
return Math.Atanh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Cbrt(double)"/>
|
||||
public static double Cbrt(this double num)
|
||||
{
|
||||
return Math.Cbrt(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Ceiling(double)"/>
|
||||
public static double Ceiling(this double num)
|
||||
{
|
||||
return Math.Ceiling(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(double,double,double)"/>
|
||||
public static double Clamp(this double num, double min, double max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Cos(double)"/>
|
||||
public static double Cos(this double num)
|
||||
{
|
||||
return Math.Cos(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Cosh(double)"/>
|
||||
public static double Cosh(this double num)
|
||||
{
|
||||
return Math.Cosh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Exp(double)"/>
|
||||
public static double Exp(this double num)
|
||||
{
|
||||
return Math.Exp(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Floor(double)"/>
|
||||
public static double Floor(this double num)
|
||||
{
|
||||
return Math.Floor(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.IEEERemainder(double,double)"/>
|
||||
public static double IEEERemainder(this double num, double valuee)
|
||||
{
|
||||
return Math.IEEERemainder(num, valuee);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Log(double)"/>
|
||||
public static double Log(this double num)
|
||||
{
|
||||
return Math.Log(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Log(double,double)"/>
|
||||
public static double Log(this double num, double newBase)
|
||||
{
|
||||
return Math.Log(num, newBase);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Log10(double)"/>
|
||||
public static double Log10(this double num)
|
||||
{
|
||||
return Math.Log10(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Pow(double,double)"/>
|
||||
public static double Pow(this double num, double power)
|
||||
{
|
||||
return Math.Pow(num, power);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(double)"/>
|
||||
public static double Round(this double num)
|
||||
{
|
||||
return Math.Round(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(double,MidpointRounding)"/>
|
||||
public static double Round(this double num, MidpointRounding mode)
|
||||
{
|
||||
return Math.Round(num, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(double,int)"/>
|
||||
public static double Round(this double num, int digits)
|
||||
{
|
||||
return Math.Round(num, digits);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Round(double,int,MidpointRounding)"/>
|
||||
public static double Round(this double num, int digits, MidpointRounding mode)
|
||||
{
|
||||
return Math.Round(num, digits, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sign(double)"/>
|
||||
public static int Sign(this double num)
|
||||
{
|
||||
return Math.Sign(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sin(double)"/>
|
||||
public static double Sin(this double num)
|
||||
{
|
||||
return Math.Sin(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sinh(double)"/>
|
||||
public static double Sinh(this double num)
|
||||
{
|
||||
return Math.Sinh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sqrt(double)"/>
|
||||
public static double Sqrt(this double num)
|
||||
{
|
||||
return Math.Sqrt(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Tan(double)"/>
|
||||
public static double Tan(this double num)
|
||||
{
|
||||
return Math.Tan(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Tanh(double)"/>
|
||||
public static double Tanh(this double num)
|
||||
{
|
||||
return Math.Tanh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Truncate(double)"/>
|
||||
public static double Truncate(this double num)
|
||||
{
|
||||
return Math.Truncate(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// IntegerFluent class
|
||||
/// </summary>
|
||||
public static class Int16Fluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static decimal ToDecimal(this short num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="float"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="float"/></returns>
|
||||
public static float ToSingle(this short num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="double"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="double"/></returns>
|
||||
public static double ToDouble(this short num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="int"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="int"/></returns>
|
||||
public static int ToInt32(this short num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="long"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="long"/></returns>
|
||||
public static long ToInt64(this short num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Add(this short num, short value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Subtract(this short num, short value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Multiply(this short num, short value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Divide(this short num, short value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Abs(short)"/>
|
||||
public static short Abs(this short num)
|
||||
{
|
||||
return Math.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(short,short,short)"/>
|
||||
public static short Clamp(this short num, short min, short max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sign(short)"/>
|
||||
public static int Sign(this short num)
|
||||
{
|
||||
return Math.Sign(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// IntegerFluent class
|
||||
/// </summary>
|
||||
public static class Int32Fluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static decimal ToDecimal(this int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="float"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="float"/></returns>
|
||||
public static float ToSingle(this int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="double"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="double"/></returns>
|
||||
public static double ToDouble(this int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="short"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="short"/></returns>
|
||||
public static short ToInt16(this int num)
|
||||
{
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="long"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="long"/></returns>
|
||||
public static long ToInt64(this int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Add(this int num, int value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Subtract(this int num, int value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Multiply(this int num, int value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int Divide(this int num, int value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Abs(int)"/>
|
||||
public static int Abs(this int num)
|
||||
{
|
||||
return Math.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(int,int,int)"/>
|
||||
public static int Clamp(this int num, int min, int max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sign(int)"/>
|
||||
public static int Sign(this int num)
|
||||
{
|
||||
return Math.Sign(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// IntegerFluent class
|
||||
/// </summary>
|
||||
public static class Int64Fluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static decimal ToDecimal(this long num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="float"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="float"/></returns>
|
||||
public static float ToSingle(this long num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="double"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="double"/></returns>
|
||||
public static double ToDouble(this long num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="short"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="short"/></returns>
|
||||
public static short ToInt16(this long num)
|
||||
{
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="int"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="int"/></returns>
|
||||
public static int ToInt32(this long num)
|
||||
{
|
||||
return (int)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static long Add(this long num, long value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static long Subtract(this long num, long value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static long Multiply(this long num, long value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static long Divide(this long num, long value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Abs(long)"/>
|
||||
public static long Abs(this long num)
|
||||
{
|
||||
return Math.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(long,long,long)"/>
|
||||
public static long Clamp(this long num, long min, long max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Sign(long)"/>
|
||||
public static long Sign(this long num)
|
||||
{
|
||||
return Math.Sign(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
namespace CuteUtils.FluentMath.TypeExtentions;
|
||||
|
||||
/// <summary>
|
||||
/// FloatFluent class
|
||||
/// </summary>
|
||||
public static class SingleFluent
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="decimal"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="decimal"/></returns>
|
||||
public static decimal ToDecimal(this float num)
|
||||
{
|
||||
return (decimal)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="double"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="double"/></returns>
|
||||
public static double ToDouble(this float num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="short"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="short"/></returns>
|
||||
public static short ToInt16(this float num)
|
||||
{
|
||||
return (short)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="int"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="int"/></returns>
|
||||
public static int ToInt32(this float num)
|
||||
{
|
||||
return (int)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts number to <see cref="long"/>
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns>Number as <see cref="long"/></returns>
|
||||
public static long ToInt64(this float num)
|
||||
{
|
||||
return (long)num;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float Add(this float num, float value)
|
||||
{
|
||||
return num + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float Subtract(this float num, float value)
|
||||
{
|
||||
return num - value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiples the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float Multiply(this float num, float value)
|
||||
{
|
||||
return num * value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the two nums
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float Divide(this float num, float value)
|
||||
{
|
||||
return num / value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Abs(float)"/>
|
||||
public static float Abs(this float num)
|
||||
{
|
||||
return MathF.Abs(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Acos(float)"/>
|
||||
public static float Acos(this float num)
|
||||
{
|
||||
return MathF.Acos(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Acosh(float)"/>
|
||||
public static float Acosh(this float num)
|
||||
{
|
||||
return MathF.Acosh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Asin(float)"/>
|
||||
public static float Asin(this float num)
|
||||
{
|
||||
return MathF.Asin(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Asinh(float)"/>
|
||||
public static float Asinh(this float num)
|
||||
{
|
||||
return MathF.Asinh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Atan(float)"/>
|
||||
public static float Atan(this float num)
|
||||
{
|
||||
return MathF.Atan(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Atan2(float,float)"/>
|
||||
public static float Atan2(this float num, float value)
|
||||
{
|
||||
return MathF.Atan2(num, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Atanh(float)"/>
|
||||
public static float Atanh(this float num)
|
||||
{
|
||||
return MathF.Atanh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Cbrt(float)"/>
|
||||
public static float Cbrt(this float num)
|
||||
{
|
||||
return MathF.Cbrt(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Ceiling(float)"/>
|
||||
public static float Ceiling(this float num)
|
||||
{
|
||||
return MathF.Ceiling(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Math.Clamp(float,float,float)"/>
|
||||
public static float Clamp(this float num, float min, float max)
|
||||
{
|
||||
return Math.Clamp(num, min, max);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Cos(float)"/>
|
||||
public static float Cos(this float num)
|
||||
{
|
||||
return MathF.Cos(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Cosh(float)"/>
|
||||
public static float Cosh(this float num)
|
||||
{
|
||||
return MathF.Cosh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Exp(float)"/>
|
||||
public static float Exp(this float num)
|
||||
{
|
||||
return MathF.Exp(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Floor(float)"/>
|
||||
public static float Floor(this float num)
|
||||
{
|
||||
return MathF.Floor(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.IEEERemainder(float,float)"/>
|
||||
public static float IEEERemainder(this float num, float value)
|
||||
{
|
||||
return MathF.IEEERemainder(num, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Log(float)"/>
|
||||
public static float Log(this float num)
|
||||
{
|
||||
return MathF.Log(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Log(float,float)"/>
|
||||
public static float Log(this float num, float newBase)
|
||||
{
|
||||
return MathF.Log(num, newBase);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Log10(float)"/>
|
||||
public static float Log10(this float num)
|
||||
{
|
||||
return MathF.Log10(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Pow(float,float)"/>
|
||||
public static float Pow(this float num, float power)
|
||||
{
|
||||
return MathF.Pow(num, power);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Round(float)"/>
|
||||
public static float Round(this float num)
|
||||
{
|
||||
return MathF.Round(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Round(float,MidpointRounding)"/>
|
||||
public static float Round(this float num, MidpointRounding mode)
|
||||
{
|
||||
return MathF.Round(num, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Round(float,int)"/>
|
||||
public static float Round(this float num, int digits)
|
||||
{
|
||||
return MathF.Round(num, digits);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Round(float,int,MidpointRounding)"/>
|
||||
public static float Round(this float num, int digits, MidpointRounding mode)
|
||||
{
|
||||
return MathF.Round(num, digits, mode);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Sign(float)"/>
|
||||
public static int Sign(this float num)
|
||||
{
|
||||
return MathF.Sign(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Sin(float)"/>
|
||||
public static float Sin(this float num)
|
||||
{
|
||||
return MathF.Sin(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Sinh(float)"/>
|
||||
public static float Sinh(this float num)
|
||||
{
|
||||
return MathF.Sinh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Sqrt(float)"/>
|
||||
public static float Sqrt(this float num)
|
||||
{
|
||||
return MathF.Sqrt(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Tan(float)"/>
|
||||
public static float Tan(this float num)
|
||||
{
|
||||
return MathF.Tan(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Tanh(float)"/>
|
||||
public static float Tanh(this float num)
|
||||
{
|
||||
return MathF.Tanh(num);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MathF.Truncate(float)"/>
|
||||
public static float Truncate(this float num)
|
||||
{
|
||||
return MathF.Truncate(num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Logging configuration.
|
||||
/// </summary>
|
||||
public class LogConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The configuration for <see cref="LogSeverity.Debug"/> messages.
|
||||
/// </summary>
|
||||
public OutputConfig DebugConfig { get; set; } = new OutputConfig();
|
||||
|
||||
/// <summary>
|
||||
/// The configuration for <see cref="LogSeverity.Info"/> messages.
|
||||
/// </summary>
|
||||
public OutputConfig InfoConfig { get; set; } = new OutputConfig();
|
||||
|
||||
/// <summary>
|
||||
/// The configuration for <see cref="LogSeverity.Warn"/> messages.
|
||||
/// </summary>
|
||||
public OutputConfig WarnConfig { get; set; } = new OutputConfig();
|
||||
|
||||
/// <summary>
|
||||
/// The configuration for <see cref="LogSeverity.Error"/> messages.
|
||||
/// </summary>
|
||||
public OutputConfig ErrorConfig { get; set; } = new OutputConfig();
|
||||
|
||||
/// <summary>
|
||||
/// The configuration for <see cref="LogSeverity.Fatal"/> messages.
|
||||
/// </summary>
|
||||
public OutputConfig FatalConfig { get; set; } = new OutputConfig();
|
||||
|
||||
/// <summary>
|
||||
/// The configuration for the message format.
|
||||
/// </summary>
|
||||
public FormatConfig FormatConfig { get; set; } = new FormatConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output configuration.
|
||||
/// </summary>
|
||||
public class OutputConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The console color of the log message.
|
||||
/// </summary>
|
||||
public ConsoleColor ConsoleColor { get; set; } = ConsoleColor.White;
|
||||
|
||||
/// <summary>
|
||||
/// The target for the log message.
|
||||
/// </summary>
|
||||
public LogTarget LogTarget { get; set; } = LogTarget.DebugConsole;
|
||||
|
||||
/// <summary>
|
||||
/// The log file path.
|
||||
/// </summary>
|
||||
public string FilePath { get; set; } = "log.log";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format configuration.
|
||||
/// </summary>
|
||||
public class FormatConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The format for the debug console.
|
||||
/// </summary>
|
||||
public LogFormatBuilder DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
|
||||
|
||||
/// <summary>
|
||||
/// The format for the console.
|
||||
/// </summary>
|
||||
public LogFormatBuilder ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
|
||||
|
||||
/// <summary>
|
||||
/// The format for the log file.
|
||||
/// </summary>
|
||||
public LogFormatBuilder FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}";
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System.Text;
|
||||
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// A builder for <see cref="FormatConfig"/>
|
||||
/// </summary>
|
||||
public class LogFormatBuilder
|
||||
{
|
||||
private readonly StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="LogFormatBuilder"/> instance.
|
||||
/// </summary>
|
||||
public LogFormatBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="LogFormatBuilder"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="value">The inital format.</param>
|
||||
public LogFormatBuilder(string value)
|
||||
{
|
||||
_ = stringBuilder.Append(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="LogFormatBuilder"/> to <see cref="string"/>
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="LogFormatBuilder"/> to convert.</param>
|
||||
public static implicit operator string(LogFormatBuilder value)
|
||||
{
|
||||
return value.stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="string"/> to <see cref="LogFormatBuilder"/>
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="stringBuilder"/> to convert.</param>
|
||||
public static implicit operator LogFormatBuilder(string value)
|
||||
{
|
||||
return new LogFormatBuilder(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends text to the log format.
|
||||
/// </summary>
|
||||
/// <param name="value">The text to append.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder Text(string value)
|
||||
{
|
||||
_ = stringBuilder.Append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the log datie time to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder DateTime(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.DateTime},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the log severity to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder LogSeverity(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.LogSeverity},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the line number to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder LineNumber(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.LineNumber},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the file path to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder FilePath(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.FilePath},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the log source to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder MemberName(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.MemberName},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the log source to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
public LogFormatBuilder Source(string format = "", int padding = 0)
|
||||
{
|
||||
_ = stringBuilder.Append($"{{{LogFormatType.Source},{padding}{GetFormat(format)}}}");
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the log message to the log format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to apply.</param>
|
||||
/// <param name="padding">The padding to apply.</param>
|
||||
/// <returns>A reference to this <see cref="LogFormatBuilder"/> instance.</returns>
|
||||
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}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the info type of the log message format.
|
||||
/// </summary>
|
||||
public static class LogFormatType
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="System.DateTime"/> of the log message.
|
||||
/// </summary>
|
||||
public const string DateTime = "<DateTime>";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LogSeverity"/> of the log message.
|
||||
/// </summary>
|
||||
public const string LogSeverity = "<LogSeverity>";
|
||||
|
||||
/// <summary>
|
||||
/// The line number of the log message.
|
||||
/// </summary>
|
||||
public const string LineNumber = "<LineNumber>";
|
||||
|
||||
/// <summary>
|
||||
/// The file path of the log message.
|
||||
/// </summary>
|
||||
public const string FilePath = "<FilePath>";
|
||||
|
||||
/// <summary>
|
||||
/// The member name of the log message.
|
||||
/// </summary>
|
||||
public const string MemberName = "<MemberName>";
|
||||
|
||||
/// <summary>
|
||||
/// The source of the log message.
|
||||
/// </summary>
|
||||
public const string Source = "<Source>";
|
||||
|
||||
/// <summary>
|
||||
/// The message of the log message.
|
||||
/// </summary>
|
||||
public const string Message = "<Message>";
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the severity of the log message.
|
||||
/// </summary>
|
||||
public enum LogSeverity
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs that contain the most detailed messages.
|
||||
/// </summary>
|
||||
Debug,
|
||||
|
||||
/// <summary>
|
||||
/// Logs that track the general flow of the application.
|
||||
/// </summary>
|
||||
Info,
|
||||
|
||||
/// <summary>
|
||||
/// Logs that highlight an abnormal activity in the flow of execution.
|
||||
/// </summary>
|
||||
Warn,
|
||||
|
||||
/// <summary>
|
||||
/// Logs that highlight when the flow of execution is stopped due to a failure.
|
||||
/// </summary>
|
||||
Error,
|
||||
|
||||
/// <summary>
|
||||
/// Logs that contain the most severe level of error. This type of error indicate that immediate attention may be required.
|
||||
/// </summary>
|
||||
Fatal
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the target of the log message.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum LogTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes log to console
|
||||
/// </summary>
|
||||
Console = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Writes log to debug console
|
||||
/// </summary>
|
||||
DebugConsole = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Writes log to file
|
||||
/// </summary>
|
||||
File = 3
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
using CuteUtils.Misc;
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace CuteUtils.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Class used for logging
|
||||
/// </summary>
|
||||
public class Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the log configuration.
|
||||
/// </summary>
|
||||
public LogConfig Config { get; init; } = new LogConfig();
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message with the specified source, log severity, and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="logSeverity">The severity level of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message with the specified log severity and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="logSeverity">The severity level of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an informational message with the specified source and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an informational message with additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
WriteLog(message, string.Empty, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message with the specified source and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message with additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
public void LogWarn(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
WriteLog(message, string.Empty, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
WriteLog(message, string.Empty, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with the specified source and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal error message with additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
public void LogFatal(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
WriteLog(message, string.Empty, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal error message with the specified source and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message with additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
public void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
WriteLog(message, string.Empty, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message with the specified source and additional caller information.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message with the specified source, log severity, and additional caller information if the condition is met.
|
||||
/// </summary>
|
||||
/// <param name="condition">The condition to check.</param>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="source">The source of the log message.</param>
|
||||
/// <param name="logSeverity">The severity level of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message with the specified log severity and additional caller information if the condition is met.
|
||||
/// </summary>
|
||||
/// <param name="condition">The condition to check.</param>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="logSeverity">The severity level of the log message.</param>
|
||||
/// <param name="memberName">The name of the calling member.</param>
|
||||
/// <param name="sourceFilePath">The path of the source file.</param>
|
||||
/// <param name="sourceLineNumber">The line number in the source file.</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the log file for the specified log severity.
|
||||
/// </summary>
|
||||
/// <param name="logSeverity">The severity level of the log messages to clear.</param>
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace CuteUtils.Misc;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="bool"/> Extensions
|
||||
/// </summary>
|
||||
public static class BoolExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets value to true if input is true. If input is false the value will not change.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="input"></param>
|
||||
public static void OneWayTrue(this ref bool value, bool input)
|
||||
{
|
||||
if (!value && input)
|
||||
{
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets value to false if input is false. If input is true the value will not change.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="input"></param>
|
||||
public static void OneWayFalse(this ref bool value, bool input)
|
||||
{
|
||||
if (value && !input)
|
||||
{
|
||||
value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts bool to int.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static int ToInt(this bool input)
|
||||
{
|
||||
return input ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts int to bool.
|
||||
/// </summary>
|
||||
/// <param name="bol"></param>
|
||||
/// <param name="input"></param>
|
||||
public static void FromInt(this ref bool bol, int input)
|
||||
{
|
||||
bol = input == 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace CuteUtils.Misc;
|
||||
|
||||
/// <summary>
|
||||
/// Table Style
|
||||
/// </summary>
|
||||
public enum TableStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// The default representation of the table
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// The minimal representation of the table
|
||||
/// </summary>
|
||||
Minimum,
|
||||
|
||||
/// <summary>
|
||||
/// The alternative representation of the table
|
||||
/// </summary>
|
||||
Alternative,
|
||||
|
||||
/// <summary>
|
||||
/// The list representation of the table
|
||||
/// </summary>
|
||||
List
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IEnumerable{T}"/> and <see cref="Array"/> Extensions
|
||||
/// </summary>
|
||||
public static class CollectionExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Prints the elements of the collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the elements in the collection.</typeparam>
|
||||
/// <param name="collection">The collection to print.</param>
|
||||
/// <param name="delimiter">The delimiter character to use between elements. Default is ','.</param>
|
||||
/// <param name="printToDebugConsole">Indicates whether to print to the debug console. Default is false.</param>
|
||||
public static void Print<T>(this IEnumerable<T> 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<T> 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++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints the elements of the 2D array in a table format.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the elements in the array.</typeparam>
|
||||
/// <param name="array">The 2D array to print.</param>
|
||||
/// <param name="tableStyle">The style of the table. Default is TableStyle.Default.</param>
|
||||
public static void PrintTable<T>(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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
#pragma warning disable S3998 // Threads should not lock on objects with weak identity
|
||||
|
||||
namespace CuteUtils.Misc;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Console"/> Extensions
|
||||
/// </summary>
|
||||
public static class ConsoleExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the specified value to the console with the specified color.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <param name="color">The color of the text.</param>
|
||||
public static void Write(object value, ConsoleColor color)
|
||||
{
|
||||
lock (Console.Out)
|
||||
{
|
||||
ConsoleColor oldColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = color;
|
||||
Console.Write(value);
|
||||
Console.ForegroundColor = oldColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified value to the console with the specified color and appends a new line.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <param name="color">The color of the text.</param>
|
||||
public static void WriteLine(object value, ConsoleColor color)
|
||||
{
|
||||
lock (Console.Out)
|
||||
{
|
||||
ConsoleColor oldColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = color;
|
||||
Console.WriteLine(value);
|
||||
Console.ForegroundColor = oldColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next line of characters from the standard input stream and tries to convert it to the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to convert the input string to.</typeparam>
|
||||
/// <returns>The input string converted to the specified type.</returns>
|
||||
/// <exception cref="NotSupportedException">Thrown if the conversion is not supported.</exception>
|
||||
public static T ReadLine<T>()
|
||||
{
|
||||
string attemptedValue = Console.ReadLine() ?? string.Empty;
|
||||
Type type = typeof(T);
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(type);
|
||||
|
||||
return (T)converter.ConvertFromString(attemptedValue)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next line of characters from the standard input stream and tries to convert it to the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to convert the input string to.</typeparam>
|
||||
/// <param name="input">The input string converted to the specified type.</param>
|
||||
/// <returns><see langword="true"/> if the conversion was successful. Otherwise <see langword="false"/>.</returns>
|
||||
public static bool TryReadLine<T>([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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to convert the input character to.</typeparam>
|
||||
/// <returns>The input character converted to the specified type.</returns>
|
||||
/// <exception cref="NotSupportedException">Thrown if the conversion is not supported.</exception>
|
||||
public static T ReadKey<T>()
|
||||
{
|
||||
string attemptedValue = Console.ReadKey().KeyChar.ToString();
|
||||
Type type = typeof(T);
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(type);
|
||||
|
||||
return (T)converter.ConvertFromString(attemptedValue)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="input">The input character converted to the specified type.</param>
|
||||
/// <typeparam name="T">The type to convert the input character to.</typeparam>
|
||||
/// <returns><see langword="true"/> if the conversion was successful. Otherwise <see langword="false"/>.</returns>
|
||||
public static bool TryReadKey<T>([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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends execution of the current method until the user presses a key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key that has to be pressed.</param>
|
||||
/// <param name="message">The message that will be displayed.</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends execution of the current method until the user presses a key.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that will be displayed.</param>
|
||||
public static void Pause(string message = "Press any key to continue...")
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
_ = Console.ReadKey(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
namespace CuteUtils.Misc;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Random"/> Extensions
|
||||
/// </summary>
|
||||
public static class RandomExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a random item from the specified enumerable.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items in the enumerable.</typeparam>
|
||||
/// <param name="random">The random number generator.</param>
|
||||
/// <param name="enumerable">The enumerable to select a random item from.</param>
|
||||
/// <returns>A random item from the enumerable.</returns>
|
||||
public static T NextItem<T>(this Random random, IEnumerable<T> enumerable)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(enumerable);
|
||||
|
||||
return enumerable.ElementAt(random.Next(enumerable.Count()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random boolean value.
|
||||
/// </summary>
|
||||
/// <param name="random">The random number generator.</param>
|
||||
/// <returns>A random boolean value.</returns>
|
||||
public static bool NextBool(this Random random)
|
||||
{
|
||||
return random.Next(2) == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random value from the specified enum type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="random">The random number generator.</param>
|
||||
/// <returns>A random value from the enum type.</returns>
|
||||
public static T NextEnum<T>(this Random random) where T : struct, Enum
|
||||
{
|
||||
T[] values = Enum.GetValues<T>();
|
||||
return values[random.Next(values.Length)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random value from the specified array of enum values.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="random">The random number generator.</param>
|
||||
/// <param name="values">The array of enum values.</param>
|
||||
/// <returns>A random value from the array of enum values.</returns>
|
||||
public static T NextEnum<T>(this Random random, T[] values) where T : struct, Enum
|
||||
{
|
||||
return values[random.Next(values.Length)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
using System.Dynamic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CuteUtils.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Provides utility methods for converting objects to and from dynamic DTOs.
|
||||
/// </summary>
|
||||
public static class DynDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an object to a dynamic DTO.
|
||||
/// </summary>
|
||||
/// <param name="data">The object to convert.</param>
|
||||
/// <returns>The dynamic DTO.</returns>
|
||||
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<DynDtoNameAttribute>();
|
||||
|
||||
if (dynDtoNameAttribute is not null)
|
||||
{
|
||||
_ = dto.TryAdd(dynDtoNameAttribute.Name, property.GetValue(data));
|
||||
}
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an object to a specified type of DTO.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of DTO.</typeparam>
|
||||
/// <param name="data">The object to convert.</param>
|
||||
/// <param name="dto">The DTO instance to populate.</param>
|
||||
/// <returns>The populated DTO.</returns>
|
||||
public static T ToDto<T>(this object data, T dto)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(dto);
|
||||
|
||||
PropertyInfo[] dataProperties = data.GetType().GetProperties();
|
||||
PropertyInfo[] dtoProperties = dto.GetType().GetProperties();
|
||||
|
||||
foreach (PropertyInfo dataProperty in dataProperties)
|
||||
{
|
||||
DynDtoNameAttribute? dynDtoNameAttribute = dataProperty.GetCustomAttribute<DynDtoNameAttribute>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an object to a new instance of a specified type of DTO.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of DTO.</typeparam>
|
||||
/// <param name="data">The object to convert.</param>
|
||||
/// <returns>The new instance of the DTO.</returns>
|
||||
public static T ToDto<T>(this object data) where T : new()
|
||||
{
|
||||
return ToDto(data, new T());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dynamic DTO to an object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object.</typeparam>
|
||||
/// <param name="dto">The dynamic DTO.</param>
|
||||
/// <param name="data">The object instance to populate.</param>
|
||||
/// <returns>The populated object.</returns>
|
||||
public static T FromDto<T>(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<DynDtoNameAttribute>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dynamic DTO to an object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object.</typeparam>
|
||||
/// <param name="dto">The dynamic DTO.</param>
|
||||
/// <param name="data">The new instance of the object.</param>
|
||||
/// <returns>The populated object.</returns>
|
||||
public static T FromDto<T>(this ExpandoObject dto, T data)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(dto);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
IDictionary<string, object> dtoProperties = dto!;
|
||||
|
||||
PropertyInfo[] dataProperties = data.GetType().GetProperties();
|
||||
|
||||
foreach (PropertyInfo property in dataProperties)
|
||||
{
|
||||
DynDtoNameAttribute? dynDtoNameAttribute = property.GetCustomAttribute<DynDtoNameAttribute>();
|
||||
if (dynDtoNameAttribute is not null && dtoProperties.TryGetValue(dynDtoNameAttribute.Name, out object? value))
|
||||
{
|
||||
property.SetValue(data, value);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dynamic DTO to a new instance of an object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object.</typeparam>
|
||||
/// <param name="dto">The dynamic DTO.</param>
|
||||
/// <returns>The new instance of the object.</returns>
|
||||
public static T FromDto<T>(this object dto) where T : new()
|
||||
{
|
||||
return FromDto(dto, new T());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dynamic DTO to a new instance of an object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object.</typeparam>
|
||||
/// <param name="dto">The dynamic DTO.</param>
|
||||
/// <returns>The new instance of the object.</returns>
|
||||
public static T FromDto<T>(this ExpandoObject dto) where T : new()
|
||||
{
|
||||
return FromDto(dto, new T());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace CuteUtils.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an attribute that specifies the dynamic DTO name for a property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="DynDtoNameAttribute"/> class with the specified name.
|
||||
/// </remarks>
|
||||
/// <param name="name">The dynamic DTO name.</param>
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class DynDtoNameAttribute(string name) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the dynamic DTO name.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = name;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace CuteUtils.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for reflection operations.
|
||||
/// </summary>
|
||||
public static class ReflectionExtentions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the specified type and copies the properties from the source object to the new instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the new instance.</typeparam>
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <returns>A new instance of the specified type with copied properties.</returns>
|
||||
public static T CopyProperties<T>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the properties from the source object to the specified target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the target object.</typeparam>
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <param name="newObj">The target object.</param>
|
||||
/// <returns>The target object with copied properties.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when the target object is null.</exception>
|
||||
public static T CopyProperties<T>(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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace CuteUtils;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="string"/> Extensions
|
||||
/// </summary>
|
||||
public static class StringExt
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes all invalid chars from the specified <see cref="string"/>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="allowSpaces"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all invalid chars from the specified <see cref="string"/>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="allowSpaces"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Truncates a <see cref="string"/> to the specified length.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static string Truncate(this string str, int length)
|
||||
{
|
||||
if (str.Length > length && length > 0)
|
||||
{
|
||||
return str[..length];
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Truncates a <see cref="string"/> to the specified length.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="ellipsis"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the correct newline <see cref="string"/> defined for this environment.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all white spaces from the specified <see cref="string"/>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverses the specified <see cref="string"/>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string Reverse(this string str)
|
||||
{
|
||||
char[] array = str.ToCharArray();
|
||||
Array.Reverse(array);
|
||||
return new string(array);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
namespace CuteUtils.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a blocking task queue that allows enqueueing tasks and functions.
|
||||
/// </summary>
|
||||
public class BlockingTaskQueue
|
||||
{
|
||||
private readonly SemaphoreSlim semaphore;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BlockingTaskQueue"/> class.
|
||||
/// </summary>
|
||||
public BlockingTaskQueue()
|
||||
{
|
||||
semaphore = new SemaphoreSlim(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task that returns a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the return value.</typeparam>
|
||||
/// <param name="function">The function to execute.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task<T> Enqueue<T>(Func<T> function)
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
return await Task.Run(function);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task that does not return a value.
|
||||
/// </summary>
|
||||
/// <param name="function">The action to execute.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task Enqueue(Action function)
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
await Task.Run(function);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task.
|
||||
/// </summary>
|
||||
/// <param name="task">The task to enqueue.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task Enqueue(Task task)
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task that returns a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the return value.</typeparam>
|
||||
/// <param name="task">The task to enqueue.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task<T> Enqueue<T>(Task<T> task)
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
return await task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = semaphore.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
|
||||
namespace CuteUtils.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a queue of tasks that can be enqueued and processed asynchronously.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task that returns a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value returned by the task.</typeparam>
|
||||
/// <param name="function">The function representing the task.</param>
|
||||
/// <returns>An observable that emits the task when it completes.</returns>
|
||||
public IObservable<Task<T>> Enqueue<T>(Func<T> function)
|
||||
{
|
||||
Subject<Task<T>> subject = new Subject<Task<T>>();
|
||||
Task<T> task = new Task<T>(function);
|
||||
|
||||
tasks.Add((task, () => subject.OnNext(task)));
|
||||
|
||||
ProcessTasks();
|
||||
|
||||
return subject.AsObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a task that does not return a value.
|
||||
/// </summary>
|
||||
/// <param name="function">The action representing the task.</param>
|
||||
/// <returns>An observable that emits the task when it completes.</returns>
|
||||
public IObservable<Task> Enqueue(Action function)
|
||||
{
|
||||
Subject<Task> subject = new Subject<Task>();
|
||||
Task task = new Task(function);
|
||||
|
||||
tasks.Add((task, () => subject.OnNext(task)));
|
||||
|
||||
ProcessTasks();
|
||||
|
||||
return subject.AsObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a pre-created task.
|
||||
/// </summary>
|
||||
/// <param name="task">The task to enqueue.</param>
|
||||
/// <returns>An observable that emits the task when it completes.</returns>
|
||||
public IObservable<Task> Enqueue(Task task)
|
||||
{
|
||||
Subject<Task> subject = new Subject<Task>();
|
||||
|
||||
tasks.Add((task, () => subject.OnNext(task)));
|
||||
|
||||
ProcessTasks();
|
||||
|
||||
return subject.AsObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a pre-created task that returns a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value returned by the task.</typeparam>
|
||||
/// <param name="task">The task to enqueue.</param>
|
||||
/// <returns>An observable that emits the task when it completes.</returns>
|
||||
public IObservable<Task<T>> Enqueue<T>(Task<T> task)
|
||||
{
|
||||
Subject<Task<T>> subject = new Subject<Task<T>>();
|
||||
|
||||
tasks.Add((task, () => subject.OnNext(task)));
|
||||
|
||||
ProcessTasks();
|
||||
|
||||
return subject.AsObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the task queue and cancels any pending tasks.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IDisposable.Dispose"/>
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user