/// <summary> /// Metabolic evolution rule constructor. /// </summary> /// <param name="priority">Priority of the evolution rule.</param> /// <param name="leftSideObjects">List of left side objects.</param> /// <param name="rightSideObjects">List of right side objects.</param> /// <param name="delay">Number of steps which must be done before rule is applied to tiles.</param> /// <exception cref="ArgumentException"> /// If format of the metabolic rule is invalid /// </exception> public EvoMetabolicRule(int priority, List <ISimulationObject> leftSideObjects, List <ISimulationObject> rightSideObjects, int delay) : base(RuleType.Metabolic, priority, leftSideObjects, rightSideObjects, delay) { string errorMessage = string.Format("{0}\n{1} ", "Invalid metabolic rule format:", this); // The rules must contain exactly one protein. try { RProtein = LeftSideObjects.OfType <Protein>().Single(); if (RProtein != RightSideObjects.OfType <Protein>().Single()) { throw new ArgumentException(errorMessage); } } catch (InvalidOperationException) { throw new ArgumentException(errorMessage); } // The objects before protein are "out" (must be on the outer side of 2D object). // The objects after protein are "in" (must be on the inner side of 2D object). MLeftOutNames = new NamedMultiset(LeftSideObjects.TakeWhile(obj => obj is FloatingObject)); MLeftInNames = new NamedMultiset(LeftSideObjects.SkipWhile(obj => obj is FloatingObject).OfType <FloatingObject>()); MRightOutNames = new NamedMultiset(RightSideObjects.TakeWhile(obj => obj is FloatingObject)); MRightInNames = new NamedMultiset(RightSideObjects.SkipWhile(obj => obj is FloatingObject).OfType <FloatingObject>()); // Both left and right-hand side of the rule must contain at least one floating object if (MLeftInNames.Count + MLeftOutNames.Count > 0 && MRightInNames.Count + MRightOutNames.Count > 0) { if (MLeftOutNames.Count + MRightOutNames.Count == 0 || MLeftInNames.Count + MRightInNames.Count == 0) { SubType = MetabolicRuleType.Catalyzed; } else if (MLeftInNames.Equals(MRightOutNames) && MLeftOutNames.Equals(MRightInNames)) { if (MLeftInNames.Count == 0 || MLeftOutNames.Count == 0) { SubType = MetabolicRuleType.Symport; } else { SubType = MetabolicRuleType.Antiport; } } } if (SubType == MetabolicRuleType.Undefined) { throw new ArgumentException(errorMessage); } }
/// <summary> /// Non-metabolic evolution rule constructor. /// </summary> /// <param name="type">Type of the evolution rule.</param> /// <param name="priority">Priority of the evolution rule.</param> /// <param name="leftSideObjects">List of left side objects.</param> /// <param name="rightSideObjects">List of right side objects.</param> /// <param name="delay">Number of steps which must be done before rule is applied to tiles.</param> /// <exception cref="ArgumentException"> /// If format of the non-metabolic rule is invalid /// </exception> public EvoNonMetabolicRule(RuleType type, int priority, List <ISimulationObject> leftSideObjects, List <ISimulationObject> rightSideObjects, int delay) : base(type, priority, leftSideObjects, rightSideObjects, delay) { string errorMessage = $"{"Invalid rule format:"}\n{this} "; bool correct = false; switch (type) { case RuleType.Create: case RuleType.Insert: correct = //leftSideObjects.Count >= 1 && leftSideObjects.TrueForAll(obj => obj is FloatingObject) && rightSideObjects.SingleOrDefault() is Tile; break; case RuleType.Destroy: correct = leftSideObjects.Count >= 2 && leftSideObjects.OfType <Tile>().Count() == 1 && leftSideObjects.TrueForAll(obj => obj is FloatingObject || obj is Tile) && rightSideObjects.TrueForAll(obj => obj is FloatingObject); break; case RuleType.Divide: correct = leftSideObjects.Count >= 3 && leftSideObjects.OfType <Glue>().Count() == 2 && leftSideObjects.TrueForAll(obj => obj is FloatingObject || obj is Glue) && rightSideObjects.Count() == 2 && rightSideObjects[0] == leftSideObjects.OfType <Glue>().First() && rightSideObjects[1] == leftSideObjects.OfType <Glue>().Last(); break; } if (!correct) { throw new ArgumentException(errorMessage); } MLeftSideFloatingNames = new NamedMultiset(LeftSideObjects.OfType <FloatingObject>()); MRightSideFloatingNames = new NamedMultiset(RightSideObjects.OfType <FloatingObject>()); }