From 7b6115da214af2a0477c73450fdb6e3946abcd6b Mon Sep 17 00:00:00 2001 From: "Nuno \"Omega Leo\" Diogo" Date: Tue, 18 Feb 2025 21:09:25 +0000 Subject: [PATCH] Dev changes (#3) * Fixed dependency * Updates to NeoDictionary * Changes to NeoDictionary * Started working on a Git implementation to integrate into Game Engines in the future * Added commit functionality to the git library * New changes * Added select for NeoDictionary.cs * Fixed issue with previous new method * Added a Benchmarking Tool to be used mostly in game engines * Added IndexOf to NeoDictionary.cs * Added new method for BenchmarkUtility.cs * added an instacedobject class * Added a new shuffle method for lists * fixed return type * Added new Changelog generator --- .github/workflows/changelog.yml | 44 ++++++ .github/workflows/nuget-publish.yml | 26 +++- .../Attributes/ChangelogAttribute.cs | 18 +++ OmegaLeo.HelperLib.Changelog/CHANGELOG.md | 7 + .../Models/Changelog.cs | 14 ++ .../OmegaLeo.HelperLib.Changelog.csproj | 9 ++ .../Tools/ChangelogTool.cs | 63 +++++++++ ...OmegaLeo.HelperLib.ChangelogHandler.csproj | 15 ++ .../Program.cs | 42 ++++++ .../OmegaLeo.HelperLib.ConsoleApp.csproj | 16 +++ OmegaLeo.HelperLib.ConsoleApp/Program.cs | 102 ++++++++++++++ OmegaLeo.HelperLib.ConsoleApp/TestClass.cs | 10 ++ OmegaLeo.HelperLib.Git/GitClient.cs | 130 ++++++++++++++++++ OmegaLeo.HelperLib.Git/Models/ChangeFolder.cs | 56 ++++++++ .../OmegaLeo.HelperLib.Git.csproj | 23 ++++ OmegaLeo.HelperLib.sln | 24 ++++ OmegaLeo.HelperLib.sln.DotSettings.user | 5 + OmegaLeo.HelperLib/CHANGELOG.md | 2 + .../Extensions/IListExtensions.cs | 30 +++- .../Helpers/BenchmarkUtility.cs | 89 ++++++++++++ OmegaLeo.HelperLib/Models/InstancedObject.cs | 31 +++++ OmegaLeo.HelperLib/Models/NeoDictionary.cs | 6 + 22 files changed, 759 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/changelog.yml create mode 100644 OmegaLeo.HelperLib.Changelog/Attributes/ChangelogAttribute.cs create mode 100644 OmegaLeo.HelperLib.Changelog/CHANGELOG.md create mode 100644 OmegaLeo.HelperLib.Changelog/Models/Changelog.cs create mode 100644 OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj create mode 100644 OmegaLeo.HelperLib.Changelog/Tools/ChangelogTool.cs create mode 100644 OmegaLeo.HelperLib.ChangelogHandler/OmegaLeo.HelperLib.ChangelogHandler.csproj create mode 100644 OmegaLeo.HelperLib.ChangelogHandler/Program.cs create mode 100644 OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj create mode 100644 OmegaLeo.HelperLib.ConsoleApp/Program.cs create mode 100644 OmegaLeo.HelperLib.ConsoleApp/TestClass.cs create mode 100644 OmegaLeo.HelperLib.Git/GitClient.cs create mode 100644 OmegaLeo.HelperLib.Git/Models/ChangeFolder.cs create mode 100644 OmegaLeo.HelperLib.Git/OmegaLeo.HelperLib.Git.csproj create mode 100644 OmegaLeo.HelperLib.sln.DotSettings.user create mode 100644 OmegaLeo.HelperLib/CHANGELOG.md create mode 100644 OmegaLeo.HelperLib/Helpers/BenchmarkUtility.cs create mode 100644 OmegaLeo.HelperLib/Models/InstancedObject.cs diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..08fdadc --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,44 @@ +name: Create Tag +on: + workflow_dispatch: + inputs: + tagName: + description: 'Tag name:' + type: string + required: true +jobs: + generate_changelog: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + token: ${{ secrets.TOKEN }} + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '7.0.x' + - name: Update Project Versions + run: sed -i "s/\(\([0-9]\+\.\)\{2\}\)\([0-9]\+\)/\1${{github.event.inputs.tagName}}/" "./OmegaLeo.HelperLib/OmegaLeo.HelperLib.csproj" + - name: Update Project Versions + run: sed -i "s/\(\([0-9]\+\.\)\{2\}\)\([0-9]\+\)/\1${{github.event.inputs.tagName}}/" "./OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj" + - name: Build and Run Changelog Generator + run: dotnet run --project "./OmegaLeo.HelperLib.ChangelogHandler/OmegaLeo.HelperLib.ChangelogHandler.csproj" + env: + UNITYFLOW_SECRET: ${{ secrets.TOKEN }} + - name: Create Tag + run: | + git config --local user.email "nunodiogo@omegaleo.pt" + git config --local user.name "Nuno Diogo" + git add . + git commit -m "Automatically generated changelog for v${{github.event.inputs.tagName}}" + git tag -a "${{ github.event.inputs.tagName }}" -m "Release ${{ github.event.inputs.tagName }}" + git push origin "${{ github.event.inputs.tagName }}" + - name: Create Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: '${{ github.event.inputs.tagName }}' + release_name: 'Release v${{ github.event.inputs.tagName }}' \ No newline at end of file diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 72fd518..b81fe7f 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -16,7 +16,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.TOKEN }} outputs: upload_url: ${{ steps.get_release.outputs.upload_url }} - publish_doc_helper: + publish-helper-lib: runs-on: ubuntu-latest needs: [get-release] steps: @@ -40,3 +40,27 @@ jobs: asset_path: ./OmegaLeo.HelperLib/bin/Release/OmegaLeo.HelperLib.${{ github.event.release.tag_name }}.nupkg asset_name: OmegaLeo.HelperLib.${{ github.event.release.tag_name }}.nupkg asset_content_type: application/zip + publish-changelog-lib: + runs-on: ubuntu-latest + needs: [ get-release ] + steps: + - uses: actions/checkout@v2 + - name: Setup .Net Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '7.0.x' + - name: Update Project Version + run: sed -i "s/\(\([0-9]\+\.\)\{2\}\)\([0-9]\+\)/\1${{ github.event.release.tag_name }}/" "./OmegaLeo.HelperLib/OmegaLeo.HelperLib.Changelog.csproj" + - name: Create Nuget Package + run: dotnet pack "./OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj" -c Release /p:Version=${{ github.event.release.tag_name }} /p:PackageReleaseNotes="See https://github.com/omegaleo/OmegaLeo.HelperLib/releases/tag/${{ github.event.release.tag_name }}" + - name: Publish Nuget Package + run: dotnet nuget push ./OmegaLeo.HelperLib.Changelog/bin/Release/OmegaLeo.HelperLib.Changelog.${{ github.event.release.tag_name }}.nupkg --api-key ${{ secrets.nuget_api_key }} --source https://api.nuget.org/v3/index.json --skip-duplicate + - name: Upload assets to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.TOKEN }} + with: + upload_url: ${{ needs.get-release.outputs.upload_url }} + asset_path: ./OmegaLeo.HelperLib/bin/Release/OmegaLeo.HelperLib.Changelog.${{ github.event.release.tag_name }}.nupkg + asset_name: OmegaLeo.HelperLib.Changelog.${{ github.event.release.tag_name }}.nupkg + asset_content_type: application/zip \ No newline at end of file diff --git a/OmegaLeo.HelperLib.Changelog/Attributes/ChangelogAttribute.cs b/OmegaLeo.HelperLib.Changelog/Attributes/ChangelogAttribute.cs new file mode 100644 index 0000000..e66633b --- /dev/null +++ b/OmegaLeo.HelperLib.Changelog/Attributes/ChangelogAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace OmegaLeo.HelperLib.Changelog.Attributes +{ + [Changelog("v1.0.0", "Created ChangelogAttribute to be used to register changes in the code.")] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] + public class ChangelogAttribute : Attribute + { + public string Version { get; } + public string Description { get; } + + public ChangelogAttribute(string version, string description) + { + Version = version; + Description = description; + } + } +} diff --git a/OmegaLeo.HelperLib.Changelog/CHANGELOG.md b/OmegaLeo.HelperLib.Changelog/CHANGELOG.md new file mode 100644 index 0000000..d853d46 --- /dev/null +++ b/OmegaLeo.HelperLib.Changelog/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## Version v1.0.0 + +- **Class: ChangelogTool**: Created the class ChangelogTool to extract changelogs via attributes +- **Class: ChangelogAttribute**: Created ChangelogAttribute to be used to register changes in the code. + diff --git a/OmegaLeo.HelperLib.Changelog/Models/Changelog.cs b/OmegaLeo.HelperLib.Changelog/Models/Changelog.cs new file mode 100644 index 0000000..3bb4848 --- /dev/null +++ b/OmegaLeo.HelperLib.Changelog/Models/Changelog.cs @@ -0,0 +1,14 @@ +namespace OmegaLeo.HelperLib.Changelog.Models +{ + public class Changelog + { + public string Target; + public string Description; + + public Changelog(string target, string description) + { + Target = target; + Description = description; + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj b/OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj new file mode 100644 index 0000000..30b770a --- /dev/null +++ b/OmegaLeo.HelperLib.Changelog/OmegaLeo.HelperLib.Changelog.csproj @@ -0,0 +1,9 @@ + + + + netstandard2.1 + enable + enable + + + diff --git a/OmegaLeo.HelperLib.Changelog/Tools/ChangelogTool.cs b/OmegaLeo.HelperLib.Changelog/Tools/ChangelogTool.cs new file mode 100644 index 0000000..fcc33ce --- /dev/null +++ b/OmegaLeo.HelperLib.Changelog/Tools/ChangelogTool.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using OmegaLeo.HelperLib.Changelog.Attributes; + +namespace OmegaLeo.HelperLib.Changelog.Tools +{ + [Changelog("v1.0.0", "Created the class ChangelogTool to extract changelogs via attributes")] + public class ChangelogTool + { + public static Dictionary> ExtractChangelog(Assembly assembly) + { + var changelogByVersion = new Dictionary>(); + + foreach (var type in assembly.GetTypes()) + { + foreach (var attr in type.GetCustomAttributes()) + { + AddChangelogEntry(changelogByVersion, attr.Version, $"Class: {type.Name}", attr.Description); + } + + foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) + { + foreach (var attr in method.GetCustomAttributes()) + AddChangelogEntry(changelogByVersion, attr.Version, $"Method: {type.Name}.{method.Name}()", attr.Description); + } + } + + changelogByVersion = new Dictionary>(changelogByVersion.OrderByDescending(x => x.Key)); + + return changelogByVersion; + } + + public static string GetMarkdown(Assembly assembly) + { + var changelog = ExtractChangelog(assembly); + + var sb = new StringBuilder(); + + sb.AppendLine("# Changelog\n"); + foreach (var version in changelog) + { + sb.AppendLine($"## Version {version.Key}\n"); + foreach (var entry in version.Value) + { + sb.AppendLine($"- **{entry.Target}**: {entry.Description}"); + } + sb.AppendLine(); + } + + return sb.ToString(); + } + + private static void AddChangelogEntry(Dictionary> changelog, string version, string target, string description) + { + if (!changelog.ContainsKey(version)) + changelog[version] = new List(); + + changelog[version].Add(new Models.Changelog(target, description)); + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.ChangelogHandler/OmegaLeo.HelperLib.ChangelogHandler.csproj b/OmegaLeo.HelperLib.ChangelogHandler/OmegaLeo.HelperLib.ChangelogHandler.csproj new file mode 100644 index 0000000..649c15b --- /dev/null +++ b/OmegaLeo.HelperLib.ChangelogHandler/OmegaLeo.HelperLib.ChangelogHandler.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + diff --git a/OmegaLeo.HelperLib.ChangelogHandler/Program.cs b/OmegaLeo.HelperLib.ChangelogHandler/Program.cs new file mode 100644 index 0000000..a2538a7 --- /dev/null +++ b/OmegaLeo.HelperLib.ChangelogHandler/Program.cs @@ -0,0 +1,42 @@ +// See https://aka.ms/new-console-template for more information + +using System.Reflection; +using GameDevLibrary.Helpers; +using OmegaLeo.HelperLib.Changelog.Models; +using OmegaLeo.HelperLib.Changelog.Tools; + +var root = GetSolutionRoot(); + +var changelogs = new Dictionary() +{ + {Path.Join(root, "OmegaLeo.HelperLib.Changelog", "CHANGELOG.md"), typeof(Changelog).Assembly}, + {Path.Join(root, "OmegaLeo.HelperLib", "CHANGELOG.md"), typeof(BenchmarkUtility).Assembly}, +}; + +foreach (var changelog in changelogs) +{ + GenerateChangelog(changelog.Key, changelog.Value); +} + + +void GenerateChangelog(string path, Assembly libraryAssembly) +{ + var changelogMarkdown = ChangelogTool.GetMarkdown(libraryAssembly); + + File.WriteAllText(path,changelogMarkdown); +} + +static string GetSolutionRoot() +{ + string dir = AppContext.BaseDirectory; + + while (!string.IsNullOrEmpty(dir)) + { + if (Directory.GetFiles(dir, "*.sln").Length > 0) + return dir; // Found the solution root + + dir = Directory.GetParent(dir)?.FullName; // Move up a directory + } + + throw new Exception("Solution root not found."); +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj b/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj new file mode 100644 index 0000000..ca1ddff --- /dev/null +++ b/OmegaLeo.HelperLib.ConsoleApp/OmegaLeo.HelperLib.ConsoleApp.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + diff --git a/OmegaLeo.HelperLib.ConsoleApp/Program.cs b/OmegaLeo.HelperLib.ConsoleApp/Program.cs new file mode 100644 index 0000000..d4f2ccc --- /dev/null +++ b/OmegaLeo.HelperLib.ConsoleApp/Program.cs @@ -0,0 +1,102 @@ +// See https://aka.ms/new-console-template for more information + +// /media/omegaleo/Development/Library Dev/HelperLib + +using System.Reflection; +using GameDevLibrary.Extensions; +using GameDevLibrary.Helpers; +using LibGit2Sharp; +using OmegaLeo.HelperLib.Changelog.Tools; +using OmegaLeo.HelperLib.Git; +using OmegaLeo.HelperLib.Git.Models; + +Console.WriteLine("Insert repo path to check changes:"); +var repo = Console.ReadLine(); + +if (repo.IsNullOrEmpty()) +{ + repo = "/media/omegaleo/Development/Library Dev/HelperLib"; +} + +var git = new GitClient(repo); + +var result = BenchmarkUtility.Record(() => +{ + var changes = git.GetChanges(); + + if (changes.FolderName.IsNotNullOrEmpty()) + { + RecursiveOutput(new List() { changes }); + + var option = 99; + + while (option != 0) + { + ShowOptions(); + if (option != 99) + { + switch (option) + { + case 1: + Console.WriteLine("Write the commit message"); + var msg = Console.ReadLine(); + + while (msg.IsNullOrEmpty()) + { + Console.WriteLine("Empty message detected, please write a commit message..."); + msg = Console.ReadLine(); + } + + var signature = new Signature("Nuno 'Omega Leo' Diogo", "nunodiogo@omegaleo.pt", + DateTimeOffset.Now); + git.Commit(msg, signature); + + break; + case 2: + git.Push(); + break; + default: + Console.WriteLine("Invalid Option!"); + break; + } + } + + int.TryParse(Console.ReadLine(), out option); + } + } + else + { + Console.WriteLine("No changes found in specified repository"); + } +}); + +Console.WriteLine($"Time for checking for changes: {result} ms"); + +Console.ReadLine(); + + +void RecursiveOutput(List folders, int depth = 0) +{ + foreach (var folder in folders) + { + Console.WriteLine($"{new string('\t', depth)}>{folder.FolderName}"); + if (folder.SubFolders.Any()) + { + RecursiveOutput(folder.SubFolders, depth + 1); + } + + foreach (var change in folder.ChangesInFolder) + { + Console.WriteLine($"{new string('\t', depth + 1)}>{Path.GetFileName(change.Path)} ({change.Status})"); + } + } +} + +void ShowOptions() +{ + Console.Clear(); + Console.WriteLine(new string('=', 20)); + Console.WriteLine("What do you want to do in this repository?"); + Console.WriteLine("1. Commit all changes"); + Console.WriteLine("2. Push"); +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.ConsoleApp/TestClass.cs b/OmegaLeo.HelperLib.ConsoleApp/TestClass.cs new file mode 100644 index 0000000..65d9104 --- /dev/null +++ b/OmegaLeo.HelperLib.ConsoleApp/TestClass.cs @@ -0,0 +1,10 @@ +using OmegaLeo.HelperLib.Changelog.Attributes; + +namespace OmegaLeo.HelperLib.ConsoleApp; + +[Changelog("v1.0.0", "Test")] +[Changelog("v1.0.1", "Test 1")] +public class TestClass +{ + +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.Git/GitClient.cs b/OmegaLeo.HelperLib.Git/GitClient.cs new file mode 100644 index 0000000..ac12680 --- /dev/null +++ b/OmegaLeo.HelperLib.Git/GitClient.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using GameDevLibrary.Extensions; +using LibGit2Sharp; +using OmegaLeo.HelperLib.Git.Models; + +namespace OmegaLeo.HelperLib.Git +{ + public class GitClient + { + private Repository _repo; + + public GitClient(string path) + { + if (path.IsNullOrEmpty()) + { + path = AppDomain.CurrentDomain.BaseDirectory; + } + + _repo = new Repository(path); + } + + public void CheckoutBranch(string branchName) + { + var branch = _repo.Branches[branchName]; + + if (branch == null) + { + branch = _repo.CreateBranch(branchName); + } + + Commands.Checkout(_repo, branch); + } + + public bool HasChanges() => _repo.Diff.Compare().Count > 0; + + public ChangeFolder GetChanges() + { + var folder = new ChangeFolder(); + + if (HasChanges()) + { + var changes = _repo.Diff.Compare(); + + var allChanges = new List(); + allChanges.AddRange(changes.Added); + allChanges.AddRange(changes.Modified); + allChanges.AddRange(changes.Deleted); + + var uniqueFolderPaths = allChanges.Select(x => Path.GetDirectoryName(x.Path)).Distinct(); + + foreach (var path in uniqueFolderPaths) + { + if (path.IsNullOrEmpty()) continue; + + if (path.Contains(Path.DirectorySeparatorChar)) + { + var paths = path.Split(Path.DirectorySeparatorChar); + + for (var i = 0; i < paths.Length; i++) + { + var p = paths[i]; + + if (folder.FolderName.Equals(p)) + { + if (folder.ChangesInFolder.Any()) continue; + + folder.ChangesInFolder = + allChanges.Where(x => Path.GetDirectoryName(x.Path)!.Equals(p, StringComparison.OrdinalIgnoreCase)); + } + else + { + var pathList = paths[0..(i+1)].ToList(); + var subFolder = folder.RecursiveGet(pathList); + var fullPath = string.Join(Path.DirectorySeparatorChar, pathList); + + if (!subFolder.ChangesInFolder.Any()) + { + subFolder.ChangesInFolder = allChanges.Where(x => + Path.GetDirectoryName(x.Path)!.Equals(fullPath, StringComparison.OrdinalIgnoreCase)); + } + } + } + } + else + { + folder.FolderName = path; + folder.ChangesInFolder = + allChanges.Where(x => Path.GetDirectoryName(x.Path)!.Equals(path, StringComparison.OrdinalIgnoreCase)); + } + } + } + + return folder; + } + + public void Commit(string message, Signature author) + { + if (HasChanges()) + { + var changes = _repo.Diff.Compare(); + var allChanges = new List(); + allChanges.AddRange(changes.Added); + allChanges.AddRange(changes.Modified); + allChanges.AddRange(changes.Deleted); + + var filePaths = allChanges.Select(x => x.Path).Where(x => x.IsNotNullOrEmpty()); + + Commands.Stage(_repo, filePaths); + } + + _repo.Commit(message, author, author); + } + + public void Push() + { + try { + var remote = _repo.Network.Remotes["origin"]; + var options = new PushOptions(); + var pushRefSpec = @"refs/heads/master"; + _repo.Network.Push(remote, new string[] {pushRefSpec}, options); + } + catch (Exception e) { + Console.WriteLine("Exception:RepoActions:PushChanges " + e.Message); + } + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.Git/Models/ChangeFolder.cs b/OmegaLeo.HelperLib.Git/Models/ChangeFolder.cs new file mode 100644 index 0000000..ecb9c71 --- /dev/null +++ b/OmegaLeo.HelperLib.Git/Models/ChangeFolder.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using LibGit2Sharp; + +namespace OmegaLeo.HelperLib.Git.Models +{ + public class ChangeFolder + { + public string FolderName { get; set; } + public List SubFolders { get; set; } + public IEnumerable ChangesInFolder { get; set; } + + public ChangeFolder() + { + FolderName = ""; + SubFolders = new List(); + ChangesInFolder = new List(); + } + + public ChangeFolder RecursiveGet(List paths) + { + if (!paths.Any()) return null; + + var tempPaths = paths; + var pathToCheck = tempPaths.FirstOrDefault(); + + ChangeFolder folder = new ChangeFolder(); + + if (FolderName.Equals(pathToCheck, StringComparison.OrdinalIgnoreCase)) + { + folder = this; + } + else if (SubFolders.Any(x => x.FolderName.Equals(pathToCheck))) + { + folder = SubFolders.FirstOrDefault(x => x.FolderName.Equals(pathToCheck))!; + } + else + { + folder.FolderName = pathToCheck; + SubFolders.Add(folder); + } + + tempPaths.RemoveAt(0); + + if (tempPaths.Any()) + { + return folder.RecursiveGet(tempPaths); + } + else + { + return folder; + } + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib.Git/OmegaLeo.HelperLib.Git.csproj b/OmegaLeo.HelperLib.Git/OmegaLeo.HelperLib.Git.csproj new file mode 100644 index 0000000..c149dcf --- /dev/null +++ b/OmegaLeo.HelperLib.Git/OmegaLeo.HelperLib.Git.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.1 + enable + GameDevLibrary.Git + 0.0.2 + Omega Leo's Helper Library - LibGit2Sharp Implementation + Nuno "Omega Leo" Diogo + https://github.com/omegaleo/HelperLib + https://github.com/omegaleo/HelperLib + + + + + + + + + + + + diff --git a/OmegaLeo.HelperLib.sln b/OmegaLeo.HelperLib.sln index 9e6e5fc..c73f60a 100644 --- a/OmegaLeo.HelperLib.sln +++ b/OmegaLeo.HelperLib.sln @@ -2,6 +2,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib", "OmegaLeo.HelperLib\OmegaLeo.HelperLib.csproj", "{A7256931-5D66-46FA-BA50-22B2FA4CD9E9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.Git", "OmegaLeo.HelperLib.Git\OmegaLeo.HelperLib.Git.csproj", "{A9579FFB-9A05-4EBF-B298-513C48FB0F91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.ConsoleApp", "OmegaLeo.HelperLib.ConsoleApp\OmegaLeo.HelperLib.ConsoleApp.csproj", "{3B77B177-FD47-470A-B0EF-01EF8B30CE09}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.Changelog", "OmegaLeo.HelperLib.Changelog\OmegaLeo.HelperLib.Changelog.csproj", "{378D8125-66B5-42B8-9881-33F951E5E04A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmegaLeo.HelperLib.ChangelogHandler", "OmegaLeo.HelperLib.ChangelogHandler\OmegaLeo.HelperLib.ChangelogHandler.csproj", "{359536F7-02DE-43E9-A383-D83853227B0F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +20,21 @@ Global {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7256931-5D66-46FA-BA50-22B2FA4CD9E9}.Release|Any CPU.Build.0 = Release|Any CPU + {A9579FFB-9A05-4EBF-B298-513C48FB0F91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9579FFB-9A05-4EBF-B298-513C48FB0F91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9579FFB-9A05-4EBF-B298-513C48FB0F91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9579FFB-9A05-4EBF-B298-513C48FB0F91}.Release|Any CPU.Build.0 = Release|Any CPU + {3B77B177-FD47-470A-B0EF-01EF8B30CE09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B77B177-FD47-470A-B0EF-01EF8B30CE09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B77B177-FD47-470A-B0EF-01EF8B30CE09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B77B177-FD47-470A-B0EF-01EF8B30CE09}.Release|Any CPU.Build.0 = Release|Any CPU + {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {378D8125-66B5-42B8-9881-33F951E5E04A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {378D8125-66B5-42B8-9881-33F951E5E04A}.Release|Any CPU.Build.0 = Release|Any CPU + {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {359536F7-02DE-43E9-A383-D83853227B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {359536F7-02DE-43E9-A383-D83853227B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {359536F7-02DE-43E9-A383-D83853227B0F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/OmegaLeo.HelperLib.sln.DotSettings.user b/OmegaLeo.HelperLib.sln.DotSettings.user new file mode 100644 index 0000000..28e7949 --- /dev/null +++ b/OmegaLeo.HelperLib.sln.DotSettings.user @@ -0,0 +1,5 @@ + + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded \ No newline at end of file diff --git a/OmegaLeo.HelperLib/CHANGELOG.md b/OmegaLeo.HelperLib/CHANGELOG.md new file mode 100644 index 0000000..4dc68c6 --- /dev/null +++ b/OmegaLeo.HelperLib/CHANGELOG.md @@ -0,0 +1,2 @@ +# Changelog + diff --git a/OmegaLeo.HelperLib/Extensions/IListExtensions.cs b/OmegaLeo.HelperLib/Extensions/IListExtensions.cs index 1d22ed4..6036723 100644 --- a/OmegaLeo.HelperLib/Extensions/IListExtensions.cs +++ b/OmegaLeo.HelperLib/Extensions/IListExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; namespace GameDevLibrary.Extensions { @@ -98,7 +99,7 @@ namespace GameDevLibrary.Extensions return values; } - public static IEnumerable DistinctBy + /*public static IEnumerable DistinctBy (this IEnumerable source, Func keySelector) { HashSet seenKeys = new HashSet(); @@ -109,7 +110,7 @@ namespace GameDevLibrary.Extensions yield return element; } } - } + }*/ // Idea obtained from TaroDev's video on things to do in Unity - https://youtu.be/Ic5ux-tpkCE?t=302 @@ -117,5 +118,30 @@ namespace GameDevLibrary.Extensions { return array[currentIndex++ % array.Count]; } + + /// + /// Shuffle around items in a list. + /// Code obtained from https://stackoverflow.com/a/1262619 + /// + /// + /// + public static IList Shuffle(this IList list) + { + RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); + int n = list.Count; + while (n > 1) + { + byte[] box = new byte[1]; + do provider.GetBytes(box); + while (!(box[0] < n * (Byte.MaxValue / n))); + int k = (box[0] % n); + n--; + (list[k], list[n]) = (list[n], list[k]); + } + + return list; + } + + } } \ No newline at end of file diff --git a/OmegaLeo.HelperLib/Helpers/BenchmarkUtility.cs b/OmegaLeo.HelperLib/Helpers/BenchmarkUtility.cs new file mode 100644 index 0000000..a6ec962 --- /dev/null +++ b/OmegaLeo.HelperLib/Helpers/BenchmarkUtility.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace GameDevLibrary.Helpers +{ + public class BenchmarkUtility + { + private static Dictionary> _benchmarks = new Dictionary>(); + private static Dictionary _stopwatches = new Dictionary(); + + private static Stopwatch GetStopwatch(string key) + { + Stopwatch stopwatch = new Stopwatch(); + + if (_stopwatches.TryGetValue(key, out stopwatch)) + { + } + else + { + stopwatch = new Stopwatch(); + _stopwatches.Add(key, stopwatch); + } + + return stopwatch; + } + + public static long Record(Action actionToRecord) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + actionToRecord.Invoke(); + + stopwatch.Stop(); + return stopwatch.ElapsedMilliseconds; + } + + public static long RecordAndSaveToResults(string key, Action actionToRecord) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + actionToRecord.Invoke(); + + stopwatch.Stop(); + + if (!_benchmarks.ContainsKey(key)) + { + _benchmarks[key] = new List(); + } + + _benchmarks[key].Add(stopwatch.ElapsedMilliseconds); + + return stopwatch.ElapsedMilliseconds; + } + + public static void Start(string key) + { + GetStopwatch(key).Restart(); + } + + public static void Stop(string key) + { + if (!_benchmarks.ContainsKey(key)) + { + _benchmarks[key] = new List(); + } + + GetStopwatch(key).Stop(); + _benchmarks[key].Add(GetStopwatch(key).ElapsedMilliseconds); + } + + public static List GetResults(string key) + { + return _benchmarks.ContainsKey(key) ? _benchmarks[key] : new List(); + } + + public static void ClearResults() + { + _benchmarks.Clear(); + } + + public static Dictionary> GetAllResults() + { + return new Dictionary>(_benchmarks); + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib/Models/InstancedObject.cs b/OmegaLeo.HelperLib/Models/InstancedObject.cs new file mode 100644 index 0000000..1c156e2 --- /dev/null +++ b/OmegaLeo.HelperLib/Models/InstancedObject.cs @@ -0,0 +1,31 @@ +using System; + +namespace GameDevLibrary.Models +{ + public abstract class InstancedObject where T : class + { + public static T Instance { get; private set; } + + protected InstancedObject() + { + if (Instance != null) + { + throw new InvalidOperationException($"An instance of {typeof(T).Name} already exists."); + } + + Instance = this as T; + if (Instance == null) + { + throw new InvalidOperationException($"Failed to cast {GetType().Name} to {typeof(T).Name}."); + } + } + + ~InstancedObject() + { + if (Instance == this) + { + Instance = null; + } + } + } +} \ No newline at end of file diff --git a/OmegaLeo.HelperLib/Models/NeoDictionary.cs b/OmegaLeo.HelperLib/Models/NeoDictionary.cs index fbcbec9..f160f4c 100644 --- a/OmegaLeo.HelperLib/Models/NeoDictionary.cs +++ b/OmegaLeo.HelperLib/Models/NeoDictionary.cs @@ -81,6 +81,12 @@ namespace GameDevLibrary.Models public NeoDictionaryItem? LastOrDefault(Func, bool> predicate) => Items.LastOrDefault(predicate); + + public IEnumerable> Select(Func, NeoDictionaryItem> selector) => + Items.Select(selector); + + public int IndexOf(NeoDictionaryItem selector) => + Items.IndexOf(selector); public void Remove(TKey key) {