Пример #1
0
        public ProfileResult Run(Context c, string behaviour, Dictionary <string, string> tags)
        {
            if (!Behaviours.ContainsKey(behaviour))
            {
                throw new ArgumentException(
                          $"Profile {Name} does not contain the behaviour {behaviour}\nTry one of {string.Join(",", Behaviours.Keys)}");
            }

            var parameters = new Dictionary <string, IExpression>();

            foreach (var(k, v) in DefaultParameters)
            {
                parameters[k.TrimStart('#')] = v;
            }

            foreach (var(k, v) in Behaviours[behaviour])
            {
                parameters[k.TrimStart('#')] = v;
            }

            c = c.WithParameters(parameters)
                .WithAspectName(this.Name);
            tags = new Dictionary <string, string>(tags);
            var canAccess = Access.Run(c, tags);

            tags["access"] = "" + canAccess;
            var speed = (double)Speed.Run(c, tags);

            tags["speed"] = "" + speed;
            var oneway = Oneway.Run(c, tags);

            tags["oneway"] = "" + oneway;

            c.AddFunction("speed", new AspectMetadata(new Constant(Typs.Double, speed),
                                                      "speed", "Actual speed of this function", "NA", "NA", "NA", true));
            c.AddFunction("oneway", new AspectMetadata(new Constant(Typs.String, oneway),
                                                       "oneway", "Actual direction of this function", "NA", "NA", "NA", true));
            c.AddFunction("access", new AspectMetadata(new Constant(Typs.String, canAccess),
                                                       "access", "Actual access of this function", "NA", "NA", "NA", true));


            var priority          = 0.0;
            var weightExplanation = new List <string>();

            foreach (var(paramName, expression) in Priority)
            {
                var aspectInfluence = (double)c.Parameters[paramName].Evaluate(c);
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (aspectInfluence == 0)
                {
                    continue;
                }


                var aspectWeightObj = new Apply(
                    Funcs.EitherFunc.Apply(Funcs.Id, Funcs.Const, expression)
                    , new Constant(tags)).Evaluate(c);

                double aspectWeight;
                switch (aspectWeightObj)
                {
                case bool b:
                    aspectWeight = b ? 1.0 : 0.0;
                    break;

                case double d:
                    aspectWeight = d;
                    break;

                case int j:
                    aspectWeight = j;
                    break;

                case string s:
                    if (s.Equals("yes"))
                    {
                        aspectWeight = 1.0;
                        break;
                    }
                    else if (s.Equals("no"))
                    {
                        aspectWeight = 0.0;
                        break;
                    }

                    throw new Exception($"Invalid value as result for {paramName}: got string {s}");

                default:
                    throw new Exception($"Invalid value as result for {paramName}: got object {aspectWeightObj}");
                }

                weightExplanation.Add($"({paramName} = {aspectInfluence}) * {aspectWeight}");
                priority += aspectInfluence * aspectWeight;
            }

            if (priority <= 0)
            {
                canAccess = "no";
            }

            return(new ProfileResult((string)canAccess, (string)oneway, speed, priority,
                                     string.Join("\n  ", weightExplanation)));
        }