<commit_before>﻿using Humanizer;
using System;
using System.Collections.Generic;
using RandomizeFunc = System.Func<Atata.UIComponentMetadata, object>;

namespace Atata
{
    public static class ValueRandomizer
    {
        private static readonly Dictionary<Type, RandomizeFunc> Randomizers;

        static ValueRandomizer()
        {
            Randomizers = new Dictionary<Type, RandomizeFunc>();

            RegisterRandomizer<string>(RandomizeString);
            RegisterNumberRandomizer<sbyte>();
            RegisterNumberRandomizer<byte>();
            RegisterNumberRandomizer<short>();
            RegisterNumberRandomizer<ushort>();
            RegisterNumberRandomizer<int>();
            RegisterNumberRandomizer<uint>();
            RegisterNumberRandomizer<long>();
            RegisterNumberRandomizer<ulong>();
            RegisterNumberRandomizer<float>();
            RegisterNumberRandomizer<double>();
            RegisterNumberRandomizer<decimal>();
        }

        public static void RegisterRandomizer<T>(Func<UIComponentMetadata, T> randomizeFunction)
        {
            if (randomizeFunction == null)
                throw new ArgumentNullException("randomizeFunction");

            Randomizers[typeof(T)] = m => (object)randomizeFunction(m);
        }

        private static void RegisterNumberRandomizer<T>()
        {
            Randomizers[typeof(T)] = m => (object)RandomizeNumber<T>(m);
        }

        private static string RandomizeString(UIComponentMetadata metadata)
        {
            var attribute = metadata.GetFirstOrDefaultDeclaringAttribute<GeneratableStringAttribute>() ?? new GeneratableStringAttribute();

            string format = NormalizeStringFormat(attribute.Format);
            return Randomizer.GetString(format, attribute.NumberOfCharacters);
        }

        private static T RandomizeNumber<T>(UIComponentMetadata metadata)
        {
            var attribute = metadata.GetFirstOrDefaultDeclaringAttribute<GeneratableNumberAttribute>() ?? new GeneratableNumberAttribute();

            decimal value = Randomizer.GetDecimal(attribute.Min, attribute.Max, attribute.Precision);
            return (T)Convert.ChangeType(value, typeof(T));
        }

        private static string NormalizeStringFormat(string format)
        {
            if (string.IsNullOrEmpty(format))
                return "{0}";
            else if (!format.Contains("{0}"))
                return format + "{0}";
            else
                return format;
        }

        public static T GetRandom<T>(UIComponentMetadata metadata)
        {
            RandomizeFunc randomizeFunction;
            if (Randomizers.TryGetValue(typeof(T), out randomizeFunction))
                return (T)randomizeFunction(metadata);
            else
                throw new InvalidOperationException("Cannot get random value for '{0}' type. There is no registered randomizer for this type.".FormatWith(typeof(T).FullName));
        }
    }
}<commit_msg>Fix ValueRandomizer to handle nullable types<commit_after>﻿using Humanizer;
using System;
using System.Collections.Generic;
using RandomizeFunc = System.Func<Atata.UIComponentMetadata, object>;

namespace Atata
{
    public static class ValueRandomizer
    {
        private static readonly Dictionary<Type, RandomizeFunc> Randomizers;

        static ValueRandomizer()
        {
            Randomizers = new Dictionary<Type, RandomizeFunc>();

            RegisterRandomizer(RandomizeString);
            RegisterNumberRandomizer<sbyte>();
            RegisterNumberRandomizer<byte>();
            RegisterNumberRandomizer<short>();
            RegisterNumberRandomizer<ushort>();
            RegisterNumberRandomizer<int>();
            RegisterNumberRandomizer<uint>();
            RegisterNumberRandomizer<long>();
            RegisterNumberRandomizer<ulong>();
            RegisterNumberRandomizer<float>();
            RegisterNumberRandomizer<double>();
            RegisterNumberRandomizer<decimal>();
        }

        public static void RegisterRandomizer<T>(Func<UIComponentMetadata, T> randomizeFunction)
        {
            if (randomizeFunction == null)
                throw new ArgumentNullException("randomizeFunction");

            Randomizers[typeof(T)] = m => randomizeFunction(m);
        }

        private static void RegisterNumberRandomizer<T>()
        {
            Randomizers[typeof(T)] = m => RandomizeNumber<T>(m);
        }

        private static string RandomizeString(UIComponentMetadata metadata)
        {
            var attribute = metadata.GetFirstOrDefaultDeclaringAttribute<GeneratableStringAttribute>() ?? new GeneratableStringAttribute();

            string format = NormalizeStringFormat(attribute.Format);
            return Randomizer.GetString(format, attribute.NumberOfCharacters);
        }

        private static T RandomizeNumber<T>(UIComponentMetadata metadata)
        {
            var attribute = metadata.GetFirstOrDefaultDeclaringAttribute<GeneratableNumberAttribute>() ?? new GeneratableNumberAttribute();

            decimal value = Randomizer.GetDecimal(attribute.Min, attribute.Max, attribute.Precision);
            return (T)Convert.ChangeType(value, typeof(T));
        }

        private static string NormalizeStringFormat(string format)
        {
            if (string.IsNullOrEmpty(format))
                return "{0}";
            else if (!format.Contains("{0}"))
                return format + "{0}";
            else
                return format;
        }

        public static T GetRandom<T>(UIComponentMetadata metadata)
        {
            Type type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            RandomizeFunc randomizeFunction;

            if (Randomizers.TryGetValue(type, out randomizeFunction))
                return (T)randomizeFunction(metadata);
            else
                throw new InvalidOperationException("Cannot get random value for '{0}' type. There is no registered randomizer for this type.".FormatWith(typeof(T).FullName));
        }
    }
}
{'fraction_non_alphanumeric': 0.09102880658436215, 'fraction_numerical': 0.0013168724279835392, 'mean_word_length': 2.6080760095011875, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 52, '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': '3282057', 'n_tokens_mistral': 1414, 'n_tokens_neox': 1391, 'n_words': 299}