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))); }