/// <summary> /// Tries to find the object corresponding to a given one with respect to a given mapping. /// If the object is not present in the mapping, it assumed the passed object is /// a constructed one and tries to construct it by remapping its arguments. If it fails, /// a <see cref="GeoGenException"/> is thrown. (This is a helper method used by implementations /// of <see cref="Remap(IReadOnlyDictionary{ConfigurationObject, ConfigurationObject})"/>). /// </summary> /// <param name="configurationObject">The configuration object to be mapped.</param> /// <param name="mapping">The dictionary representing the mapping.</param> /// <returns>The remapped configuration object, or null, if mapping would yield a new incorrect constructed object.</returns> protected static ConfigurationObject Map(ConfigurationObject configurationObject, IReadOnlyDictionary <ConfigurationObject, ConfigurationObject> mapping) { // If the object is directly present in the map, return it if (mapping.ContainsKey(configurationObject)) { return(mapping[configurationObject]); } // Otherwise we assume the passed object is a constructed one var constructedObject = configurationObject as ConstructedConfigurationObject // If not, make aware ?? throw new GeoGenException("Cannot do the mapping, because the passed object is not in the map, nor it's constructed."); // Convert the individual passed objects var mappedObjects = constructedObject.PassedArguments.FlattenedList // Look for the inner objects in the mapping .Select(innerObject => mapping.GetValueOrDefault(innerObject) // They must be there ?? throw new GeoGenException("Cannot do the mapping, because not all the arguments of the passed object are in the map.")) // Enumerate .ToArray(); // If the objects are not same, the mapping cannot be done if (mappedObjects.AnyDuplicates()) { return(null); } // Otherwise construct the remapped object return(new ConstructedConfigurationObject(constructedObject.Construction, mappedObjects)); }
/// <summary> /// Initializes a new instance of the <see cref="PointTheoremObject"/> class. /// </summary> /// <param name="configurationObject">The configuration object whose type must be <see cref="ConfigurationObjectType.Point"/>.</param> public PointTheoremObject(ConfigurationObject configurationObject) : base(configurationObject) { // Make sure the object is not null if (configurationObject == null) { throw new GeoGenException("A point theorem object must have its configuration object set."); } }
/// <summary> /// Initializes a new instance of the <see cref="TheoremObjectWithPoints"/> class /// defining by a <see cref="ConfigurationObject"/>. /// </summary> /// <param name="configurationObject">The configuration object representing this theorem object.</param> protected TheoremObjectWithPoints(ConfigurationObject configurationObject) : base(configurationObject) { // Make sure the defining object exists if (configurationObject == null) { throw new GeoGenException("The defining configuration object cannot be null."); } }
/// <summary> /// Gets the string definition of a passed configuration object. Loose objects have only /// names as their definition, whereas constructed objects have the construction and arguments. /// </summary> /// <param name="configurationObject">The object that we're formatting.</param> /// <returns>The string representing the object.</returns> public string FormatConfigurationObject(ConfigurationObject configurationObject) { // Switch based on the object return(configurationObject switch { // Loose objects have their names as the definition LooseConfigurationObject _ => _objectNames[configurationObject], // For constructed objects we include the construction and arguments ConstructedConfigurationObject constructedObject => $"{constructedObject.Construction.Name}({constructedObject.PassedArguments.Select(FormatArgument).ToJoinedString()})", // Unhandled cases _ => throw new GeoGenException($"Unhandled type of {nameof(ConfigurationObject)}: {configurationObject.GetType()}") });
/// <summary> /// Finds the objects that define this object, in an order in which they can be constructed, including this one. /// </summary> /// <param name="configurationObject">The configuration object.</param> /// <returns>The collection of the defining objects.</returns> public static IReadOnlyList <ConfigurationObject> GetDefiningObjects(this ConfigurationObject configurationObject) => configurationObject.ToEnumerable().GetDefiningObjects();
/// <summary> /// Initializes a new instance of the <see cref="LineTheoremObject"/> /// class defined by points. /// </summary> /// <param name="point1">A point of the line.</param> /// <param name="point2">A point of the line.</param> public LineTheoremObject(ConfigurationObject point1, ConfigurationObject point2) : base(point1, point2) { }
/// <summary> /// Initializes a new instance of the <see cref="LineTheoremObject"/> class /// defined by a line configuration object. /// </summary> /// <param name="lineObject">The configuration line object representing this theorem object.</param> public LineTheoremObject(ConfigurationObject lineObject) : base(lineObject) { }
/// <summary> /// Initializes a new instance of the <see cref="CircleTheoremObject"/> /// class defined by points. /// </summary> /// <param name="point1">A point of the circle.</param> /// <param name="point2">A point of the circle.</param> /// <param name="point3">A point of the circle.</param> public CircleTheoremObject(ConfigurationObject point1, ConfigurationObject point2, ConfigurationObject point3) : base(point1, point2, point3) { }
/// <summary> /// Initializes a new instance of the <see cref="CircleTheoremObject"/> class /// defined by a circle configuration object. /// </summary> /// <param name="circleObject">The configuration circle object representing this theorem object.</param> public CircleTheoremObject(ConfigurationObject circleObject) : base(circleObject) { }
/// <summary> /// Initializes a new instance of the <see cref="ObjectConstructionArgument"/> class. /// </summary> /// <param name="passedObject">The configuration object that is passed as an argument.</param> public ObjectConstructionArgument(ConfigurationObject passedObject) { PassedObject = passedObject ?? throw new ArgumentNullException(nameof(passedObject)); }
/// <inheritdoc/> public override int GetHashCode() => ConfigurationObject.GetHashCode();
/// <inheritdoc/> public override IEnumerable <ConfigurationObject> GetInnerConfigurationObjects() => ConfigurationObject.ToEnumerable();
/// <summary> /// Initializes a new instance of the <see cref="LineSegmentTheoremObject"/> class. /// </summary> /// <param name="point1">The first point of the line segment.</param> /// <param name="point2">The second line of the line segment.</param> public LineSegmentTheoremObject(ConfigurationObject point1, ConfigurationObject point2) : this(new PointTheoremObject(point1), new PointTheoremObject(point2)) { }