Skip to content

Commit

Permalink
add - doc - Added kaomoji manager
Browse files Browse the repository at this point in the history
---

You can now manage Kaomoji emoticons! (*^‿^*)

---

Type: add
Breaking: False
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Nov 20, 2024
1 parent 781abc9 commit ba7a826
Show file tree
Hide file tree
Showing 8 changed files with 364 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
[submodule "assets/UnicodeList"]
path = assets/UnicodeList
url = https://github.com/Aptivi-Analytics/UnicodeList
[submodule "assets/KaomojiList"]
path = assets/KaomojiList
url = https://github.com/Aptivi-Analytics/KaomojiList
1 change: 1 addition & 0 deletions Textify.Data/Textify.Data.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

<ItemGroup>
<ProjectReference Include="..\Textify.EmojiArrayGen\Textify.EmojiArrayGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\Textify.KaomojiArrayGen\Textify.KaomojiArrayGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
Expand Down
69 changes: 69 additions & 0 deletions Textify.Data/Unicode/KaomojiManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Textify Copyright (C) 2023-2024 Aptivi
//
// This file is part of Textify
//
// Textify is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Textify is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using System.Linq;
using Textify.Tools;

namespace Textify.Data.Unicode
{
/// <summary>
/// Kaomoji management class
/// </summary>
public static partial class KaomojiManager
{
/// <summary>
/// Gets all kaomoji subcategories
/// </summary>
/// <param name="category">Kaomoji category</param>
/// <returns>An array of kaomoji subcategories</returns>
public static KaomojiSubcategory[] GetKaomojiSubcategories(KaomojiCategory category)
{
if (!kaomojis.TryGetValue(category, out var subcategory))
throw new TextifyException("Category doesn't exist");
return [.. subcategory.Keys];
}

/// <summary>
/// Gets all kaomoji sequences
/// </summary>
/// <param name="category">Kaomoji category</param>
/// <param name="subcategory">Kaomoji subcategory</param>
/// <returns>An array of kaomoji sequences</returns>
public static string[] GetKaomojis(KaomojiCategory category, KaomojiSubcategory subcategory)
{
var subcategories = GetKaomojiSubcategories(category);
if (!subcategories.Contains(subcategory))
throw new TextifyException($"There is no such subcategory for {category}");
return kaomojis[category][subcategory];
}

/// <summary>
/// Gets a kaomoji sequence
/// </summary>
/// <param name="category">Kaomoji category</param>
/// <param name="subcategory">Kaomoji subcategory</param>
/// <param name="sequenceIdx">Sequence index</param>
/// <returns>Kaomoji sequence</returns>
public static string GetKaomoji(KaomojiCategory category, KaomojiSubcategory subcategory, int sequenceIdx)
{
var sequences = GetKaomojis(category, subcategory);
return sequences[sequenceIdx];
}
}
}
239 changes: 239 additions & 0 deletions Textify.KaomojiArrayGen/ArrayGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
//
// Textify Copyright (C) 2023-2024 Aptivi
//
// This file is part of Textify
//
// Textify is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Textify is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Textify.KaomojiArrayGen
{
[Generator]
public class ArrayGenerator : IIncrementalGenerator
{
private static readonly Assembly asm = typeof(ArrayGenerator).Assembly;

public void Initialize(IncrementalGeneratorInitializationContext context)
{
string header =
$$"""
//
// Textify Copyright (C) 2023-2024 Aptivi
//
// This file is part of Textify
//
// Textify is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Textify is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// <auto-generated/>
using System.Collections.Generic;
namespace Textify.Data.Unicode
{
public static partial class KaomojiManager
{
""";
string kaomojiCategory =
$$"""
}
/// <summary>
/// Kaomoji category
/// </summary>
public enum KaomojiCategory
{
""";
string kaomojiSubcategory =
$$"""
}
/// <summary>
/// Kaomoji subcategory
/// </summary>
public enum KaomojiSubcategory
{
""";
string footer =
$$"""
}
}
""";
var builder = new StringBuilder(header);
var kaomojis = GetKaomojis();

// Populate the ultimate array for all kaomojis
builder.Append(PopulateKaomojiArray(kaomojis));
builder.AppendLine(kaomojiCategory);
builder.Append(PopulateKaomojiCategory(kaomojis));
builder.AppendLine(kaomojiSubcategory);
builder.Append(PopulateKaomojiSubcategory(kaomojis));

// End the file
builder.AppendLine(footer);
context.RegisterPostInitializationOutput(ctx =>
{
ctx.AddSource("KaomojiManager.g.cs", SourceText.From(builder.ToString(), Encoding.UTF8));
});
}

private static string PopulateKaomojiCategory(Dictionary<string, Dictionary<string, List<string>>> kaomojis)
{
var builder = new StringBuilder();
foreach (var category in kaomojis.Keys)
{
builder.AppendLine( " /// <summary>");
builder.AppendLine($" /// Kaomoji enumeration for \"{category}\"");
builder.AppendLine( " /// </summary>");
builder.AppendLine($" {category},");
}
return builder.ToString();
}

private static string PopulateKaomojiSubcategory(Dictionary<string, Dictionary<string, List<string>>> kaomojis)
{
var builder = new StringBuilder();
foreach (var category in kaomojis.Keys)
{
var subcategories = kaomojis[category];
foreach (var subcategory in subcategories.Keys)
{
builder.AppendLine( " /// <summary>");
builder.AppendLine($" /// Kaomoji enumeration for \"{subcategory}\", subcategory of \"{category}\"");
builder.AppendLine( " /// </summary>");
builder.AppendLine($" {subcategory},");
}
}
return builder.ToString();
}

private static string PopulateKaomojiArray(Dictionary<string, Dictionary<string, List<string>>> kaomojis)
{
string arrayFooter =
$$"""
};
""";
string header =
$$"""
private static readonly Dictionary<KaomojiCategory, Dictionary<KaomojiSubcategory, string[]>> kaomojis = new()
{
""";
var builder = new StringBuilder(header);
int categories = 0;
foreach (var category in kaomojis.Keys)
{
var subcategories = kaomojis[category];
int subcategoriesCount = 0;

// Populate the KaomojiCategory string
string kaomojiCategoryRef = $"KaomojiCategory.{category}";
builder.Append(
$" {{ {kaomojiCategoryRef}, new()" +
$" {{"
);
foreach (var subcategory in subcategories.Keys)
{
// Populate the KaomojiSubcategory string
string kaomojiSubcategoryRef = $"KaomojiSubcategory.{subcategory}";
builder.Append(
$" {{ {kaomojiSubcategoryRef},\n" +
$" [\n" +
$" @\""
);

// Add the sequences
var sequences = subcategories[subcategory].Select((str) => str.Replace("\"", "\"\""));
builder.AppendLine(string.Join("\",\n @\"", sequences) + "\"");

// Add the resultant subcategory info
subcategoriesCount++;
builder.AppendLine(
$" ]\n" +
$" }}");
if (subcategoriesCount < subcategories.Count)
builder.AppendLine(",");
}

// Add the resultant category info
categories++;
builder.Append(
$" }}\n" +
$" }}"
);
if (categories < kaomojis.Count)
builder.AppendLine(",");
}
builder.AppendLine("");
builder.Append(arrayFooter);
return builder.ToString();
}

private static Dictionary<string, Dictionary<string, List<string>>> GetKaomojis()
{
// Open the stream that contains the kaomoji list
var stream = asm.GetManifestResourceStream($"{asm.GetName().Name}.kaomojis.json") ??
throw new Exception("Failed to find kaomoji file.");

// Add the whole list
var kaomojis = new Dictionary<string, Dictionary<string, List<string>>>();
var kaomojiStreamReader = new StreamReader(stream);
var kaomojiReader = new JsonTextReader(kaomojiStreamReader);
var kaomojiArray = JArray.Load(kaomojiReader);
foreach (var categoryObject in kaomojiArray)
{
var name = categoryObject["name"] ?? "Unknown name";
var subcategories = categoryObject["categories"] ??
throw new Exception("Can't get categories");
var subcategoriesDict = new Dictionary<string, List<string>>();
foreach (var subcategory in subcategories)
{
var subcategoryName = subcategory["name"] ?? "Unknown name";
var subcategoryKaomojis = subcategory["emoticons"] ??
throw new Exception("Can't get kaomojis");
var sequences = new List<string>();
foreach (var kaomoji in subcategoryKaomojis)
sequences.Add(kaomoji.ToString());
subcategoriesDict.Add(subcategoryName.ToString(), sequences);
}
kaomojis.Add(name.ToString(), subcategoriesDict);
}
return kaomojis;
}
}
}
34 changes: 34 additions & 0 deletions Textify.KaomojiArrayGen/Textify.KaomojiArrayGen.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

<ItemGroup>
<!--
Microsoft.CodeAnalysis.CSharp must not be updated unless DocFX updates it to the latest version and a release is made.
Ignoring this warning leads to build failures when building the documentation!
-->
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="[4.10.0]" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" PrivateAssets="all" GeneratePathProperty="true" />

<PackageReference Remove="Microsoft.SourceLink.GitHub" />
</ItemGroup>

<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
</PropertyGroup>

<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PKGNewtonsoft_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>

<ItemGroup>
<EmbeddedResource Include="../assets/KaomojiList/kaomojis.json" Visible="false" />
</ItemGroup>

</Project>
10 changes: 10 additions & 0 deletions Textify.Tests/Unicode/UnicodeQueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,15 @@ public void QueryEmojiFromEmojiEnums(EmojiEnum emoji, string expectedName, strin
emojiInstance.Name.ShouldBe(expectedName);
emojiInstance.Sequence.ShouldBe(expectedSequence);
}

[TestMethod]
[DataRow(KaomojiCategory.Positive, KaomojiSubcategory.Joy, 0, "(* ^ ω ^)")]
[DataRow(KaomojiCategory.Negative, KaomojiSubcategory.Dissatisfaction, 1, "(;⌣̀_⌣́)")]
[DataRow(KaomojiCategory.Neutral, KaomojiSubcategory.Doubt, 2, "(¬ ¬)")]
public void QueryKaomojiFromKaomojiEnums(KaomojiCategory category, KaomojiSubcategory subcategory, int sequenceIdx, string expectedSequence)
{
string sequence = KaomojiManager.GetKaomoji(category, subcategory, sequenceIdx);
sequence.ShouldBe(expectedSequence);
}
}
}
Loading

0 comments on commit ba7a826

Please sign in to comment.