private static void AppendAndOrNext(StringBuilder andNext, Requirement requirement, NumberFormat numberFormat, StringBuilder addSources, StringBuilder subSources, StringBuilder addAddress, ref RequirementType lastAndNext) { if (addSources.Length > 0 || subSources.Length > 0 || addAddress.Length > 0) { andNext.Append('('); requirement.AppendString(andNext, numberFormat, addSources.Length > 0 ? addSources.ToString() : null, subSources.Length > 0 ? subSources.ToString() : null, null, null, addAddress.Length > 0 ? addAddress.ToString() : null); andNext.Append(')'); addAddress.Clear(); addSources.Clear(); subSources.Clear(); } else { requirement.AppendString(andNext, numberFormat); } if (lastAndNext != requirement.Type) { if (lastAndNext != RequirementType.None) { andNext.Insert(0, '('); andNext.Append(')'); } lastAndNext = requirement.Type; } if (requirement.Type == RequirementType.OrNext) { andNext.Append(" || "); } else { andNext.Append(" && "); } }
private static void AppendFieldModifier(StringBuilder builder, Requirement requirement, NumberFormat numberFormat) { switch (requirement.Operator) { case RequirementOperator.Multiply: builder.Append(" * "); requirement.Right.AppendString(builder, numberFormat); break; case RequirementOperator.Divide: builder.Append(" / "); requirement.Right.AppendString(builder, numberFormat); break; case RequirementOperator.BitwiseAnd: builder.Append(" & "); requirement.Right.AppendString(builder, numberFormat); break; } }
internal Achievement() { CoreRequirements = new Requirement[0]; AlternateRequirements = new IEnumerable <Requirement> [0]; }
/// <summary> /// Constructs a series of <see cref="RequirementEx" />s from a series of <see cref="Requirement" />s. /// </summary> public static List <RequirementEx> Combine(IEnumerable <Requirement> requirements) { var group = new List <RequirementEx>(); Requirement combiningRequirement = null; foreach (var requirement in requirements) { if (combiningRequirement != null && (combiningRequirement.Type == RequirementType.AndNext || combiningRequirement.Type == RequirementType.OrNext)) { // "A || always_false()" and "A && always_true()" are both just "A", // but we need to preserve the flag and hit target from the second condition. // create a copy without the hit count for evaluation var newRequirement = new Requirement { Left = requirement.Left, Operator = requirement.Operator, Right = requirement.Right }; bool redundantEvaluation = (combiningRequirement.Type == RequirementType.AndNext); if (newRequirement.Evaluate() == redundantEvaluation) { if (combiningRequirement.HitCount != 0 && requirement.HitCount != 0) { // if both requirements have separate hit targets, we can't combine them } else { // going to be modifying the combiningRequirement, create a copy newRequirement = new Requirement { // use the flag from the redundant condition Type = requirement.Type, Left = combiningRequirement.Left, Operator = combiningRequirement.Operator, Right = combiningRequirement.Right }; // one of the two conditions has a hit count of zero, so this // effectively takes whichever isn't zero. newRequirement.HitCount = requirement.HitCount + combiningRequirement.HitCount; // replace the last requirement with the updated requirement var lastGroupRequirements = group.Last().Requirements; lastGroupRequirements.Remove(combiningRequirement); lastGroupRequirements.Add(newRequirement); // decide if the condition is still combining combiningRequirement = requirement.IsCombining ? newRequirement : null; continue; } } } else { switch (requirement.Type) { case RequirementType.AddHits: case RequirementType.SubHits: // an always_false() condition will never generate a hit if (requirement.Evaluate() == false) { continue; } break; case RequirementType.AndNext: // an always_true() condition will not affect the next condition if (requirement.Evaluate() == true) { continue; } break; case RequirementType.OrNext: // an always_false() condition will not affect the next condition if (requirement.Evaluate() == false) { continue; } break; } } if (combiningRequirement == null) { group.Add(new RequirementEx()); } group.Last().Requirements.Add(requirement); combiningRequirement = requirement.IsCombining ? requirement : null; } return(group); }
internal void AppendCondition(StringBuilder builder, NumberFormat numberFormat, string addSources = null, string subSources = null, string addHits = null, string andNext = null, string addAddress = null) { if (!string.IsNullOrEmpty(addSources)) { builder.Append('('); builder.Append(addSources); } else if (!string.IsNullOrEmpty(subSources)) { builder.Append('('); } else if (!string.IsNullOrEmpty(addHits)) { builder.Append(addHits); } else if (!string.IsNullOrEmpty(andNext)) { builder.Append(andNext); } string suffix = null; switch (Type) { case RequirementType.AddSource: Left.AppendString(builder, numberFormat); suffix = " + "; break; case RequirementType.SubSource: builder.Append(" - "); Left.AppendString(builder, numberFormat); break; default: if (Operator != RequirementOperator.None && string.IsNullOrEmpty(subSources) && string.IsNullOrEmpty(addSources)) { var clone = new Requirement { Left = this.Left, Operator = this.Operator, Right = this.Right }; var result = clone.Evaluate(); if (result == true) { builder.Append("always_true()"); return; } else if (result == false) { builder.Append("always_false()"); return; } } Left.AppendString(builder, numberFormat, addAddress); break; } // scaling operators need to be appended before chained operations switch (Operator) { case RequirementOperator.Multiply: builder.Append(" * "); Right.AppendString(builder, numberFormat, addAddress); break; case RequirementOperator.Divide: builder.Append(" / "); Right.AppendString(builder, numberFormat, addAddress); break; case RequirementOperator.BitwiseAnd: builder.Append(" & "); Right.AppendString(builder, numberFormat, addAddress); break; } // append chained operations if (!string.IsNullOrEmpty(subSources)) { builder.Append(subSources); builder.Append(')'); } else if (!string.IsNullOrEmpty(addSources)) { builder.Append(')'); } // handle comparison operators switch (Operator) { case RequirementOperator.Equal: builder.Append(" == "); break; case RequirementOperator.NotEqual: builder.Append(" != "); break; case RequirementOperator.LessThan: builder.Append(" < "); break; case RequirementOperator.LessThanOrEqual: builder.Append(" <= "); break; case RequirementOperator.GreaterThan: builder.Append(" > "); break; case RequirementOperator.GreaterThanOrEqual: builder.Append(" >= "); break; case RequirementOperator.Multiply: case RequirementOperator.Divide: case RequirementOperator.BitwiseAnd: // handled above, treat like none case RequirementOperator.None: if (suffix != null) { builder.Append(suffix); } return; } Right.AppendString(builder, numberFormat, addAddress); if (suffix != null) { builder.Append(suffix); } }