/// <summary>
        /// Merges <paramref name="left"/> with <paramref name="right"/> and returns the result.
        /// </summary>
        /// <remarks>
        /// The converters are merged by creating new converters that successively apply both. The entries of
        /// <paramref name="left"/> are merged with the entries of <paramref name="right"/>.
        /// <para> Two entries are merged by anding the conditions and taking the non-null form, stat and value,
        /// i.e. two merged entries may not both have forms, stats or values.
        /// </para>
        /// <para> Which entries are merged depends on the number of entries in <paramref name="left"/> and
        /// <paramref name="right"/>.
        /// <list type="bullet">
        /// <item>Both have more than one entry: An <see cref="ArgumentException"/> is thrown.</item>
        /// <item>One has no entries: The result has no entries.</item>
        /// <item>Otherwise: The single entry of one <see cref="IIntermediateModifier"/>
        /// is merged with every entry of the other <see cref="IIntermediateModifier"/>, i.e. the result has as much
        /// entries as the other <see cref="IIntermediateModifier"/>.</item>
        /// </list>
        /// </para>
        /// </remarks>
        public static IIntermediateModifier MergeWith(this IIntermediateModifier left, IIntermediateModifier right)
        {
            IStatBuilder ConvertStat(IStatBuilder s) =>
            right.StatConverter(left.StatConverter(s));

            IValueBuilder ConvertValue(IValueBuilder v) =>
            right.ValueConverter(left.ValueConverter(v));

            if (left.Entries.Count > 1 && right.Entries.Count > 1)
            {
                // This simple solution will fail once there are stat lines that parse into multiple stats
                // and have a condition requiring splitting by main hand and off hand.
                throw new ArgumentException("There may only be one IIntermediateModifier with multiple entries");
            }

            IEnumerable <IntermediateModifierEntry> entries;

            if (left.Entries.IsEmpty())
            {
                entries = right.Entries;
            }
            else if (right.Entries.IsEmpty())
            {
                entries = left.Entries;
            }
            else
            {
                entries = left.Entries.SelectMany(l => right.Entries.Select(r => Merge(l, r)));
            }
            return(new SimpleIntermediateModifier(entries.ToList(), ConvertStat, ConvertValue));
        }
        private static IEnumerable <Modifier> Build(
            IIntermediateModifier modifier, IntermediateModifierEntry entry, ModifierSource originalSource,
            Entity modifierSourceEntity)
        {
            if (entry.Form == null || entry.Stat == null || entry.Value == null)
            {
                yield break;
            }

            var(form, formValueConverter) = entry.Form.Build();
            var buildParameters = new BuildParameters(originalSource, modifierSourceEntity, form);

            var statBuilder = entry.Stat;

            if (entry.Condition != null)
            {
                statBuilder = statBuilder.WithCondition(entry.Condition);
            }
            statBuilder = modifier.StatConverter(statBuilder);
            var statBuilderResults = statBuilder.Build(buildParameters);

            foreach (var(stats, source, statValueConverter) in statBuilderResults)
            {
                var valueBuilder = formValueConverter(statValueConverter(modifier.ValueConverter(entry.Value)));
                var value        = valueBuilder.Build(buildParameters);
                yield return(new Modifier(stats, form, value, source));
            }
        }
 public IntermediateModifierBuilder(
     IIntermediateModifier modifier, ModifierSource originalSource, Entity modifierSourceEntity)
 {
     _modifier             = modifier;
     _originalSource       = originalSource;
     _modifierSourceEntity = modifierSourceEntity;
 }
Beispiel #4
0
        public IStatBuilder ResolveToReferencedBuilder(IIntermediateModifier unresolved, ResolveContext context)
        {
            if (unresolved.Entries.Count != 1)
            {
                throw new ParseException(
                          $"Referenced matchers must have exactly one IntermediateModifierEntry, {unresolved.Entries.Count} given ({unresolved})");
            }

            var entry = unresolved.Entries.Single();

            if (entry.Value != null)
            {
                throw new ParseException($"Referenced matchers may not have values ({entry})");
            }
            if (entry.Form != null)
            {
                throw new ParseException($"Referenced matchers may not have forms ({entry})");
            }
            if (entry.Stat == null)
            {
                throw new ParseException($"Referenced matchers must have stats ({entry})");
            }
            var stat = unresolved.StatConverter(entry.Stat);

            if (entry.Condition != null)
            {
                stat = stat.WithCondition(entry.Condition);
            }

            return(stat.Resolve(context));
        }
Beispiel #5
0
        /// <summary>
        /// Merges <paramref name="left"/> with <paramref name="right"/> and returns the result.
        /// </summary>
        /// <remarks>
        /// The converters are merged by creating new converters that successively apply both. The entries of
        /// <paramref name="left"/> are merged with the entries of <paramref name="right"/>.
        /// <para> Two entries are merged by anding the conditions and taking the non-null form, stat and value,
        /// i.e. two merged entries may not both have forms, stats or values.
        /// </para>
        /// <para> Which entries are merged depends on the number of entries in <paramref name="left"/> and
        /// <paramref name="right"/>.
        /// <list type="bullet">
        /// <item>Both have more than one entry: An <see cref="ArgumentException"/> is thrown.</item>
        /// <item>One has no entries: The result has no entries.</item>
        /// <item>Otherwise: The single entry of one <see cref="IIntermediateModifier"/>
        /// is merged with every entry of the other <see cref="IIntermediateModifier"/>, i.e. the result has as much
        /// entries as the other <see cref="IIntermediateModifier"/>.</item>
        /// </list>
        /// </para>
        /// </remarks>
        public static IIntermediateModifier MergeWith(this IIntermediateModifier left, IIntermediateModifier right)
        {
            IStatBuilder ConvertStat(IStatBuilder s) =>
            right.StatConverter(left.StatConverter(s));

            IValueBuilder ConvertValue(IValueBuilder v) =>
            right.ValueConverter(left.ValueConverter(v));

            if (left.Entries.Count > right.Entries.Count)
            {
                (left, right) = (right, left);
            }

            if (left.Entries.Count > 1)
            {
                throw new ArgumentException("There may only be one IIntermediateModifier with multiple entries");
            }

            if (left.Entries.IsEmpty())
            {
                return(new SimpleIntermediateModifier(right.Entries, ConvertStat, ConvertValue));
            }

            var leftEntry = left.Entries.Single();
            IEnumerable <IntermediateModifierEntry> entries = right.Entries.Select(r => Merge(leftEntry, r));

            return(new SimpleIntermediateModifier(entries.ToList(), ConvertStat, ConvertValue));
        }
Beispiel #6
0
        private static Modifier Build(
            IIntermediateModifier modifier, IntermediateModifierEntry entry, ModifierSource originalSource)
        {
            if (entry.Form == null || entry.Stat == null || entry.Value == null)
            {
                return(null);
            }

            var statBuilder = modifier.StatConverter(entry.Stat);

            if (entry.Condition != null)
            {
                statBuilder = statBuilder.WithCondition(entry.Condition);
            }
            var(stats, sourceConverter, statValueConverter) = statBuilder.Build();

            var(form, formValueConverter) = entry.Form.Build();

            var value =
                formValueConverter(
                    statValueConverter(
                        modifier.ValueConverter(entry.Value))).Build();

            return(new Modifier(stats, form, value, sourceConverter(originalSource)));
        }
 /// <summary>
 /// Builds <paramref name="modifier"/> by creating a <see cref="Modifier"/> from each of its entries.
 /// The <see cref="IIntermediateModifier.StatConverter"/> is applied to each stat and
 /// <see cref="IIntermediateModifier.ValueConverter"/> to each value. Entries with null form, stat or value
 /// are ignored.
 /// </summary>
 public static IReadOnlyList <Modifier> Build(this IIntermediateModifier modifier,
                                              ModifierSource originalSource, Entity modifierSourceEntity)
 {
     return((
                from entry in modifier.Entries
                from m in Build(modifier, entry, originalSource, modifierSourceEntity)
                select m
                ).ToList());
 }
Beispiel #8
0
 /// <summary>
 /// Builds <paramref name="modifier"/> by creating a <see cref="Modifier"/> from each of its entries.
 /// The <see cref="IIntermediateModifier.StatConverter"/> is applied to each stat and
 /// <see cref="IIntermediateModifier.ValueConverter"/> to each value. Entries with null form, stat or value
 /// are ignored.
 /// </summary>
 public static IReadOnlyList <Modifier> Build(this IIntermediateModifier modifier, ModifierSource originalSource)
 {
     return((
                from entry in modifier.Entries
                let m = Build(modifier, entry, originalSource)
                        where m != null
                        select m
                ).ToList());
 }
Beispiel #9
0
 public IIntermediateModifier Resolve(IIntermediateModifier unresolved, ResolveContext context)
 {
     return(_builder
            .WithValues(unresolved.Entries.Select(e => e.Value?.Resolve(context)))
            .WithForms(unresolved.Entries.Select(e => e.Form?.Resolve(context)))
            .WithStats(unresolved.Entries.Select(e => e.Stat?.Resolve(context)))
            .WithConditions(unresolved.Entries.Select(e => e.Condition?.Resolve(context)))
            .WithValueConverter(v => unresolved.ValueConverter(v)?.Resolve(context))
            .WithStatConverter(s => unresolved.StatConverter(s)?.Resolve(context))
            .Build());
 }
Beispiel #10
0
        public IIntermediateModifier Resolve(IIntermediateModifier unresolved, ResolveContext context)
        {
            var entries = unresolved.Entries;

            return(_builder
                   .WithValues(Resolve(entries, e => e.Value, context))
                   .WithForms(Resolve(entries, e => e.Form, context))
                   .WithStats(Resolve(entries, e => e.Stat, context))
                   .WithConditions(Resolve(entries, e => e.Condition, context))
                   .WithValueConverter(v => unresolved.ValueConverter(v).Resolve(context))
                   .WithStatConverter(s => unresolved.StatConverter(s).Resolve(context))
                   .Build());
        }
Beispiel #11
0
        /// <summary>
        /// Builds <paramref name="modifier"/> by creating a <see cref="Modifier"/> from each of its entries.
        /// The <see cref="IIntermediateModifier.StatConverter"/> is applied to each non-null stat and
        /// <see cref="IIntermediateModifier.ValueConverter"/> to each non-null value.
        /// <paramref name="defaultCondition"/> is set as the condition for each entry that has a null condition.
        /// </summary>
        public static IReadOnlyList <Modifier> Build(this IIntermediateModifier modifier, object defaultCondition)
        {
            IStatBuilder ConvertStat(IIntermediateModifier r, IStatBuilder s) =>
            s == null ? null : r.StatConverter(s);

            IValueBuilder ConvertValue(IIntermediateModifier r, IValueBuilder v) =>
            v == null ? null : r.ValueConverter(v);

            return((from entry in modifier.Entries
                    let stat = ConvertStat(modifier, entry.Stat)
                               let value = ConvertValue(modifier, entry.Value)
                                           select new Modifier(stat, entry.Form, value, entry.Condition ?? defaultCondition))
                   .ToList());
        }
 /// <summary>
 /// Builds <paramref name="modifier"/> by creating a <see cref="Modifier"/> from each of its entries.
 /// The <see cref="IIntermediateModifier.StatConverter"/> is applied to each stat and
 /// <see cref="IIntermediateModifier.ValueConverter"/> to each value. Entries with null form, stat or value
 /// are ignored.
 /// </summary>
 public static IReadOnlyList <Modifier> Build(
     this IIntermediateModifier modifier, ModifierSource originalSource, Entity modifierSourceEntity)
 => new IntermediateModifierBuilder(modifier, originalSource, modifierSourceEntity).Build();
Beispiel #13
0
 public MatcherData(string regex, IIntermediateModifier modifier, string matchSubstitution = "")
 {
     Regex             = regex;
     Modifier          = modifier;
     MatchSubstitution = matchSubstitution;
 }
 public MatcherDataParseResult(IIntermediateModifier modifier, IReadOnlyDictionary <string, string> regexGroups)
 {
     Modifier    = modifier;
     RegexGroups = regexGroups;
 }