/// <summary> /// Generates a single change call without calling positions. /// </summary> /// <param name="method">The method to which this call belongs.</param> /// <param name="name">The full name of the call, e.g. "Bob".</param> /// <param name="notations">A list of possible notations, e.g. ['-'. 'b']. Should be lower case.</param> /// <param name="place_notation">The place notation of the call.</param> /// <param name="every">Every how many changes the call can be called.</param> /// <param name="from">How many changes from the `every` changes the call can be called. E.g. for Stedman, this is -3 and `every` is 6.</param> /// <param name="cover">How many plain course changes this change covers (CCCBR now allow calls which change the lead length of the method).</param> public Call(Method method, string name, char [] notations, PlaceNotation place_notation, int every, int from = 0, int cover = -1) { this.method = method; this.name = name; this.notations = notations; place_notations = new PlaceNotation [] { place_notation }; this.every = every; this.from = from; this.cover = cover == -1 ? place_notations.Length : cover; Init(); }
/// <summary> /// Finds a method with a given place notation (uses slow linear search). Returns null if none is found. /// </summary> /// <param name="full_notation">The place notation to check for.</param> /// <returns>The method with that notation.</returns> public static Method GetMethodByPlaceNotation(PlaceNotation [] full_notation) { foreach (StoredMethod stored_method in library.stored_methods) { if (stored_method.stage != full_notation [0].stage) { continue; } if (PlaceNotation.AreEquivalent(full_notation, stored_method.place_notation, stored_method.stage)) { return(stored_method.method); } } return(null); }
/// <summary> /// Checks equality between this object and another object. /// </summary> /// <param name="obj">The other object.</param> /// <returns>True if this is equal to `obj`.</returns> public override bool Equals(object obj) { if (!(obj is PlaceNotation)) { return(false); } PlaceNotation other = obj as PlaceNotation; if (other.array.Length != array.Length) { return(false); } for (int i = 0; i < array.Length; i++) { if (other.array [i] != array [i]) { return(false); } } return(true); }
/// <summary> /// Finds a method with a given stage and place notation (uses slow linear search). Returns null if none is found. /// </summary> /// <param name="notation">The notation to check for.</param> /// <param name="stage">The stage of methods to check.</param> /// <returns>The method with that notation and stage.</returns> public static Method GetMethodByPlaceNotation(string notation, Stage stage) => GetMethodByPlaceNotation(PlaceNotation.DecodeFullNotation(notation, stage));
/// <summary> /// Removes implicit places from a given place notation, as well as adding symmetry. /// </summary> /// <param name="input">The input place notation.</param> /// <param name="stage">The stage on which this place notation is being rung.</param> /// <returns>The place notation compressed as much as possible.</returns> public static string CompressPlaceNotation(string input, Stage stage) { Method method = new Method(input, "", stage, null, false); string output = ""; switch (method.symmetry_type) { case Method.SymmetryType.Asymmetric: for (int i = 0; i < method.lead_length; i++) { PlaceNotation current_notation = method.place_notations [i]; PlaceNotation next_notation = i == method.lead_length - 1 ? null : method.place_notations [i + 1]; if (current_notation.is_x) { output += current_notation.compact_notation; } else if (next_notation == null || next_notation.is_x) { output += current_notation.compact_notation; } else { output += current_notation.compact_notation + basic_delimiters [0]; } } break; case Method.SymmetryType.PlainBobLike: for (int i = 0; i < method.lead_length / 2; i++) { PlaceNotation current_notation = method.place_notations [i]; PlaceNotation next_notation = i == method.lead_length / 2 - 1 ? null : method.place_notations [i + 1]; if (current_notation.is_x) { output += current_notation.compact_notation; } else if (next_notation == null || next_notation.is_x) { output += current_notation.compact_notation; } else { output += current_notation.compact_notation + basic_delimiters [0]; } } output += leadend_delimiters [0] + method.place_notations [method.lead_length - 1].compact_notation; break; case Method.SymmetryType.GrandsireLike: output += method.place_notations [0].compact_notation + leadend_delimiters [0]; for (int i = 1; i < method.lead_length / 2 + 1; i++) { PlaceNotation current_notation = method.place_notations [i]; PlaceNotation next_notation = i == method.lead_length / 2 ? null : method.place_notations [i + 1]; if (current_notation.is_x) { output += current_notation.compact_notation; } else if (next_notation == null || next_notation.is_x) { output += current_notation.compact_notation; } else { output += current_notation.compact_notation + basic_delimiters [0]; } } break; } return(output); }
// Static Stuff /// <summary> /// Converts a string of place notations (with lead end shortcuts, implicit places, etc.) to an array of <see cref="PlaceNotation"/> objects. /// </summary> /// <param name="full_notation">The string of place notations.</param> /// <param name="stage">The <see cref="Stage"/> of the place notations.</param> /// <returns>An array of converted place notations</returns> public static PlaceNotation [] DecodeFullNotation(string full_notation, Stage stage) { full_notation = full_notation.ToUpper(); List <string> segments = new List <string> (); string segment = ""; int index = 0; int leadend_index = -1; string GetNextSubstringFrom(string [] list) { string delimiter = ""; foreach (string i in list) { if (index + i.Length > full_notation.Length) { continue; } if (full_notation.Substring(index, i.Length) == i) { delimiter = i; } } return(delimiter); } while (index < full_notation.Length) { // Delimiter string delimiter = GetNextSubstringFrom(basic_delimiters); if (delimiter != "") { index += delimiter.Length; if (segment != "") { segments.Add(segment); segment = ""; } continue; } // Lead-end string le_delimiter = GetNextSubstringFrom(leadend_delimiters); if (le_delimiter != "") { index += le_delimiter.Length; if (segment != "") { segments.Add(segment); segment = ""; } leadend_index = segments.Count; continue; } // X string x = GetNextSubstringFrom(x_notations); if (x != "") { index += x.Length; if (segment != "") { segments.Add(segment); segment = ""; } segments.Add(x); continue; } // Just bog standard notation string next_char = full_notation.Substring(index, 1); if (Constants.bell_names.Contains(next_char)) { segment += next_char; index += 1; continue; } // If the loop gets this far, just reject the character, // 'cos no-one cares about it index += 1; } // Add the last segment if (segment != "") { segments.Add(segment); } // Expand lead-end notation if (leadend_index != -1) { if (leadend_index == 1) { // Grandsire-like method List <String> part_to_reverse = segments.GetRange(1, segments.Count - 2); string half_lead = segments [segments.Count - 1]; string lead_end = segments [0]; segments.Clear(); segments.Add(lead_end); segments.AddRange(part_to_reverse); segments.Add(half_lead); part_to_reverse.Reverse(); segments.AddRange(part_to_reverse); } if (leadend_index == segments.Count - 1) { // Plain Bob-like method List <String> part_to_reverse = segments.GetRange(0, segments.Count - 2); string half_lead = segments [segments.Count - 2]; string lead_end = segments [segments.Count - 1]; segments.Clear(); segments.AddRange(part_to_reverse); segments.Add(half_lead); part_to_reverse.Reverse(); segments.AddRange(part_to_reverse); segments.Add(lead_end); } } // Build notations from strings PlaceNotation [] notations = new PlaceNotation [segments.Count]; for (int i = 0; i < segments.Count; i++) { notations [i] = new PlaceNotation(segments [i], stage); } return(notations); }
/// <summary> /// Shorthand for transposing a change by a list of place notations, e.g. a list of the place notations in a plain lead of a method. /// </summary> /// <param name="change">The change which is being transposed.</param> /// <param name="place_notations">The list of place notations over which the change will be transposed.</param> /// <returns>The transposed change.</returns> public static Change operator *(Change change, PlaceNotation [] place_notations) { return(change.Transpose(PlaceNotation.CombinePlaceNotations(place_notations))); }
/// <summary> /// Creates a `single` call over the lead end of a given method. /// </summary> /// <param name="method">The method to which the call belongs.</param> /// <param name="notation">The full place notation of the call, e.g. "3.123" for Grandsire Singles.</param> /// <param name="calling_positions">The array of calling positions by place at the lead end.</param> /// <returns>The `single` call that was created.</returns> public static Call LeadEndSingle(Method method, string notation, string [] calling_positions = null) => LeadEndSingle(method, PlaceNotation.DecodeFullNotation(notation, method.stage), calling_positions);
/// <summary> /// Creates a `single` call over the lead end of a given method. /// </summary> /// <param name="method">The method to which the call belongs.</param> /// <param name="place_notation">The place notation of the call.</param> /// <param name="calling_positions">The array of calling positions by place at the lead end.</param> /// <returns>The `single` call that was created.</returns> public static Call LeadEndSingle(Method method, PlaceNotation place_notation, string [] calling_positions = null) => LeadEndSingle(method, new PlaceNotation [] { place_notation }, calling_positions);