public void TestStartRule() { var rule = new StartRule(); var randomRule = new StringRule("Test"); Assert.IsTrue(rule.Match("sometihng")); Assert.IsFalse((randomRule + rule).Match("Test dingen")); }
//通过自定义活动文本描述解析自定义活动列表 用于首次发布时解析 private IList <ActivitySetting> ParseActivitySettings(string activitySettingsDefinition , List <XElement> variableElements) { var timeZoneService = DependencyResolver.Resolve <ITimeZoneService>(); var activitySettings = new List <ActivitySetting>(); var rootElement = XElement.Parse(activitySettingsDefinition); rootElement.Descendants("human").ToList().ForEach(element => { #region human var activityName = element.Attribute("name").Value; var actions = element.Descendants("actions") .Descendants("action") .Select(o => o.Value) .ToList(); var actioners = element.Descendants("actioners") .Descendants("actioner") .Select(o => o.Value) .ToArray(); var actionerRules = actioners; var slotCount = element.Attribute("slot") != null ? element.Attribute("slot").Value : "-1"; var slotMode = element.Attribute("slotMode") != null ? element.Attribute("slotMode").Value : "allatonce"; var url = element.Attribute("url") != null ? element.Attribute("url").Value : string.Empty; //HACK:设计器变量替换url占位符 variableElements.ForEach(variableElement => { url = url.Replace("{" + variableElement.Attribute("Name").Value + "}", variableElement.Attribute("Value").Value); }); #region 开始规则解析 string startRule_At = null, startRule_afterMinutes = null, startRule_timeZoneName = null, startRule_unlimited = null; Nullable <DateTime> nullTime = null; Nullable <Int32> nullInt = null; Nullable <Double> nullDouble = null; StartRule startRule = null; if (element.Element("start") != null) { var startRuleElement = element.Element("start"); startRule_At = startRuleElement.Attribute("at") != null ? startRuleElement.Attribute("at").Value : null; startRule_afterMinutes = startRuleElement.Attribute("after") != null ? startRuleElement.Attribute("after").Value : null; startRule_timeZoneName = startRuleElement.Attribute("zone") != null ? startRuleElement.Attribute("zone").Value : null; //无限期延迟标记 startRule_unlimited = startRuleElement.Attribute("unlimited") != null ? startRuleElement.Attribute("unlimited").Value : null; bool unlimited; if (bool.TryParse(startRule_unlimited, out unlimited) && unlimited) { startRule = StartRule.UnlimitedDelay(); } else if (startRule_At != null || startRule_afterMinutes != null || startRule_timeZoneName != null) { startRule = new StartRule(!string.IsNullOrEmpty(startRule_At) ? Convert.ToDateTime(startRule_At) : nullTime , !string.IsNullOrEmpty(startRule_afterMinutes) ? Convert.ToInt32(startRule_afterMinutes) : nullInt , string.IsNullOrEmpty(startRule_timeZoneName) ? null : timeZoneService.GetTimeZone(startRule_timeZoneName)); } } #endregion #region 完成规则解析 var scripts = element.Descendants("finish") .Descendants("line") .ToDictionary(o => o.Attribute("name").Value , o => o.Value); #endregion bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); #region 超时升级规则解析 HumanEscalationRule escalationRule = null; if (element.Element("escalation") != null) { var escalationRuleElement = element.Element("escalation"); string escalationRule_timeZoneName = escalationRuleElement.Attribute("zone") != null ? escalationRuleElement.Attribute("zone").Value : null; TimeZone escalationRuleTimeZone = null; if (!string.IsNullOrEmpty(escalationRule_timeZoneName)) { escalationRuleTimeZone = timeZoneService.GetTimeZone(escalationRule_timeZoneName); } var escalationRule_ExpirationMinute = escalationRuleElement.Attribute("expiration") != null ? escalationRuleElement.Attribute("expiration").Value : null; double?expirationMinute = !string.IsNullOrEmpty(escalationRule_ExpirationMinute) ? Convert.ToDouble(escalationRule_ExpirationMinute) : nullDouble; var escalationRule_NotifyRepeatMinutes = escalationRuleElement.Attribute("repeat") != null ? escalationRuleElement.Attribute("repeat").Value : null; double?repeatMinutes = !string.IsNullOrEmpty(escalationRule_NotifyRepeatMinutes) ? Convert.ToDouble(escalationRule_NotifyRepeatMinutes) : nullDouble; var escalationRule_NotifyEmailTemplateName = escalationRuleElement.Attribute("notifyTemplateName") != null && !string.IsNullOrEmpty(escalationRuleElement.Attribute("notifyTemplateName").Value) ? escalationRuleElement.Attribute("notifyTemplateName").Value : null; var escalationRule_GotoActivityName = escalationRuleElement.Attribute("gotoActivityName") != null && !string.IsNullOrEmpty(escalationRuleElement.Attribute("gotoActivityName").Value) ? escalationRuleElement.Attribute("gotoActivityName").Value : null; var escalationRule_RedirectTo = escalationRuleElement.Attribute("redirectTo") != null && !string.IsNullOrEmpty(escalationRuleElement.Attribute("redirectTo").Value) ? escalationRuleElement.Attribute("redirectTo").Value : null; //构造超时升级规则 escalationRule = new HumanEscalationRule(expirationMinute , escalationRuleTimeZone , repeatMinutes , escalationRule_NotifyEmailTemplateName , escalationRule_GotoActivityName , escalationRule_RedirectTo); } #endregion activitySettings.Add(new HumanSetting(WorkflowBuilder.Default_FlowNodeIndex//HACK:设置默认索引,用于临时标记 , activityName , actions.ToArray() , Convert.ToInt32(slotCount) , slotMode.ToLower() == "oneatonce" ? HumanSetting.SlotDistributionMode.OneAtOnce : HumanSetting.SlotDistributionMode.AllAtOnce , url , startRule , new HumanActionerRule(actionerRules) , new FinishRule(scripts) , escalationRule , isChildOfActivity)); #endregion }); rootElement.Descendants("server").ToList().ForEach(element => { #region server var activityName = element.Attribute("name").Value; string startRule_At = null, startRule_afterMinutes = null, startRule_timeZoneName = null, startRule_unlimited = null; Nullable <DateTime> nullTime = null; Nullable <Int32> nullInt = null; StartRule startRule = null; if (element.Element("start") != null) { var startRuleElement = element.Element("start"); startRule_At = startRuleElement.Attribute("at") != null ? startRuleElement.Attribute("at").Value : null; startRule_afterMinutes = startRuleElement.Attribute("after") != null ? startRuleElement.Attribute("after").Value : null; startRule_timeZoneName = startRuleElement.Attribute("zone") != null ? startRuleElement.Attribute("zone").Value : null; //无限期延迟标记 startRule_unlimited = startRuleElement.Attribute("unlimited") != null ? startRuleElement.Attribute("unlimited").Value : null; bool unlimited; if (bool.TryParse(startRule_unlimited, out unlimited) && unlimited) { startRule = StartRule.UnlimitedDelay(); } else if (startRule_At != null || startRule_afterMinutes != null || startRule_timeZoneName != null) { startRule = new StartRule(!string.IsNullOrEmpty(startRule_At) ? Convert.ToDateTime(startRule_At) : nullTime , !string.IsNullOrEmpty(startRule_afterMinutes) ? Convert.ToInt32(startRule_afterMinutes) : nullInt , string.IsNullOrEmpty(startRule_timeZoneName) ? null : timeZoneService.GetTimeZone(startRule_timeZoneName)); } } var scripts = element.Descendants("finish") .Descendants("line") .ToDictionary(o => o.Attribute("name").Value , o => o.Value); var serverScript = element.Element("script") != null ? element.Element("script").Value : string.Empty; var resultTo = element.Attribute("resultTo") != null ? element.Attribute("resultTo").Value : string.Empty; bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new ServerSetting(WorkflowBuilder.Default_FlowNodeIndex , activityName , serverScript , resultTo , startRule , new FinishRule(scripts) , isChildOfActivity)); #endregion }); rootElement.Descendants("subprocess").ToList().ForEach(element => { #region subprocess var activityName = element.Attribute("name").Value; var subProcessTypeName = element.Attribute("processTypeName").Value; string startRule_At = null, startRule_afterMinutes = null, startRule_timeZoneName = null, startRule_unlimited = null; Nullable <DateTime> nullTime = null; Nullable <Int32> nullInt = null; StartRule startRule = null; if (element.Element("start") != null) { var startRuleElement = element.Element("start"); startRule_At = startRuleElement.Attribute("at") != null ? startRuleElement.Attribute("at").Value : null; startRule_afterMinutes = startRuleElement.Attribute("after") != null ? startRuleElement.Attribute("after").Value : null; startRule_timeZoneName = startRuleElement.Attribute("zone") != null ? startRuleElement.Attribute("zone").Value : null; //无限期延迟标记 startRule_unlimited = startRuleElement.Attribute("unlimited") != null ? startRuleElement.Attribute("unlimited").Value : null; bool unlimited; if (bool.TryParse(startRule_unlimited, out unlimited) && unlimited) { startRule = StartRule.UnlimitedDelay(); } else if (startRule_At != null || startRule_afterMinutes != null || startRule_timeZoneName != null) { startRule = new StartRule(!string.IsNullOrEmpty(startRule_At) ? Convert.ToDateTime(startRule_At) : nullTime , !string.IsNullOrEmpty(startRule_afterMinutes) ? Convert.ToInt32(startRule_afterMinutes) : nullInt , string.IsNullOrEmpty(startRule_timeZoneName) ? null : new Taobao.Workflow.Activities.TimeZone(startRule_timeZoneName)); } } var scripts = element.Descendants("finish") .Descendants("line") .ToDictionary(o => o.Attribute("name").Value , o => o.Value); bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new SubProcessSetting(WorkflowBuilder.Default_FlowNodeIndex//HACK:设置默认索引,用于临时标记 , subProcessTypeName , activityName , startRule , new FinishRule(scripts) , isChildOfActivity)); #endregion }); rootElement.Descendants("parallel").ToList().ForEach(element => { #region parallel var activityName = element.Attribute("name").Value; var completionCondition = element.Element("condition") != null ? element.Element("condition").Value : string.Empty; bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new ParallelSetting(WorkflowBuilder.Default_FlowNodeIndex , activityName , completionCondition , isChildOfActivity)); #endregion }); return(activitySettings); }
public static void DoWork(string[] lines) { Dictionary <int, IRule> rules = new(); List <string> stringsToTest = new(); { bool doRules = true; foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line)) { doRules = false; continue; } if (doRules) { var split1 = line.Split(":"); int ruleNumber = int.Parse(split1[0]); string ruleData = split1[1]; if (ruleData.Contains("\"")) { var ruleChar = ruleData.Replace("\"", "").Trim()[0]; rules.Add(ruleNumber, new CharRule(ruleChar)); } else if (ruleData.Contains("|")) { var sides = ruleData.Split("|"); var leftSide = sides[0].Trim().Split(" ").Select(x => int.Parse(x)).ToList(); var left = new MultiRefRule(leftSide.Select(x => new RefRule(x)).ToArray()); var rightSide = sides[1].Trim().Split(" ").Select(x => int.Parse(x)).ToList(); var right = new MultiRefRule(rightSide.Select(x => new RefRule(x)).ToArray()); rules.Add(ruleNumber, new OrRule(left, right)); } else { var ruleDatas = ruleData.Trim().Split(" ").Select(x => int.Parse(x)).ToList(); if (ruleDatas.Count == 1) { rules.Add(ruleNumber, new RefRule(ruleDatas[0])); } else { rules.Add( ruleNumber, new MultiRefRule(ruleDatas.Select(x => new RefRule(x)).ToArray())); } } } else { stringsToTest.Add(line); } } } //part1 { var count = 0; foreach (var test in stringsToTest) { var rule = new StartRule(); var result = rule.Eval(test.ToCharArray().AsSpan(), rules); if (result.match) { count++; } //Console.WriteLine(result); } Console.WriteLine(count); } //part2 { // Cheating: ok something is wrong with checking stuff at the end of the string. Resulting at false positives. Fail. //8: 42 | 42 8 //11: 42 31 | 42 11 31 rules[8] = new OrRule(new RefRule(42), new MultiRefRule(new[] { new RefRule(42), new RefRule(8) })); rules[11] = new OrRule( new MultiRefRule(new[] { new RefRule(42), new RefRule(31) }), new MultiRefRule(new[] { new RefRule(42), new RefRule(11), new RefRule(31) }) ); // foreach (var (number,rule) in rules.ToArray()) // { // rules[number] = Simplify(rule, number); // } IRule Simplify(IRule r, int index) { if (r is MultiRefRule multiRefRule) { var list = new List <IRule>(); foreach (var refRule in multiRefRule.RefRules) { if (refRule.RuleNumber == index) { list.Add(refRule); continue; } var nr = Simplify(refRule, refRule.RuleNumber); list.Add(nr); } int count = 0; foreach (var nr in list) { if (nr is CharRule cr) { count++; } if (nr is SolvedRule sr) { count++; } } if (count == list.Count) { var chArr = new List <char>(); foreach (var nr in list) { if (nr is CharRule cr) { chArr.Add(cr.Char); } if (nr is SolvedRule sr) { chArr.AddRange(sr.Chars); } } return(new SolvedRule(chArr.ToArray())); } } else if (r is RefRule refRule) { var nr = Simplify(rules[refRule.RuleNumber], refRule.RuleNumber); if (nr is CharRule cr) { return(cr); } if (nr is SolvedRule sr) { return(sr); } } else if (r is OrRule orRule) { return(new OrRule(Simplify(orRule.Left, index), Simplify(orRule.Right, index))); } return(r); } var count = 0; foreach (var test in stringsToTest) { var rule = new StartRule(); var result = rule.Eval(test.ToCharArray().AsSpan(), rules); if (result.match) { count++; } // Console.WriteLine($"{result} : {test}"); } Console.WriteLine(count); } }
public IEnumerable <ActivitySetting> GetActivitySettings() { //2 yield return(new HumanSetting(2 , "节点2" , new string[] { "完成" } , 0 , HumanSetting.SlotDistributionMode.AllAtOnce , "" , new StartRule(null, 0.1, null) , new HumanActionerRule("originator") , null , null , false)); //4 yield return(new HumanSetting(4 , "节点3" , new string[] { "完成" } , 2 , HumanSetting.SlotDistributionMode.OneAtOnce , "" , null , new HumanActionerRule("originator", "getSuperior()", "username1") , new FinishRule(new Dictionary <string, string>()) , null , false)); //6 yield return(new ServerSetting(6 , "节点4" , "'1'" , "v1" , null , null , false)); //8 yield return(new ParallelSetting(8, "并行节点", null, false)); yield return(new HumanSetting(8, "并行子节点1", new string[] { "完成" }, 0 , HumanSetting.SlotDistributionMode.AllAtOnce, "" , StartRule.UnlimitedDelay()//无限期延迟 , new HumanActionerRule("originator") , null, null, true)); yield return(new HumanSetting(8, "并行子节点2", new string[] { "完成" }, 0 , HumanSetting.SlotDistributionMode.AllAtOnce, "" , null, new HumanActionerRule("getSuperior()") , null, null, true)); //9 yield return(new HumanSetting(9 , "节点6" , new string[] { "同意", "否决" } , 2 , HumanSetting.SlotDistributionMode.AllAtOnce , "" , null , new HumanActionerRule("originator") , new FinishRule(new Dictionary <string, string>() { { "同意", "all('同意')" } }) , null , false)); //11 yield return(new HumanSetting(11 , "节点7" , new string[] { "同意", "否决" } , 1 , HumanSetting.SlotDistributionMode.AllAtOnce , "" , null , new HumanActionerRule("originator", "getSuperior()") , new FinishRule(new Dictionary <string, string>() { { "同意", "all('同意')" } }) , null , false)); }
//通过自定义活动文本描述解析自定义活动列表 用于首次发布时解析 private IList <ActivitySetting> ParseActivitySettings(string activitySettingsDefinition) { var timeZoneService = DependencyResolver.Resolve <ITimeZoneService>(); var activitySettings = new List <ActivitySetting>(); var rootElement = XElement.Parse(activitySettingsDefinition); rootElement.Descendants("human").ToList().ForEach(element => { #region human var activityName = element.Attribute("name").Value; var actions = element.Descendants("actions") .Descendants("action") .Select(o => o.Value) .ToList(); var actioners = element.Descendants("actioners") .Descendants("actioner") .Select(o => o.Value) .ToArray(); var actionerRules = actioners; var slotCount = element.Attribute("slot") != null ? element.Attribute("slot").Value : "-1"; var slotMode = element.Attribute("slotMode") != null ? element.Attribute("slotMode").Value : "allatonce"; var url = element.Attribute("url") != null ? element.Attribute("url").Value : string.Empty; string startRule_At = null, startRule_afterMinutes = null, startRule_timeZoneName = null, startRule_unlimited = null; Nullable <DateTime> nullTime = null; Nullable <Int32> nullInt = null; StartRule startRule = null; if (element.Element("start") != null) { var startRuleElement = element.Element("start"); startRule_At = startRuleElement.Attribute("at") != null ? startRuleElement.Attribute("at").Value : null; startRule_afterMinutes = startRuleElement.Attribute("after") != null ? startRuleElement.Attribute("after").Value : null; startRule_timeZoneName = startRuleElement.Attribute("zone") != null ? startRuleElement.Attribute("zone").Value : null; //无限期延迟标记 startRule_unlimited = startRuleElement.Attribute("unlimited") != null ? startRuleElement.Attribute("unlimited").Value : null; bool unlimited; if (bool.TryParse(startRule_unlimited, out unlimited) && unlimited) { startRule = StartRule.UnlimitedDelay(); } else if (startRule_At != null || startRule_afterMinutes != null || startRule_timeZoneName != null) { startRule = new StartRule(!string.IsNullOrEmpty(startRule_At) ? Convert.ToDateTime(startRule_At) : nullTime , !string.IsNullOrEmpty(startRule_afterMinutes) ? Convert.ToInt32(startRule_afterMinutes) : nullInt , string.IsNullOrEmpty(startRule_timeZoneName) ? null : timeZoneService.GetTimeZone(startRule_timeZoneName)); } } var scripts = element.Descendants("finish") .Descendants("line") .ToDictionary(o => o.Attribute("name").Value , o => o.Value); bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new HumanSetting(WorkflowBuilder.Default_FlowNodeIndex//HACK:设置默认索引,用于临时标记 , activityName , actions.ToArray() , Convert.ToInt32(slotCount) , slotMode.ToLower() == "oneatonce" ? HumanSetting.SlotDistributionMode.OneAtOnce : HumanSetting.SlotDistributionMode.AllAtOnce , url , startRule , new HumanActionerRule(actionerRules) , new FinishRule(scripts) , null , isChildOfActivity)); #endregion }); rootElement.Descendants("server").ToList().ForEach(element => { #region server var activityName = element.Attribute("name").Value; string startRule_At = null, startRule_afterMinutes = null, startRule_timeZoneName = null, startRule_unlimited = null; Nullable <DateTime> nullTime = null; Nullable <Int32> nullInt = null; StartRule startRule = null; if (element.Element("start") != null) { var startRuleElement = element.Element("start"); startRule_At = startRuleElement.Attribute("at") != null ? startRuleElement.Attribute("at").Value : null; startRule_afterMinutes = startRuleElement.Attribute("after") != null ? startRuleElement.Attribute("after").Value : null; startRule_timeZoneName = startRuleElement.Attribute("zone") != null ? startRuleElement.Attribute("zone").Value : null; //无限期延迟标记 startRule_unlimited = startRuleElement.Attribute("unlimited") != null ? startRuleElement.Attribute("unlimited").Value : null; bool unlimited; if (bool.TryParse(startRule_unlimited, out unlimited) && unlimited) { startRule = StartRule.UnlimitedDelay(); } else if (startRule_At != null || startRule_afterMinutes != null || startRule_timeZoneName != null) { startRule = new StartRule(!string.IsNullOrEmpty(startRule_At) ? Convert.ToDateTime(startRule_At) : nullTime , !string.IsNullOrEmpty(startRule_afterMinutes) ? Convert.ToInt32(startRule_afterMinutes) : nullInt , string.IsNullOrEmpty(startRule_timeZoneName) ? null : timeZoneService.GetTimeZone(startRule_timeZoneName)); } } var scripts = element.Descendants("finish") .Descendants("line") .ToDictionary(o => o.Attribute("name").Value , o => o.Value); var serverScript = element.Element("script") != null ? element.Element("script").Value : string.Empty; var resultTo = element.Attribute("resultTo") != null ? element.Attribute("resultTo").Value : string.Empty; bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new ServerSetting(WorkflowBuilder.Default_FlowNodeIndex , activityName , serverScript , resultTo , startRule , new FinishRule(scripts) , isChildOfActivity)); #endregion }); rootElement.Descendants("parallel").ToList().ForEach(element => { #region parallel var activityName = element.Attribute("name").Value; var completionCondition = element.Element("condition") != null ? element.Element("condition").Value : string.Empty; bool isChildOfActivity; bool.TryParse(element.Attribute("isChildOfActivity") == null ? "False" : element.Attribute("isChildOfActivity").Value, out isChildOfActivity); activitySettings.Add(new ParallelSetting(WorkflowBuilder.Default_FlowNodeIndex , activityName , completionCondition , isChildOfActivity)); #endregion }); return(activitySettings); }