예제 #1
0
        private static NodeValue?SelectSingleValue(List <NodeValue?> values)
        {
            NodeValue?result            = null;
            var       hasDistinctValues = false;

            foreach (var nullableValue in values)
            {
                if (nullableValue is NodeValue value)
                {
                    if (value.IsZero)
                    {
                        return(new NodeValue(0));
                    }

                    if (result is null)
                    {
                        result = value;
                    }
                    else if (!value.AlmostEquals(result.Value))
                    {
                        hasDistinctValues = true;
                    }
                }
            }

            if (hasDistinctValues)
            {
                throw new NotSupportedException("Multiple modifiers with none having value 0 are not supported");
            }

            return(result);
        }
예제 #2
0
        public void GetValuesReturnsCorrectResult()
        {
            var expected        = new NodeValue?[] { new NodeValue(0), new NodeValue(1), new NodeValue(2), new NodeValue(3), };
            var nodes           = expected.Select(MockNode).ToList();
            var nodeCollections = new[]
            {
                MockNodeCollection(nodes[0], nodes[1]),
                MockNodeCollection(nodes[1], nodes[2]),
                MockNodeCollection(nodes[2], nodes[3]),
            };
            var stats = new IStat[] { new StatStub(), new StatStub(), new StatStub(), };
            var nodeRepositoryMock = new Mock <INodeRepository>();

            for (var i = 0; i < stats.Length; i++)
            {
                var iClosure = i;
                nodeRepositoryMock.Setup(r => r.GetFormNodeCollection(stats[iClosure], Form.More, Path))
                .Returns(nodeCollections[i]);
            }
            var sut = CreateSut(nodeRepositoryMock.Object);

            var actual = sut.GetValues(Form.More, stats, Path);

            Assert.AreEqual(expected, actual);
        }
예제 #3
0
 public static double Single(this NodeValue? @this)
 {
     if (!(@this is NodeValue value))
     {
         throw new InvalidOperationException("NodeValue? has no value");
     }
     return(value.Single);
 }
예제 #4
0
 private void CalculateValue()
 {
     using (_cycleGuard.Guard())
     {
         _value = _decoratedNode.Value;
     }
     _calculatedValue = true;
 }
예제 #5
0
        public void CalculateBaseSetCorrectlyAggregatesValuesThatArePartlyZero()
        {
            var values = new NodeValue?[] { new NodeValue(-42, 0), new NodeValue(0, 5), new NodeValue(0) };

            var actual = NodeValueAggregators.CalculateBaseSet(values);

            Assert.AreEqual(new NodeValue(-42, 5), actual);
        }
        private static ResultNodeViewModel CreateSut <T>(NodeValue?value)
        {
            var stat = new Stat("", dataType: typeof(T));

            return(new ResultNodeViewModel(stat)
            {
                Value = value
            });
        }
예제 #7
0
        private static NodeValue Combine(NodeValue left, NodeValue?right, Func <double, double, double> operation)
        {
            if (!right.HasValue)
            {
                return(left);
            }

            return(NodeValue.Combine(left, right.Value, operation));
        }
예제 #8
0
 public static NodeValue?SumWhereNotNull(this NodeValue?left, NodeValue?right)
 {
     if (left is null)
     {
         return(right);
     }
     if (right is null)
     {
         return(left);
     }
     return(left + right);
 }
예제 #9
0
        public void InitializeSetsNodeValuesCorrectly()
        {
            var stats    = new[] { new Stat("a"), new Stat("b"), };
            var expected = new NodeValue?[] { new NodeValue(42), null };
            var build    = new PoEBuild();

            build.ConfigurationStats.SetValue(stats[0], expected[0]);
            var nodes = stats.Select(s => new ConfigurationNodeViewModel(s)).ToArray();

            SetupSut(build, nodes);

            Assert.AreEqual(expected, nodes.Select(n => n.Value));
        }
예제 #10
0
 public NodeValue?Round(NodeValue?value)
 {
     if (_rounding != null)
     {
         return(_rounding(value));
     }
     else if (!NumericTypes.Contains(DataType) || DataType == typeof(double))
     {
         return(value);
     }
     else
     {
         return(RoundingBehaviors.Floor(value));
     }
 }
        private IReadOnlyList <Modifier> CreateModifiers(NodeValue?value)
        {
            if (value is null)
            {
                return(new Modifier[0]);
            }

            return(new[]
            {
                new Modifier(new[] { Stat }, Form.TotalOverride,
                             new FunctionalValue(c => Calculate(c, value.Value),
                                                 $"{Stat.Minimum} <= {value} <= {Stat.Maximum}"),
                             new ModifierSource.Global(new ModifierSource.Local.UserSpecified()))
            });
        }
예제 #12
0
            public NodeValue?GetValue(IStat stat, NodeType nodeType, PathDefinition path)
            {
                if (nodeType != NodeType.PathTotal || !_value._regens(_value._pool).Equals(stat))
                {
                    return(_originalContext.GetValue(stat, nodeType, path));
                }

                NodeValue?result = null;

                foreach (var pool in _applyingPools)
                {
                    var value = _originalContext.GetValue(_value._regens(pool), nodeType, path);
                    result = result.SumWhereNotNull(value);
                }
                return(result);
            }
예제 #13
0
        private static ValueConverter ApplyToDamageValueConverter(IEnumerable <IStat> applyStats)
        {
            var values = applyStats
                         .Select(s => new FunctionalValue(c => c.GetValue(s) / 100, s + ".Value / 100"))
                         .ToList();
            var multiplier = new FunctionalValue(Calculate,
                                                 $"RequireEqualWhereNotNull({string.Join(",", values)})");

            return(v => v.Multiply(new ValueBuilderImpl(multiplier)));

            // There isn't any obvious way to combine different values but it currently can't happen:
            // - More than one source damage source for ApplyModifiersToSkillDamage can't happen because
            //   With(DamageSource) only takes one argument.
            // - Different ApplyModifiersToAilmentDamage values for different source damage sources don't make sense.
            //   If e.g. crit multi for spells and attacks would be applied to ailments at different values, it would
            //   be ambiguous how to apply generic crit multi, which is split into the damage sources, to ailments.
            // - The current solution would not work if different stats of the original StatBuilderResult (built from
            //   the core builder) have different ApplyModifiersTo values. That is possible with IDamageStatBuilder and
            //   its damage types, but damage-type specific ApplyModifiersTo modifiers do not exist.
            NodeValue?Calculate(IValueCalculationContext context)
            {
                NodeValue?result = null;

                foreach (var functionalValue in values)
                {
                    if (!(functionalValue.Calculate(context) is NodeValue value))
                    {
                        continue;
                    }

                    if (result is NodeValue r && !r.AlmostEquals(value))
                    {
                        throw new ParseException(
                                  $"ApplyModifiersToDamage values must be equal for all concretized stats. {result} and {value} given");
                    }

                    result = value;
                }
                return(result);
            }
        }
예제 #14
0
        private IValue BuildInPastXSecondsValue(BuildParameters parameters, IValueBuilder seconds)
        {
            var builtEntity           = BuildEntity(parameters, Entity);
            var recentOccurrencesStat = BuildRecentOccurrencesStat(parameters, builtEntity);
            var lastOccurenceStat     = BuildLastOccurrenceStat(parameters, builtEntity);
            var secondsValue          = seconds.Build(parameters);

            return(new ConditionalValue(Calculate,
                                        $"({RecentlySeconds} <= {secondsValue} && {recentOccurrencesStat} > 0) " +
                                        $"|| {lastOccurenceStat} <= {secondsValue}"));

            bool Calculate(IValueCalculationContext context)
            {
                NodeValue?threshold = secondsValue.Calculate(context);

                if (RecentlySeconds <= threshold && context.GetValue(recentOccurrencesStat) > 0)
                {
                    return(true);
                }
                return(context.GetValue(lastOccurenceStat) <= threshold);
            }
        }
예제 #15
0
 /// <summary>
 /// Returns the value created by applying <paramref name="operation"/> to <paramref name="value"/> if
 /// <paramref name="value"/> is not <c>null</c>. Returns <c>null</c> otherwise.
 /// </summary>
 public static NodeValue?Select(this NodeValue?value, Func <double, double> operation) =>
 value.Select(v => v.Select(operation));
예제 #16
0
        public void CalculateBaseSetThrowsExceptionIfMultipleValuesWithNonUZeroMaximumArePassed()
        {
            var values = new NodeValue?[] { new NodeValue(0, 5), new NodeValue(0, 44) };

            Assert.Throws <NotSupportedException>(() => NodeValueAggregators.CalculateBaseSet(values));
        }
예제 #17
0
 private static NodeValue?CalculateFromMinAndMax(NodeValue?min, NodeValue?max) =>
 min.HasValue && max.HasValue
         ? new NodeValue(min.Value.Minimum, max.Value.Maximum)
         : (NodeValue?)null;
예제 #18
0
 public NodeValue?Round(NodeValue?value) => value;
예제 #19
0
 /// <summary>
 /// Returns true if this <c>NodeValue?</c> representing a boolean value represents <c>true</c>.
 /// </summary>
 public static bool IsTrue(this NodeValue? @this) => @this.HasValue;
 public static ExplicitRegistrationType.UserSpecifiedValue UserSpecifiedValue(NodeValue?defaultValue)
 => new ExplicitRegistrationType.UserSpecifiedValue(defaultValue);
예제 #21
0
 private static Tags ToTags(NodeValue?value) =>
 value is NodeValue v ? ((Tags)(int)v.Maximum) : Tags.Default;
예제 #22
0
 public static Modifier CreateModifier(string stat, Form form, NodeValue?value, ModifierSource source = null)
 => CreateModifier(stat, form, new Constant(value), source);
 public ConfigurationNodeViewModel(IStat stat, NodeValue?defaultValue = null) : base(stat)
 {
     _defaultValue = defaultValue;
 }
예제 #24
0
 public Constant(NodeValue?value) : base(value) =>
예제 #25
0
 /// <summary>
 /// Returns true if this <c>NodeValue?</c> representing a boolean value represents <c>true</c>.
 /// </summary>
 public static bool IsTrue(this NodeValue? @this) => @this.HasValue && @this.Value != new NodeValue(0);
 private static Tags ToTags(NodeValue?value)
 => value is NodeValue v?TagsExtensions.DecodeFromDouble(v.Single) : Tags.Default;
예제 #27
0
 public static double?SingleOrNull(this NodeValue? @this) =>
 @this.Select(v => v.Single);
예제 #28
0
 private static NodeValue Max(NodeValue left, NodeValue?right) =>
 Combine(left, right, Math.Max);
예제 #29
0
 public static ICalculationNode MockNode(NodeValue?value = null) =>
 Mock.Of <ICalculationNode>(n => n.Value == value);
 public UserSpecifiedValue(NodeValue?defaultValue)
 => DefaultValue = defaultValue;