<commit_before>﻿// #define DEFINE_TEST

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using IBinaryReadable = ThScoreFileConverter.Models.IBinaryReadable;

#if DEFINE_TEST
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ThScoreFileConverter.Extensions;
#endif

namespace ThScoreFileConverterTests.UnitTesting
{
#if DEFINE_TEST
    [TestClass]
#endif
    public static class TestUtils
    {
        static TestUtils()
        {
            Unreachable = nameof(Unreachable);
            Random = new Random();

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            CP932Encoding = Encoding.GetEncoding(932);
        }

        public static string Unreachable { get; }

        public static Random Random { get; }

        public static Encoding CP932Encoding { get; }

#if DEFINE_TEST
        private static Dictionary<string, int> Counter { get; } = new();

        [AssemblyCleanup]
        public static void Cleanup()
        {
            Counter.OrderByDescending(static pair => pair.Value).ForEach(static pair => Console.WriteLine(pair));
        }
#endif

        public static byte[] MakeByteArray(params object[] args)
        {
            if (args is null)
                throw new ArgumentNullException(nameof(args));

            static bool IsRankOneArray<T>(Array array)
            {
                return (array.Rank == 1) && (array.GetType().GetElementType() == typeof(T));
            }

            using var stream = new MemoryStream();
            using var writer = new BinaryWriter(stream, CP932Encoding);

            foreach (var arg in args)
            {
#if DEFINE_TEST
                Counter.TryAdd(arg.GetType().Name, 0);
                ++Counter[arg.GetType().Name];
#endif
                switch (arg)
                {
                    case int intArg:
                        writer.Write(intArg);
                        break;
                    case byte[] bytesArg:
                        writer.Write(bytesArg);
                        break;
                    case uint uintArg:
                        writer.Write(uintArg);
                        break;
                    case byte byteArg:
                        writer.Write(byteArg);
                        break;
                    case float floatArg:
                        writer.Write(floatArg);
                        break;
                    case ushort ushortArg:
                        writer.Write(ushortArg);
                        break;
                    case short shortArg:
                        writer.Write(shortArg);
                        break;
                    case char[] charsArg:
                        writer.Write(charsArg);
                        break;
                    case string stringArg:
                        writer.Write(stringArg);
                        break;
                    case Array arrayArg when IsRankOneArray<int>(arrayArg):
                        ((int[])arrayArg).ForEach(writer.Write);
                        break;
                    case Array arrayArg when IsRankOneArray<short>(arrayArg):
                        ((short[])arrayArg).ForEach(writer.Write);
                        break;
                    case Array arrayArg when IsRankOneArray<uint>(arrayArg):
                        ((uint[])arrayArg).ForEach(writer.Write);
                        break;
                    case Array arrayArg when IsRankOneArray<ushort>(arrayArg):
                        ((ushort[])arrayArg).ForEach(writer.Write);
                        break;
                    case IEnumerable<byte> enumerable:
                        enumerable.ForEach(writer.Write);
                        break;
                    case IEnumerable<int> enumerable:
                        enumerable.ForEach(writer.Write);
                        break;
                    case IEnumerable<short> enumerable:
                        enumerable.ForEach(writer.Write);
                        break;
                    case IEnumerable<uint> enumerable:
                        enumerable.ForEach(writer.Write);
                        break;
                    case IEnumerable<ushort> enumerable:
                        enumerable.ForEach(writer.Write);
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }

            writer.Flush();
            return stream.ToArray();
        }

        public static TResult[] MakeRandomArray<TResult>(int length)
            where TResult : struct
        {
            var defaultValue = default(TResult);

            Func<object> getNextValue = defaultValue switch
            {
                byte _ => () => Random.Next(byte.MaxValue + 1),
                short _ => () => Random.Next(short.MaxValue + 1),
                ushort _ => () => Random.Next(ushort.MaxValue + 1),
                int _ => () =>
                {
                    var maxValue = ushort.MaxValue + 1;
                    return (Random.Next(maxValue) << 16) | Random.Next(maxValue);
                },
                uint _ => () =>
                {
                    var maxValue = ushort.MaxValue + 1;
                    return ((uint)Random.Next(maxValue) << 16) | (uint)Random.Next(maxValue);
                },
                _ => throw new NotImplementedException(),
            };

            return Enumerable
                .Repeat(defaultValue, length)
                .Select(i => (TResult)Convert.ChangeType(getNextValue(), typeof(TResult), CultureInfo.InvariantCulture))
                .ToArray();
        }

        public static T Create<T>(byte[] array)
            where T : IBinaryReadable, new()
        {
            var instance = new T();

            using var stream = new MemoryStream(array);
            using var reader = new BinaryReader(stream);
            instance.ReadFrom(reader);

            return instance;
        }

        public static TResult Cast<TResult>(object value)
            where TResult : struct
        {
            var type = typeof(TResult);
            if (type.IsEnum)
                return (TResult)Enum.ToObject(type, value);

            return (TResult)Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
        }

        public static IEnumerable<object[]> GetInvalidEnumerators(Type type)
        {
            var values = Enum.GetValues(type).Cast<int>();
            yield return new object[] { values.Min() - 1 };
            yield return new object[] { values.Max() + 1 };
        }
    }
}<commit_msg>Reorder patterns in order of frequency<commit_after>﻿// #define DEFINE_TEST

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using IBinaryReadable = ThScoreFileConverter.Models.IBinaryReadable;

#if DEFINE_TEST
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ThScoreFileConverter.Extensions;
#endif

namespace ThScoreFileConverterTests.UnitTesting
{
#if DEFINE_TEST
    [TestClass]
#endif
    public static class TestUtils
    {
        static TestUtils()
        {
            Unreachable = nameof(Unreachable);
            Random = new Random();

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            CP932Encoding = Encoding.GetEncoding(932);
        }

        public static string Unreachable { get; }

        public static Random Random { get; }

        public static Encoding CP932Encoding { get; }

#if DEFINE_TEST
        private static Dictionary<string, int> Counter { get; } = new();

        [AssemblyCleanup]
        public static void Cleanup()
        {
            Counter.OrderByDescending(static pair => pair.Value).ForEach(static pair => Console.WriteLine(pair));
        }
#endif

        public static byte[] MakeByteArray(params object[] args)
        {
            if (args is null)
                throw new ArgumentNullException(nameof(args));

            static bool IsRankOneArray<T>(Array array)
            {
                return (array.Rank == 1) && (array.GetType().GetElementType() == typeof(T));
            }

            using var stream = new MemoryStream();
            using var writer = new BinaryWriter(stream, CP932Encoding);

            foreach (var arg in args)
            {
                switch (arg)
                {
                    case int value:
                        Invoke(writer.Write, "int", value);
                        break;
                    case uint value:
                        Invoke(writer.Write, "uint", value);
                        break;
                    case byte[] array:
                        Invoke(writer.Write, "byte[]", array);
                        break;
                    case byte value:
                        Invoke(writer.Write, "byte", value);
                        break;
                    case float value:
                        Invoke(writer.Write, "float", value);
                        break;
                    case ushort value:
                        Invoke(writer.Write, "ushort", value);
                        break;
                    case IEnumerable<byte> enumerable:
                        Invoke(writer.Write, "IEnumerable<byte>", enumerable);
                        break;
                    case short value:
                        Invoke(writer.Write, "short", value);
                        break;
                    case char[] array:
                        Invoke(writer.Write, "char[]", array);
                        break;
                    case string value:
                        Invoke(writer.Write, "string", value);
                        break;
                    case Array array when IsRankOneArray<int>(array):
                        Invoke(writer.Write, "int[]", (int[])array);
                        break;
                    case Array array when IsRankOneArray<uint>(array):
                        Invoke(writer.Write, "uint[]", (uint[])array);
                        break;
                    case IEnumerable<int> enumerable:
                        Invoke(writer.Write, "IEnumerable<int>", enumerable);
                        break;
                    case IEnumerable<short> enumerable:
                        Invoke(writer.Write, "IEnumerable<short>", enumerable);
                        break;
                    case IEnumerable<uint> enumerable:
                        Invoke(writer.Write, "IEnumerable<uint>", enumerable);
                        break;
                    case IEnumerable<ushort> enumerable:
                        Invoke(writer.Write, "IEnumerable<ushort>", enumerable);
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }

            writer.Flush();
            return stream.ToArray();
        }

        public static TResult[] MakeRandomArray<TResult>(int length)
            where TResult : struct
        {
            var defaultValue = default(TResult);

            Func<object> getNextValue = defaultValue switch
            {
                byte _ => () => Random.Next(byte.MaxValue + 1),
                short _ => () => Random.Next(short.MaxValue + 1),
                ushort _ => () => Random.Next(ushort.MaxValue + 1),
                int _ => () =>
                {
                    var maxValue = ushort.MaxValue + 1;
                    return (Random.Next(maxValue) << 16) | Random.Next(maxValue);
                },
                uint _ => () =>
                {
                    var maxValue = ushort.MaxValue + 1;
                    return ((uint)Random.Next(maxValue) << 16) | (uint)Random.Next(maxValue);
                },
                _ => throw new NotImplementedException(),
            };

            return Enumerable
                .Repeat(defaultValue, length)
                .Select(i => (TResult)Convert.ChangeType(getNextValue(), typeof(TResult), CultureInfo.InvariantCulture))
                .ToArray();
        }

        public static T Create<T>(byte[] array)
            where T : IBinaryReadable, new()
        {
            var instance = new T();

            using var stream = new MemoryStream(array);
            using var reader = new BinaryReader(stream);
            instance.ReadFrom(reader);

            return instance;
        }

        public static TResult Cast<TResult>(object value)
            where TResult : struct
        {
            var type = typeof(TResult);
            if (type.IsEnum)
                return (TResult)Enum.ToObject(type, value);

            return (TResult)Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
        }

        public static IEnumerable<object[]> GetInvalidEnumerators(Type type)
        {
            var values = Enum.GetValues(type).Cast<int>();
            yield return new object[] { values.Min() - 1 };
            yield return new object[] { values.Max() + 1 };
        }

        private static void Invoke<T>(Action<T> action, string key, T value)
        {
            Countup(key);
            action(value);
        }

        private static void Invoke<T>(Action<T> action, string key, IEnumerable<T> enumerable)
        {
            Countup(key);
            enumerable.ForEach(action);
        }

        [Conditional("DEFINE_TEST")]
        private static void Countup(string key)
        {
#if DEFINE_TEST
            Counter.TryAdd(key, 0);
            ++Counter[key];
#endif
        }
    }
}
{'fraction_non_alphanumeric': 0.09271523178807947, 'fraction_numerical': 0.0036387453605996652, 'mean_word_length': 1.366046831955923, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1454852', 'n_tokens_mistral': 3409, 'n_tokens_neox': 3145, 'n_words': 755}