diff --git a/Basic.props b/Basic.props new file mode 100644 index 00000000..131a29f2 --- /dev/null +++ b/Basic.props @@ -0,0 +1,36 @@ + + + Trivial + Kingcean Tuan + Nanchang Jinchen Software Co., Ltd. + 8.0.0 + 8.0.0.0 + 8.0.0.0 + Copyright (c) 2018 Kingcean Tuan. + MIT + https://github.com/nuscien/trivial + git + true + README.md + 12.0 + True + ..\Trivial.snk + + + + NETOLDVER + + + + + + + + + + + + + + + diff --git a/Chemistry/Chemistry.csproj b/Chemistry/Chemistry.csproj deleted file mode 100644 index f329f1dd..00000000 --- a/Chemistry/Chemistry.csproj +++ /dev/null @@ -1,72 +0,0 @@ - - - - net8.0;net6.0;net48;net462;net461 - Trivial.Chemistry - Trivial - Trivial.Chemistry - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 - A library with basic chemical models. - Copyright (c) 2021 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/chemistry - true - true - snupkg - https://github.com/nuscien/trivial - git - true - chemistry.png - https://github.com/nuscien/trivial/raw/master/Materials/logo.png - chemistry chemical-element periodic-table molecular - README.md - 12.0 - True - ..\Trivial.snk - - - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Chemistry.xml - - - - ..\bin\Release\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Chemistry.xml - - - - - - - - - - - - - - - - - - - True - True - ChemistryResource.resx - - - - - - ResXFileCodeGenerator - ChemistryResource.Designer.cs - - - - diff --git a/Chemistry/Chemistry/ChemicalBond.cs b/Chemistry/Chemistry/ChemicalBond.cs deleted file mode 100644 index 05e26015..00000000 --- a/Chemistry/Chemistry/ChemicalBond.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Chemistry; - -/// -/// The types of chemcial bond. -/// -public enum ChemicalBondTypes : byte -{ - /// - /// Ionic bond. - /// - Ionic = 0, - - /// - /// Covalent bound. - /// - Covalent = 1, - - /// - /// Metallic bound. - /// - Metallic = 2 -} - -/// -/// The chemical bond information. -/// -public class ChemicalBond -{ - /// - /// Initializes a new instance of the ChemicalBond class. - /// - /// The chemical bond type. - /// The bond numbers. - public ChemicalBond(ChemicalBondTypes type, int numbers) - { - Type = type; - Numbers = numbers; - } - - /// - /// Gets the chemical bond type. - /// - public ChemicalBondTypes Type { get; } - - /// - /// Gets the bound numbers. - /// - public int Numbers { get; } -} diff --git a/Chemistry/Chemistry/ChemicalElement.cs b/Chemistry/Chemistry/ChemicalElement.cs deleted file mode 100644 index 1747651a..00000000 --- a/Chemistry/Chemistry/ChemicalElement.cs +++ /dev/null @@ -1,825 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.Chemistry; - -/// -/// The model of chemical element. -/// -[JsonConverter(typeof(ChemicalElementJsonConverter))] -public partial class ChemicalElement : IEquatable -{ - /// - /// The maximum atomic number in each period. - /// - private readonly static int[] periodNumbers = new []{ 2, 10, 18, 36, 54, 86, 118, 168, 218, 290, 362, 460, 558, 686, 814, 976, 1138, 1338, 1538 }; - - /// - /// The element name. - /// - private readonly Func name; - - /// - /// All mass information of its isotopes. - /// - private double[] mass; - - /// - /// All isotopes. - /// - private List isotopes; - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element identifier. - /// The English name. - /// The atomic weight in dalton (unified atomic mass unit). - /// All mass information of its isotopes. - internal ChemicalElement(int number, string symbol, string englishName, double atomicWeight, double[] isotopicMass = null) - { - symbol = symbol?.Trim(); - Symbol = string.IsNullOrEmpty(symbol) ? GetSymbol(number) : symbol; - AtomicNumber = number; - (Period, IndexInPeriod) = GetPeriod(number); - Group = GetGroup(Period, IndexInPeriod); - englishName = englishName?.Trim(); - EnglishName = string.IsNullOrEmpty(englishName) ? GetName(number) : englishName; - AtomicWeight = atomicWeight; - HasAtomicWeight = !double.IsNaN(atomicWeight); - mass = isotopicMass; - Block = Group switch - { - 1 or 2 => "s", - 18 => AtomicNumber == 2 ? "s" : "p", - 13 or 14 or 15 or 16 or 17 => "p", - 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 => "d", - 11 or 12 => "ds", - _ => string.Empty - }; - if (Group != 3 || Period < 6) return; - var count = CountInPeriod(Period); - var countdown = count - IndexInPeriod; - if (countdown <= 16) return; - Block = "f"; - if (Period < 8 || countdown <= 30) return; - Block = "g"; - if (Period < 10 || countdown <= 48) return; - Block = "i"; - if (Period < 12 || countdown <= 70) return; - Block = "j"; - if (Period < 14 || countdown <= 96) return; - Block = string.Empty; - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element symbol. - /// The English name. - /// The atomic weight in dalton (unified atomic mass unit). - /// All mass information of its isotopes. - internal ChemicalElement(int number, string symbol, string englishName, int atomicWeight, double[] isotopicMass = null) - : this(number, symbol, englishName, double.NaN, isotopicMass) - { - AtomicWeight = atomicWeight; - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element symbol. - /// The English name. - /// The name resolver. - /// The atomic weight in dalton (unified atomic mass unit). - /// The optional isotopes. - public ChemicalElement(int number, string symbol, string englishName, Func name, double atomicWeight, IEnumerable isotopes = null) - : this(number, symbol, englishName, atomicWeight) - { - if (name is null) return; - this.name = name; - this.isotopes = isotopes?.ToList(); - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element symbol. - /// The English name. - /// The name. - /// The atomic weight in dalton (unified atomic mass unit). - /// The optional isotopes. - public ChemicalElement(int number, string symbol, string englishName, string name, double atomicWeight, IEnumerable isotopes = null) - : this(number, symbol, englishName, atomicWeight) - { - name = name?.Trim(); - if (!string.IsNullOrEmpty(name)) this.name = () => name; - this.isotopes = isotopes?.ToList(); - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element symbol. - /// The name. - /// true if the parameter name is also an English name. - /// The atomic weight in dalton (unified atomic mass unit). - /// The optional isotopes. - public ChemicalElement(int number, string symbol, string name, bool isAlsoEnglishName, double atomicWeight, IEnumerable isotopes = null) - : this(number, symbol, isAlsoEnglishName ? name : null, name, atomicWeight, isotopes) - { - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element identifier. - /// The English name. - /// The name. - public ChemicalElement(int number, string symbol, string englishName, string name) - : this(number, symbol, englishName, name, double.NaN) - { - } - - /// - /// Initializes a new instance of the ChemicalElement class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The element symbol. - /// The name. - /// true if the parameter name is also an English name. - public ChemicalElement(int number, string symbol, string name, bool isAlsoEnglishName) - : this(number, symbol, isAlsoEnglishName ? name : null, name, double.NaN) - { - } - - /// - /// The element symbol. - /// - public string Symbol { get; } - - /// - /// The name. - /// - public string Name - { - get - { - var s = name?.Invoke(); - if (!string.IsNullOrEmpty(s)) return s; - var table = periodicTable; - if (name is null && table != null && AtomicNumber <= table.Length) - { - try - { - s = ChemistryResource.ResourceManager.GetString("Element" + AtomicNumber.ToString("000"))?.Trim(); - if (!string.IsNullOrEmpty(s)) return s; - } - catch (InvalidOperationException) - { - } - catch (System.Resources.MissingManifestResourceException) - { - } - catch (System.Resources.MissingSatelliteAssemblyException) - { - } - } - - s = ChemistryResource.ElementX?.Trim(); - if (!string.IsNullOrEmpty(s) && s.Contains('{')) - return s - .Replace("{0}", AtomicNumber.ToString("g")) - .Replace("{number}", AtomicNumber.ToString("g")) - .Replace("{symbol}", Symbol); - return EnglishName ?? Symbol ?? ChemistryResource.Element; - } - } - - /// - /// Gets the element name in English accepted by IUPAC. - /// - public string EnglishName { get; } - - /// - /// Gets the atomic number (or proton number, Atomzahl, symbol Z) of the chemical element. - /// It is the one-based number of protons found in the nucleus of every atom of that element. - /// - public int AtomicNumber { get; } - - /// - /// Gets the period which is a one-based index of horizontal row in the periodic table. - /// - public int Period { get; } - - /// - /// Gets a zero-based index of the element in the period. - /// - public int IndexInPeriod { get; } - - /// - /// Gets the IUPAC group (or family) which is a one-based index of vertical column in the periodic table. - /// -1 for others (N/A) which only appears in Period 6 and later. - /// - public int Group { get; } - - /// - /// Gets the atomic weight in dalton (unified atomic mass unit). - /// - public double AtomicWeight { get; } - - /// - /// Gets a value indicating whether has atomic weight information. - /// - public bool HasAtomicWeight { get; } - - /// - /// Gets block which is a set of elements unified by the orbitals their valence electrons or vacancies lie in. - /// - public string Block { get; } - - /// - /// Gets a value indicating whether it is alkali metal. - /// - public bool IsAlkaliMetal => Period > 1 && Group == 1; - - /// - /// Gets a value indicating whether it is alkaline-earth metal. - /// - public bool IsAlkalineEarthMetal => Group == 2; - - /// - /// Gets a value indicating whether it is in VIII group. - /// - public bool IsInVIII => Group > 7 && Group < 11; - - /// - /// Gets a value indicating whether it is transition element. - /// - public bool IsTransition => Group > 2 && Group < 13; - - /// - /// Gets a value indicating whether it is metallic element. - /// - public bool IsMetal - { - get - { - if (Period < 2 || Group > 16) return false; - if (Group < 13 || Period > 5) return true; - return Period + 10 >= Group; - } - } - - /// - /// Gets a value indicating whether it is non-metallic element. - /// - public bool IsNonMetallic => !IsMetal; - - /// - /// Gets a value indicating whether it is in boron group. - /// - public bool IsInBoronGroup => Group == 13; - - /// - /// Gets a value indicating whether it is in carbon group. - /// - public bool IsInCarbonGroup => Group == 14; - - /// - /// Gets a value indicating whether it is in nitrogen group. - /// - public bool IsInNitrogenGroup => Group == 15; - - /// - /// Gets a value indicating whether it is chalcogen. - /// - public bool IsChalcogen => Group == 16; - - /// - /// Gets a value indicating whether it is halogen. - /// - public bool IsHalogen => Group == 17; - - /// - /// Gets a value indicating whether it is one of noble gases. - /// - public bool IsNoble => Group == 18; - - /// - /// Gets a value indicating whether this element is valid. - /// - public bool IsValid() - => Period > 0 && !string.IsNullOrEmpty(Symbol); - - /// - /// Gets all isotopes registered. - /// - /// The isotope collection. - public IReadOnlyList Isotopes() - { - if (isotopes is null) - { - var col = mass?.Select(ele => new Isotope(this, (int)Math.Round(ele), ele))?.ToList() ?? new(); - isotopes ??= col; - mass = null; - } - - return isotopes.AsReadOnly(); - } - - /// - /// Gets an isotope. - /// - /// The atomic mass number (total protons and neutrons). - /// An isotope of this element with the specific numbers of neutrons. - public Isotope Isotope(int atomicMassNumber) - { - var col = Isotopes(); - return col?.FirstOrDefault(ele => ele.AtomicMassNumber == atomicMassNumber) - ?? new(this, atomicMassNumber, AtomicNumber < 160 && Math.Abs(atomicMassNumber - AtomicWeight) < 0.4 ? AtomicWeight : double.NaN); - } - - /// - /// Gets an isotope. - /// - /// The atomic mass number (total protons and neutrons). - /// The atomic weight in dalton (unified atomic mass unit). - /// An isotope of this element with the specific numbers of neutrons. - public Isotope Isotope(int atomicMassNumber, double atomicWeight) - { - var isotope = Isotopes()?.FirstOrDefault(ele => ele.AtomicMassNumber == atomicMassNumber); - if (isotope != null && Math.Abs(isotope.AtomicWeight - atomicWeight) > 0.000000001) isotope = null; - return isotope ?? new(this, atomicMassNumber, atomicWeight); - } - - /// - /// Adds an isotope. - /// - /// The atomic mass number (total protons and neutrons). - /// The atomic weight in dalton (unified atomic mass unit). - /// An isotope of this element with the specific numbers of neutrons. - public Isotope AddIsotope(int atomicMassNumber, double atomicWeight) - { - var isotope = Isotopes()?.FirstOrDefault(ele => ele.AtomicMassNumber == atomicMassNumber); - if (isotope != null && Math.Abs(isotope.AtomicWeight - atomicWeight) > 0.000000001) isotope = null; - if (isotope is null) - { - isotope = new(this, atomicMassNumber, atomicWeight); - isotopes.Add(isotope); - } - - return isotope; - } - - /// - /// Removes an isotope. - /// - /// The isotope to remove. - /// true if exists; otherwise, false. - public bool RemoveIsotope(Isotope isotope) - { - if (!isotopes.Remove(isotope)) return false; - if (isotopes.Remove(isotope)) isotopes.Remove(isotope); - return true; - } - - /// - /// Removes all isotopes registered. - /// - public void ClearIsotopes() - { - isotopes.Clear(); - } - - /// - /// Writes this instance to the specified writer as a JSON value. - /// - /// The writer to which to write this instance. - public void WriteTo(Utf8JsonWriter writer) - { - var json = (JsonObjectNode)this; - json.WriteTo(writer); - } - - /// - /// Writes to file. - /// - /// The file to write. - /// The indent style. - /// IO exception. - /// Write failed because of security exception. - /// The file path was null. - /// The file was not supported. - /// Write failed because of unauthorized access exception. - public void WriteTo(FileInfo file, IndentStyles style = IndentStyles.Minified) - { - var json = (JsonObjectNode)this; - json.WriteTo(file, style); - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public bool Equals(ChemicalElement other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return AtomicNumber == other.AtomicNumber - && Symbol == other.Symbol; - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public bool Equals(JsonObjectNode other) - { - if (other is null) return false; - return AtomicNumber == other.TryGetInt32Value("number") - && Symbol == other.TryGetStringValue("symbol"); - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is ChemicalElement element) return Equals(element); - if (other is JsonObjectNode json) return Equals(json); - return false; - } - - /// - /// Compares two chemical elements to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two chemical elements to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Compares a chemical elements is less than another one. - /// leftValue < rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator <(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue) || rightValue is null) return false; - if (leftValue is null) return true; - return leftValue.AtomicNumber < rightValue.AtomicNumber; - } - - /// - /// Compares a chemical elements is greater than another one. - /// leftValue > rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator >(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue) || leftValue is null) return false; - if (rightValue is null) return true; - return leftValue.AtomicNumber > rightValue.AtomicNumber; - } - - /// - /// Compares a chemical elements is less than or equals to another one. - /// leftValue <= rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator <=(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue) || leftValue is null) return true; - if (rightValue is null) return false; - return leftValue.AtomicNumber <= rightValue.AtomicNumber; - } - - /// - /// Compares a chemical elements is greater than or equals to another one. - /// leftValue <= rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator >=(ChemicalElement leftValue, ChemicalElement rightValue) - { - if (ReferenceEquals(leftValue, rightValue) || rightValue is null) return true; - if (leftValue is null) return false; - return leftValue.AtomicNumber >= rightValue.AtomicNumber; - } - - /// - /// Peturns a string that represents the current chemical element information. - /// - /// A string that represents the current chemical element information. - public override string ToString() - { - var sb = new StringBuilder(); - sb.Append(Name); - sb.Append(" ("); - if (AtomicNumber < 1) - sb.Append('?'); - else - sb.Append(AtomicNumber); - - if (!Name.Equals(Symbol, StringComparison.OrdinalIgnoreCase) - && !"?".Equals(Symbol, StringComparison.OrdinalIgnoreCase)) - { - sb.Append(' '); - sb.Append(Symbol); - } - - sb.Append(')'); - return sb.ToString(); - } - - /// - public override int GetHashCode() - { - return base.GetHashCode(); - } - - /// - /// Converts to a JSON object. - /// - /// The chemical element to convert. - public static explicit operator JsonObjectNode(ChemicalElement element) - { - if (element is null || element.AtomicNumber < 1) return null; - var json = new JsonObjectNode - { - { "number", element.AtomicNumber }, - { "symbol", element.Symbol }, - { "period", element.Period }, - { "name", element.Name } - }; - if (element.Group > 0) - json.SetValue("group", element.Group); - if (!double.IsNaN(element.AtomicWeight)) - json["weight"] = element.HasAtomicWeight ? new JsonDoubleNode(element.AtomicWeight) : new JsonIntegerNode(element.AtomicWeight); - if (!element.EnglishName.Equals(element.Name)) - json.SetValue("name_en", element.EnglishName); - if (element.isotopes != null && element.isotopes.Count > 0) - { - var arr = new JsonArrayNode(); - foreach (var isotope in element.isotopes) - { - var json2 = new JsonObjectNode - { - { "symbol", isotope.ToString() }, - { "neutrons", isotope.Neutrons }, - { "mass", isotope.AtomicMassNumber } - }; - if (!double.IsNaN(isotope.AtomicWeight)) json2.SetValue("weight", isotope.AtomicWeight); - arr.Add(json2); - } - - json.SetValue("isotopes", arr); - } - - return json; - } - - /// - /// Converts to a JSON object. - /// - /// The chemical element to convert. - public static explicit operator JsonDocument(ChemicalElement element) - { - if (element is null || element.AtomicNumber < 1) return null; - return (JsonDocument)(JsonObjectNode)element; - } - - /// - /// Converts to a JSON object. - /// - /// The chemical element to convert. - public static explicit operator System.Text.Json.Nodes.JsonObject(ChemicalElement element) - { - if (element is null || element.AtomicNumber < 1) return null; - return (System.Text.Json.Nodes.JsonObject)(JsonObjectNode)element; - } - - /// - /// Converts to a JSON object. - /// - /// The chemical element to convert. - public static explicit operator JsonStringNode(ChemicalElement element) - { - return element is null ? null : new JsonStringNode(element.Symbol); - } - - /// - /// Converts to a JSON object. - /// - /// The chemical element to convert. - public static explicit operator JsonIntegerNode(ChemicalElement element) - { - return element is null ? null : new JsonIntegerNode(element.AtomicNumber); - } - - /// - /// Pluses two chemical elements. - /// - /// The left value for addition operator. - /// The right value for addition operator. - /// A result after addition. - public static MolecularFormula operator +(ChemicalElement leftValue, ChemicalElement rightValue) - { - var isLeftEmpty = string.IsNullOrEmpty(leftValue?.Symbol); - var isRightEmpty = string.IsNullOrEmpty(rightValue?.Symbol); - if (isLeftEmpty && isRightEmpty) return null; - if (isLeftEmpty) return new MolecularFormula(rightValue); - if (isRightEmpty) return new MolecularFormula(leftValue); - return new MolecularFormula(leftValue, 1, rightValue, 1); - } - - /// - /// Multiplies a chemical element and an integer number. - /// - /// The left value for multiple operator. - /// The right value for multiple operator. - /// A result after multiple. - public static MolecularFormula operator *(ChemicalElement leftValue, int rightValue) - { - if (string.IsNullOrEmpty(leftValue?.Symbol) || rightValue < 1) return null; - return new MolecularFormula(leftValue, rightValue); - } - - /// - /// Multiplies a chemical element and an integer number. - /// - /// The left value for multiple operator. - /// The right value for multiple operator. - /// A result after multiple. - public static MolecularFormula operator *(int leftValue, ChemicalElement rightValue) - { - if (string.IsNullOrEmpty(rightValue?.Symbol) || leftValue < 1) return null; - return new MolecularFormula(rightValue, leftValue); - } - - /// - /// Gets the atomic number of the first element in the specific period. - /// - /// The period. - /// The atomic number of the first element in the specific period; or -1, if the period is invalid. - public static int FirstAtomicNumberInPeriod(int period) - { - if (period < 1) return -1; - var number = 1; - var count = 2; - var diff = 2; - for (var i = 1; i < period; i++) - { - number += count; - diff += 4; - count += diff; - i++; - if (i >= period) break; - number += count; - } - - return number; - } - - /// - /// Gets the atomic number of the first element in the specific period. - /// - /// The period. - /// The atomic number of the first element in the specific period; or -1, if the period is invalid. - public static int LastAtomicNumberInPeriod(int period) - { - if (period < 1) return -1; - var number = 2; - var count = 2; - var diff = 2; - for (var i = 1; i < period; i++) - { - diff += 4; - count += diff; - i++; - number += count; - if (i >= period) break; - number += count; - } - - return number; - } - - /// - /// Gets the element count in a specific period. - /// - /// The period which is a one-based index of horizontal row in the periodic table. - /// The count in this period; or -1, if the period is out of range. - public static int CountInPeriod(int period) - { - if (period < 1) return -1; - var count = 2; - var diff = 2; - for (var i = 1; i < period; i++) - { - diff += 4; - count += diff; - i++; - if (i >= period) break; - } - - return count > 0 ? count : -1; - } - - /// - /// Gets the group. - /// - /// The period which is a one-based index of horizontal row in the periodic table. - /// Gets a zero-based index of the element in the period. - /// The count in this period; or -1, if not available. - private static int GetGroup(int period, int index) - { - if (period < 1 || index < 0) return -1; - if (index == 0) return 1; - if (period == 1) return 18; - if (index == 1) return 2; - if (period < 4) return index + 11; - if (period < 6) return index + 1; - var i = 18 - CountInPeriod(period) + index + 1; - return i < 3 ? 3 : i; - } - - /// - /// Gets the period which is a one-based index of horizontal row in the periodic table. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. - /// The period, and the index in this period. - private static (int, int) GetPeriod(int number) - { - if (number < 1) return (-1, -1); - if (number <= 2) return (1, number - 1); - for (var i = 1; i < periodNumbers.Length; i++) - { - if (number > periodNumbers[i]) continue; - var j = number - periodNumbers[i - 1] - 1; - return (i + 1, j); - } - - var diff = 42; - var count = 242; - var max = 1780; - for (var i = 20; max > 0; i++) - { - if (number <= max) return (i, number - max + count - 1); - max += count; - if (number <= max) return (i, number - max + count - 1); - count += diff; - max += count; - } - - return (-1, -1); - } -} diff --git a/Chemistry/Chemistry/ChemicalElementJsonConverter.cs b/Chemistry/Chemistry/ChemicalElementJsonConverter.cs deleted file mode 100644 index c94a7c63..00000000 --- a/Chemistry/Chemistry/ChemicalElementJsonConverter.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -using Trivial.Text; - -namespace Trivial.Chemistry; - -/// -/// Chemical element JSON converter. -/// -sealed class ChemicalElementJsonConverter : JsonConverter -{ - /// - public override ChemicalElement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - return null; - try - { - if (reader.TokenType == JsonTokenType.Number) - return ChemicalElement.Get(reader.GetInt32()); - } - catch (FormatException ex) - { - throw new JsonException("Expect a valid chemical element symbol or the atomic numbers.", ex); - } - - if (reader.TokenType == JsonTokenType.String) - return ChemicalElement.Get(reader.GetString()); - if (reader.TokenType != JsonTokenType.StartObject) - throw new JsonException("The format is not correct. Expect a JSON object, a number or a string for the chemical element.", new FormatException("The value should be a JSON object token format.")); - var obj = new JsonObjectNode(); - obj.SetRange(ref reader); - var z = obj.TryGetInt32Value("number") ?? obj.TryGetInt32Value("z"); - var s = obj.TryGetStringValue("symbol")?.Trim(); - var n = obj.TryGetStringValue("name_en")?.Trim() ?? obj.TryGetStringValue("name")?.Trim(); - var w = obj.TryGetDoubleValue("weight"); - ChemicalElement ele = null; - if (z.HasValue && z != 0) - { - if (z.Value < 1) return null; - ele = ChemicalElement.Get(z.Value); - } - else if (!string.IsNullOrEmpty(s)) - { - ele = ChemicalElement.Get(s); - } - else if (!string.IsNullOrEmpty(n)) - { - ele = ChemicalElement.Where(ele => n.Equals(ele.EnglishName, StringComparison.Ordinal)).FirstOrDefault(); - if (ele is null && n.Length < 4) ele = ChemicalElement.Get(n); - } - else - { - return null; - } - - if (ele != null - && (!z.HasValue || ele.AtomicNumber == z.Value) - && (string.IsNullOrEmpty(s) || s.Equals(ele.Symbol, StringComparison.OrdinalIgnoreCase)) - && (double.IsNaN(w) || (ele.HasAtomicWeight && !double.IsNaN(w) && Math.Abs(ele.AtomicWeight - w) < 0.000000001))) - return ele; - - if (!z.HasValue || z.Value < 1 || string.IsNullOrEmpty(s)) - return null; - return string.IsNullOrEmpty(n) - ? new ChemicalElement(z.Value, s, null, w) - : new ChemicalElement(z.Value, s, n, true, w); - } - - /// - public override void Write(Utf8JsonWriter writer, ChemicalElement value, JsonSerializerOptions options) - { - value.WriteTo(writer); - } -} diff --git a/Chemistry/Chemistry/ChemicalElements.cs b/Chemistry/Chemistry/ChemicalElements.cs deleted file mode 100644 index 3ca00caf..00000000 --- a/Chemistry/Chemistry/ChemicalElements.cs +++ /dev/null @@ -1,446 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Concurrent; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.Chemistry; - -/// -/// The periodic table of chemical element. -/// -public partial class ChemicalElement -{ - /// - /// Periodic table initialization locker. - /// - private readonly static object locker = new(); - - /// - /// The latin numbers. - /// - private readonly static string[] latinNumbers = new[] - { - "Nil", "Un", "Bi", "Tri", "Quad", "Pent", "Hex", "Sept", "Oct", "Enn" - }; - - /// - /// The periodic table. - /// - private static ChemicalElement[] periodicTable; - - /// - /// The periodic table by symbol indexing. - /// - private static Dictionary symbols; - - /// - /// Other elements. - /// - private readonly static ConcurrentDictionary others = new(); - - /// - /// Gets a chemical element. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The chemical element; or null, if not found. - public static ChemicalElement Get(int number) - { - Init(); - if (number < 1) return null; - if (number <= periodicTable.Length) return periodicTable[number - 1]; - if (others.TryGetValue(number, out var r)) return r; - r = new(number, null, null, double.NaN); - var max = ChemistryExtensions.MaxAtomicNumber; - if (r.Period > 0 && (max < 0 || number <= max)) - { - others.TryAdd(number, r); - if (others.TryGetValue(number, out var r2)) return r2; - } - - return r; - } - - /// - /// Gets a chemical element. - /// - /// The element symbol. - /// The chemical element; or null, if not found. - public static ChemicalElement Get(string symbol) - { - Init(); - symbol = symbol?.Trim(); - if (string.IsNullOrEmpty(symbol)) return null; - if (symbols.TryGetValue(symbol, out var r)) return r; - foreach (var item in others.Values) - { - if (symbol.Equals(item?.Symbol, StringComparison.OrdinalIgnoreCase)) - return item; - } - - if (int.TryParse(symbol, out var i) && i > 0) return Get(i); - if (symbol.Length < 3) return null; - i = symbol[0] switch - { - 'U' => 1, - 'B' => 2, - 'T' => 3, - 'Q' => 4, - 'P' => 5, - 'H' => 6, - 'S' => 7, - 'O' => 8, - 'E' => 9, - _ => -1 - }; - if (i < 0) return null; - for (var j = 1; j < symbol.Length; j++) - { - i *= 10; - var k = symbol[j] switch - { - 'n' => 0, - 'u' => 1, - 'b' => 2, - 't' => 3, - 'q' => 4, - 'p' => 5, - 'h' => 6, - 's' => 7, - 'o' => 8, - 'e' => 9, - _ => -1 - }; - if (k < 0) return null; - i += k; - } - - return Get(i); - } - - /// - /// Gets a value indicating whether the symbol is valid. - /// - /// The element symbol. - /// true if valid; otherwise, false. - public static bool IsValid(string symbol) - { - return Get(symbol) != null; - } - - /// - /// Registers a chemical element into periodic table. - /// - /// The chemical element to register. - public static void Register(ChemicalElement element) - { - if (string.IsNullOrWhiteSpace(element?.Symbol)) return; - Init(); - var number = element.AtomicNumber; - if (number < 1) return; - lock (locker) - { - if (number < periodicTable.Length) periodicTable[number - 1] = element; - else others[number] = element; - symbols[element.Symbol.Trim()] = element; - } - } - - /// - /// Registers a chemical element into periodic table. - /// - /// The chemical element to register. - public static void Register(IEnumerable elements) - { - if (elements is null) return; - Init(); - lock (locker) - { - foreach (var element in elements) - { - if (string.IsNullOrWhiteSpace(element?.Symbol)) continue; - var number = element.AtomicNumber; - if (number < 1) continue; - if (number < periodicTable.Length) periodicTable[number - 1] = element; - else others[number] = element; - symbols[element.Symbol.Trim()] = element; - } - } - } - - /// - /// Registers all chemical elements 1 - number. - /// - /// The atomic number to register. - public static void Register(int number) - { - Init(); - Get(number); - if (number > 10000) number = 10000; - for (var i = periodicTable.Length + 1; i < number; i++) - { - Get(i); - } - } - - /// - /// Filters the periodic table based on a predicate. - /// - /// A function to test each element for a condition. - /// An enumerable instance that contains elements from the periodic table that satisfy the condition. - public static IEnumerable Where(Func predicate) - { - Init(); - if (predicate is null) predicate = ele => true; - foreach (var item in periodicTable.Where(predicate)) - { - yield return item; - } - - foreach (var item in others.Values.Where(predicate)) - { - yield return item; - } - } - - /// - /// Gets a range. - /// - /// The start atomic numbers. - /// The count to get. - /// A specific range of chemical element. - public static IEnumerable Range(int start, int count) - { - Init(); - var end = start + count; - if (end < 1 || end < start) yield break; - if (start <= periodicTable.Length) - { - var col = start > 1 ? periodicTable.Skip(start - 1) : periodicTable; - if (end > periodicTable.Length) - { - foreach (var item in col) - { - yield return item; - } - } - else - { - foreach (var item in col) - { - if (item.AtomicNumber > end) break; - yield return item; - } - - yield break; - } - } - - foreach (var item in others.Values) - { - if (item.AtomicNumber > end) break; - yield return item; - } - } - - /// - /// Filters all elements in the specific period. - /// - /// The period. - /// A collection after filter. - public static IEnumerable PeriodElements(int period) - => periodicTable.Where(ele => ele.Period == period); - - internal static bool Has(int number) - { - if (number < 1) return false; - Init(); - if (number <= periodicTable.Length) return true; - return others.ContainsKey(number); - } - - internal static IEnumerable GetExisted() - { - Init(); - foreach (var item in periodicTable) - { - yield return item; - } - } - - internal static IEnumerable GetOthers() - { - Init(); - return others.Values; - } - - /// - /// Gets the symbol of unidentified element. - /// - /// The atomic number. - /// The symbol. - private static string GetSymbol(int number) - { - if (number < 1) return "?"; - var s = number.ToString("g"); - for (var i = 0; i < 10; i++) - { - s = s.Replace(i.ToString("g"), latinNumbers[i][0].ToString()); - } - - return s.ToLowerInvariant().ToSpecificCaseInvariant(Cases.Capitalize); - } - - /// - /// Gets the name in English of unidentified element. - /// - /// The atomic number. - /// The name. - private static string GetName(int number) - { - var s = number.ToString("g"); - for (var i = 0; i < 10; i++) - { - s = s.Replace(i.ToString("g"), latinNumbers[i]); - } - - return s.ToLowerInvariant().ToSpecificCaseInvariant(Cases.Capitalize) + (s.EndsWith("i") ? "um" : "ium"); - } - - /// - /// Initializes the periodic table. - /// - private static void Init() - { - if (periodicTable != null) return; - lock (locker) - { - if (periodicTable != null) return; - periodicTable = new ChemicalElement[] - { - new(1, "H", "Hydrogen", 1.008, new [] { 1.00782503223, 2.01410177812, 3.0160492779, 4.02643, 5.035311, 6.04496, 7.0527 }), - new(2, "He", "Helium", 4.002602, new [] { 3.0160293201, 4.00260325413, 5.012057, 6.018885891, 7.0279907, 8.03393439, 9.043946, 10.05279 }), - new(3, "Li", "Lithium", 6.94, new [] { 3.0308, 4.02719, 5.012538, 6.0151228874, 7.0160034366, 8.022486246, 9.02679019, 10.035483, 11.04372358, 12.052517, 13.06263 }), - new(4, "Be", "Beryllium", 9.0121831, new [] { 5.0399, 6.0197264, 7.016928717, 8.005305102, 9.012183065, 10.013534695, 11.02166108, 12.0269221, 13.036135, 14.04289, 15.05342, 16.06167 }), - new(5, "B", "Boron", 10.81, new [] { 6.0508, 7.029712, 8.0246073, 9.01332965, 10.01293695, 11.00930536, 12.0143527, 13.0177802, 14.025404, 15.031088, 16.039842, 17.04699, 18.05566, 19.0631, 20.07207, 21.08129 }), - new(6, "C", "Carbon", 12.011, new [] { 8.037643, 9.0310372, 10.01685331, 11.0114336, 12, 13.00335483507, 14.0032419884, 15.01059926, 16.0147013, 17.022577, 18.026751, 19.0348, 20.04032, 21.049, 22.05753, 23.0689 }), - new(7, "N", "Nitrogen", 14.007, new [] { 10.04165, 11.026091, 12.0186132, 13.00573861, 14.00307400443, 15.00010889888, 16.0061019, 17.008449, 18.014078, 19.017022, 20.023366, 21.02711, 22.03439, 23.04114, 24.05039, 25.0601 }), - new(8, "O", "Oxygen", 15.999, new [] { 12.034262, 13.024815, 14.00859636, 15.00306562, 15.99491461957, 16.9991317565, 17.99915961286, 19.003578, 20.00407535, 21.008655, 22.009966, 23.015696, 24.01986, 25.02936, 26.03729, 27.04772, 28.05591 }), - new(9, "F", "Fluorine", 18.998403163, new [] { 14.034315, 15.018043, 16.0114657, 17.00209524, 18.00093733, 18.99840316273, 19.999981252, 20.9999489, 22.002999, 23.003557, 24.008115, 25.012199, 26.020038, 27.02644, 28.03534, 29.04254, 30.05165, 31.05971 }), - new(10, "Ne", "Neon", 20.1797, new [] { 16.02575, 17.01771396, 18.0057087, 19.00188091, 19.9924401762, 20.993846685, 21.991385114, 22.99446691, 23.99361065, 24.997789, 26.000515, 27.007553, 28.01212, 29.01975, 30.02473, 31.0331, 32.03972, 33.04938, 34.05673 }), - new(11, "Na", "Sodium", 22.98976928, new [] { 18.02688, 19.01388, 20.0073544, 20.99765469, 21.99443741, 22.989769282, 23.99096295, 24.989954, 25.9926346, 26.9940765, 27.998939, 29.0028771, 30.0090979, 31.013163, 32.02019, 33.02573, 34.03359, 35.04062, 36.04929, 37.05705 }), - new(12, "Mg", "Magnesium", 24.305, new [] { 19.034169, 20.01885, 21.011716, 21.99957065, 22.99412421, 23.985041697, 24.985836976, 25.982592968, 26.984340624, 27.9838767, 28.988617, 29.9904629, 30.996648, 31.9991102, 33.0053271, 34.008935, 35.01679, 36.02188, 37.03037, 38.03658, 39.04538, 40.05218 }), - new(13, "Al", "Aluminium", 26.9815384, new [] { 21.02897, 22.01954, 23.00724435, 23.9999489, 24.9904281, 25.986891904, 26.98153853, 27.98191021, 28.9804565, 29.98296, 30.983945, 31.988085, 32.990909, 33.996705, 34.999764, 36.00639, 37.01053, 38.0174, 39.02254, 40.03003, 41.03638, 42.04384, 43.05147 }), - new(14, "Si", "Silicon", 28.085, new [] { 22.03579, 23.02544, 24.011535, 25.004109, 25.99233384, 26.98670481, 27.97692653465, 28.9764946649, 29.973770136, 30.975363194, 31.97415154, 32.97797696, 33.978576, 34.984583, 35.986695, 36.992921, 37.995523, 39.002491, 40.00583, 41.01301, 42.01778, 43.0248, 44.03061, 45.03995 }), - new(15, "P", "Phosphorus", 30.973761998, new [] { 24.03577, 25.02119, 26.01178, 26.999224, 27.9923266, 28.98180079, 29.97831375, 30.97376199842, 31.973907643, 32.9717257, 33.97364589, 34.9733141, 35.97826, 36.979607, 37.984252, 38.986227, 39.99133, 40.994654, 42.00108, 43.00502, 44.01121, 45.01645, 46.02446, 47.03139 }), - new(16, "S", "Sulfur", 32.06, new [] { 26.02907, 27.01828, 28.00437, 28.996611, 29.98490703, 30.97955701, 31.9720711744, 32.9714589098, 33.967867004, 34.96903231, 35.96708071, 36.97112551, 37.9711633, 38.975134, 39.9754826, 40.9795935, 41.9810651, 42.9869076, 43.9901188, 44.99572, 46.00004, 47.00795, 48.0137, 49.02276 }), - new(17, "Cl", "Chlorine", 35.45, new [] { 28.02954, 29.01478, 30.00477, 30.992414, 31.98568464, 32.97745199, 33.973762485, 34.968852682, 35.968306809, 36.965902602, 37.96801044, 38.9680082, 39.970415, 40.970685, 41.97325, 42.97389, 43.97787, 44.98029, 45.98517, 46.98916, 47.99564, 49.00123, 50.00905, 51.01554 }), - new(18, "Ar", "Argon", 39.95, new [] { 30.02307, 31.01212, 31.9976378, 32.98992555, 33.98027009, 34.97525759, 35.967545105, 36.96677633, 37.96273211, 38.964313, 39.9623831237, 40.96450057, 41.9630457, 42.9656361, 43.9649238, 44.96803973, 45.968083, 46.972935, 47.97591, 48.9819, 49.98613, 50.9937, 51.99896, 53.00729 }), - new(19, "K", "Potassium", 39.0983, new [] { 32.02265, 33.00756, 33.99869, 34.98800541, 35.98130201, 36.97337589, 37.96908112, 38.9637064864, 39.963998166, 40.9618252579, 41.96240231, 42.9607347, 43.96158699, 44.96069149, 45.96198159, 46.9616616, 47.96534119, 48.96821075, 49.97238, 50.975828, 51.98224, 52.98746, 53.99463, 55.00076, 56.00851 }), - new(20, "Ca", "Calcium", 40.078, new [] { 34.01487, 35.00514, 35.993074, 36.98589785, 37.97631922, 38.97071081, 39.962590863, 40.96227792, 41.95861783, 42.95876644, 43.95548156, 44.95618635, 45.953689, 46.9545424, 47.95252276, 48.95566274, 49.9574992, 50.960989, 51.963217, 52.96945, 53.9734, 54.9803, 55.98508, 56.99262, 57.99794 }), - new(21, "Sc", "Scandium", 44.955908, new [] { 36.01648, 37.00374, 37.99512, 38.984785, 39.9779673, 40.969251105, 41.96551653, 42.9611505, 43.9594029, 44.95590828, 45.95516826, 46.9524037, 47.9522236, 48.9500146, 49.952176, 50.953592, 51.95688, 52.95909, 53.96393, 54.96782, 55.97345, 56.97777, 57.98403, 58.98894, 59.99565, 61.001 }), - new(22, "Ti", "Titanium", 47.867, new [] { 38.01145, 39.00236, 39.9905, 40.983148, 41.97304903, 42.9685225, 43.95968995, 44.95812198, 45.95262772, 46.95175879, 47.94794198, 48.94786568, 49.94478689, 50.94661065, 51.946893, 52.94973, 53.95105, 54.95527, 55.95791, 56.96364, 57.9666, 58.97247, 59.97603, 60.98245, 61.98651, 62.99375 }), - new(23, "V", "Vanadium", 50.9415, new [] { 40.01276, 41.00021, 41.99182, 42.980766, 43.97411, 44.9657748, 45.96019878, 46.95490491, 47.9522522, 48.9485118, 49.94715601, 50.94395704, 51.94477301, 52.9443367, 53.946439, 54.94724, 55.95048, 56.95252, 57.95672, 58.95939, 59.96431, 60.96725, 61.97265, 62.97639, 63.98264, 64.9875, 65.99398 }), - new(24, "Cr", "Chromium", 51.9961, new [] { 42.0067, 42.99753, 43.98536, 44.97905, 45.968359, 46.9628974, 47.9540291, 48.9513333, 49.94604183, 50.94476502, 51.94050623, 52.94064815, 53.93887916, 54.94083843, 55.9406531, 56.943613, 57.94435, 58.94859, 59.95008, 60.95442, 61.9561, 62.96165, 63.96408, 64.96996, 65.97366, 66.98016, 67.98403 }), - new(25, "Mn", "Manganese", 54.938043, new [] { 44.00715, 44.99449, 45.98609, 46.975775, 47.96852, 48.959595, 49.95423778, 50.94820847, 51.9455639, 52.94128889, 53.9403576, 54.93804391, 55.93890369, 56.9382861, 57.9400666, 58.9403911, 59.9431366, 60.9444525, 61.94795, 62.9496647, 63.9538494, 64.9560198, 65.960547, 66.96424, 67.96962, 68.97366, 69.97937, 70.98368 }), - new(26, "Fe", "Iron", 55.845, new [] { 45.01442, 46.00063, 46.99185, 47.98023, 48.973429, 49.962975, 50.956841, 51.9481131, 52.9453064, 53.93960899, 54.93829199, 55.93493633, 56.93539284, 57.93327443, 58.93487434, 59.9340711, 60.9367462, 61.9367918, 62.9402727, 63.9409878, 64.9450115, 65.94625, 66.95054, 67.95295, 68.95807, 69.96102, 70.96672, 71.96983, 72.97572, 73.97935 }), - new(27, "Co", "Cobalt", 58.933194, new [] { 47.01057, 48.00093, 48.98891, 49.98091, 50.970647, 51.96351, 52.9542041, 53.94845987, 54.9419972, 55.9398388, 56.93629057, 57.9357521, 58.93319429, 59.9338163, 60.93247662, 61.934059, 62.9336, 63.935811, 64.9364621, 65.939443, 66.9406096, 67.94426, 68.94614, 69.94963, 70.95237, 71.95729, 72.96039, 73.96515, 74.96876, 75.97413 }), - new(28, "Ni", "Nickel", 58.6934, new [] { 48.01769, 49.0077, 49.99474, 50.98611, 51.9748, 52.96819, 53.957892, 54.95133063, 55.94212855, 56.93979218, 57.93534241, 58.9343462, 59.93078588, 60.93105557, 61.92834537, 62.92966963, 63.92796682, 64.93008517, 65.9291393, 66.9315694, 67.9318688, 68.9356103, 69.9364313, 70.940519, 71.9417859, 72.9462067, 73.94798, 74.9525, 75.95533, 76.96055, 77.96336, 78.97025 }), - new(29, "Cu", "Copper", 63.546, new [] { 51.99671, 52.98459, 53.97666, 54.96604, 55.95895, 56.9492125, 57.94453305, 58.93949748, 59.9373645, 60.9334576, 61.93259541, 62.92959772, 63.92976434, 64.9277897, 65.92886903, 66.9277303, 67.9296109, 68.9294293, 69.9323921, 70.9326768, 71.9358203, 72.9366744, 73.9398749, 74.9415226, 75.945275, 76.94792, 77.95223, 78.95502, 79.96089, 80.96587, 81.97244 }), - new(30, "Zn", "Zinc", 65.38, new [] { 53.99204, 54.98398, 55.97254, 56.96506, 57.954591, 58.94931266, 59.9418421, 60.939507, 61.93433397, 62.9332115, 63.92914201, 64.92924077, 65.92603381, 66.92712775, 67.92484455, 68.9265507, 69.9253192, 70.9277196, 71.9268428, 72.9295826, 73.9294073, 74.9328402, 75.933115, 76.9368872, 77.9382892, 78.9426381, 79.9445529, 80.9504026, 81.95426, 82.96056, 83.96521, 84.97226 }), - new(31, "Ga", "Gallium", 69.723, new [] { 55.99536, 56.9832, 57.97478, 58.96353, 59.95729, 60.949399, 61.94419025, 62.9392942, 63.9368404, 64.93273459, 65.9315894, 66.9282025, 67.9279805, 68.9255735, 69.9260219, 70.92470258, 71.92636747, 72.9251747, 73.9269457, 74.9265002, 75.9288276, 76.9291543, 77.9316088, 78.9328523, 79.9364208, 80.9381338, 81.9431765, 82.9471203, 83.95246, 84.95699, 85.96301, 86.96824 }), - new(32, "Ge", "Germanium", 72.63, new [] { 57.99172, 58.98249, 59.97036, 60.96379, 61.95502, 62.949628, 63.9416899, 64.9393681, 65.9338621, 66.9327339, 67.9280953, 68.9279645, 69.92424875, 70.92495233, 71.922075826, 72.923458956, 73.921177761, 74.92285837, 75.921402726, 76.923549843, 77.9228529, 78.92536, 79.9253508, 80.9288329, 81.929774, 82.9345391, 83.9375751, 84.9429697, 85.94658, 86.95268, 87.95691, 88.96379, 89.96863 }), - new(33, "As", "Arsenic", 74.921595, new [] { 59.99388, 60.98112, 61.97361, 62.9639, 63.95743, 64.949611, 65.9441488, 66.93925111, 67.9367741, 68.932246, 69.930926, 70.9271138, 71.9267523, 72.9238291, 73.9239286, 74.92159457, 75.92239202, 76.9206476, 77.921828, 78.9209484, 79.9224746, 80.9221323, 81.9247412, 82.9252069, 83.9293033, 84.9321637, 85.9367015, 86.9402917, 87.94555, 88.94976, 89.95563, 90.96039, 91.96674 }), - new(34, "Se", "Selenium", 78.971, new [] { 63.97109, 64.9644, 65.95559, 66.949994, 67.94182524, 68.9394148, 69.9335155, 70.9322094, 71.9271405, 72.9267549, 73.922475934, 74.92252287, 75.919213704, 76.919914154, 77.91730928, 78.91849929, 79.9165218, 80.917993, 81.9166995, 82.9191186, 83.9184668, 84.9222608, 85.9243117, 86.9286886, 87.9314175, 88.9366691, 89.9401, 90.94596, 91.94984, 92.95629, 93.96049, 94.9673 }), - new(35, "Br", "Bromine", 79.904, new [] { 66.96465, 67.95873, 68.950497, 69.944792, 70.9393422, 71.9365886, 72.9316715, 73.9299102, 74.9258105, 75.924542, 76.9213792, 77.9211459, 78.9183376, 79.9185298, 80.9162897, 81.9168032, 82.9151756, 83.916496, 84.9156458, 85.9188054, 86.920674, 87.9240833, 88.9267046, 89.9312928, 90.9343986, 91.9396316, 92.94313, 93.9489, 94.95301, 95.95903, 96.96344, 97.96946 }), - new(36, "Kr", "Krypton", 83.798, new [] { 68.96518, 69.95604, 70.95027, 71.9420924, 72.9392892, 73.933084, 74.9309457, 75.9259103, 76.92467, 77.92036494, 78.9200829, 79.91637808, 80.9165912, 81.91348273, 82.91412716, 83.9114977282, 84.9125273, 85.9106106269, 86.91335476, 87.9144479, 88.9178355, 89.9195279, 90.9238063, 91.9261731, 92.9311472, 93.93414, 94.939711, 95.943017, 96.94909, 97.95243, 98.95839, 99.96237, 100.96873 }), - new(37, "Rb", "Rubidium", 85.4678, new [] { 70.96532, 71.95908, 72.95053, 73.9442659, 74.9385732, 75.935073, 76.9304016, 77.9281419, 78.9239899, 79.9225164, 80.9189939, 81.918209, 82.9151142, 83.9143752, 84.9117897379, 85.91116743, 86.909180531, 87.91131559, 88.9122783, 89.9147985, 90.9165372, 91.9197284, 92.9220393, 93.9263948, 94.92926, 95.9341334, 96.9371771, 97.9416869, 98.94503, 99.95003, 100.95404, 101.95952, 102.96392 }), - new(38, "Sr", "Strontium", 87.62, new [] { 72.9657, 73.95617, 74.94995, 75.941763, 76.9379455, 77.93218, 78.9297077, 79.9245175, 80.9232114, 81.9183999, 82.9175544, 83.9134191, 84.912932, 85.9092606, 86.9088775, 87.9056125, 88.9074511, 89.90773, 90.9101954, 91.9110382, 92.9140242, 93.9153556, 94.9193529, 95.9217066, 96.926374, 97.9286888, 98.9328907, 99.93577, 100.940352, 101.943791, 102.94909, 103.95265, 104.95855, 105.96265, 106.96897 }), - new(39, "Y", "Yttrium", 88.90584, new [] { 75.95856, 76.949781, 77.94361, 78.93735, 79.9343561, 80.9294556, 81.9269314, 82.922485, 83.9206721, 84.916433, 85.914886, 86.9108761, 87.9095016, 88.9058403, 89.9071439, 90.9072974, 91.9089451, 92.909578, 93.9115906, 94.9128161, 95.9158968, 96.9182741, 97.9223821, 98.924148, 99.927715, 100.9301477, 101.9343277, 102.937243, 103.94196, 104.94544, 105.95056, 106.95452, 107.95996, 108.96436 }), - new(40, "Zr", "Zirconium", 91.224, new [] { 77.95566, 78.94948, 79.9404, 80.93731, 81.93135, 82.9292421, 83.9233269, 84.9214444, 85.9162972, 86.914818, 87.9102213, 88.9088814, 89.9046977, 90.9056396, 91.9050347, 92.9064699, 93.9063108, 94.9080385, 95.9082714, 96.9109512, 97.9127289, 98.916667, 99.9180006, 100.921448, 101.9231409, 102.927191, 103.929436, 104.934008, 105.93676, 106.94174, 107.94487, 108.95041, 109.95396, 110.95968, 111.9637 }), - new(41, "Nb", "Niobium", 92.90637, new [] { 80.9496, 81.94396, 82.93729, 83.93449, 84.9288458, 85.9257828, 86.9206937, 87.918222, 88.913445, 89.9112584, 90.9069897, 91.9071881, 92.906373, 93.9072788, 94.9068324, 95.9080973, 96.9080959, 97.9103265, 98.911613, 99.9143276, 100.9153103, 101.9180772, 102.9194572, 103.9228925, 104.9249465, 105.9289317, 106.9315937, 107.9360748, 108.93922, 109.94403, 110.94753, 111.95247, 112.95651, 113.96201, 114.96634 }), - new(42, "Mo", "Molybdenum", 95.95, new [] { 82.94988, 83.94149, 84.938261, 85.9311748, 86.9281962, 87.9219678, 88.9194682, 89.9139309, 90.9117453, 91.90680796, 92.90680958, 93.9050849, 94.90583877, 95.90467612, 96.90601812, 97.90540482, 98.90770851, 99.9074718, 100.9103414, 101.9102834, 102.913079, 103.9137344, 104.916969, 105.918259, 106.922106, 107.924033, 108.928424, 109.930704, 110.935654, 111.93831, 112.94335, 113.94653, 114.95196, 115.95545, 116.96117 }), - new(43, "Tc", "Technetium", 98, new [] { 84.95058, 85.94493, 86.9380672, 87.93378, 88.9276487, 89.9240739, 90.9184254, 91.9152698, 92.910246, 93.9096536, 94.9076536, 95.907868, 96.9063667, 97.9072124, 98.9062508, 99.9076539, 100.907309, 101.9092097, 102.909176, 103.911425, 104.911655, 105.914358, 106.9154606, 107.9184957, 108.920256, 109.923744, 110.925901, 111.9299458, 112.932569, 113.93691, 114.93998, 115.94476, 116.94806, 117.95299, 118.95666, 119.96187 }), - new(44, "Ru", "Ruthenium", 101.07, new [] { 86.95069, 87.9416, 88.93762, 89.9303444, 90.9267419, 91.9202344, 92.9171044, 93.9113429, 94.910406, 95.90759025, 96.9075471, 97.9052868, 98.9059341, 99.9042143, 100.9055769, 101.9043441, 102.9063186, 103.9054275, 104.9077476, 105.9073291, 106.909972, 107.910188, 108.913326, 109.9140407, 110.91757, 111.918809, 112.922844, 113.9246136, 114.92882, 115.9312192, 116.9361, 117.93853, 118.94357, 119.94631, 120.95164, 121.95447, 122.95989, 123.96305 }), - new(45, "Rh", "Rhodium", 102.90549, new [] { 88.95058, 89.94422, 90.93688, 91.9323677, 92.9259128, 93.9217305, 94.9158979, 95.914453, 96.911329, 97.910708, 98.9081282, 99.908117, 100.9061606, 101.9068374, 102.905498, 103.9066492, 104.9056885, 105.9072868, 106.906748, 107.908714, 108.9087488, 109.911079, 110.9116423, 111.914403, 112.9154393, 113.918718, 114.9203116, 115.924059, 116.9260354, 117.93034, 118.932557, 119.93686, 120.93942, 121.94399, 122.94685, 123.95151, 124.95469, 125.95946 }), - new(46, "Pd", "Palladium", 106.42, new [] { 90.95032, 91.94088, 92.93651, 93.9290376, 94.9248898, 95.9182151, 96.916472, 97.9126983, 98.9117748, 99.908505, 100.9082864, 101.9056022, 102.9060809, 103.9040305, 104.9050796, 105.9034804, 106.9051282, 107.9038916, 108.9059504, 109.9051722, 110.90768968, 111.9073297, 112.910261, 113.9103686, 114.913659, 115.914297, 116.9179547, 117.9190667, 118.9233402, 119.9245511, 120.9289503, 121.930632, 122.93514, 123.93714, 124.94179, 125.94416, 126.94907, 127.95183 }), - new(47, "Ag", "Silver", 107.8682, new [] { 92.95033, 93.94373, 94.93602, 95.930744, 96.92397, 97.92156, 98.9176458, 99.9161154, 100.912684, 101.9117047, 102.9089631, 103.9086239, 104.9065256, 105.9066636, 106.9050916, 107.9059503, 108.9047553, 109.9061102, 110.9052959, 111.9070486, 112.906573, 113.908823, 114.908767, 115.9113868, 116.911774, 117.9145955, 118.91557, 119.9187848, 120.920125, 121.923664, 122.925337, 123.92893, 124.93105, 125.93475, 126.93711, 127.94106, 128.94395, 129.9507 }), - new(48, "Cd", "Cadmium", 112.414, new [] { 94.94994, 95.94034, 96.9351, 97.927389, 98.9249258, 99.9203488, 100.9185862, 101.914482, 102.9134165, 103.9098564, 104.9094639, 105.9064599, 106.9066121, 107.9041834, 108.9049867, 109.90300661, 110.90418287, 111.90276287, 112.90440813, 113.90336509, 114.90543751, 115.90476315, 116.907226, 117.906922, 118.909847, 119.9098681, 120.9129637, 121.9134591, 122.9168925, 123.9176574, 124.9212576, 125.9224291, 126.926472, 127.9278129, 128.93182, 129.93394, 130.9406, 131.94604, 132.95285 }), - new(49, "In", "Indium", 114.818, new [] { 96.94934, 97.94214, 98.93411, 99.93096, 100.92634, 101.9241071, 102.9198819, 103.9182145, 104.914502, 105.913464, 106.91029, 107.9096935, 108.9071514, 109.90717, 110.9051085, 111.9055377, 112.90406184, 113.90491791, 114.903878776, 115.90525999, 116.9045157, 117.9063566, 118.9058507, 119.907967, 120.907851, 121.910281, 122.910434, 123.913182, 124.913605, 125.916507, 126.917446, 127.9204, 128.9218053, 129.924977, 130.9269715, 131.933001, 132.93831, 133.94454, 134.95005 }), - new(50, "Sn", "Tin", 118.71, new [] { 98.94853, 99.9385, 100.93526, 101.93029, 102.928105, 103.9231052, 104.9212684, 105.9169574, 106.9157137, 107.9118943, 108.9112921, 109.907845, 110.9077401, 111.90482387, 112.9051757, 113.9027827, 114.903344699, 115.9017428, 116.90295398, 117.90160657, 118.90331117, 119.90220163, 120.9042426, 121.9034438, 122.9057252, 123.9052766, 124.9077864, 125.907659, 126.91039, 127.910507, 128.913465, 129.9139738, 130.917045, 131.9178267, 132.9239134, 133.9286821, 134.9349086, 135.93999, 136.94655, 137.95184 }), - new(51, "Sb", "Antimony", 121.76, new [] { 102.93969, 103.93648, 104.931276, 105.928638, 106.9241506, 107.9222267, 108.9181411, 109.9168543, 110.9132182, 111.9124, 112.909375, 113.90929, 114.906598, 115.9067931, 116.9048415, 117.9055321, 118.9039455, 119.9050794, 120.903812, 121.9051699, 122.9042132, 123.905935, 124.905253, 125.907253, 126.9069243, 127.909146, 128.909147, 129.911662, 130.9119888, 131.9145077, 132.9152732, 133.9205357, 134.9251851, 135.9307459, 136.93555, 137.94145, 138.94655, 139.95283 }), - new(52, "Te", "Tellurium", 127.6, new [] { 104.9433, 105.9375, 106.935012, 107.9293805, 108.9273045, 109.9224581, 110.9210006, 111.9167279, 112.915891, 113.912089, 114.911902, 115.90846, 116.908646, 117.905854, 118.9064071, 119.9040593, 120.904944, 121.9030435, 122.9042698, 123.9028171, 124.9044299, 125.9033109, 126.9052257, 127.90446128, 128.90659646, 129.906222748, 130.908522213, 131.9085467, 132.9109688, 133.911394, 134.9165557, 135.9201006, 136.9255989, 137.9294722, 138.9353672, 139.939499, 140.9458, 141.95022, 142.95676 }), - new(53, "I", "Iodine", 126.90447, new [] { 106.94678, 107.94348, 108.9380853, 109.935089, 110.9302692, 111.928005, 112.9236501, 113.92185, 114.918048, 115.91681, 116.913648, 117.913074, 118.910074, 119.910087, 120.9074051, 121.9075888, 122.9055885, 123.906209, 124.9046294, 125.9056233, 126.9044719, 127.9058086, 128.9049837, 129.9066702, 130.9061263, 131.9079935, 132.907797, 133.9097588, 134.9100488, 135.914604, 136.9180282, 137.9227264, 138.926506, 139.93173, 140.93569, 141.9412, 142.94565, 143.95139, 144.95605 }), - new(54, "Xe", "Xenon", 131.293, new [] { 108.95043, 109.94426, 110.941607, 111.935559, 112.9332217, 113.92798, 114.926294, 115.921581, 116.920359, 117.916179, 118.915411, 119.911784, 120.911453, 121.908368, 122.908482, 123.905892, 124.9063944, 125.9042983, 126.9051829, 127.903531, 128.9047808611, 129.903509349, 130.90508406, 131.9041550856, 132.9059108, 133.90539466, 134.9072278, 135.907214484, 136.91155778, 137.9141463, 138.9187922, 139.9216458, 140.9267872, 141.9299731, 142.9353696, 143.9389451, 144.94472, 145.948518, 146.95426, 147.95813 }), - new(55, "Cs", "Caesium", 132.90545196, new [] { 111.950309, 112.9444291, 113.941296, 114.93591, 115.93337, 116.928617, 117.92656, 118.922377, 119.920677, 120.917227, 121.916108, 122.912996, 123.9122578, 124.909728, 125.909446, 126.9074174, 127.9077487, 128.9060657, 129.9067093, 130.9054649, 131.9064339, 132.905451961, 133.906718503, 134.905977, 135.9073114, 136.90708923, 137.9110171, 138.9133638, 139.9172831, 140.9200455, 141.924296, 142.927349, 143.932076, 144.935527, 145.940344, 146.944156, 147.94923, 148.95302, 149.95833, 150.96258 }), - new(56, "Ba", "Barium", 137.327, new [] { 113.95066, 114.94737, 115.94128, 116.93814, 117.93306, 118.93066, 119.92605, 120.92405, 121.919904, 122.918781, 123.915094, 124.914472, 125.91125, 126.911091, 127.908342, 128.908681, 129.9063207, 130.906941, 131.9050611, 132.9060074, 133.90450818, 134.90568838, 135.90457573, 136.90582714, 137.905247, 138.9088411, 139.9106057, 140.9144033, 141.9164324, 142.9206253, 143.9229549, 144.9275184, 145.930284, 146.935304, 147.938171, 148.94308, 149.94605, 150.95127, 151.95481, 152.96036 }), - new(57, "La", "Lanthanum", 138.90547, new [] { 115.9563, 116.94999, 117.94673, 118.94099, 119.93807, 120.93315, 121.93071, 122.9263, 123.924574, 124.920816, 125.919513, 126.916375, 127.915592, 128.912694, 129.912369, 130.91007, 131.910119, 132.908218, 133.908514, 134.906984, 135.907635, 136.9064504, 137.9071149, 138.9063563, 139.9094806, 140.910966, 141.9140909, 142.9160795, 143.919646, 144.921808, 145.925875, 146.928418, 147.932679, 148.93535, 149.93947, 150.94232, 151.94682, 152.95036, 153.95517, 154.95901 }), - new(58, "Ce", "Cerium", 140.116, new [] { 118.95271, 119.94654, 120.94335, 121.93787, 122.93528, 123.93031, 124.92844, 125.923971, 126.922727, 127.918911, 128.918102, 129.914736, 130.914429, 131.911464, 132.91152, 133.908928, 134.909161, 135.90712921, 136.90776236, 137.905991, 138.9066551, 139.9054431, 140.9082807, 141.9092504, 142.9123921, 143.9136529, 144.917265, 145.918802, 146.9226899, 147.924424, 148.928427, 149.930384, 150.934272, 151.9366, 152.94093, 153.9438, 154.94855, 155.95183, 156.95705 }), - new(59, "Pr", "Praseodymium", 140.90766, new [] { 120.95532, 121.95175, 122.94596, 123.94294, 124.9377, 125.93524, 126.93071, 127.928791, 128.925095, 129.92359, 130.920235, 131.919255, 132.916331, 133.915697, 134.913112, 135.912677, 136.9106792, 137.910754, 138.9089408, 139.9090803, 140.9076576, 141.9100496, 142.9108228, 143.9133109, 144.9145182, 145.91768, 146.919008, 147.92213, 148.923736, 149.9266765, 150.928309, 151.931553, 152.933904, 153.93753, 154.940509, 155.94464, 156.94789, 157.95241, 158.95589 }), - new(60, "Nd", "Neodymium", 144.242, new [] { 123.9522, 124.9489, 125.94311, 126.94038, 127.93525, 128.9331, 129.928506, 130.927248, 131.923321, 132.922348, 133.91879, 134.918181, 135.914976, 136.914562, 137.91195, 138.911954, 139.90955, 140.9096147, 141.907729, 142.90982, 143.910093, 144.9125793, 145.9131226, 146.9161061, 147.9168993, 148.9201548, 149.9209022, 150.9238403, 151.924692, 152.927718, 153.92948, 154.9331357, 155.93508, 156.939386, 157.94197, 158.94653, 159.9494, 160.95428 }), - new(61, "Pm", "Promethium", 145, new [] { 125.95792, 126.95192, 127.9487, 128.94323, 129.94053, 130.93567, 131.93384, 132.929782, 133.928353, 134.924823, 135.923585, 136.92048, 137.919548, 138.9168, 139.91604, 140.913555, 141.91289, 142.9109383, 143.9125964, 144.9127559, 145.9147024, 146.915145, 147.9174819, 148.9183423, 149.920991, 150.9212175, 151.923506, 152.9241567, 153.926472, 154.928137, 155.9311175, 156.9331214, 157.936565, 158.939287, 159.9431, 160.94607, 161.95022, 162.95357 }), - new(62, "Sm", "Samarium", 150.36, new [] { 127.95842, 128.95476, 129.949, 130.94618, 131.94087, 132.93856, 133.93411, 134.93252, 135.928276, 136.926971, 137.923244, 138.922297, 139.918995, 140.9184816, 141.9152044, 142.9146353, 143.9120065, 144.9134173, 145.913047, 146.9149044, 147.9148292, 148.9171921, 149.9172829, 150.9199398, 151.9197397, 152.9221047, 153.9222169, 154.9246477, 155.925536, 156.9284187, 157.929951, 158.9332172, 159.9353353, 160.9391602, 161.94146, 162.94555, 163.94836, 164.95297 }), - new(63, "Eu", "Europium", 151.964, new [] { 129.96369, 130.95784, 131.95467, 132.94929, 133.9464, 134.94187, 135.93962, 136.93546, 137.933709, 138.929792, 139.928088, 140.924932, 141.923442, 142.920299, 143.91882, 144.9162726, 145.917211, 146.9167527, 147.918089, 148.9179378, 149.9197077, 150.9198578, 151.9217522, 152.921238, 153.922987, 154.9229011, 155.9247605, 156.9254334, 157.927799, 158.9291001, 159.931851, 160.933664, 161.936989, 162.939196, 163.94274, 164.94559, 165.94962, 166.95289 }), - new(64, "Gd", "Gadolinium", 157.25, new [] { 132.96133, 133.95566, 134.95245, 135.9473, 136.94502, 137.94025, 138.93813, 139.933674, 140.932126, 141.928116, 142.92675, 143.922963, 144.921713, 145.9183188, 146.9191014, 147.9181215, 148.9193481, 149.9186644, 150.920356, 151.9197995, 152.921758, 153.9208741, 154.9226305, 155.9221312, 156.9239686, 157.9241123, 158.926397, 159.9270624, 160.9296775, 161.930993, 162.9341769, 163.93583, 164.93936, 165.94146, 166.94545, 167.94808, 168.9526 }), - new(65, "Tb", "Terbium", 158.925354, new [] { 134.96476, 135.96129, 136.95602, 137.95312, 138.94833, 139.94581, 140.94145, 141.93928, 142.935137, 143.933045, 144.92882, 145.927253, 146.9240548, 147.924282, 148.9232535, 149.9236649, 150.9231096, 151.924083, 152.9234424, 153.924685, 154.923511, 155.9247552, 156.924033, 157.9254209, 158.9253547, 159.9271756, 160.9275778, 161.929495, 162.9306547, 163.93336, 164.93498, 165.93786, 166.93996, 167.9434, 168.94597, 169.94984, 170.95273 }), - new(66, "Dy", "Dysprosium", 162.5, new [] { 137.9625, 138.95959, 139.95402, 140.95128, 141.94619, 142.943994, 143.9392695, 144.937474, 145.9328445, 146.9310827, 147.927157, 148.927322, 149.9255933, 150.9261916, 151.9247253, 152.9257724, 153.9244293, 154.925759, 155.9242847, 156.9254707, 157.9244159, 158.925747, 159.9252046, 160.9269405, 161.9268056, 162.9287383, 163.9291819, 164.9317105, 165.9328139, 166.935661, 167.93713, 168.94031, 169.94239, 170.94612, 171.94846, 172.95283 }), - new(67, "Ho", "Holmium", 164.930328, new [] { 139.96859, 140.96311, 141.96001, 142.95486, 143.9521097, 144.9472674, 145.9449935, 146.9401423, 147.937744, 148.933803, 149.933498, 150.9316983, 151.931724, 152.9302064, 153.9306068, 154.929104, 155.929706, 156.928254, 157.928946, 158.9277197, 159.928737, 160.9278615, 161.9291023, 162.928741, 163.9302403, 164.9303288, 165.9322909, 166.9331385, 167.935522, 168.936878, 169.939625, 170.94147, 171.94473, 172.94702, 173.95095, 174.95362 }), - new(68, "Er", "Erbium", 167.259, new [] { 141.9701, 142.96662, 143.9607, 144.95805, 145.9524184, 146.949964, 147.944735, 148.942306, 149.937916, 150.937449, 151.935057, 152.93508, 153.9327908, 154.9332159, 155.931067, 156.931949, 157.929893, 158.9306918, 159.929077, 160.9300046, 161.9287884, 162.9300408, 163.9292088, 164.9307345, 165.9302995, 166.9320546, 167.9323767, 168.9345968, 169.9354702, 170.9380357, 171.9393619, 172.9424, 173.94423, 174.94777, 175.94994, 176.95399 }), - new(69, "Tm", "Thulium", 168.934218, new [] { 143.97628, 144.97039, 145.96684, 146.9613799, 147.958384, 148.95289, 149.95009, 150.945488, 151.944422, 152.94204, 153.94157, 154.93921, 155.938992, 156.936944, 157.93698, 158.934975, 159.935263, 160.933549, 161.934002, 162.9326592, 163.933544, 164.9324431, 165.933561, 166.9328562, 167.9341774, 168.9342179, 169.935806, 170.9364339, 171.9384055, 172.9396084, 173.942173, 174.943841, 175.947, 176.94904, 177.95264, 178.95534 }), - new(70, "Yb", "Ytterbium", 173.045, new [] { 147.96758, 148.96436, 149.95852, 150.9554, 151.95027, 152.94932, 153.946396, 154.945783, 155.942825, 156.942645, 157.9398705, 158.940055, 159.937557, 160.937907, 161.935774, 162.93634, 163.934495, 164.93527, 165.9338747, 166.934953, 167.9338896, 168.9351825, 169.9347664, 170.9363302, 171.9363859, 172.9382151, 173.9388664, 174.9412808, 175.9425764, 176.9452656, 177.946651, 178.95004, 179.95212, 180.95589 }), - new(71, "Lu", "Lutetium", 174.9668, new [] { 149.97355, 150.96768, 151.96412, 152.95875, 153.95736, 154.954321, 155.953033, 156.950127, 157.949316, 158.946636, 159.946033, 160.943572, 161.943283, 162.941179, 163.941339, 164.939407, 165.939859, 166.93827, 167.938736, 168.9376441, 169.938478, 170.937917, 171.9390891, 172.938934, 173.9403409, 174.9407752, 175.9426897, 176.9437615, 177.945958, 178.9473309, 179.949888, 180.95191, 181.95504, 182.957363, 183.96091, 184.96362 }), - new(72, "Hf", "Hafnium", 178.49, new [] { 152.97069, 153.96486, 154.96311, 155.95935, 156.95824, 157.954801, 158.953996, 159.950691, 160.950278, 161.9472148, 162.947113, 163.944371, 164.944567, 165.94218, 166.9426, 167.940568, 168.941259, 169.939609, 170.940492, 171.93945, 172.940513, 173.9400461, 174.9415092, 175.9414076, 176.9432277, 177.9437058, 178.9458232, 179.946557, 180.9491083, 181.9505612, 182.95353, 183.955446, 184.958862, 185.960897, 186.96477, 187.96685, 188.97084 }), - new(73, "Ta", "Tantalum", 180.94788, new [] { 154.97424, 155.97203, 156.96818, 157.96654, 158.963023, 159.961488, 160.958452, 161.957294, 162.954337, 163.953534, 164.950781, 165.950512, 166.948093, 167.948047, 168.946011, 169.946175, 170.944476, 171.944895, 172.94375, 173.944454, 174.943737, 175.944857, 176.9444795, 177.945678, 178.9459366, 179.9474648, 180.9479958, 181.9501519, 182.9513726, 183.954008, 184.955559, 185.958551, 186.960386, 187.963916, 188.96583, 189.96939, 190.97156, 191.97514 }), - new(74, "W", "Tungsten", 183.84, new [] { 156.97884, 157.97456, 158.97264, 159.96846, 160.9672, 161.963499, 162.962524, 163.958961, 164.958281, 165.955031, 166.954805, 167.951806, 168.951779, 169.949232, 170.949451, 171.947292, 172.947689, 173.946079, 174.946717, 175.945634, 176.946643, 177.945883, 178.947077, 179.9467108, 180.9481978, 181.94820394, 182.95022275, 183.95093092, 184.95341897, 185.9543628, 186.9571588, 187.9584862, 188.961763, 189.963091, 190.966531, 191.96817, 192.97178, 193.97367 }), - new(75, "Re", "Rhenium", 186.207, new [] { 158.98418, 159.98182, 160.97757, 161.97584, 162.97208, 163.970453, 164.967103, 165.965761, 166.962595, 167.961573, 168.958766, 169.95822, 170.955716, 171.95542, 172.953243, 173.953115, 174.951381, 175.951623, 176.950328, 177.950989, 178.949989, 179.950792, 180.950058, 181.95121, 182.9508196, 183.9525228, 184.9529545, 185.9549856, 186.9557501, 187.9581115, 188.959226, 189.961744, 190.963122, 191.966088, 192.967541, 193.97076, 194.97254, 195.9758, 196.97799, 197.9816 }), - new(76, "Os", "Osmium", 190.23, new [] { 160.98903, 161.98443, 162.98241, 163.97802, 164.9766, 165.972692, 166.971549, 167.967808, 168.967018, 169.963578, 170.963174, 171.960017, 172.959808, 173.957064, 174.956945, 175.954806, 176.954966, 177.953254, 178.953817, 179.952375, 180.953247, 181.95211, 182.953125, 183.9524885, 184.9540417, 185.953835, 186.9557474, 187.9558352, 188.9581442, 189.9584437, 190.9609264, 191.961477, 192.9641479, 193.9651772, 194.968318, 195.969641, 196.97283, 197.97441, 198.97801, 199.97984, 200.98364, 201.98595 }), - new(77, "Ir", "Iridium", 192.217, new [] { 163.99191, 164.9875, 165.98566, 166.981666, 167.979907, 168.976298, 169.974922, 170.97164, 171.970607, 172.967506, 173.966861, 174.96415, 175.96365, 176.961301, 177.961082, 178.95912, 179.959229, 180.957625, 181.958076, 182.95684, 183.957476, 184.956698, 185.957944, 186.957542, 187.958828, 188.958715, 189.9605412, 190.9605893, 191.9626002, 192.9629216, 193.9650735, 194.9659747, 195.968397, 196.969655, 197.97228, 198.973805, 199.9768, 200.97864, 201.98199, 202.98423, 203.9896 }), - new(78, "Pt", "Platinum", 195.084, new [] { 165.99486, 166.99269, 167.98813, 168.98657, 169.982496, 170.981245, 171.977351, 172.976443, 173.97282, 174.97241, 175.968938, 176.96847, 177.96565, 178.965359, 179.963032, 180.963098, 181.961172, 182.961597, 183.959915, 184.960614, 185.959351, 186.960617, 187.9593889, 188.960831, 189.9599297, 190.9616729, 191.9610387, 192.9629824, 193.9626809, 194.9647917, 195.96495209, 196.96734069, 197.9678949, 198.9705952, 199.971443, 200.974513, 201.975639, 202.97893, 203.98076, 204.98608, 205.98966 }), - new(79, "Au", "Gold", 196.96657, new [] { 168.99808, 169.99597, 170.991876, 171.989942, 172.986241, 173.984717, 174.981304, 175.98025, 176.97687, 177.976032, 178.973174, 179.972523, 180.970079, 181.969618, 182.967591, 183.967452, 184.96579, 185.965953, 186.964543, 187.965349, 188.963948, 189.964698, 190.963702, 191.964814, 192.9641373, 193.9654178, 194.9650352, 195.9665699, 196.96656879, 197.96824242, 198.96876528, 199.970756, 200.9716575, 201.973856, 202.9751544, 203.97783, 204.97985, 205.98474, 206.9884, 207.99345, 208.99735, 210.0025 }), - new(80, "Hg", "Mercury", 200.592, new [] { 171.00353, 171.99881, 172.99709, 173.992865, 174.991441, 175.987361, 176.986277, 177.982484, 178.981831, 179.97826, 180.977819, 181.974689, 182.9744448, 183.971714, 184.971899, 185.969362, 186.969814, 187.967567, 188.968195, 189.966323, 190.967157, 191.965635, 192.966653, 193.9654491, 194.966721, 195.9658326, 196.9672128, 197.9667686, 198.96828064, 199.96832659, 200.97030284, 201.9706434, 202.9728728, 203.97349398, 204.9760734, 205.977514, 206.9823, 207.985759, 208.99072, 209.99424, 210.99933, 212.00296, 213.00823, 214.012, 215.0174, 216.02132 }), - new(81, "Tl", "Thallium", 204.38, new [] { 176.000624, 176.996431, 177.99485, 178.991111, 179.990057, 180.98626, 181.985713, 182.982193, 183.981886, 184.978789, 185.978651, 186.9759063, 187.976021, 188.973588, 189.973828, 190.9717842, 191.972225, 192.970502, 193.971081, 194.969774, 195.970481, 196.969576, 197.970483, 198.969877, 199.9709633, 200.970822, 201.972102, 202.9723446, 203.9738639, 204.9744278, 205.9761106, 206.9774197, 207.982019, 208.9853594, 209.990074, 210.993475, 211.99834, 213.001915, 214.00694, 215.01064, 216.0158, 217.01966, 218.02479 }), - new(82, "Pb", "Lead", 207.2, new [] { 178.003831, 179.002201, 179.997928, 180.996653, 181.992672, 182.991872, 183.988136, 184.98761, 185.984238, 186.9839109, 187.980875, 188.980807, 189.978082, 190.978276, 191.975775, 192.976173, 193.974012, 194.974543, 195.972774, 196.9734312, 197.972034, 198.972913, 199.971819, 200.972883, 201.972152, 202.9733911, 203.973044, 204.9744822, 205.9744657, 206.9758973, 207.9766525, 208.9810905, 209.9841889, 210.9887371, 211.9918977, 212.9965629, 213.9998059, 215.00474, 216.00803, 217.01314, 218.01659, 219.02177, 220.02541 }), - new(83, "Bi", "Bismuth", 208.9804, new [] { 184.001275, 184.9976, 185.996644, 186.993147, 187.992287, 188.989195, 189.988622, 190.9857866, 191.985469, 192.98296, 193.982785, 194.9806488, 195.980667, 196.9788651, 197.979206, 198.977673, 199.978131, 200.97701, 201.977734, 202.976893, 203.9778361, 204.9773867, 205.9784993, 206.978471, 207.9797425, 208.9803991, 209.9841207, 210.9872697, 211.991286, 212.9943851, 213.998712, 215.00177, 216.006306, 217.009372, 218.014188, 219.01748, 220.02235, 221.02587, 222.03078, 223.0345, 224.03947 }), - new(84, "Po", "Polonium", 209, new [] { 186.004393, 187.003041, 187.999416, 188.998473, 189.995101, 190.9945585, 191.991336, 192.991026, 193.988186, 194.988126, 195.985526, 196.98566, 197.983389, 198.983667, 199.981799, 200.9822598, 201.980758, 202.9814161, 203.98031, 204.981203, 205.980474, 206.9815938, 207.9812461, 208.9824308, 209.9828741, 210.9866536, 211.9888684, 212.9928576, 213.9952017, 214.9994201, 216.0019152, 217.0063182, 218.0089735, 219.013614, 220.016386, 221.021228, 222.02414, 223.02907, 224.03211, 225.03707, 226.04031, 227.04539 }), - new(85, "At", "Astatine", 210, new [] { 191.004148, 192.003152, 192.999927, 193.999236, 194.9962685, 195.9958, 196.993189, 197.992784, 198.9905277, 199.990351, 200.9884171, 201.98863, 202.986943, 203.987251, 204.986076, 205.986657, 206.9858, 207.9866133, 208.9861702, 209.9871479, 210.9874966, 211.9907377, 212.992937, 213.9963721, 214.9986528, 216.0024236, 217.0047192, 218.008695, 219.0111618, 220.015433, 221.018017, 222.022494, 223.025151, 224.029749, 225.03263, 226.03716, 227.04024, 228.04475, 229.04812 }), - new(86, "Rn", "Radon", 222, new [] { 193.009708, 194.006144, 195.005422, 196.002116, 197.001585, 197.998679, 198.99839, 199.99569, 200.995628, 201.993264, 202.993388, 203.99143, 204.991719, 205.990214, 206.9907303, 207.989635, 208.990415, 209.9896891, 210.9906011, 211.9907039, 212.9938831, 213.995363, 214.9987459, 216.0002719, 217.003928, 218.0056016, 219.0094804, 220.0113941, 221.0155371, 222.0175782, 223.0218893, 224.024096, 225.028486, 226.030861, 227.035304, 228.037835, 229.042257, 230.04514, 231.04987 }), - new(87, "Fr", "Francium", 223, new [] { 199.007259, 200.006586, 201.003867, 202.00332, 203.0009407, 204.000652, 204.9985939, 205.998666, 206.996946, 207.997138, 208.995955, 209.996422, 210.995556, 211.9962257, 212.996186, 213.9989713, 215.0003418, 216.0031899, 217.0046323, 218.0075787, 219.0092524, 220.0123277, 221.0142552, 222.017552, 223.019736, 224.023398, 225.025573, 226.029566, 227.031869, 228.035823, 229.038298, 230.042416, 231.045158, 232.04937, 233.05264 }), - new(88, "Ra", "Radium", 226, new [] { 201.01271, 202.00976, 203.009304, 204.006492, 205.006268, 206.003828, 207.003799, 208.001841, 209.00199, 210.000494, 211.0008932, 211.999787, 213.000384, 214.0000997, 215.0027204, 216.0035334, 217.0063207, 218.007141, 219.0100855, 220.0110259, 221.0139177, 222.0153748, 223.0185023, 224.020212, 225.0236119, 226.0254103, 227.0291783, 228.0310707, 229.034942, 230.037055, 231.041027, 232.0434753, 233.047582, 234.050342, 235.05497 }), - new(89, "Ac", "Actinium", 227, new [] { 206.014452, 207.011966, 208.01155, 209.009495, 210.009436, 211.007732, 212.007813, 213.006609, 214.006918, 215.006475, 216.008743, 217.009344, 218.011642, 219.012421, 220.0147549, 221.015592, 222.0178442, 223.0191377, 224.0217232, 225.02323, 226.0260984, 227.0277523, 228.0310215, 229.032956, 230.036327, 231.038393, 232.042034, 233.044346, 234.048139, 235.05084, 236.054988, 237.05827 }), - new(90, "Th", "Thorium", 232.0377, new [] { 208.0179, 209.017753, 210.015094, 211.014929, 212.012988, 213.013009, 214.0115, 215.0117248, 216.011056, 217.013117, 218.013276, 219.015537, 220.015748, 221.018184, 222.018469, 223.0208119, 224.021464, 225.0239514, 226.0249034, 227.0277042, 228.0287413, 229.0317627, 230.0331341, 231.0363046, 232.0380558, 233.0415823, 234.0436014, 235.047255, 236.049657, 237.053629, 238.0565, 239.06077 }), - new(91, "Pa", "Protactinium", 231.03588, new [] { 212.023203, 213.021109, 214.020918, 215.019183, 216.019109, 217.018325, 218.020059, 219.019904, 220.021705, 221.021875, 222.023784, 223.023963, 224.0256176, 225.026131, 226.027948, 227.0288054, 228.0310517, 229.0320972, 230.034541, 231.0358842, 232.0385917, 233.0402472, 234.0433072, 235.045399, 236.048668, 237.051023, 238.054637, 239.05726, 240.06098, 241.06408 }), - new(92, "U", "Uranium", 238.02891, new [] { 217.02466, 218.023523, 219.024999, 220.02462, 221.02628, 222.026, 223.027739, 224.027605, 225.029391, 226.029339, 227.031157, 228.031371, 229.0335063, 230.0339401, 231.0362939, 232.0371563, 233.0396355, 234.0409523, 235.0439301, 236.0455682, 237.0487304, 238.0507884, 239.0542935, 240.0565934, 241.06033, 242.06293, 243.06699 }), - new(93, "Np", "Neptunium", 237, new [] { 219.03143, 220.03254, 221.03204, 222.0333, 223.03285, 224.03422, 225.033911, 226.035188, 227.034957, 228.036067, 229.036264, 230.037828, 231.038245, 232.04011, 233.040741, 234.0428953, 235.0440635, 236.04657, 237.0481736, 238.0509466, 239.0529392, 240.056165, 241.058253, 242.06164, 243.06428, 244.06785, 245.0708 }), - new(94, "Pu", "Plutonium", 244, new [] { 228.038732, 229.040144, 230.03965, 231.041102, 232.041185, 233.042998, 234.0433174, 235.045286, 236.0460581, 237.0484098, 238.0495601, 239.0521636, 240.0538138, 241.0568517, 242.0587428, 243.0620036, 244.0642053, 245.067826, 246.070205, 247.07419 }), - new(95, "Am", "Americium", 243, new [] { 230.04609, 231.04556, 232.04645, 233.04644, 234.04773, 235.047908, 236.04943, 237.049996, 238.051985, 239.0530247, 240.0553, 241.0568293, 242.0595494, 243.0613813, 244.0642851, 245.0664548, 246.069775, 247.07209, 248.07575, 249.07848 }), - new(96, "Cm", "Curium", 247, new [] { 232.04982, 233.05077, 234.05016, 235.05154, 236.051374, 237.052869, 238.053081, 239.05491, 240.0555297, 241.0576532, 242.058836, 243.0613893, 244.0627528, 245.0654915, 246.0672238, 247.0703541, 248.0723499, 249.0759548, 250.078358, 251.082286, 252.08487 }), - new(97, "Bk", "Berkelium", 247, new [] { 234.05727, 235.05658, 236.05748, 237.0571, 238.0582, 239.05824, 240.05976, 241.06016, 242.06198, 243.0630078, 244.065181, 245.0663618, 246.068673, 247.0703073, 248.073088, 249.0749877, 250.0783167, 251.080762, 252.08431, 253.08688, 254.0906 }), - new(98, "Cf", "Californium", 251, new [] { 237.062198, 238.06149, 239.06253, 240.062256, 241.06369, 242.063754, 243.06548, 244.0660008, 245.0680487, 246.0688055, 247.070965, 248.0721851, 249.0748539, 250.0764062, 251.0795886, 252.0816272, 253.0851345, 254.087324, 255.09105, 256.09344 }), - new(99, "Es", "Einsteinium", 252, new [] { 239.06823, 240.06892, 241.06856, 242.06957, 243.06951, 244.07088, 245.07125, 246.0729, 247.073622, 248.075471, 249.076411, 250.07861, 251.0799936, 252.08298, 253.0848257, 254.0880222, 255.090275, 256.0936, 257.09598, 258.09952 }), - new(100, "Fm", "Fermium", 257, new [] { 241.07421, 242.07343, 243.07446, 244.07404, 245.07535, 246.07535, 247.07694, 248.0771865, 249.0789275, 250.079521, 251.08154, 252.0824671, 253.0851846, 254.0868544, 255.089964, 256.0917745, 257.0951061, 258.09708, 259.1006, 260.10281 }), - new(101, "Md", "Mendelevium", 258, new [] { 245.08081, 246.08171, 247.08152, 248.08282, 249.08291, 250.08441, 251.084774, 252.08643, 253.087144, 254.08959, 255.0910841, 256.09389, 257.0955424, 258.0984315, 259.10051, 260.10365, 261.10583, 262.1091 }), - new(102, "No", "Nobelium", 259, new [] { 248.08655, 249.0878, 250.08756, 251.08894, 252.088967, 253.0905641, 254.090956, 255.093191, 256.0942829, 257.0968878, 258.09821, 259.10103, 260.10264, 261.1057, 262.10746, 263.11071, 264.11273 }), - new(103, "Lr", "Lawrencium", 266, new [] { 251.09418, 252.09526, 253.09509, 254.09648, 255.096562, 256.098494, 257.099418, 258.10176, 259.102902, 260.1055, 261.10688, 262.10961, 263.11136, 264.1142, 265.11619, 266.11983 }), - new(104, "Rf", "Rutherfordium", 267, new [] { 253.10044, 254.10005, 255.10127, 256.101152, 257.102918, 258.103428, 259.105596, 260.10644, 261.108773, 262.10992, 263.11249, 264.11388, 265.11668, 266.11817, 267.12179, 268.12397 }), - new(105, "Db", "Dubnium", 268, new [] { 255.10707, 256.10789, 257.10758, 258.10928, 259.109492, 260.1113, 261.11192, 262.11407, 263.11499, 264.11741, 265.11861, 266.12103, 267.12247, 268.12567, 269.12791, 270.13136 }), - new(106, "Sg", "Seaborgium", 269, new [] { 258.11298, 259.1144, 260.114384, 261.115949, 262.116337, 263.11829, 264.11893, 265.12109, 266.12198, 267.12436, 268.12539, 269.12863, 270.13043, 271.13393, 272.13589, 273.13958 }), - new(107, "Bh", "Bohrium", 270, new [] { 260.12166, 261.12145, 262.12297, 263.12292, 264.12459, 265.12491, 266.12679, 267.1275, 268.12969, 269.13042, 270.13336, 271.13526, 272.13826, 273.14024, 274.14355, 275.14567 }), - new(108, "Hs", "Hassium", 270, new [] { 263.12852, 264.128357, 265.129793, 266.130046, 267.13167, 268.13186, 269.13375, 270.13429, 271.13717, 272.1385, 273.14168, 274.1433, 275.14667, 276.14846, 277.1519 }), - new(109, "Mt", "Meitnerium", 278, new [] { 265.136, 266.13737, 267.13719, 268.13865, 269.13882, 270.14033, 271.14074, 272.14341, 273.1444, 274.14724, 275.14882, 276.15159, 277.15327, 278.15631, 279.15808 }), - new(110, "Ds", "Darmstadtium", 281, new [] { 267.14377, 268.14348, 269.144752, 270.144584, 271.14595, 272.14602, 273.14856, 274.14941, 275.15203, 276.15303, 277.15591, 278.15704, 279.1601, 280.16131, 281.16451 }), - new(111, "Rg", "Roentgenium", 282, new [] { 272.15327, 273.15313, 274.15525, 275.15594, 276.15833, 277.15907, 278.16149, 279.16272, 280.16514, 281.16636, 282.16912, 283.17054 }), - new(112, "Cn", "Copernicium", 285, new [] { 276.16141, 277.16364, 278.16416, 279.16654, 280.16715, 281.16975, 282.1705, 283.17327, 284.17416, 285.17712 }), - new(113, "Nh", "Nihonium", 286, new [] { 278.17058, 279.17095, 280.17293, 281.17348, 282.17567, 283.17657, 284.17873, 285.17973, 286.18221, 287.18339 }), - new(114, "Fl", "Flerovium", 289, new [] { 285.18364, 286.18423, 287.18678, 288.18757, 289.19042 }), - new(115, "Mc", "Moscovium", 290, new [] { 287.1907, 288.19274, 289.19363, 290.19598, 291.19707 }), - new(116, "Lv", "Livermorium", 293, new [] { 289.19816, 290.19864, 291.20108, 292.20174, 293.20449 }), - new(117, "Ts", "Tennessine", 294, new [] { 291.20553, 292.20746, 293.20824, 294.21046 }), - new(118, "Og", "Oganesson", 294, new [] { 293.21356, 294.21392, 295.21624 }) - }; - symbols = periodicTable.ToDictionary(ele => ele.Symbol); - } - } -} diff --git a/Chemistry/Chemistry/ChemistryExtensions.cs b/Chemistry/Chemistry/ChemistryExtensions.cs deleted file mode 100644 index 7db9a929..00000000 --- a/Chemistry/Chemistry/ChemistryExtensions.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Chemistry; - -/// -/// The helpers and extensions of chemistry. -/// -public static class ChemistryExtensions -{ - /// - /// Gets or sets the max atomic number of periodic table; or -1 for unlimited. - /// But this will not prevent creating a customized chemical element nor getting an existed from periodic table. - /// - public static int MaxAtomicNumber { get; set; } = -1; - - /// - /// Adds molecular formula into a list. - /// - /// The molecular fomula collection. - /// A molecular formula instance to add. - /// The count of the value. - /// Another optional molecular formula instance to add. - /// The count of another. - /// The optional third molecular formula instance to add - /// The count of the third molecular formula instance to add. - public static void Add(this ICollection formulas, MolecularFormula value, int count, MolecularFormula another = null, int countForAnother = 1, MolecularFormula other = null, int countForLast = 1) - { - if (formulas is null) return; - if (value != null) - { - for (var i = 0; i < count; i++) - { - formulas.Add(value); - } - } - - if (another != null) - { - for (var i = 0; i < countForAnother; i++) - { - formulas.Add(another); - } - } - - if (other != null) - { - for (var i = 0; i < countForLast; i++) - { - formulas.Add(other); - } - } - } - - /// - /// Adds molecular formula into a list. - /// - /// The molecular fomula collection. - /// A chemical element to add. - /// The count of the value. - public static void Add(this ICollection formulas, ChemicalElement value, int count = 1) - { - if (formulas is null) return; - if (value != null && count > 0) formulas.Add(new MolecularFormula(value, count)); - } - - /// - /// Filters all elements in the specific period. - /// - /// The source collection. - /// The period. - /// A collection after filter. - public static IEnumerable PeriodElements(this IEnumerable source, int period) - => (source ?? new List()).Where(ele => ele.Period == period); - - /// - /// Gets a value indicating whether an element is radioelement. - /// - /// The element to test - /// true if it is a radioelement; otherwise, false. - public static bool IsRadioelement(this ChemicalElement element) - { - if (element is null) return false; - return element.AtomicNumber >= 84 || element.AtomicNumber == 61 || element.AtomicNumber == 43; - } - - /// - /// Gets the electron configuration. - /// - /// The element to test - /// A string that represents the electron configuation of the specific chemical element; or null, if not supported. - public static string GetElectronConfigurationString(ChemicalElement element) - { - if (element is null || element.Period < 1 || element.Period > 7) return null; - if (element.AtomicNumber > 105 && element.AtomicNumber < 113) return null; - return element.Group switch - { - 1 => element.Period.ToString("g") + "s¹", - 2 => element.Period.ToString("g") + "s²", - 3 => element.IndexInPeriod switch - { - 2 => $"{element.Period - 1}d¹{element.Period}s²", - 3 => element.AtomicNumber == 58 ? $"{element.Period - 2}f¹{element.Period - 1}d¹{element.Period}s²" : $"{element.Period - 1}d²{element.Period}s²", - 4 => element.AtomicNumber == 59 ? $"{element.Period - 2}f³{element.Period}s²" : $"{element.Period - 2}f²{element.Period - 1}d¹{element.Period}s²", - 5 => element.AtomicNumber == 60 ? $"{element.Period - 2}f⁴{element.Period}s²" : $"{element.Period - 2}f³{element.Period - 1}d¹{element.Period}s²", - 6 => element.AtomicNumber == 61 ? $"{element.Period - 2}f⁵{element.Period}s²" : $"{element.Period - 2}f⁴{element.Period - 1}d¹{element.Period}s²", - 7 => $"{element.Period - 2}f⁶{element.Period}s²", - 8 => $"{element.Period - 2}f⁷{element.Period}s²", - 9 => $"{element.Period - 2}f⁷{element.Period - 1}d¹{element.Period}s²", - 10 => $"{element.Period - 2}f⁹{element.Period}s²", - 11 => $"{element.Period - 2}f¹⁰{element.Period}s²", - 12 => $"{element.Period - 2}f¹¹{element.Period}s²", - 13 => $"{element.Period - 2}f¹²{element.Period}s²", - 14 => $"{element.Period - 2}f¹³{element.Period}s²", - 15 => $"{element.Period - 2}f¹⁴{element.Period}s²", - 16 => $"{element.Period - 2}f¹⁴{element.Period - 1}d¹{element.Period}s²", - _ => null - }, - 4 => $"{element.Period - 1}d²{element.Period}s¹", - 5 => element.AtomicNumber == 41 ? $"{element.Period - 1}d⁴{element.Period}s¹" : $"{element.Period - 1}d³{element.Period}s²", - 6 => element.AtomicNumber == 74 ? $"{element.Period - 1}d⁴{element.Period}s²" : $"{element.Period - 1}d⁵{element.Period}s¹", - 7 => $"{element.Period - 1}d⁵{element.Period}s²", - 8 => element.AtomicNumber == 44 ? $"{element.Period - 1}d⁷{element.Period}s¹" : $"{element.Period - 1}d⁶{element.Period}s²", - 9 => element.AtomicNumber == 45 ? $"{element.Period - 1}d⁸{element.Period}s¹" : $"{element.Period - 1}d⁷{element.Period}s²", - 10 => element.AtomicNumber == 28 ? $"{element.Period - 1}d⁸{element.Period}s²" : (element.AtomicNumber == 46 ? $"{element.Period - 1}d¹⁰{element.Period}s¹" : $"{element.Period - 1}d⁹{element.Period}s¹"), - 11 => $"{element.Period - 1}d¹⁰{element.Period}s¹", - 12 => $"{element.Period - 1}d¹⁰{element.Period}s²", - 13 => $"{element.Period}s²{element.Period}p¹", - 14 => $"{element.Period}s²{element.Period}p²", - 15 => $"{element.Period}s²{element.Period}p³", - 16 => $"{element.Period}s²{element.Period}p⁴", - 17 => $"{element.Period}s²{element.Period}p⁵", - 18 => $"{element.Period}s²{element.Period}p⁶", - _ => null - }; - } -} diff --git a/Chemistry/Chemistry/ChemistryResource.Designer.cs b/Chemistry/Chemistry/ChemistryResource.Designer.cs deleted file mode 100644 index 4282e9a2..00000000 --- a/Chemistry/Chemistry/ChemistryResource.Designer.cs +++ /dev/null @@ -1,1179 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -namespace Trivial.Chemistry { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ChemistryResource { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ChemistryResource() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Trivial.Chemistry.ChemistryResource", typeof(ChemistryResource).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性,对 - /// 使用此强类型资源类的所有资源查找执行重写。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找类似 Chemical element 的本地化字符串。 - /// - internal static string ChemicalElement { - get { - return ResourceManager.GetString("ChemicalElement", resourceCulture); - } - } - - /// - /// 查找类似 Chemistry 的本地化字符串。 - /// - internal static string Chemistry { - get { - return ResourceManager.GetString("Chemistry", resourceCulture); - } - } - - /// - /// 查找类似 Element 的本地化字符串。 - /// - internal static string Element { - get { - return ResourceManager.GetString("Element", resourceCulture); - } - } - - /// - /// 查找类似 Hydrogen 的本地化字符串。 - /// - internal static string Element001 { - get { - return ResourceManager.GetString("Element001", resourceCulture); - } - } - - /// - /// 查找类似 Helium 的本地化字符串。 - /// - internal static string Element002 { - get { - return ResourceManager.GetString("Element002", resourceCulture); - } - } - - /// - /// 查找类似 Lithium 的本地化字符串。 - /// - internal static string Element003 { - get { - return ResourceManager.GetString("Element003", resourceCulture); - } - } - - /// - /// 查找类似 Beryllium 的本地化字符串。 - /// - internal static string Element004 { - get { - return ResourceManager.GetString("Element004", resourceCulture); - } - } - - /// - /// 查找类似 Boron 的本地化字符串。 - /// - internal static string Element005 { - get { - return ResourceManager.GetString("Element005", resourceCulture); - } - } - - /// - /// 查找类似 Carbon 的本地化字符串。 - /// - internal static string Element006 { - get { - return ResourceManager.GetString("Element006", resourceCulture); - } - } - - /// - /// 查找类似 Nitrogen 的本地化字符串。 - /// - internal static string Element007 { - get { - return ResourceManager.GetString("Element007", resourceCulture); - } - } - - /// - /// 查找类似 Oxygen 的本地化字符串。 - /// - internal static string Element008 { - get { - return ResourceManager.GetString("Element008", resourceCulture); - } - } - - /// - /// 查找类似 Fluorine 的本地化字符串。 - /// - internal static string Element009 { - get { - return ResourceManager.GetString("Element009", resourceCulture); - } - } - - /// - /// 查找类似 Neon 的本地化字符串。 - /// - internal static string Element010 { - get { - return ResourceManager.GetString("Element010", resourceCulture); - } - } - - /// - /// 查找类似 Sodium 的本地化字符串。 - /// - internal static string Element011 { - get { - return ResourceManager.GetString("Element011", resourceCulture); - } - } - - /// - /// 查找类似 Magnesium 的本地化字符串。 - /// - internal static string Element012 { - get { - return ResourceManager.GetString("Element012", resourceCulture); - } - } - - /// - /// 查找类似 Aluminium 的本地化字符串。 - /// - internal static string Element013 { - get { - return ResourceManager.GetString("Element013", resourceCulture); - } - } - - /// - /// 查找类似 Silicon 的本地化字符串。 - /// - internal static string Element014 { - get { - return ResourceManager.GetString("Element014", resourceCulture); - } - } - - /// - /// 查找类似 Phosphorus 的本地化字符串。 - /// - internal static string Element015 { - get { - return ResourceManager.GetString("Element015", resourceCulture); - } - } - - /// - /// 查找类似 Sulfur 的本地化字符串。 - /// - internal static string Element016 { - get { - return ResourceManager.GetString("Element016", resourceCulture); - } - } - - /// - /// 查找类似 Chlorine 的本地化字符串。 - /// - internal static string Element017 { - get { - return ResourceManager.GetString("Element017", resourceCulture); - } - } - - /// - /// 查找类似 Argon 的本地化字符串。 - /// - internal static string Element018 { - get { - return ResourceManager.GetString("Element018", resourceCulture); - } - } - - /// - /// 查找类似 Potassium 的本地化字符串。 - /// - internal static string Element019 { - get { - return ResourceManager.GetString("Element019", resourceCulture); - } - } - - /// - /// 查找类似 Calcium 的本地化字符串。 - /// - internal static string Element020 { - get { - return ResourceManager.GetString("Element020", resourceCulture); - } - } - - /// - /// 查找类似 Scandium 的本地化字符串。 - /// - internal static string Element021 { - get { - return ResourceManager.GetString("Element021", resourceCulture); - } - } - - /// - /// 查找类似 Titanium 的本地化字符串。 - /// - internal static string Element022 { - get { - return ResourceManager.GetString("Element022", resourceCulture); - } - } - - /// - /// 查找类似 Vanadium 的本地化字符串。 - /// - internal static string Element023 { - get { - return ResourceManager.GetString("Element023", resourceCulture); - } - } - - /// - /// 查找类似 Chromium 的本地化字符串。 - /// - internal static string Element024 { - get { - return ResourceManager.GetString("Element024", resourceCulture); - } - } - - /// - /// 查找类似 Manganese 的本地化字符串。 - /// - internal static string Element025 { - get { - return ResourceManager.GetString("Element025", resourceCulture); - } - } - - /// - /// 查找类似 Iron 的本地化字符串。 - /// - internal static string Element026 { - get { - return ResourceManager.GetString("Element026", resourceCulture); - } - } - - /// - /// 查找类似 Cobalt 的本地化字符串。 - /// - internal static string Element027 { - get { - return ResourceManager.GetString("Element027", resourceCulture); - } - } - - /// - /// 查找类似 Nickel 的本地化字符串。 - /// - internal static string Element028 { - get { - return ResourceManager.GetString("Element028", resourceCulture); - } - } - - /// - /// 查找类似 Copper 的本地化字符串。 - /// - internal static string Element029 { - get { - return ResourceManager.GetString("Element029", resourceCulture); - } - } - - /// - /// 查找类似 Zinc 的本地化字符串。 - /// - internal static string Element030 { - get { - return ResourceManager.GetString("Element030", resourceCulture); - } - } - - /// - /// 查找类似 Gallium 的本地化字符串。 - /// - internal static string Element031 { - get { - return ResourceManager.GetString("Element031", resourceCulture); - } - } - - /// - /// 查找类似 Germanium 的本地化字符串。 - /// - internal static string Element032 { - get { - return ResourceManager.GetString("Element032", resourceCulture); - } - } - - /// - /// 查找类似 Arsenic 的本地化字符串。 - /// - internal static string Element033 { - get { - return ResourceManager.GetString("Element033", resourceCulture); - } - } - - /// - /// 查找类似 Selenium 的本地化字符串。 - /// - internal static string Element034 { - get { - return ResourceManager.GetString("Element034", resourceCulture); - } - } - - /// - /// 查找类似 Bromine 的本地化字符串。 - /// - internal static string Element035 { - get { - return ResourceManager.GetString("Element035", resourceCulture); - } - } - - /// - /// 查找类似 Krypton 的本地化字符串。 - /// - internal static string Element036 { - get { - return ResourceManager.GetString("Element036", resourceCulture); - } - } - - /// - /// 查找类似 Rubidium 的本地化字符串。 - /// - internal static string Element037 { - get { - return ResourceManager.GetString("Element037", resourceCulture); - } - } - - /// - /// 查找类似 Strontium 的本地化字符串。 - /// - internal static string Element038 { - get { - return ResourceManager.GetString("Element038", resourceCulture); - } - } - - /// - /// 查找类似 Yttrium 的本地化字符串。 - /// - internal static string Element039 { - get { - return ResourceManager.GetString("Element039", resourceCulture); - } - } - - /// - /// 查找类似 Zirconium 的本地化字符串。 - /// - internal static string Element040 { - get { - return ResourceManager.GetString("Element040", resourceCulture); - } - } - - /// - /// 查找类似 Niobium 的本地化字符串。 - /// - internal static string Element041 { - get { - return ResourceManager.GetString("Element041", resourceCulture); - } - } - - /// - /// 查找类似 Molybdenum 的本地化字符串。 - /// - internal static string Element042 { - get { - return ResourceManager.GetString("Element042", resourceCulture); - } - } - - /// - /// 查找类似 Technetium 的本地化字符串。 - /// - internal static string Element043 { - get { - return ResourceManager.GetString("Element043", resourceCulture); - } - } - - /// - /// 查找类似 Ruthenium 的本地化字符串。 - /// - internal static string Element044 { - get { - return ResourceManager.GetString("Element044", resourceCulture); - } - } - - /// - /// 查找类似 Rhodium 的本地化字符串。 - /// - internal static string Element045 { - get { - return ResourceManager.GetString("Element045", resourceCulture); - } - } - - /// - /// 查找类似 Palladium 的本地化字符串。 - /// - internal static string Element046 { - get { - return ResourceManager.GetString("Element046", resourceCulture); - } - } - - /// - /// 查找类似 Silver 的本地化字符串。 - /// - internal static string Element047 { - get { - return ResourceManager.GetString("Element047", resourceCulture); - } - } - - /// - /// 查找类似 Cadmium 的本地化字符串。 - /// - internal static string Element048 { - get { - return ResourceManager.GetString("Element048", resourceCulture); - } - } - - /// - /// 查找类似 Indium 的本地化字符串。 - /// - internal static string Element049 { - get { - return ResourceManager.GetString("Element049", resourceCulture); - } - } - - /// - /// 查找类似 Tin 的本地化字符串。 - /// - internal static string Element050 { - get { - return ResourceManager.GetString("Element050", resourceCulture); - } - } - - /// - /// 查找类似 Antimony 的本地化字符串。 - /// - internal static string Element051 { - get { - return ResourceManager.GetString("Element051", resourceCulture); - } - } - - /// - /// 查找类似 Tellurium 的本地化字符串。 - /// - internal static string Element052 { - get { - return ResourceManager.GetString("Element052", resourceCulture); - } - } - - /// - /// 查找类似 Iodine 的本地化字符串。 - /// - internal static string Element053 { - get { - return ResourceManager.GetString("Element053", resourceCulture); - } - } - - /// - /// 查找类似 Xenon 的本地化字符串。 - /// - internal static string Element054 { - get { - return ResourceManager.GetString("Element054", resourceCulture); - } - } - - /// - /// 查找类似 Caesium 的本地化字符串。 - /// - internal static string Element055 { - get { - return ResourceManager.GetString("Element055", resourceCulture); - } - } - - /// - /// 查找类似 Barium 的本地化字符串。 - /// - internal static string Element056 { - get { - return ResourceManager.GetString("Element056", resourceCulture); - } - } - - /// - /// 查找类似 Lanthanum 的本地化字符串。 - /// - internal static string Element057 { - get { - return ResourceManager.GetString("Element057", resourceCulture); - } - } - - /// - /// 查找类似 Cerium 的本地化字符串。 - /// - internal static string Element058 { - get { - return ResourceManager.GetString("Element058", resourceCulture); - } - } - - /// - /// 查找类似 Praseodymium 的本地化字符串。 - /// - internal static string Element059 { - get { - return ResourceManager.GetString("Element059", resourceCulture); - } - } - - /// - /// 查找类似 Neodymium 的本地化字符串。 - /// - internal static string Element060 { - get { - return ResourceManager.GetString("Element060", resourceCulture); - } - } - - /// - /// 查找类似 Promethium 的本地化字符串。 - /// - internal static string Element061 { - get { - return ResourceManager.GetString("Element061", resourceCulture); - } - } - - /// - /// 查找类似 Samarium 的本地化字符串。 - /// - internal static string Element062 { - get { - return ResourceManager.GetString("Element062", resourceCulture); - } - } - - /// - /// 查找类似 Europium 的本地化字符串。 - /// - internal static string Element063 { - get { - return ResourceManager.GetString("Element063", resourceCulture); - } - } - - /// - /// 查找类似 Gadolinium 的本地化字符串。 - /// - internal static string Element064 { - get { - return ResourceManager.GetString("Element064", resourceCulture); - } - } - - /// - /// 查找类似 Terbium 的本地化字符串。 - /// - internal static string Element065 { - get { - return ResourceManager.GetString("Element065", resourceCulture); - } - } - - /// - /// 查找类似 Dysprosium 的本地化字符串。 - /// - internal static string Element066 { - get { - return ResourceManager.GetString("Element066", resourceCulture); - } - } - - /// - /// 查找类似 Holmium 的本地化字符串。 - /// - internal static string Element067 { - get { - return ResourceManager.GetString("Element067", resourceCulture); - } - } - - /// - /// 查找类似 Erbium 的本地化字符串。 - /// - internal static string Element068 { - get { - return ResourceManager.GetString("Element068", resourceCulture); - } - } - - /// - /// 查找类似 Thulium 的本地化字符串。 - /// - internal static string Element069 { - get { - return ResourceManager.GetString("Element069", resourceCulture); - } - } - - /// - /// 查找类似 Ytterbium 的本地化字符串。 - /// - internal static string Element070 { - get { - return ResourceManager.GetString("Element070", resourceCulture); - } - } - - /// - /// 查找类似 Lutetium 的本地化字符串。 - /// - internal static string Element071 { - get { - return ResourceManager.GetString("Element071", resourceCulture); - } - } - - /// - /// 查找类似 Hafnium 的本地化字符串。 - /// - internal static string Element072 { - get { - return ResourceManager.GetString("Element072", resourceCulture); - } - } - - /// - /// 查找类似 Tantalum 的本地化字符串。 - /// - internal static string Element073 { - get { - return ResourceManager.GetString("Element073", resourceCulture); - } - } - - /// - /// 查找类似 Tungsten 的本地化字符串。 - /// - internal static string Element074 { - get { - return ResourceManager.GetString("Element074", resourceCulture); - } - } - - /// - /// 查找类似 Rhenium 的本地化字符串。 - /// - internal static string Element075 { - get { - return ResourceManager.GetString("Element075", resourceCulture); - } - } - - /// - /// 查找类似 Osmium 的本地化字符串。 - /// - internal static string Element076 { - get { - return ResourceManager.GetString("Element076", resourceCulture); - } - } - - /// - /// 查找类似 Iridium 的本地化字符串。 - /// - internal static string Element077 { - get { - return ResourceManager.GetString("Element077", resourceCulture); - } - } - - /// - /// 查找类似 Platinum 的本地化字符串。 - /// - internal static string Element078 { - get { - return ResourceManager.GetString("Element078", resourceCulture); - } - } - - /// - /// 查找类似 Gold 的本地化字符串。 - /// - internal static string Element079 { - get { - return ResourceManager.GetString("Element079", resourceCulture); - } - } - - /// - /// 查找类似 Mercury 的本地化字符串。 - /// - internal static string Element080 { - get { - return ResourceManager.GetString("Element080", resourceCulture); - } - } - - /// - /// 查找类似 Thallium 的本地化字符串。 - /// - internal static string Element081 { - get { - return ResourceManager.GetString("Element081", resourceCulture); - } - } - - /// - /// 查找类似 Lead 的本地化字符串。 - /// - internal static string Element082 { - get { - return ResourceManager.GetString("Element082", resourceCulture); - } - } - - /// - /// 查找类似 Bismuth 的本地化字符串。 - /// - internal static string Element083 { - get { - return ResourceManager.GetString("Element083", resourceCulture); - } - } - - /// - /// 查找类似 Polonium 的本地化字符串。 - /// - internal static string Element084 { - get { - return ResourceManager.GetString("Element084", resourceCulture); - } - } - - /// - /// 查找类似 Astatine 的本地化字符串。 - /// - internal static string Element085 { - get { - return ResourceManager.GetString("Element085", resourceCulture); - } - } - - /// - /// 查找类似 Radon 的本地化字符串。 - /// - internal static string Element086 { - get { - return ResourceManager.GetString("Element086", resourceCulture); - } - } - - /// - /// 查找类似 Francium 的本地化字符串。 - /// - internal static string Element087 { - get { - return ResourceManager.GetString("Element087", resourceCulture); - } - } - - /// - /// 查找类似 Radium 的本地化字符串。 - /// - internal static string Element088 { - get { - return ResourceManager.GetString("Element088", resourceCulture); - } - } - - /// - /// 查找类似 Actinium 的本地化字符串。 - /// - internal static string Element089 { - get { - return ResourceManager.GetString("Element089", resourceCulture); - } - } - - /// - /// 查找类似 Thorium 的本地化字符串。 - /// - internal static string Element090 { - get { - return ResourceManager.GetString("Element090", resourceCulture); - } - } - - /// - /// 查找类似 Protactinium 的本地化字符串。 - /// - internal static string Element091 { - get { - return ResourceManager.GetString("Element091", resourceCulture); - } - } - - /// - /// 查找类似 Uranium 的本地化字符串。 - /// - internal static string Element092 { - get { - return ResourceManager.GetString("Element092", resourceCulture); - } - } - - /// - /// 查找类似 Neptunium 的本地化字符串。 - /// - internal static string Element093 { - get { - return ResourceManager.GetString("Element093", resourceCulture); - } - } - - /// - /// 查找类似 Plutonium 的本地化字符串。 - /// - internal static string Element094 { - get { - return ResourceManager.GetString("Element094", resourceCulture); - } - } - - /// - /// 查找类似 Americium 的本地化字符串。 - /// - internal static string Element095 { - get { - return ResourceManager.GetString("Element095", resourceCulture); - } - } - - /// - /// 查找类似 Curium 的本地化字符串。 - /// - internal static string Element096 { - get { - return ResourceManager.GetString("Element096", resourceCulture); - } - } - - /// - /// 查找类似 Berkelium 的本地化字符串。 - /// - internal static string Element097 { - get { - return ResourceManager.GetString("Element097", resourceCulture); - } - } - - /// - /// 查找类似 Californium 的本地化字符串。 - /// - internal static string Element098 { - get { - return ResourceManager.GetString("Element098", resourceCulture); - } - } - - /// - /// 查找类似 Einsteinium 的本地化字符串。 - /// - internal static string Element099 { - get { - return ResourceManager.GetString("Element099", resourceCulture); - } - } - - /// - /// 查找类似 Fermium 的本地化字符串。 - /// - internal static string Element100 { - get { - return ResourceManager.GetString("Element100", resourceCulture); - } - } - - /// - /// 查找类似 Mendelevium 的本地化字符串。 - /// - internal static string Element101 { - get { - return ResourceManager.GetString("Element101", resourceCulture); - } - } - - /// - /// 查找类似 Nobelium 的本地化字符串。 - /// - internal static string Element102 { - get { - return ResourceManager.GetString("Element102", resourceCulture); - } - } - - /// - /// 查找类似 Lawrencium 的本地化字符串。 - /// - internal static string Element103 { - get { - return ResourceManager.GetString("Element103", resourceCulture); - } - } - - /// - /// 查找类似 Rutherfordium 的本地化字符串。 - /// - internal static string Element104 { - get { - return ResourceManager.GetString("Element104", resourceCulture); - } - } - - /// - /// 查找类似 Dubnium 的本地化字符串。 - /// - internal static string Element105 { - get { - return ResourceManager.GetString("Element105", resourceCulture); - } - } - - /// - /// 查找类似 Seaborgium 的本地化字符串。 - /// - internal static string Element106 { - get { - return ResourceManager.GetString("Element106", resourceCulture); - } - } - - /// - /// 查找类似 Bohrium 的本地化字符串。 - /// - internal static string Element107 { - get { - return ResourceManager.GetString("Element107", resourceCulture); - } - } - - /// - /// 查找类似 Hassium 的本地化字符串。 - /// - internal static string Element108 { - get { - return ResourceManager.GetString("Element108", resourceCulture); - } - } - - /// - /// 查找类似 Meitnerium 的本地化字符串。 - /// - internal static string Element109 { - get { - return ResourceManager.GetString("Element109", resourceCulture); - } - } - - /// - /// 查找类似 Darmstadtium 的本地化字符串。 - /// - internal static string Element110 { - get { - return ResourceManager.GetString("Element110", resourceCulture); - } - } - - /// - /// 查找类似 Roentgenium 的本地化字符串。 - /// - internal static string Element111 { - get { - return ResourceManager.GetString("Element111", resourceCulture); - } - } - - /// - /// 查找类似 Copernicium 的本地化字符串。 - /// - internal static string Element112 { - get { - return ResourceManager.GetString("Element112", resourceCulture); - } - } - - /// - /// 查找类似 Nihonium 的本地化字符串。 - /// - internal static string Element113 { - get { - return ResourceManager.GetString("Element113", resourceCulture); - } - } - - /// - /// 查找类似 Flerovium 的本地化字符串。 - /// - internal static string Element114 { - get { - return ResourceManager.GetString("Element114", resourceCulture); - } - } - - /// - /// 查找类似 Moscovium 的本地化字符串。 - /// - internal static string Element115 { - get { - return ResourceManager.GetString("Element115", resourceCulture); - } - } - - /// - /// 查找类似 Livermorium 的本地化字符串。 - /// - internal static string Element116 { - get { - return ResourceManager.GetString("Element116", resourceCulture); - } - } - - /// - /// 查找类似 Tennessine 的本地化字符串。 - /// - internal static string Element117 { - get { - return ResourceManager.GetString("Element117", resourceCulture); - } - } - - /// - /// 查找类似 Oganesson 的本地化字符串。 - /// - internal static string Element118 { - get { - return ResourceManager.GetString("Element118", resourceCulture); - } - } - - /// - /// 查找类似 的本地化字符串。 - /// - internal static string ElementX { - get { - return ResourceManager.GetString("ElementX", resourceCulture); - } - } - - /// - /// 查找类似 Isotope 的本地化字符串。 - /// - internal static string Isotope { - get { - return ResourceManager.GetString("Isotope", resourceCulture); - } - } - - /// - /// 查找类似 Isotopes 的本地化字符串。 - /// - internal static string Isotopes { - get { - return ResourceManager.GetString("Isotopes", resourceCulture); - } - } - } -} diff --git a/Chemistry/Chemistry/ChemistryResource.de.resx b/Chemistry/Chemistry/ChemistryResource.de.resx deleted file mode 100644 index 74789616..00000000 --- a/Chemistry/Chemistry/ChemistryResource.de.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Chemisches element - - - Chemie - - - Elemente - - - Wasserstoff - - - Helium - - - Lithium - - - Beryllium - - - Bor - - - Kohlenstoff - - - Stickstoff - - - Sauerstoff - - - Fluor - - - Neon - - - Natrium - - - Magnesium - - - Aluminium - - - Silicium - - - Phosphor - - - Schwefel - - - Chlor - - - Argon - - - Kalium - - - Calcium - - - Scandium - - - Titan - - - Vanadium - - - Chrom - - - Mangan - - - Eisen - - - Cobalt - - - Nickel - - - Kupfer - - - Zink - - - Gallium - - - Germanium - - - Arsen - - - Selen - - - Brom - - - Krypton - - - Rubidium - - - Strontium - - - Yttrium - - - Zirconium - - - Niob - - - Molybdän - - - Technetium - - - Ruthenium - - - Rhodium - - - Palladium - - - Silber - - - Cadmium - - - Indium - - - Zinn - - - Antimon - - - Tellur - - - Iod - - - Xenon - - - Caesium - - - Barium - - - Lanthan - - - Cer - - - Praseodym - - - Neodym - - - Pro­methium - - - Samarium - - - Europium - - - Gadolinium - - - Terbium - - - Dysprosium - - - Holmium - - - Erbium - - - Thulium - - - Ytterbium - - - Lutetium - - - Hafnium - - - Tantal - - - Wolfram - - - Rhenium - - - Osmium - - - Iridium - - - Platin - - - Gold - - - Quecksilber - - - Thallium - - - Blei - - - Bismut - - - Polonium - - - Astat - - - Radon - - - Francium - - - Radium - - - Actinium - - - Thorium - - - Protac­tinium - - - Uran - - - Neptunium - - - Plutonium - - - Americium - - - Curium - - - Berkelium - - - Californium - - - Einsteinium - - - Fermium - - - Mende­levium - - - Nobelium - - - Lawren­cium - - - Ruther­fordium - - - Dubnium - - - Seaborgium - - - Bohrium - - - Hassium - - - Meitnerium - - - Darm­stadtium - - - Roent­genium - - - Coper­nicium - - - Nihonium - - - Flerovium - - - Moscovium - - - Liver­morium - - - Tenness - - - Oganesson - - - - - - Isotop - - - Isotope - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.en.resx b/Chemistry/Chemistry/ChemistryResource.en.resx deleted file mode 100644 index 0f90d5ab..00000000 --- a/Chemistry/Chemistry/ChemistryResource.en.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Chemical element - - - Chemistry - - - Element - - - Hydrogen - - - Helium - - - Lithium - - - Beryllium - - - Boron - - - Carbon - - - Nitrogen - - - Oxygen - - - Fluorine - - - Neon - - - Sodium - - - Magnesium - - - Aluminium - - - Silicon - - - Phosphorus - - - Sulfur - - - Chlorine - - - Argon - - - Potassium - - - Calcium - - - Scandium - - - Titanium - - - Vanadium - - - Chromium - - - Manganese - - - Iron - - - Cobalt - - - Nickel - - - Copper - - - Zinc - - - Gallium - - - Germanium - - - Arsenic - - - Selenium - - - Bromine - - - Krypton - - - Rubidium - - - Strontium - - - Yttrium - - - Zirconium - - - Niobium - - - Molybdenum - - - Technetium - - - Ruthenium - - - Rhodium - - - Palladium - - - Silver - - - Cadmium - - - Indium - - - Tin - - - Antimony - - - Tellurium - - - Iodine - - - Xenon - - - Caesium - - - Barium - - - Lanthanum - - - Cerium - - - Praseodymium - - - Neodymium - - - Promethium - - - Samarium - - - Europium - - - Gadolinium - - - Terbium - - - Dysprosium - - - Holmium - - - Erbium - - - Thulium - - - Ytterbium - - - Lutetium - - - Hafnium - - - Tantalum - - - Tungsten - - - Rhenium - - - Osmium - - - Iridium - - - Platinum - - - Gold - - - Mercury - - - Thallium - - - Lead - - - Bismuth - - - Polonium - - - Astatine - - - Radon - - - Francium - - - Radium - - - Actinium - - - Thorium - - - Protactinium - - - Uranium - - - Neptunium - - - Plutonium - - - Americium - - - Curium - - - Berkelium - - - Californium - - - Einsteinium - - - Fermium - - - Mendelevium - - - Nobelium - - - Lawrencium - - - Rutherfordium - - - Dubnium - - - Seaborgium - - - Bohrium - - - Hassium - - - Meitnerium - - - Darmstadtium - - - Roentgenium - - - Copernicium - - - Nihonium - - - Flerovium - - - Moscovium - - - Livermorium - - - Tennessine - - - Oganesson - - - - - - Isotope - - - Isotopes - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.es.resx b/Chemistry/Chemistry/ChemistryResource.es.resx deleted file mode 100644 index c60ac137..00000000 --- a/Chemistry/Chemistry/ChemistryResource.es.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Elemento químico - - - Química - - - Elemento - - - Hidrógeno - - - Helio - - - Litio - - - Berilio - - - Boro - - - Carbono - - - Nitrógeno - - - Oxígeno - - - Flúor - - - Neón - - - Sodio - - - Magnesio - - - Aluminio - - - Silicio - - - Fósforo - - - Azufre - - - Cloro - - - Argón - - - Potasio - - - Calcio - - - Escandio - - - Titanio - - - Vanadio - - - Cromo - - - Manganeso - - - Hierro - - - Cobalto - - - Níquel - - - Cobre - - - Zinc - - - Galio - - - Germanio - - - Arsénico - - - Selenio - - - Bromo - - - Kriptón - - - Rubidio - - - Estroncio - - - Itrio - - - Zirconio - - - Niobio - - - Molibdeno - - - Tecnecio - - - Rutenio - - - Rodio - - - Paladio - - - Plata - - - Cadmio - - - Indio - - - Estaño - - - Antimonio - - - Teluro - - - Yodo - - - Xenón - - - Cesio - - - Bario - - - Lantano - - - Cerio - - - Praseodimio - - - Neodimio - - - Prometio - - - Samario - - - Europio - - - Gadolinio - - - Terbio - - - Disprosio - - - Holmio - - - Erbio - - - Tulio - - - Iterbio - - - Lutecio - - - Hafnio - - - Tantalio - - - Wolframio - - - Renio - - - Osmio - - - Iridio - - - Platino - - - Oro - - - Mercurio - - - Talio - - - Plomo - - - Bismuto - - - Polonio - - - Astato - - - Radón - - - Francio - - - Radio - - - Actinio - - - Torio - - - Protactinio - - - Uranio - - - Neptunio - - - Plutonio - - - Americio - - - Curio - - - Berkelio - - - Californio - - - Einstenio - - - Fermio - - - Mendelevio - - - Nobelio - - - Laurencio - - - Rutherfordio - - - Dubnio - - - Seaborgio - - - Bohrio - - - Hassio - - - Meitnerio - - - Darmstatio - - - Roentgenio - - - Copernicio - - - Nihonio - - - Flerovio - - - Moscovio - - - Livermorio - - - Teneso - - - Oganesón - - - Elemento {0} - - - Isótopo - - - Isótopos - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.fr.resx b/Chemistry/Chemistry/ChemistryResource.fr.resx deleted file mode 100644 index 62ac2116..00000000 --- a/Chemistry/Chemistry/ChemistryResource.fr.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Élément chimique - - - Chimie - - - Élément - - - Hydrogène - - - Hélium - - - Lithium - - - Béryllium - - - Bore - - - Carbone - - - Azote - - - Oxygène - - - Fluor - - - Néon - - - Sodium - - - Magnésium - - - Aluminium - - - Silicium - - - Phosphore - - - Soufre - - - Chlore - - - Argon - - - Potassium - - - Calcium - - - Scandium - - - Titane - - - Vanadium - - - Chrome - - - Manganèse - - - Fer - - - Cobalt - - - Nickel - - - Cuivre - - - Zinc - - - Gallium - - - Germanium - - - Arsenic - - - Sélénium - - - Brome - - - Krypton - - - Rubidium - - - Strontium - - - Yttrium - - - Zirconium - - - Niobium - - - Molybdène - - - Technétium - - - Ruthénium - - - Rhodium - - - Palladium - - - Argent - - - Cadmium - - - Indium - - - Étain - - - Antimoine - - - Tellure - - - Iode - - - Xénon - - - Césium - - - Baryum - - - Lanthane - - - Cérium - - - Praséodyme - - - Néodyme - - - Prométhium - - - Samarium - - - Europium - - - Gadolinium - - - Terbium - - - Dysprosium - - - Holmium - - - Erbium - - - Thulium - - - Ytterbium - - - Lutécium - - - Hafnium - - - Tantale - - - Tungstène - - - Rhénium - - - Osmium - - - Iridium - - - Platine - - - Or - - - Mercure - - - Thallium - - - Plomb - - - Bismuth - - - Polonium - - - Astate - - - Radon - - - Francium - - - Radium - - - Actinium - - - Thorium - - - Protactinium - - - Uranium - - - Neptunium - - - Plutonium - - - Américium - - - Curium - - - Berkélium - - - Californium - - - Einsteinium - - - Fermium - - - Mendélévium - - - Nobélium - - - Lawrencium - - - Rutherfordium - - - Dubnium - - - Seaborgium - - - Bohrium - - - Hassium - - - Meitnérium - - - Darmstadtium - - - Roentgenium - - - Copernicium - - - Nihonium - - - Flérovium - - - Moscovium - - - Livermorium - - - Tennesse - - - Oganesson - - - - - - Isotope - - - Isotopes - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.it.resx b/Chemistry/Chemistry/ChemistryResource.it.resx deleted file mode 100644 index 74fea946..00000000 --- a/Chemistry/Chemistry/ChemistryResource.it.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Elemento chimico - - - Chimica - - - Elemento - - - Idrogeno - - - Elio - - - Litio - - - Berillio - - - Boro - - - Carbonio - - - Azoto - - - Ossigeno - - - Fluoro - - - Neon - - - Sodio - - - Magnesio - - - Alluminio - - - Silicio - - - Fosforo - - - Zolfo - - - Cloro - - - Argon - - - Potassio - - - Calcio - - - Scandio - - - Titanio - - - Vanadio - - - Cromo - - - Manganese - - - Ferro - - - Cobalto - - - Nichel - - - Rame - - - Zinco - - - Gallio - - - Germanio - - - Arsenico - - - Selenio - - - Bromo - - - Kripton - - - Rubidio - - - Stronzio - - - Ittrio - - - Zirconio - - - Niobio - - - Molibdeno - - - Tecnezio - - - Rutenio - - - Rodio - - - Palladio - - - Argento - - - Cadmio - - - Indio - - - Stagno - - - Antimonio - - - Tellurio - - - Iodio - - - Xenon - - - Cesio - - - Bario - - - Lantanio - - - Cerio - - - Praseodimio - - - Neodimio - - - Promezio - - - Samario - - - Europio - - - Gadolinio - - - Terbio - - - Disprosio - - - Olmio - - - Erbio - - - Tulio - - - Itterbio - - - Lutezio - - - Afnio - - - Tantalio - - - Tungsteno - - - Renio - - - Osmio - - - Iridio - - - Platino - - - Oro - - - Mercurio - - - Tallio - - - Piombo - - - Bismuto - - - Polonio - - - Astato - - - Radon - - - Francio - - - Radio - - - Attinio - - - Torio - - - Protoattinio - - - Uranio - - - Nettunio - - - Plutonio - - - Americio - - - Curio - - - Berkelio - - - Californio - - - Einsteinio - - - Fermio - - - Mendelevio - - - Nobelio - - - Laurenzio - - - Rutherfordio - - - Dubnio - - - Seaborgio - - - Bohrio - - - Hassio - - - Meitnerio - - - Darmstadtio - - - Roentgenio - - - Copernicio - - - Nihonio - - - Flerovio - - - Moscovio - - - Livermorio - - - Tennesso - - - Oganesson - - - Elemento {0} - - - Isotopo - - - Isotopi - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.ja.resx b/Chemistry/Chemistry/ChemistryResource.ja.resx deleted file mode 100644 index f6f8213b..00000000 --- a/Chemistry/Chemistry/ChemistryResource.ja.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 元素 - - - 化学 - - - 元素 - - - 水素 - - - ヘリウム - - - リチウム - - - ベリリウム - - - ホウ素 - - - 炭素 - - - 窒素 - - - 酸素 - - - フッ素 - - - ネオン - - - ナトリウム - - - マグネシウム - - - アルミニウム - - - ケイ素 - - - - - - 硫黄 - - - 塩素 - - - アルゴン - - - カリウム - - - カルシウム - - - スカンジウム - - - チタン - - - バナジウム - - - クロム - - - マンガン - - - - - - コバルト - - - ニッケル - - - - - - 亜鉛 - - - ガリウム - - - ゲルマニウム - - - ヒ素 - - - セレン - - - 臭素 - - - クリプトン - - - ルビジウム - - - ストロンチウム - - - イットリウム - - - ジルコニウム - - - ニオブ - - - モリブデン - - - テクネチウム - - - ルテニウム - - - ロジウム - - - パラジウム - - - - - - カドミウム - - - インジウム - - - - - - アンチモン - - - テルル - - - ヨウ素 - - - キセノン - - - セシウム - - - バリウム - - - ランタン - - - セリウム - - - プラセオジム - - - ネオジム - - - プロメチウム - - - サマリウム - - - ユウロピウム - - - ガドリニウム - - - テルビウム - - - ジスプロシウム - - - ホルミウム - - - エルビウム - - - ツリウム - - - イッテルビウム - - - ルテチウム - - - ハフニウム - - - タンタル - - - タングステン - - - レニウム - - - オスミウム - - - イリジウム - - - 白金 - - - - - - 水銀 - - - タリウム - - - - - - ビスマス - - - ポロニウム - - - アスタチン - - - ラドン - - - フランシウム - - - ラジウム - - - アクチニウム - - - トリウム - - - プロトアクチニウム - - - ウラン - - - ネプツニウム - - - プルトニウム - - - アメリシウム - - - キュリウム - - - バークリウム - - - カリホルニウム - - - アインスタイニウム - - - フェルミウム - - - メンデレビウム - - - ノーベリウム - - - ローレンシウム - - - ラザホージウム - - - ドブニウム - - - シーボーギウム - - - ボーリウム - - - ハッシウム - - - マイトネリウム - - - ダームスタチウム - - - レントゲニウム - - - コペルニシウム - - - ニホニウム - - - フレロビウム - - - モスコビウム - - - リバモリウム - - - テネシン - - - オガネソン - - - 番号{0} - - - 同位体 - - - 同位体 - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.ko.resx b/Chemistry/Chemistry/ChemistryResource.ko.resx deleted file mode 100644 index 64b2960e..00000000 --- a/Chemistry/Chemistry/ChemistryResource.ko.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 원소 - - - 화학 - - - 원소 - - - 수소 - - - 헬륨 - - - 리튬 - - - 베릴륨 - - - 붕소 - - - 탄소 - - - 질소 - - - 산소 - - - 플루오린 - - - 네온 - - - 나트륨 - - - 마그네슘 - - - 알루미늄 - - - 규소 - - - - - - - - - 염소 - - - 아르곤 - - - 칼륨 - - - 칼슘 - - - 스칸듐 - - - 티타늄 - - - 바나듐 - - - 크롬 - - - 망가니즈 - - - - - - 코발트 - - - 니켈 - - - 구리 - - - 아연 - - - 갈륨 - - - 게르마늄 - - - 비소 - - - 셀레늄 - - - 브로민 - - - 크립톤 - - - 루비듐 - - - 스트론튬 - - - 이트륨 - - - 지르코늄 - - - 나이오븀 - - - 몰리브데넘 - - - 테크네튬 - - - 루테늄 - - - 로듐 - - - 팔라듐 - - - - - - 카드뮴 - - - 인듐 - - - 주석 - - - 안티모니 - - - 텔루륨 - - - 아이오딘 - - - 제논 - - - 세슘 - - - 바륨 - - - 란타넘 - - - 세륨 - - - 프라세오디뮴 - - - 네오디뮴 - - - 프로메튬 - - - 사마륨 - - - 유로퓸 - - - 가돌리늄 - - - 터븀 - - - 디스프로슘 - - - 홀뮴 - - - 어븀 - - - 툴륨 - - - 이터븀 - - - 루테튬 - - - 하프늄 - - - 탄탈럼 - - - 텅스텐 - - - 레늄 - - - 오스뮴 - - - 이리듐 - - - 백금 - - - - - - 수은 - - - 탈륨 - - - - - - 비스무트 - - - 폴로늄 - - - 아스타틴 - - - 라돈 - - - 프랑슘 - - - 라듐 - - - 악티늄 - - - 토륨 - - - 프로트악티늄 - - - 우라늄 - - - 넵투늄 - - - 플루토늄 - - - 아메리슘 - - - 퀴륨 - - - 버클륨 - - - 캘리포늄 - - - 아인슈타이늄 - - - 페르뮴 - - - 멘델레븀 - - - 노벨륨 - - - 로렌슘 - - - 러더포듐 - - - 더브늄 - - - 시보귬 - - - 보륨 - - - 하슘 - - - 마이트너륨 - - - 다름슈타튬 - - - 뢴트게늄 - - - 코페르니슘 - - - 니호늄 - - - 플레로븀 - - - 모스코븀 - - - 리버모륨 - - - 테네신 - - - 오가네손 - - - 원소{0} - - - 동위 원소 - - - 동위 원소 - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.pt.resx b/Chemistry/Chemistry/ChemistryResource.pt.resx deleted file mode 100644 index 64472515..00000000 --- a/Chemistry/Chemistry/ChemistryResource.pt.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Elemento químico - - - Química - - - Elemento - - - Hidrogênio - - - Hélio - - - Lítio - - - Berílio - - - Boro - - - Carbono - - - Nitrogênio - - - Oxigênio - - - Flúor - - - Neônio - - - Sódio - - - Magnésio - - - Alumínio - - - Silício - - - Fósforo - - - Enxofre - - - Cloro - - - Argônio - - - Potássio - - - Cálcio - - - Escândio - - - Titânio - - - Vanádio - - - Cromo - - - Manganês - - - Ferro - - - Cobalto - - - Níquel - - - Cobre - - - Zinco - - - Gálio - - - Germânio - - - Arsénio - - - Selénio - - - Bromo - - - Criptônio - - - Rubídio - - - Estrôncio - - - Ítrio - - - Zircônio - - - Nióbio - - - Molibdénio - - - Tecnécio - - - Rutênio - - - Ródio - - - Paládio - - - Prata - - - Cádmio - - - Índio - - - Estanho - - - Antimônio - - - Telúrio - - - Iodo - - - Xenônio - - - Césio - - - Bário - - - Lantânio - - - Cério - - - Praseodímio - - - Neodímio - - - Promécio - - - Samário - - - Európio - - - Gadolínio - - - Térbio - - - Disprósio - - - Hólmio - - - Érbio - - - Túlio - - - Itérbio - - - Lutécio - - - Háfnio - - - Tântalo - - - Tungstênio - - - Rênio - - - Ósmio - - - Irídio - - - Platina - - - Ouro - - - Mercúrio - - - Tálio - - - Chumbo - - - Bismuto - - - Polônio - - - Ástato - - - Rádon - - - Frâncio - - - Rádio - - - Actínio - - - Tório - - - Protactínio - - - Urânio - - - Ne(p)túnio - - - Plutônio - - - Amerício - - - Cúrio - - - Berquélio - - - Califórnio - - - Einsténio - - - Férmio - - - Mendelévio - - - Nobélio - - - Laurêncio - - - Rutherfórdio - - - Dúbnio - - - Seabórgio - - - Bóhrio - - - Hássio - - - Meitnério - - - Darmstácio - - - Roentgénio - - - Copernício - - - Nipônio - - - Fleróvio - - - Moscóvio - - - Livermório - - - Tenesso - - - Oganésson - - - Elemento {0} - - - Isótopo - - - Isótopos - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.resx b/Chemistry/Chemistry/ChemistryResource.resx deleted file mode 100644 index 0f90d5ab..00000000 --- a/Chemistry/Chemistry/ChemistryResource.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Chemical element - - - Chemistry - - - Element - - - Hydrogen - - - Helium - - - Lithium - - - Beryllium - - - Boron - - - Carbon - - - Nitrogen - - - Oxygen - - - Fluorine - - - Neon - - - Sodium - - - Magnesium - - - Aluminium - - - Silicon - - - Phosphorus - - - Sulfur - - - Chlorine - - - Argon - - - Potassium - - - Calcium - - - Scandium - - - Titanium - - - Vanadium - - - Chromium - - - Manganese - - - Iron - - - Cobalt - - - Nickel - - - Copper - - - Zinc - - - Gallium - - - Germanium - - - Arsenic - - - Selenium - - - Bromine - - - Krypton - - - Rubidium - - - Strontium - - - Yttrium - - - Zirconium - - - Niobium - - - Molybdenum - - - Technetium - - - Ruthenium - - - Rhodium - - - Palladium - - - Silver - - - Cadmium - - - Indium - - - Tin - - - Antimony - - - Tellurium - - - Iodine - - - Xenon - - - Caesium - - - Barium - - - Lanthanum - - - Cerium - - - Praseodymium - - - Neodymium - - - Promethium - - - Samarium - - - Europium - - - Gadolinium - - - Terbium - - - Dysprosium - - - Holmium - - - Erbium - - - Thulium - - - Ytterbium - - - Lutetium - - - Hafnium - - - Tantalum - - - Tungsten - - - Rhenium - - - Osmium - - - Iridium - - - Platinum - - - Gold - - - Mercury - - - Thallium - - - Lead - - - Bismuth - - - Polonium - - - Astatine - - - Radon - - - Francium - - - Radium - - - Actinium - - - Thorium - - - Protactinium - - - Uranium - - - Neptunium - - - Plutonium - - - Americium - - - Curium - - - Berkelium - - - Californium - - - Einsteinium - - - Fermium - - - Mendelevium - - - Nobelium - - - Lawrencium - - - Rutherfordium - - - Dubnium - - - Seaborgium - - - Bohrium - - - Hassium - - - Meitnerium - - - Darmstadtium - - - Roentgenium - - - Copernicium - - - Nihonium - - - Flerovium - - - Moscovium - - - Livermorium - - - Tennessine - - - Oganesson - - - - - - Isotope - - - Isotopes - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.ru.resx b/Chemistry/Chemistry/ChemistryResource.ru.resx deleted file mode 100644 index 29c95124..00000000 --- a/Chemistry/Chemistry/ChemistryResource.ru.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Химический элемент - - - Химия - - - Элемент - - - Водород - - - Гелий - - - Литий - - - Бериллий - - - Бор - - - Углерод - - - Азот - - - Кислород - - - Фтор - - - Неон - - - Натрий - - - Магний - - - Алюминий - - - Кремний - - - Фосфор - - - Сера - - - Хлор - - - Аргон - - - Калий - - - Кальций - - - Скандий - - - Титан - - - Ванадий - - - Хром - - - Марганец - - - Железо - - - Кобальт - - - Никель - - - Медь - - - Цинк - - - Галлий - - - Германий - - - Мышьяк - - - Селен - - - Бром - - - Криптон - - - Рубидий - - - Стронций - - - Иттрий - - - Цирконий - - - Ниобий - - - Молибден - - - Технеций - - - Рутений - - - Родий - - - Палладий - - - Серебро - - - Кадмий - - - Индий - - - Олово - - - Сурьма - - - Теллур - - - Иод - - - Ксенон - - - Цезий - - - Барий - - - Лантан - - - Церий - - - Празеодим - - - Неодим - - - Прометий - - - Самарий - - - Европий - - - Гадолиний - - - Тербий - - - Диспрозий - - - Гольмий - - - Эрбий - - - Тулий - - - Иттербий - - - Лютеций - - - Гафний - - - Тантал - - - Вольфрам - - - Рений - - - Осмий - - - Иридий - - - Платина - - - Золото - - - Ртуть - - - Таллий - - - Свинец - - - Висмут - - - Полоний - - - Астат - - - Радон - - - Франций - - - Радий - - - Актиний - - - Торий - - - Протактиний - - - Уран - - - Нептуний - - - Плутоний - - - Америций - - - Кюрий - - - Берклий - - - Калифорний - - - Эйнштейний - - - Фермий - - - Менделевий - - - Нобелий - - - Лоуренсий - - - Резерфордий - - - Дубний - - - Сиборгий - - - Борий - - - Хассий - - - Мейтнерий - - - Дармштадтий - - - Рентгений - - - Коперниций - - - Нихоний - - - Флеровий - - - Московий - - - Ливерморий - - - Теннессин - - - Оганесон - - - Элемент {0} - - - Изотоп - - - Изотопы - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.tr.resx b/Chemistry/Chemistry/ChemistryResource.tr.resx deleted file mode 100644 index d4eca6dc..00000000 --- a/Chemistry/Chemistry/ChemistryResource.tr.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Kimyasal element - - - Kimya - - - Element - - - Hidrojen - - - Helyum - - - Lityum - - - Berilyum - - - Bor - - - Karbon - - - Azot - - - Oksijen - - - Flor - - - Neon - - - Sodyum - - - Magnezyum - - - Alüminyum - - - Silisyum - - - Fosfor - - - Kükürt - - - Klor - - - Argon - - - Potasyum - - - Kalsiyum - - - Skandiyum - - - Titanyum - - - Vanadyum - - - Krom - - - Mangan - - - Demir - - - Kobalt - - - Nikel - - - Bakır - - - Çinko - - - Galyum - - - Germanyum - - - Arsenik - - - Selenyum - - - Brom - - - Kripton - - - Rubidyum - - - Stronsiyum - - - İtriyum - - - Zirkonyum - - - Niobyum - - - Molibden - - - Teknesyum - - - Rutenyum - - - Rodyum - - - Paladyum - - - Gümüş - - - Kadmiyum - - - İndiyum - - - Kalay - - - Antimon - - - Tellür - - - İyot - - - Ksenon - - - Sezyum - - - Baryum - - - Lantan - - - Seryum - - - Praseodim - - - Neodimyum - - - Prometyum - - - Samaryum - - - Evropiyum - - - Gadolinyum - - - Terbiyum - - - Disprozyum - - - Holmiyum - - - Erbiyum - - - Tulyum - - - İterbiyum - - - Lutetyum - - - Hafniyum - - - Tantal - - - Volfram - - - Renyum - - - Osmiyum - - - İridyum - - - Platin - - - Altın - - - Cıva - - - Talyum - - - Kurşun - - - Bizmut - - - Polonyum - - - Astatin - - - Radon - - - Fransiyum - - - Radyum - - - Aktinyum - - - Toryum - - - Protaktinyum - - - Uranyum - - - Neptünyum - - - Plütonyum - - - Amerikyum - - - Küriyum - - - Berkelyum - - - Kaliforniyum - - - Aynştaynyum - - - Fermiyum - - - Mendelevyum - - - Nobelyum - - - Lavrensiyum - - - Rutherfordiyum - - - Dubniyum - - - Seaborgiyum - - - Bohriyum - - - Hassiyum - - - Meitneriyum - - - Darmstadtiyum - - - Röntgenyum - - - Kopernikyum - - - Ununtriyum - - - Flerovyum - - - Ununpentiyum - - - Livermoryum - - - Ununseptiyum - - - Ununoktiyum - - - Element {0} - - - İzotop - - - İzotoplar - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.zh-Hans.resx b/Chemistry/Chemistry/ChemistryResource.zh-Hans.resx deleted file mode 100644 index 4d064f9f..00000000 --- a/Chemistry/Chemistry/ChemistryResource.zh-Hans.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 化学元素 - - - 化学 - - - 元素 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 𬬻 - - - 𬭊 - - - 𬭳 - - - 𬭛 - - - 𬭶 - - - - - - 𫟼 - - - 𬬭 - - - - - - - - - 𫓧 - - - - - - 𫟷 - - - - - - - - - {0}号元素 - - - 同位素 - - - 同位素 - - \ No newline at end of file diff --git a/Chemistry/Chemistry/ChemistryResource.zh-Hant.resx b/Chemistry/Chemistry/ChemistryResource.zh-Hant.resx deleted file mode 100644 index 8a7cc578..00000000 --- a/Chemistry/Chemistry/ChemistryResource.zh-Hant.resx +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 化學元素 - - - 化學 - - - 元素 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 𨧀 - - - 𨭎 - - - 𨨏 - - - 𨭆 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {0}號元素 - - - 同位素 - - - 同位素 - - \ No newline at end of file diff --git a/Chemistry/Chemistry/Isotope.cs b/Chemistry/Chemistry/Isotope.cs deleted file mode 100644 index e636861c..00000000 --- a/Chemistry/Chemistry/Isotope.cs +++ /dev/null @@ -1,261 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.Chemistry; - -/// -/// The model of isotope. -/// -public class Isotope : IEquatable -{ - /// - /// Initializes a new instance of the Isotope class. - /// - /// The chemical element. - /// The atomic mass number (total protons and neutrons). - public Isotope(ChemicalElement element, int atomicMassNumber) - { - Element = element; - if (element is null || element.AtomicNumber < 1) - { - AtomicMassNumber = atomicMassNumber < 0 ? -1 : atomicMassNumber; - return; - } - - AtomicMassNumber = atomicMassNumber < element.AtomicNumber - ? element.AtomicNumber - : atomicMassNumber; - } - - /// - /// Initializes a new instance of the Isotope class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The atomic mass number (total protons and neutrons). - public Isotope(int atomicNumber, int atomicMassNumber) - : this(ChemicalElement.Get(atomicNumber), atomicMassNumber) - { - } - - /// - /// Initializes a new instance of the Isotope class. - /// - /// The chemical element. - /// The atomic mass number (total protons and neutrons). - /// The atomic weight in dalton (unified atomic mass unit). - public Isotope(ChemicalElement element, int atomicMassNumber, double atomicWeight) - : this(element, atomicMassNumber) - { - AtomicWeight = atomicWeight; - } - - /// - /// Initializes a new instance of the Isotope class. - /// - /// The atomic number (or proton number, symbol Z) of the chemical element. The number is one-based. - /// The atomic mass number (total protons and neutrons). - /// The atomic weight in dalton (unified atomic mass unit). - public Isotope(int atomicNumber, int atomicMassNumber, double atomicWeight) - : this(ChemicalElement.Get(atomicNumber), atomicMassNumber) - { - AtomicWeight = atomicWeight; - } - - /// - /// Gets the chemical element. - /// - public ChemicalElement Element { get; } - - /// - /// Gets the element symbol. - /// - public string ElementSymbol => Element?.Symbol; - - /// - /// Gets the atomic number (or proton number, symbol Z) of the chemical element. - /// It is the one-based number of protons found in the nucleus of every atom of that element. - /// - public int AtomicNumber => Element?.AtomicNumber ?? -1; - - /// - /// Gets the atomic mass number (total protons and neutrons). - /// - public int AtomicMassNumber { get; } - - /// - /// Gets the atomic weight in dalton (unified atomic mass unit). - /// - public double AtomicWeight { get; } - - /// - /// Gets a value indicating whether has atomic weight information. - /// - public bool HasAtomicWeight => !double.IsNaN(AtomicWeight); - - /// - /// Gets the numbers of neutron. - /// - public int Neutrons - { - get - { - if (AtomicMassNumber < 1) - return AtomicMassNumber == 0 ? 0 : -1; - if (AtomicNumber > 0) - return AtomicMassNumber - AtomicNumber; - return AtomicMassNumber; - } - } - - /// - /// Writes this instance to the specified writer as a JSON value. - /// - /// The writer to which to write this instance. - public void WriteTo(Utf8JsonWriter writer) - { - var json = (JsonObjectNode)this; - json.WriteTo(writer); - } - - /// - /// Peturns a string that represents the current isotope information. - /// - /// A string that represents the current isotope information. - public override string ToString() - { - if (Element is null) return "?"; - if (AtomicMassNumber < 1) return Element.Symbol; - if (Element.AtomicNumber == 1 && Element.Symbol == "H") - { - switch (AtomicMassNumber) - { - case 1: - return "H"; - case 2: - return "D"; - case 3: - return "T"; - } - } - - return AtomicMassNumber - .ToString("g") - .Replace('0', '⁰') - .Replace('1', '¹') - .Replace('2', '²') - .Replace('3', '³') - .Replace('4', '⁴') - .Replace('5', '⁵') - .Replace('6', '⁶') - .Replace('7', '⁷') - .Replace('8', '⁸') - .Replace('9', '⁹') - + Element.Symbol; - } - - /// - public override int GetHashCode() - { - return base.GetHashCode(); - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public bool Equals(Isotope other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return Element == other.Element - && AtomicMassNumber == other.AtomicMassNumber; - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is Isotope isotope) return Equals(isotope); - if (other is ChemicalElement element) return element.Equals(Element); - return false; - } - - /// - /// Compares two isotopes to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(Isotope leftValue, Isotope rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two isotopes to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(Isotope leftValue, Isotope rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to a JSON object. - /// - /// The isotope to convert. - public static explicit operator JsonObjectNode(Isotope isotope) - { - if (isotope is null || isotope.AtomicNumber < 1 || isotope.AtomicWeight < 1) return null; - var json = new JsonObjectNode - { - { "symbol", isotope.ToString() }, - { "number", isotope.AtomicNumber }, - { "element", isotope.ElementSymbol }, - { "neutrons", isotope.Neutrons }, - { "mass", isotope.AtomicMassNumber } - }; - if (!double.IsNaN(isotope.AtomicWeight)) - json.SetValue("weight", isotope.AtomicWeight); - return json; - } - - /// - /// Converts to a JSON object. - /// - /// The isotope to convert. - public static explicit operator JsonDocument(Isotope isotope) - { - if (isotope is null || isotope.AtomicNumber < 1 || isotope.AtomicWeight < 1) return null; - return (JsonDocument)(JsonObjectNode)isotope; - } - - /// - /// Converts to a JSON object. - /// - /// The isotope to convert. - public static explicit operator System.Text.Json.Nodes.JsonObject(Isotope isotope) - { - if (isotope is null || isotope.AtomicNumber < 1 || isotope.AtomicWeight < 1) return null; - return (System.Text.Json.Nodes.JsonObject)(JsonObjectNode)isotope; - } -} diff --git a/Chemistry/Chemistry/MolecularFormula.cs b/Chemistry/Chemistry/MolecularFormula.cs deleted file mode 100644 index 8808fe5e..00000000 --- a/Chemistry/Chemistry/MolecularFormula.cs +++ /dev/null @@ -1,866 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Chemistry; - -/// -/// The model of the molecular formula. -/// -public class MolecularFormula : IEquatable -{ - /// - /// The item. - /// - public class Item : IEquatable - { - /// - /// Initializes a new instance of the MolecularFormula.Item class. - /// - /// The chemical element. - /// The atom count. - public Item(ChemicalElement element, int count = 1) - { - Element = element; - Count = count; - } - - /// - /// Initializes a new instance of the MolecularFormula.Item class. - /// - /// The symbol of the chemical element. - /// The atom count. - public Item(string symbol, int count = 1) - : this(ChemicalElement.Get(symbol), count) - { - } - - /// - /// Gets the chemical element. - /// - public ChemicalElement Element { get; } - - /// - /// Gets the atom count. - /// - public int Count { get; } - - /// - /// Peturns a string that represents the current chemical element information. - /// - /// A string that represents the current chemical element information. - public override string ToString() - { - var symbol = Element?.Symbol?.Trim(); - if (string.IsNullOrWhiteSpace(symbol) || Count < 1) return null; - if (Count == 1) return symbol; - return symbol + Count - .ToString("g") - .Replace('0', '₀') - .Replace('1', '₁') - .Replace('2', '₂') - .Replace('3', '₃') - .Replace('4', '₄') - .Replace('5', '₅') - .Replace('6', '₆') - .Replace('7', '₇') - .Replace('8', '₈') - .Replace('9', '₉'); - } - - /// - public override int GetHashCode() - =>new Tuple(Element, Count).GetHashCode(); - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public bool Equals(Item other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return Element == other.Element - && Count == other.Count; - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is Item isotope) return Equals(isotope); - if (other is ChemicalElement element) return Count == 1 && element.Equals(Element); - return false; - } - - /// - /// Compares two molecular formula items to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(Item leftValue, Item rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two molecular formula items to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(Item leftValue, Item rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - } - - /// - /// The source cache. - /// - private readonly List list; - - /// - /// The string format cache. - /// - private string s; - - /// - /// Initializes a new instance of the MolecularFormula class. - /// - /// The items. - public MolecularFormula(IEnumerable col) - { - list = new List(col); - } - - /// - /// Initializes a new instance of the MolecularFormula class. - /// - /// The items. - /// The ionic charge numbe. - public MolecularFormula(IEnumerable col, int chargeNumber) - { - list = new List(col.Where(ele => ele?.Element != null && ele.Count > 0)); - ChargeNumber = chargeNumber; - } - - /// - /// Initializes a new instance of the MolecularFormula class. - /// - /// The chemical element. - /// The count of the specific chemical element. - public MolecularFormula(ChemicalElement element, int count = 1) - { - list = string.IsNullOrEmpty(element?.Symbol) || count < 1 - ? new List() - : new List { new Item(element, count) }; - } - - /// - /// Initializes a new instance of the MolecularFormula class. - /// - /// The chemical element A. - /// The count of the specific chemical element A. - /// The chemical element B. - /// The count of the specific chemical element B. - /// The chemical element C. - /// The count of the specific chemical element C. - /// The chemical element D. - /// The count of the specific chemical element D. - /// The chemical element F. - /// The count of the specific chemical element E. - /// The chemical element E. - /// The count of the specific chemical element F. - /// The chemical element G. - /// The count of the specific chemical element G. - public MolecularFormula(ChemicalElement elementA, int countA, ChemicalElement elementB, int countB, ChemicalElement elementC = null, int countC = 1, ChemicalElement elementD = null, int countD = 1, ChemicalElement elementE = null, int countE = 1, ChemicalElement elementF = null, int countF = 1, ChemicalElement elementG = null, int countG = 1) - { - list = new List(); - if (!string.IsNullOrEmpty(elementA?.Symbol) && countA > 0) - list.Add(new Item(elementA, countA)); - if (!string.IsNullOrEmpty(elementB?.Symbol) && countB > 0) - list.Add(new Item(elementB, countB)); - if (!string.IsNullOrEmpty(elementC?.Symbol) && countC > 0) - list.Add(new Item(elementC, countC)); - if (!string.IsNullOrEmpty(elementD?.Symbol) && countD > 0) - list.Add(new Item(elementD, countD)); - if (!string.IsNullOrEmpty(elementE?.Symbol) && countE > 0) - list.Add(new Item(elementE, countE)); - if (!string.IsNullOrEmpty(elementF?.Symbol) && countF > 0) - list.Add(new Item(elementF, countF)); - if (!string.IsNullOrEmpty(elementG?.Symbol) && countG > 0) - list.Add(new Item(elementG, countG)); - } - - /// - /// Gets the ionic charge number. - /// - public int ChargeNumber { get; } - - /// - /// Gets a value indicating whether this is an ion. - /// - public bool IsIon => ChargeNumber != 0; - - /// - /// Gets the items. - /// - public IReadOnlyList Items => list.AsReadOnly(); - - /// - /// Gets all elements. - /// - public IEnumerable Elements - => list.Select(ele => ele.Element).Where(ele => !string.IsNullOrEmpty(ele?.Symbol)).Distinct(); - - /// - /// Gets the atom count. - /// - public int Count => list.Sum(ele => ele.Count); - - /// - /// Gets the proton numbers. - /// - public int ProtonNumber => list.Sum(ele => ele.Count * (ele.Element?.AtomicNumber ?? 0)); - - /// - /// Gets a collection of all elements and their numbers. - /// - /// A collection of all elements and their numbers. - public IEnumerable Zip() - { - var list = new List(); - foreach (var item in this.list) - { - Zip(list, item); - } - - return list; - } - - /// - /// Reports the zero-based index of the first occurrence of the specified string in this instance. - /// - /// The string to seek. - /// The zero-based index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is 0. - /// symbol should not be null. - /// symbol should not be empty. - public int IndexOf(string symbol) - { - if (symbol == null) throw new ArgumentNullException(nameof(symbol), "symbol was null"); - symbol = symbol.Trim(); - if (symbol.Length < 1) throw new ArgumentException("symbol was empty", nameof(symbol)); - return list.FindIndex(ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Reports the zero-based index of the first occurrence of the specified string in this instance. - /// - /// The string to seek. - /// The search starting position. - /// The optional number of character positions to examine. - /// The zero-based index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is 0. - /// symbol should not be null. - public int IndexOf(string symbol, int startIndex, int? count = null) - { - if (symbol == null) throw new ArgumentNullException(nameof(symbol), "symbol was null"); - symbol = symbol.Trim(); - if (symbol.Length < 1) throw new ArgumentException("symbol was empty", nameof(symbol)); - return count.HasValue - ? list.FindIndex(startIndex, count.Value, ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)) - : list.FindIndex(startIndex, ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Reports the zero-based index position of the last occurrence of a specified string within this instance. - /// - /// The string to seek. - /// The zero-based starting index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is the last index position in this instance. - /// symbol should not be null. - public int LastIndexOf(string symbol) - { - if (symbol == null) throw new ArgumentNullException(nameof(symbol), "symbol was null"); - symbol = symbol.Trim(); - if (symbol.Length < 1) throw new ArgumentException("symbol was empty", nameof(symbol)); - return list.FindLastIndex(ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Reports the zero-based index position of the last occurrence of a specified string within this instance. - /// - /// The string to seek. - /// The search starting position. The search proceeds from startIndex toward the beginning of this instance. - /// The optional number of character positions to examine. - /// The zero-based starting index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is the last index position in this instance. - /// symbol should not be null. - public int LastIndexOf(string symbol, int startIndex, int? count = null) - { - if (symbol == null) throw new ArgumentNullException(nameof(symbol), "symbol was null"); - symbol = symbol.Trim(); - if (symbol.Length < 1) throw new ArgumentException("symbol was empty", nameof(symbol)); - return count.HasValue - ? list.FindLastIndex(startIndex, count.Value, ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)) - : list.FindLastIndex(startIndex, ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Reports the zero-based index of the first occurrence of the specified string in this instance. - /// - /// The chemical element to seek. - /// The zero-based index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is 0. - /// element should not be null. - public int IndexOf(ChemicalElement element) - => element != null ? list.FindIndex(ele => ele.Element == element) : throw new ArgumentNullException(nameof(element), "element was null."); - - /// - /// Reports the zero-based index position of the last occurrence of a specified string within this instance. - /// - /// The chemical element to seek. - /// The zero-based starting index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is the last index position in this instance. - /// element should not be null. - public int LastIndexOf(ChemicalElement element) - => element != null ? list.FindLastIndex(ele => ele.Element == element) : throw new ArgumentNullException(nameof(element), "element was null."); - - /// - /// Reports the zero-based index of the first occurrence of the specified string in this instance. - /// - /// The chemical element to seek. - /// The search starting position. - /// The optional number of character positions to examine. - /// The zero-based index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is 0. - /// element should not be null. - public int IndexOf(ChemicalElement element, int startIndex, int? count = null) - => element != null ? (count.HasValue - ? list.FindIndex(startIndex, count.Value, ele => ele.Element == element) - : list.FindIndex(startIndex, ele => ele.Element == element)) : throw new ArgumentNullException(nameof(element), "element was null."); - - /// - /// Reports the zero-based index position of the last occurrence of a specified string within this instance. - /// - /// The chemical element to seek. - /// The search starting position. The search proceeds from startIndex toward the beginning of this instance. - /// The optional number of character positions to examine. - /// The zero-based starting index position of value if that string is found, or -1 if it is not. If value is System.String.Empty, the return value is the last index position in this instance. - /// element should not be null. - public int LastIndexOf(ChemicalElement element, int startIndex, int? count = null) - => element != null ? (count.HasValue - ? list.FindLastIndex(startIndex, count.Value, ele => ele.Element == element) - : list.FindLastIndex(startIndex, ele => ele.Element == element)) : throw new ArgumentNullException(nameof(element), "element was null."); - - /// - /// Gets the count of the specific chemical element. - /// - /// The chemcial element to get count. - /// The total. - public int GetCount(ChemicalElement element) - { - if (element is null) return 0; - return list.Where(ele => ele.Element == element)?.Sum(ele => ele.Count) ?? 0; - } - - /// - /// Gets the count of the specific chemical element. - /// - /// The chemcial symbol to get count. - /// The total. - public int GetCount(string symbol) - { - symbol = symbol?.Trim(); - if (string.IsNullOrEmpty(symbol)) return 0; - return list.Where(ele => symbol.Equals(ele.Element?.Symbol, StringComparison.OrdinalIgnoreCase))?.Sum(ele => ele.Count) ?? 0; - } - - /// - /// Peturns a string that represents the current chemical element information. - /// - /// A string that represents the current chemical element information. - public override string ToString() - { - if (s != null) return s; - var sb = new StringBuilder(); - foreach (var item in list) - { - sb.Append(item.ToString()); - } - - if (sb.Length == 0) sb.Append('e'); - if (ChargeNumber != 0) - { - if (ChargeNumber > 1 || ChargeNumber < -1) sb.Append(Math.Abs(ChargeNumber) - .ToString("g") - .Replace('0', '⁰') - .Replace('1', '¹') - .Replace('2', '²') - .Replace('3', '³') - .Replace('4', '⁴') - .Replace('5', '⁵') - .Replace('6', '⁶') - .Replace('7', '⁷') - .Replace('8', '⁸') - .Replace('9', '⁹')); - sb.Append(ChargeNumber > 0 ? '﹢' : 'ˉ'); - } - - return s = sb.ToString(); - } - - /// - public override int GetHashCode() - => new Tuple, int>(list, ChargeNumber).GetHashCode(); - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public bool Equals(MolecularFormula other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - if (ChargeNumber != other.ChargeNumber) return false; - return Collection.ListExtensions.Equals(list, other.list); - } - - /// - /// Indicates whether this instance and a specified object are equal. - /// - /// The object to compare with the current instance. - /// true if obj and this instance represent the same value; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is MolecularFormula isotope) return Equals(isotope); - if (other is IEnumerable col) return ChargeNumber == 0 && Collection.ListExtensions.Equals(list, col.ToList()); - return false; - } - - /// - /// Compares two molecular formula instances to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(MolecularFormula leftValue, MolecularFormula rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two molecular formula instances to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(MolecularFormula leftValue, MolecularFormula rightValue) - { - if (ReferenceEquals(leftValue, rightValue)) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Pluses a molecular formula and a chemical element. - /// - /// The left value for addition operator. - /// The right value for addition operator. - /// A result after addition. - public static MolecularFormula operator +(MolecularFormula leftValue, ChemicalElement rightValue) - { - var isRightEmpty = string.IsNullOrEmpty(rightValue?.Symbol); - if (leftValue is null && isRightEmpty) return null; - if (leftValue is null) return new MolecularFormula(rightValue); - if (isRightEmpty) return leftValue; - var col = leftValue.list.ToList(); - col.Add(new Item(rightValue, 1)); - return new MolecularFormula(col, leftValue.ChargeNumber); - } - - /// - /// Pluses a molecular formula and a chemical element. - /// - /// The left value for addition operator. - /// The right value for addition operator. - /// A result after addition. - public static MolecularFormula operator +(ChemicalElement leftValue, MolecularFormula rightValue) - { - var isLeftEmpty = string.IsNullOrEmpty(leftValue?.Symbol); - if (rightValue is null && isLeftEmpty) return null; - if (rightValue is null) return new MolecularFormula(leftValue); - if (isLeftEmpty) return rightValue; - var col = rightValue.list.ToList(); - col.Add(new Item(leftValue, 1)); - return new MolecularFormula(col, rightValue.ChargeNumber); - } - - /// - /// Pluses two molecular formula instances. - /// - /// The left value for addition operator. - /// The right value for addition operator. - /// A result after addition. - public static MolecularFormula operator +(MolecularFormula leftValue, MolecularFormula rightValue) - { - if (leftValue is null || leftValue.Count == 0) return rightValue; - if (rightValue is null || rightValue.Count == 0) return leftValue; - var col = leftValue.list.ToList(); - col.AddRange(rightValue.list); - return new MolecularFormula(col, leftValue.ChargeNumber + rightValue.ChargeNumber); - } - - /// - /// Converts to a molecular formula instance. - /// - /// The chemical element to convert. - public static implicit operator MolecularFormula(ChemicalElement element) - { - return new MolecularFormula(element); - } - - /// - /// Parses. - /// - /// The input. - /// A molecular formula instance parsed. - public static MolecularFormula Parse(string s) - { - s = s?.Trim(); - if (string.IsNullOrWhiteSpace(s)) return null; - return TryParse(s) ?? throw new FormatException("s is invalid."); - } - - /// - /// Tries to parse a molecular formula string. - /// - /// The input. - /// The result output. - /// true if parse succeeded; otherwise, false. - public static bool TryParse(string s, out MolecularFormula result) - { - result = TryParse(s); - return result != null; - } - - /// - /// Tries to parse a molecular formula string. - /// - /// The input. - /// A molecular formula instance parsed. - public static MolecularFormula TryParse(string s) - { - s = s?.Trim(); - if (string.IsNullOrWhiteSpace(s)) return null; - var col = new List(); - var sb = new StringBuilder(); - var count = 0; - var hasCount = false; - var sup = 0; - foreach (var c in s) - { - if (c >= 'A' && c <= 'Z') - { - sup = 0; - if (sb.Length > 0) - { - if (!Add(sb, col, hasCount ? count : 1)) - return null; - } - - count = 0; - hasCount = false; - sb.Clear(); - sb.Append(c); - continue; - } - - if (c >= 'a' && c <= 'z') - { - sup = 0; - count = 0; - hasCount = false; - sb.Append(c); - continue; - } - - var push = false; - switch (c) - { - case '0': - case '₀': - sup = 0; - count *= 10; - break; - case '1': - case '₁': - sup = 0; - count = count * 10 + 1; - hasCount = true; - break; - case '2': - case '₂': - sup = 0; - count = count * 10 + 2; - hasCount = true; - break; - case '3': - case '₃': - sup = 0; - count = count * 10 + 3; - hasCount = true; - break; - case '4': - case '₄': - sup = 0; - count = count * 10 + 4; - hasCount = true; - break; - case '5': - case '₅': - sup = 0; - count = count * 10 + 5; - hasCount = true; - break; - case '6': - case '₆': - sup = 0; - count = count * 10 + 6; - hasCount = true; - break; - case '7': - case '₇': - sup = 0; - count = count * 10 + 7; - hasCount = true; - break; - case '8': - case '₈': - count = count * 10 + 8; - hasCount = true; - break; - case '9': - case '₉': - sup = 0; - count = count * 10 + 9; - hasCount = true; - break; - case ' ': - case '_': - case '·': - case '.': - case ',': - case '~': - sup = 0; - push = true; - break; - case '-': - case '+': - case 'ˉ': - case '﹢': - push = true; - break; - case '⁰': - sup *= 10; - push = true; - break; - case '¹': - sup = sup * 10 + 1; - push = true; - break; - case '²': - sup = sup * 10 + 2; - push = true; - break; - case '³': - sup = sup * 10 + 3; - push = true; - break; - case '⁴': - sup = sup * 10 + 4; - push = true; - break; - case '⁵': - sup = sup * 10 + 5; - push = true; - break; - case '⁶': - sup = sup * 10 + 6; - push = true; - break; - case '⁷': - sup = sup * 10 + 7; - push = true; - break; - case '⁸': - sup = sup * 10 + 8; - push = true; - break; - case '⁹': - sup = sup * 10 + 9; - push = true; - break; - default: - return null; - } - - if (push) - { - if (sb.Length > 0) - { - if (!Add(sb, col, hasCount ? count : 1)) - return null; - sb.Clear(); - } - - count = 0; - hasCount = false; - } - } - - if (sb.Length > 0) - { - if (!Add(sb, col, hasCount ? count : 1)) - return null; - sb.Clear(); - } - - var ion = 0; - if (s.EndsWith("+") || s.EndsWith("﹢")) - { - ion = sup; - } - else if (s.EndsWith("-") || s.EndsWith("ˉ")) - { - ion = -sup; - } - - var result = new MolecularFormula(col, ion); - return result.list.Count > 0 ? result : null; - } - - /// - /// Gets a collection of all elements and their numbers. - /// - /// The collection. - /// A collection of all elements and their numbers. - public static IEnumerable Zip(IEnumerable col) - { - var list = new List(); - if (col is null) return list; - foreach (var item in col.SelectMany(ele => ele.list)) - { - Zip(list, item); - } - - return list; - } - - /// - /// Tests the elements in the two molecular formula instances are passed by the law of conservation of mass. - /// - /// The left collection. - /// The right collection. - /// true if conservation of mass; otherwise, false. - public static bool ConservationOfMass(IEnumerable a, IEnumerable b) - { - try - { - var dictA = Zip(a).ToList(); - var dictB = Zip(b).ToList(); - if (dictA.Count != dictB.Count) return false; - var chargeA = a.Sum(ele => ele.ChargeNumber); - var chargeB = b.Sum(ele => ele.ChargeNumber); - if (chargeA != chargeB) return false; - foreach (var item in dictA) - { - if (item is null) continue; - if (!dictB.Any(ele => item.Equals(ele))) return false; - } - - return true; - } - catch (ArgumentException) - { - return false; - } - } - - /// - /// Returns a string that represents the current object. - /// - /// The molecular fomula collection. - /// A string that represents the current object. - public static string ToString(IEnumerable formulas) - { - if (formulas is null) return string.Empty; - var dict = new Dictionary(); - foreach (var item in formulas) - { - if (item is null) continue; - var f = dict.Keys.FirstOrDefault(ele => ele == item); - if (f is null) dict[item] = 1; - else dict[f]++; - } - - return string.Join(" + ", dict.Select(ele => { - if (ele.Value > 1) return ele.Value.ToString("g") + ele.Key.ToString(); - return ele.Value.ToString(); - })); - } - - private static bool Add(StringBuilder sb, List col, int count) - { - var symbol = sb.ToString(); - var item = new Item(symbol, count); - if (item.Element is null) - { - switch (symbol) - { - case "R": - col.Add(new Item(ChemicalElement.C, count)); - col.Add(new Item(ChemicalElement.H, count * 2 + 1)); - break; - case "Ph": - col.Add(new Item(ChemicalElement.C, count * 6)); - col.Add(new Item(ChemicalElement.H, count * 5)); - break; - case "Bn": - col.Add(new Item(ChemicalElement.C, count * 6)); - col.Add(new Item(ChemicalElement.H, count * 5)); - col.Add(new Item(ChemicalElement.C, count)); - col.Add(new Item(ChemicalElement.H, count * 2)); - break; - default: - return false; - } - } - - col.Add(item); - return true; - } - - private static void Zip(List list, Item item) - { - if (item?.Element is null || item.Count < 1) return; - var count = list.Where(ele => ele.Element == item.Element).Sum(ele => ele.Count); - list.RemoveAll(ele => ele.Element == item.Element); - list.Add(new Item(item.Element, count + item.Count)); - } -} diff --git a/Chemistry/Chemistry/PeriodicTable.cs b/Chemistry/Chemistry/PeriodicTable.cs deleted file mode 100644 index 87fe9295..00000000 --- a/Chemistry/Chemistry/PeriodicTable.cs +++ /dev/null @@ -1,614 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.Chemistry; - -/// -/// The periodic table of chemical element. -/// -public partial class ChemicalElement -{ - /// - /// Gets chemical element Hydrogen (Hydrogenium). - /// A colourless, odourless, tasteless, flammable gaseous substance that is the simplest member of the family of chemical elements. - /// - public static ChemicalElement H => Get(1); - - /// - /// Gets chemical element Helium. - /// The second lightest element, helium is a colourless, odourless, and tasteless gas that becomes liquid at −268.9 °C (−452 °F). - /// - public static ChemicalElement He => Get(2); - - /// - /// Gets chemical element Lithium. - /// The lightest of the solid elements. The metal itself—which is soft, white, and lustrous—and several of its alloys and compounds are produced on an industrial scale. - /// - public static ChemicalElement Li => Get(3); - - /// - /// Gets chemical element Beryllium, formerly (until 1957AD) glucinium. - /// - public static ChemicalElement Be => Get(4); - - /// - /// Gets chemical element Boron. - /// - public static ChemicalElement B => Get(5); - - /// - /// Gets chemical element Carbon (Carboneum). - /// - public static ChemicalElement C => Get(6); - - /// - /// Gets chemical element Nitrogen (Nitrogenium). - /// - public static ChemicalElement N => Get(7); - - /// - /// Gets chemical element Oxygen (Oxygenium). - /// A colourless, odourless, tasteless gas essential to living organisms, being taken up by animals, which convert it to carbon dioxide. - /// - public static ChemicalElement O => Get(8); - - /// - /// Gets chemical element Fluorine (Fluorum). - /// - public static ChemicalElement F => Get(9); - - /// - /// Gets chemical element Neon. - /// - public static ChemicalElement Ne => Get(10); - - /// - /// Gets chemical element Sodium (Natrium). - /// A very soft silvery-white metal. - /// - public static ChemicalElement Na => Get(11); - - /// - /// Gets chemical element Magnesium. - /// - public static ChemicalElement Mg => Get(12); - - /// - /// Gets chemical element Aluminium. - /// Also spelled aluminium, a lightweight silvery white metal. - /// - public static ChemicalElement Al => Get(13); - - /// - /// Gets chemical element Silicon (Silicium). - /// - public static ChemicalElement Si => Get(14); - - /// - /// Gets chemical element Phosphorus. - /// - public static ChemicalElement P => Get(15); - - /// - /// Gets chemical element Sulfur. - /// - public static ChemicalElement S => Get(16); - - /// - /// Gets chemical element Chlorine (Chlorum). - /// - public static ChemicalElement Cl => Get(17); - - /// - /// Gets chemical element Argon. - /// - public static ChemicalElement Ar => Get(18); - - /// - /// Gets chemical element Potassium (Kalium). - /// - public static ChemicalElement K => Get(19); - - /// - /// Gets chemical element Calcium. - /// - public static ChemicalElement Ca => Get(20); - - /// - /// Gets chemical element Scandium. - /// - public static ChemicalElement Sc => Get(21); - - /// - /// Gets chemical element Titanium. - /// - public static ChemicalElement Ti => Get(22); - - /// - /// Gets chemical element Vanadium. - /// - public static ChemicalElement V => Get(23); - - /// - /// Gets chemical element Chromium. - /// - public static ChemicalElement Cr => Get(24); - - /// - /// Gets chemical element Manganese (Manganum). - /// - public static ChemicalElement Mn => Get(25); - - /// - /// Gets chemical element Iron. - /// - public static ChemicalElement Fe => Get(26); - - /// - /// Gets chemical element Cobalt (Cobaltum). - /// - public static ChemicalElement Co => Get(27); - - /// - /// Gets chemical element Nickel. - /// - public static ChemicalElement Ni => Get(28); - - /// - /// Gets chemical element Copper (Cuprum). - /// - public static ChemicalElement Cu => Get(29); - - /// - /// Gets chemical element Zinc (Zincum). - /// - public static ChemicalElement Zn => Get(30); - - /// - /// Gets chemical element Gallium. - /// - public static ChemicalElement Ga => Get(31); - - /// - /// Gets chemical element Germanium. - /// - public static ChemicalElement Ge => Get(32); - - /// - /// Gets chemical element Arsenic (Arsenicum). - /// - public static ChemicalElement As => Get(33); - - /// - /// Gets chemical element Selenium. - /// - public static ChemicalElement Se => Get(34); - - /// - /// Gets chemical element Bromine (Bromum). - /// - public static ChemicalElement Br => Get(35); - - /// - /// Gets chemical element Krypton. - /// - public static ChemicalElement Kr => Get(36); - - /// - /// Gets chemical element Rubidium. - /// - public static ChemicalElement Rb => Get(37); - - /// - /// Gets chemical element Strontium. - /// - public static ChemicalElement Sr => Get(38); - - /// - /// Gets chemical element Yttrium. - /// - public static ChemicalElement Y => Get(39); - - /// - /// Gets chemical element Zirconium. - /// - public static ChemicalElement Zr => Get(40); - - /// - /// Gets chemical element Niobium, formerly Columbium. - /// - public static ChemicalElement Nb => Get(41); - - /// - /// Gets chemical element Molybdenum (Molybdaenum). - /// - public static ChemicalElement Mo => Get(42); - - /// - /// Gets chemical element Technetium. - /// - public static ChemicalElement Tc => Get(43); - - /// - /// Gets chemical element Ruthenium. - /// - public static ChemicalElement Ru => Get(44); - - /// - /// Gets chemical element Rhodium. - /// - public static ChemicalElement Rh => Get(45); - - /// - /// Gets chemical element Palladium. - /// - public static ChemicalElement Pd => Get(46); - - /// - /// Gets chemical element Silver (Argentum). - /// A white lustrous metal valued for its decorative beauty and electrical conductivity. - /// - public static ChemicalElement Ag => Get(47); - - /// - /// Gets chemical element Cadmium. - /// - public static ChemicalElement Cd => Get(48); - - /// - /// Gets chemical element Indium. - /// - public static ChemicalElement In => Get(49); - - /// - /// Gets chemical element Tin. - /// - public static ChemicalElement Sn => Get(50); - - /// - /// Gets chemical element Antimony. - /// - public static ChemicalElement Sb => Get(51); - - /// - /// Gets chemical element Tellurium. - /// - public static ChemicalElement Te => Get(52); - - /// - /// Gets chemical element Iodine (Iodum). - /// - public static ChemicalElement I => Get(53); - - /// - /// Gets chemical element Xenon. - /// - public static ChemicalElement Xe => Get(54); - - /// - /// Gets chemical element Caesium. - /// - public static ChemicalElement Cs => Get(55); - - /// - /// Gets chemical element Barium. - /// - public static ChemicalElement Ba => Get(56); - - /// - /// Gets chemical element Lanthanum. - /// - public static ChemicalElement La => Get(57); - - /// - /// Gets chemical element Cerium. - /// - public static ChemicalElement Ce => Get(58); - - /// - /// Gets chemical element Praseodymium. - /// - public static ChemicalElement Pr => Get(59); - - /// - /// Gets chemical element Neodymium. - /// - public static ChemicalElement Nd => Get(60); - - /// - /// Gets chemical element Promethium. - /// - public static ChemicalElement Pm => Get(61); - - /// - /// Gets chemical element Samarium. - /// - public static ChemicalElement Sm => Get(62); - - /// - /// Gets chemical element Europium. - /// - public static ChemicalElement Eu => Get(63); - - /// - /// Gets chemical element Gadolinium. - /// - public static ChemicalElement Gd => Get(64); - - /// - /// Gets chemical element Terbium. - /// - public static ChemicalElement Tb => Get(65); - - /// - /// Gets chemical element Dysprosium. - /// - public static ChemicalElement Dy => Get(66); - - /// - /// Gets chemical element Holmium. - /// - public static ChemicalElement Ho => Get(67); - - /// - /// Gets chemical element Erbium. - /// - public static ChemicalElement Er => Get(68); - - /// - /// Gets chemical element Thulium. - /// - public static ChemicalElement Tm => Get(69); - - /// - /// Gets chemical element Ytterbium. - /// - public static ChemicalElement Yb => Get(70); - - /// - /// Gets chemical element Lutetium. - /// - public static ChemicalElement Lu => Get(71); - - /// - /// Gets chemical element Hafnium. - /// - public static ChemicalElement Hf => Get(72); - - /// - /// Gets chemical element Tantalum. - /// - public static ChemicalElement Ta => Get(73); - - /// - /// Gets chemical element Tungsten. - /// - public static ChemicalElement W => Get(74); - - /// - /// Gets chemical element Rhenium. - /// - public static ChemicalElement Re => Get(75); - - /// - /// Gets chemical element Osmium. - /// - public static ChemicalElement Os => Get(76); - - /// - /// Gets chemical element Iridium. - /// - public static ChemicalElement Ir => Get(77); - - /// - /// Gets chemical element Platinum. - /// A very heavy, precious, silver-white metal, platinum is soft and ductile and has a high melting point and good resistance to corrosion and chemical attack. - /// - public static ChemicalElement Pt => Get(78); - - /// - /// Gets chemical element Gold (Aurum). - /// Gold has several qualities that have made it exceptionally valuable throughout history. It is attractive in colour and brightness, durable to the point of virtual indestructibility, highly malleable, and usually found in nature in a comparatively pure form. - /// - public static ChemicalElement Au => Get(79); - - /// - /// Gets chemical element Mercury (Hydrargyrum). - /// - public static ChemicalElement Hg => Get(80); - - /// - /// Gets chemical element Thallium. - /// - public static ChemicalElement Tl => Get(81); - - /// - /// Gets chemical element Lead (Plumbum). - /// - public static ChemicalElement Pb => Get(82); - - /// - /// Gets chemical element Bismuth (Bismuthum). - /// - public static ChemicalElement Bi => Get(83); - - /// - /// Gets chemical element Polonium. - /// - public static ChemicalElement Po => Get(84); - - /// - /// Gets chemical element Astatine (Astatium). - /// - public static ChemicalElement At => Get(85); - - /// - /// Gets chemical element Radon. - /// - public static ChemicalElement Rn => Get(86); - - /// - /// Gets chemical element Francium. - /// - public static ChemicalElement Fr => Get(87); - - /// - /// Gets chemical element Radium. - /// - public static ChemicalElement Ra => Get(88); - - /// - /// Gets chemical element Actinium. - /// - public static ChemicalElement Ac => Get(89); - - /// - /// Gets chemical element Thorium. - /// - public static ChemicalElement Th => Get(90); - - /// - /// Gets chemical element Protactinium. - /// - public static ChemicalElement Pa => Get(91); - - /// - /// Gets chemical element Uranium. - /// - public static ChemicalElement U => Get(92); - - /// - /// Gets chemical element Neptunium. - /// - public static ChemicalElement Np => Get(93); - - /// - /// Gets chemical element Plutonium. - /// - public static ChemicalElement Pu => Get(94); - - /// - /// Gets chemical element Americium. - /// - public static ChemicalElement Am => Get(95); - - /// - /// Gets chemical element Curium. - /// - public static ChemicalElement Cm => Get(96); - - /// - /// Gets chemical element Berkelium. - /// - public static ChemicalElement Bk => Get(97); - - /// - /// Gets chemical element Californium. - /// - public static ChemicalElement Cf => Get(98); - - /// - /// Gets chemical element Einsteinium. - /// - public static ChemicalElement Es => Get(99); - - /// - /// Gets chemical element Fermium. - /// - public static ChemicalElement Fm => Get(100); - - /// - /// Gets chemical element Mendelevium. - /// - public static ChemicalElement Md => Get(101); - - /// - /// Gets chemical element Nobelium. - /// - public static ChemicalElement No => Get(102); - - /// - /// Gets chemical element Lawrencium. - /// - public static ChemicalElement Lr => Get(103); - - /// - /// Gets chemical element Rutherfordium. - /// - public static ChemicalElement Rf => Get(104); - - /// - /// Gets chemical element Dubnium. - /// - public static ChemicalElement Db => Get(105); - - /// - /// Gets chemical element Seaborgium. - /// - public static ChemicalElement Sg => Get(106); - - /// - /// Gets chemical element Bohrium. - /// - public static ChemicalElement Bh => Get(107); - - /// - /// Gets chemical element Hassium. - /// - public static ChemicalElement Hs => Get(108); - - /// - /// Gets chemical element Meitnerium. - /// - public static ChemicalElement Mt => Get(109); - - /// - /// Gets chemical element Darmstadtium. - /// - public static ChemicalElement Ds => Get(110); - - /// - /// Gets chemical element Roentgenium. - /// - public static ChemicalElement Rg => Get(111); - - /// - /// Gets chemical element Copernicium. - /// - public static ChemicalElement Cn => Get(112); - - /// - /// Gets chemical element Nihonium. - /// - public static ChemicalElement Nh => Get(113); - - /// - /// Gets chemical element Flerovium. - /// - public static ChemicalElement Fl => Get(114); - - /// - /// Gets chemical element Moscovium. - /// - public static ChemicalElement Mc => Get(115); - - /// - /// Gets chemical element Livermorium. - /// - public static ChemicalElement Lv => Get(116); - - /// - /// Gets chemical element Tennessine. - /// - public static ChemicalElement Ts => Get(117); - - /// - /// Gets chemical element Oganesson. - /// - public static ChemicalElement Og => Get(118); -} diff --git a/Chemistry/CommandLine/Options.cs b/Chemistry/CommandLine/Options.cs deleted file mode 100644 index 793ab8b2..00000000 --- a/Chemistry/CommandLine/Options.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Chemistry; -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The kinds to represent the information of chemical element. -/// -public enum ChemicalElementRepresentationKinds -{ - /// - /// Summary. - /// - Summary = 0, - - /// - /// Detail information. - /// - Details = 1, - - /// - /// Detail information and isotopes. - /// - DetailsAndIsotopes = 2 -} - -/// -/// The console style for chemical element. -/// -public class ChemicalElementConsoleStyle : ICloneable, IConsoleTextCreator -{ - /// - /// Gets or sets the fallback console color of element name. - /// - [JsonPropertyName("name2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? NameConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of element name. - /// - [JsonPropertyName("name")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? NameRgbColor { get; set; } - - /// - /// Gets or sets the fallback console color of element symbol. - /// - [JsonPropertyName("symbol2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? SymbolConsoleColor { get; set; } = ConsoleColor.Yellow; - - /// - /// Gets or sets the RGB color of element symbol. - /// - [JsonPropertyName("symbol")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? SymbolRgbColor { get; set; } = Color.FromArgb(0xF9, 0xEE, 0x88); - - /// - /// Gets or sets the fallback console color of atomic number. - /// - [JsonPropertyName("z2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? AtomicNumberConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of atomic number. - /// - [JsonPropertyName("z")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? AtomicNumberRgbColor { get; set; } = Color.FromArgb(160, 160, 240); - - /// - /// Gets or sets the fallback console color of element additional property key. - /// - [JsonPropertyName("key2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PropertyKeyConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of additional property key. - /// - [JsonPropertyName("key")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PropertyKeyRgbColor { get; set; } = Color.FromArgb(0xCE, 0x91, 0x78); - - /// - /// Gets or sets the fallback console color of additional property value. - /// - [JsonPropertyName("value2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PropertyValueConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of additional property value. - /// - [JsonPropertyName("value")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PropertyValueRgbColor { get; set; } - - /// - /// Gets or sets the fallback console color of element isotope information. - /// - [JsonPropertyName("isotope2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? IsotopeConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of element isotope information. - /// - [JsonPropertyName("isotope")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? IsotopeRgbColor { get; set; } = Color.FromArgb(160, 160, 160); - - /// - /// Gets or sets the fallback console color of punctuation marks. - /// - [JsonPropertyName("punctuation2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PunctuationConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of element punctuation marks. - /// - [JsonPropertyName("punctuation")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PunctuationRgbColor { get; set; } = Color.FromArgb(128, 128, 128); - - /// - /// Gets or sets the fallback console color of background. - /// - [JsonPropertyName("back2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? BackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the RGB color of background. - /// - [JsonPropertyName("back")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? BackgroundRgbColor { get; set; } - - /// - /// Clears all colors. - /// - public void Clear() - { - NameConsoleColor = null; - NameRgbColor = null; - SymbolConsoleColor = null; - SymbolRgbColor = null; - AtomicNumberConsoleColor = null; - AtomicNumberRgbColor = null; - PropertyKeyConsoleColor = null; - PropertyKeyRgbColor = null; - PropertyValueConsoleColor = null; - PropertyValueRgbColor = null; - IsotopeConsoleColor = null; - IsotopeRgbColor = null; - PunctuationConsoleColor = null; - PunctuationRgbColor = null; - BackgroundConsoleColor = null; - BackgroundRgbColor = null; - } - - /// - /// Clones an object. - /// - /// The object copied from this instance. - public virtual ChemicalElementConsoleStyle Clone() - => MemberwiseClone() as ChemicalElementConsoleStyle; - - /// - /// Clones an object. - /// - /// The object copied from this instance. - object ICloneable.Clone() - => MemberwiseClone(); - - /// - /// Gets a value indicating whether it has already contained a line terminator. - /// - bool IConsoleTextCreator.ContainsTerminator => true; - - /// - /// Creates the console text collection based on this style. - /// - /// The chemical element. - /// The presentation kind. - /// A collection of console text. - IEnumerable IConsoleTextCreator.CreateTextCollection(ChemicalElement element, ChemicalElementRepresentationKinds kind) - => kind switch - { - ChemicalElementRepresentationKinds.Details => ChemistryCommandLine.ToConsoleText(this, element, false), - ChemicalElementRepresentationKinds.DetailsAndIsotopes => ChemistryCommandLine.ToConsoleText(this, element, true), - _ => ChemistryCommandLine.ToSimpleConsoleText(this, element, false), - }; -} diff --git a/Chemistry/CommandLine/Utils.cs b/Chemistry/CommandLine/Utils.cs deleted file mode 100644 index 64201cf9..00000000 --- a/Chemistry/CommandLine/Utils.cs +++ /dev/null @@ -1,484 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Chemistry; -using Trivial.Collection; - -namespace Trivial.CommandLine; - -/// -/// The chemistry command line. -/// -public static class ChemistryCommandLine -{ - /// - /// Writes the specified chemical element, followed by the current line terminator, to the standard output stream. - /// - /// A chemicial element. - /// The kind to represent the information of chemical element. - public static void WriteLine(ChemicalElement element, ChemicalElementRepresentationKinds kind) - => WriteLine(StyleConsole.Default, new ChemicalElementConsoleStyle(), element, kind); - - /// - /// Writes the specified chemical element, followed by the current line terminator, to the standard output stream. - /// - /// The console instance. - /// A chemicial element. - /// The kind to represent the information of chemical element. - public static void WriteLine(this StyleConsole console, ChemicalElement element, ChemicalElementRepresentationKinds kind) - => WriteLine(console, new ChemicalElementConsoleStyle(), element, kind); - - /// - /// Writes the specified chemical element, followed by the current line terminator, to the standard output stream. - /// - /// The console instance. - /// The style. - /// A chemicial element. - /// The kind to represent the information of chemical element. - public static void WriteLine(this StyleConsole console, ChemicalElementConsoleStyle style, ChemicalElement element, ChemicalElementRepresentationKinds kind) - { - var col = kind switch - { - ChemicalElementRepresentationKinds.Details => ToConsoleText(style, element, false), - ChemicalElementRepresentationKinds.DetailsAndIsotopes => ToConsoleText(style, element, true), - _ => ToSimpleConsoleText(style, element, false), - }; - (console ?? StyleConsole.Default).Write(col); - } - - /// - /// Writes the specified chemistry periodic table, followed by the current line terminator, to the standard output stream. - /// - /// The console instance. - /// The style. - public static void WriteTable(StyleConsole console, ChemicalElementConsoleStyle style) - { - var col = new List(); - if (style == null) style = new(); - var symbolStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.SymbolConsoleColor, - ForegroundRgbColor = style.SymbolRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var numberStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - - col.Add("1 ", punctuationStyle); - AppendSymbol(col, ChemicalElement.H, symbolStyle); - col.Add(' ', 64, punctuationStyle); - AppendSymbol(col, ChemicalElement.He, symbolStyle); - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 1, numberStyle); - col.Add(' ', 64, punctuationStyle); - AppendNumber(col, 2, numberStyle); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("2 ", punctuationStyle); - AppendSymbol(col, ChemicalElement.Li, symbolStyle); - AppendSymbol(col, ChemicalElement.Be, symbolStyle); - col.Add(' ', 40, punctuationStyle); - AppendSymbol(col, ChemicalElement.B, symbolStyle); - AppendSymbol(col, ChemicalElement.C, symbolStyle); - AppendSymbol(col, ChemicalElement.N, symbolStyle); - AppendSymbol(col, ChemicalElement.O, symbolStyle); - AppendSymbol(col, ChemicalElement.F, symbolStyle); - AppendSymbol(col, ChemicalElement.Ne, symbolStyle); - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 3, numberStyle, 2); - col.Add(' ', 40, punctuationStyle); - AppendNumber(col, 5, numberStyle, 6); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("3 ", punctuationStyle); - AppendSymbol(col, ChemicalElement.Na, symbolStyle); - AppendSymbol(col, ChemicalElement.Mg, symbolStyle); - col.Add(' ', 40, punctuationStyle); - AppendSymbol(col, ChemicalElement.Al, symbolStyle); - AppendSymbol(col, ChemicalElement.Si, symbolStyle); - AppendSymbol(col, ChemicalElement.P, symbolStyle); - AppendSymbol(col, ChemicalElement.S, symbolStyle); - AppendSymbol(col, ChemicalElement.Cl, symbolStyle); - AppendSymbol(col, ChemicalElement.Ar, symbolStyle); - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 11, numberStyle, 2); - col.Add(' ', 40, punctuationStyle); - AppendNumber(col, 13, numberStyle, 6); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("4 ", punctuationStyle); - for (var i = 19; i <= 36; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 19, numberStyle, 18); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("5 ", punctuationStyle); - for (var i = 37; i <= 54; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 37, numberStyle, 18); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("6 ", punctuationStyle); - for (var i = 55; i < 58; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - for (var i = 72; i <= 86; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 55, numberStyle, 2); - col.Add("... ", punctuationStyle); - AppendNumber(col, 72, numberStyle, 15); - col.AddNewLine(); - col.AddNewLine(); - - col.Add("7 ", punctuationStyle); - for (var i = 87; i < 90; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - for (var i = 104; i <= 118; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add(" ", punctuationStyle); - AppendNumber(col, 87, numberStyle, 2); - col.Add("... ", punctuationStyle); - AppendNumber(col, 104, numberStyle, 15); - col.AddNewLine(); - col.AddNewLine(); - - col.Add(ChemicalElement.La.Symbol, symbolStyle); - col.Add('-', 1, punctuationStyle); - col.Add(ChemicalElement.Lu.Symbol, symbolStyle); - col.Add("\t ", punctuationStyle); - for (var i = 57; i <= 71; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add("\t ", punctuationStyle); - AppendNumber(col, 57, numberStyle, 15); - col.AddNewLine(); - col.AddNewLine(); - - col.Add(ChemicalElement.Ac.Symbol, symbolStyle); - col.Add('-', 1, punctuationStyle); - col.Add(ChemicalElement.Lr.Symbol, symbolStyle); - col.Add("\t "); - for (var i = 89; i <= 103; i++) - { - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - } - - col.AddNewLine(); - col.Add("\t ", punctuationStyle); - AppendNumber(col, 89, numberStyle, 15); - col.AddNewLine(); - col.AddNewLine(); - - if (ChemicalElement.Has(119) && ChemicalElement.Has(120)) - { - col.Add("8 ", punctuationStyle); - col.Add("119 ", numberStyle); - col.Add('-', 1, punctuationStyle); - col.Add(" 168 ", numberStyle); - AppendSymbol(col, ChemicalElement.Get(119), symbolStyle); - AppendSymbol(col, ChemicalElement.Get(120), symbolStyle); - for (var i = 121; i < 131; i++) - { - if (ChemicalElement.Has(i)) - AppendSymbol(col, ChemicalElement.Get(i), symbolStyle); - else - break; - } - - col.Add("...", punctuationStyle); - col.AddNewLine(); - } - else - { - col.Add("8 ", punctuationStyle); - col.Add("119 ", numberStyle); - col.Add('-', 1, punctuationStyle); - col.Add(" 168 ", numberStyle); - col.AddNewLine(); - } - - col.Add("9 ", punctuationStyle); - col.Add("169 ", numberStyle); - col.Add('-', 1, punctuationStyle); - col.Add(" 218 ", numberStyle); - col.AddNewLine(); - - (console ?? StyleConsole.Default).Write(col); - } - - /// - /// Writes the element information to the standard output stream. - /// - /// The console style. - /// A chemicial element. - /// true if also write its isotopes; otherwise, false. - internal static List ToConsoleText(ChemicalElementConsoleStyle style, ChemicalElement element, bool containIsotopes = false) - { - if (element is null) return null; - if (style == null) style = new(); - var name = element.Name; - var col = new List - { - { - $"{element.AtomicNumber:g}\t", - new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - } - }, - { - element.Symbol, - new ConsoleTextStyle - { - ForegroundConsoleColor = style.SymbolConsoleColor, - ForegroundRgbColor = style.SymbolRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - } - } - }; - var nameStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.NameConsoleColor, - ForegroundRgbColor = style.NameRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - if (!string.IsNullOrWhiteSpace(element.EnglishName) && !name.Equals(element.EnglishName)) - col.Add($"\t{element.EnglishName}", nameStyle); - col.AddNewLine(); - col.Add($" {name}", nameStyle); - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - if (name.Length == 1 && name[0] >= 0x2E00) - col.Add($"\t(U+{(int)name[0]:X4})", punctuationStyle); - col.AddNewLine(); - var keyStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PropertyKeyConsoleColor, - ForegroundRgbColor = style.PropertyKeyRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var valueStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PropertyValueConsoleColor, - ForegroundRgbColor = style.PropertyValueRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - if (!double.IsNaN(element.AtomicWeight)) - { - col.Add(" Weight", keyStyle); - col.Add(" = ", punctuationStyle); - col.Add(element.AtomicWeight.ToString("#.########"), valueStyle); - col.AddNewLine(); - } - - if (element.Period > 0 && element.Group > 0) - { - col.Add(" Period", keyStyle); - col.Add(" = ", punctuationStyle); - col.Add(element.Period.ToString("g"), valueStyle); - col.Add(" ", punctuationStyle); - col.Add("Group", keyStyle); - col.Add(" = ", punctuationStyle); - col.Add(element.Group.ToString("g"), valueStyle); - if (!string.IsNullOrWhiteSpace(element.Block)) - { - col.Add(" ", punctuationStyle); - col.Add("Block", keyStyle); - col.Add(" = ", punctuationStyle); - col.Add(element.Block, valueStyle); - } - } - - if (!containIsotopes) return col; - var isotopes = element.Isotopes(); - if (isotopes.Count < 1) return col; - col.AddNewLine(); - var isotopeStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.IsotopeConsoleColor, - ForegroundRgbColor = style.IsotopeRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - col.Add(isotopes.Count == 1 ? ChemistryResource.Isotope : ChemistryResource.Isotopes, isotopeStyle); - col.Add($" ({isotopes.Count})", punctuationStyle); - var i = 0; - if (isotopes.Count > 150) - { - foreach (var isotope in isotopes) - { - if (i % 8 == 0) - col.AddNewLine(); - col.Add($"{isotope.AtomicMassNumber}\t", isotopeStyle); - i++; - } - - col.AddNewLine(); - return col; - } - - col.AddNewLine(); - foreach (var isotope in isotopes) - { - if (isotope is null) continue; - i++; - var weight = isotope.HasAtomicWeight ? isotope.AtomicWeight.ToString("#.########") : string.Empty; - col.Add($" {isotope.AtomicMassNumber}\t{weight}", isotopeStyle); - if (weight.Length < 8) col.Add('\t', 1, isotopeStyle); - if (i % 3 > 0) col.Add(" \t"); - else col.AddNewLine(); - } - - if (i % 3 > 0) col.AddNewLine(); - return col; - } - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// - /// The console style. - /// A chemicial element. - /// true if writes English name. - internal static List ToSimpleConsoleText(ChemicalElementConsoleStyle style, ChemicalElement element, bool writeEnglishName) - { - if (string.IsNullOrWhiteSpace(element.Symbol) || element.Period < 1) return null; - var name = writeEnglishName ? element.EnglishName : element.Name; - if (style == null) style = new(); - var col = new List - { - { - $"{element.AtomicNumber:g}\t", - new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - } - }, - { - element.Symbol, - new ConsoleTextStyle - { - ForegroundConsoleColor = style.SymbolConsoleColor, - ForegroundRgbColor = style.SymbolRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - } - }, - { - $"\t{name}", - new ConsoleTextStyle - { - ForegroundConsoleColor = style.NameConsoleColor, - ForegroundRgbColor = style.NameRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - } - } - }; - if (!double.IsNaN(element.AtomicWeight)) - { - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - if (name.Length < 8) col.Add('\t', 2, punctuationStyle); - else col.Add(" \t", punctuationStyle); - col.Add(element.AtomicWeight.ToString("#.######"), punctuationStyle); - } - - col.AddNewLine(); - return col; - } - - internal static void AddNewLine(this List col) - => col.Add(Environment.NewLine); - - internal static void AppendNumber(List col, int i, ConsoleTextStyle style, int count = 1) - { - var k = i + count; - for (var j = i; j < k; j++) - { - var s = j.ToString("g"); - col.Add(s, style); - col.Add(' ', 4 - s.Length, style); - } - } - - private static void AppendSymbol(List col, ChemicalElement element, ConsoleTextStyle style) - { - var s = element.Symbol?.Trim(); - if (string.IsNullOrEmpty(s)) return; - if (s.Length > 4) s = s.Substring(0, 4); - col.Add(s, style); - col.Add(' ', 4 - s.Length, style); - } -} diff --git a/Chemistry/CommandLine/Verb.cs b/Chemistry/CommandLine/Verb.cs deleted file mode 100644 index 0d1e5b09..00000000 --- a/Chemistry/CommandLine/Verb.cs +++ /dev/null @@ -1,667 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using Trivial.Chemistry; -using Trivial.Collection; - -namespace Trivial.CommandLine; - -/// -/// Chemistry command line verb. -/// -public class ChemistryVerb : BaseCommandVerb -{ -#pragma warning disable IDE0057 - /// - /// Gets the description. - /// - public static string Description => ChemistryResource.Chemistry; - - /// - /// Gets or sets the help document. - /// - public static string HelpInfo { get; set; } - - - /// - /// Gets or sets the tips header for usages. - /// - public static string UsagesTips { get; set; } - - /// - /// Gets or sets the tips header for examples. - /// - public static string ExamplesTips { get; set; } - - /// - /// Gets or sets the tips for error. - /// - public static string ErrorTips { get; set; } - - /// - /// Gets or sets the tips for empty. - /// - public static string EmptyTips { get; set; } - - /// - /// Gets or sets the tips for not found. - /// - public static string NotFoundTips { get; set; } - - /// - /// Gets or sets the tips for getting chemical element. - /// - public static string ElementTips { get; set; } - - /// - /// Gets or sets the tips for showing periodic table. - /// - public static string PeriodicTableTips { get; set; } - - /// - /// Gets or sets the tips for chemical elements in a specific period. - /// - public static string PeriodTips { get; set; } - - /// - /// Gets or sets the tips for all elements. - /// - public static string AllElementsTips { get; set; } - - /// - /// Gets or sets the tips for elements. - /// - public static string ElementListTips { get; set; } - - /// - /// Gets or sets the tips for molecular formula. - /// - public static string MolecularFormulaTips { get; set; } - - /// - /// Gets or sets the color of verb in help document. - /// - public static System.Drawing.Color VerbColorInHelp { get; set; } = System.Drawing.Color.FromArgb(0xF0, 0xE8, 0xA0); - - /// - /// Gets or sets the console style of chemical element. - /// - public ChemicalElementConsoleStyle ChemicalElementStyle { get; set; } - - /// - protected override async Task OnProcessAsync(CancellationToken cancellationToken = default) - { - await RunAsync(null, cancellationToken); - var s = Arguments.Verb?.TryGet(0); - var console = GetConsole(); - if (s == "period" || s == "p" || s == "周期" || (s == "Period" && Arguments.Verb.Count > 1)) - { - s = Arguments.Verb.TryGet(1); - if (string.IsNullOrEmpty(s)) - { - ChemistryCommandLine.WriteTable(GetConsole(), ChemicalElementStyle); - } - else if (int.TryParse(s, out var period) && period > 0) - { - if (period > 7) - { - var start = ChemicalElement.FirstAtomicNumberInPeriod(period); - var end = ChemicalElement.LastAtomicNumberInPeriod(period); - if (start <= 0 || end <= 0 || start >= end) - { - WriteError(" The period was too large."); - } - else - { - console.WriteLine(ChemistryResource.ChemicalElement); - console.WriteLine($"{start} - {end} (Total {end - start + 1})"); - } - - return; - } - - var elements = ChemicalElement.GetExisted(); - var has = false; - foreach (var element in elements) - { - if (element is null) continue; - if (element.Period != period) - { - if (has) break; - continue; - } - - WriteSimpleInfo(element, Arguments.Has("en")); - } - } - else if (s.Equals("help", StringComparison.OrdinalIgnoreCase) || s.Equals("?", StringComparison.Ordinal)) - { - WriteHelp(Arguments.Verb?.Key, "period"); - } - else - { - WriteError(" The period should be a natural number."); - } - - return; - } - - var q = Arguments.GetMergedValue("q")?.Trim(); - if (q.Length < 1) q = null; - - if (s == "*" || s == "all" || s == "a") - { - foreach (var i in ChemicalElement.Where(GetFilter(q))) - { - WriteSimpleInfo(i, Arguments.Has("en")); - } - - return; - } - - if (s == "ls" || s == "l" || s == "list" || s == "dir" || s == "全部") - { - var filter = Arguments.Verb.TryGet(1)?.Trim()?.Split('-'); - List col = null; - if (filter is null || filter.Length < 1 || string.IsNullOrWhiteSpace(filter[0])) - { - } - else if (filter[0].Equals("help", StringComparison.OrdinalIgnoreCase) || filter[0].Equals("?", StringComparison.Ordinal)) - { - WriteHelp(Arguments.Verb?.Key, "ls"); - return; - } - else if (!int.TryParse(filter[0], out var begin)) - { - } - else if (filter.Length == 1) - { - col = ChemicalElement.Range(0, begin).ToList(); - } - else if (filter.Length == 2 && int.TryParse(filter[1], out var end)) - { - col = ChemicalElement.Range(begin, end - begin).ToList(); - } - - if (col is null) - col = ChemicalElement.Where(null).ToList(); - var filter2 = GetFilter(q); - foreach (var i in filter2 is null ? col : col.Where(filter2)) - { - WriteSimpleInfo(i, Arguments.Has("en")); - } - - return; - } - - if (s == "molecular" || s == "formula" || s == "分子") - { - s = Arguments.Verb.Value?.Trim() ?? string.Empty; - if (s.StartsWith("molecular ")) s = s.Substring(10)?.Trim(); - if (s.StartsWith("formula ")) s = s.Substring(8)?.Trim(); - if (s.Length < 1 || s == "molecular" || s == "formula") - { - console.WriteLine(EmptyTips ?? "Empty"); - return; - } - - var m = MolecularFormula.TryParse(s); - if (m is null) - { - if (s.Equals("help", StringComparison.OrdinalIgnoreCase) || s.Equals("?", StringComparison.Ordinal)) - WriteHelp(Arguments.Verb?.Key, "molecular"); - else - WriteError(" Invalid molecular formula."); - return; - } - - console.WriteLine(m.ToString()); - var col = new List(); - var style = ChemicalElementStyle ?? new(); - var numberStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var nameStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.NameConsoleColor, - ForegroundRgbColor = style.NameRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var symbolStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.SymbolConsoleColor, - ForegroundRgbColor = style.SymbolRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var keyStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PropertyKeyConsoleColor, - ForegroundRgbColor = style.PropertyKeyRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var valueStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PropertyValueConsoleColor, - ForegroundRgbColor = style.PropertyValueRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - foreach (var ele in m.Zip()) - { - if (ele.Element is null) continue; - var name = Arguments.Has("en") ? ele.Element.EnglishName : ele.Element.Name; - col.Add($"{ele.Element.AtomicNumber:g}\t", numberStyle); - col.Add(ele.Element.Symbol, symbolStyle); - col.Add($"\t{name}", nameStyle); - if (name.Length < 8) col.Add('\t', 1, punctuationStyle); - col.Add(" \tx ", punctuationStyle); - col.Add(ele.Count.ToString("g"), valueStyle); - col.AddNewLine(); - } - - col.Add("Proton numbers \t", keyStyle); - col.Add(m.ProtonNumber.ToString("g"), valueStyle); - col.AddNewLine(); - col.Add("Atom count \t", keyStyle); - col.Add(m.Count.ToString("g"), valueStyle); - col.AddNewLine(); - if (m.IsIon) - { - col.Add("Charge number \t", keyStyle); - col.Add(m.ChargeNumber.ToString("g"), valueStyle); - col.AddNewLine(); - } - - console.Write(col); - return; - } - - if (s == "periodic" || s == "table" || s == "t" || s == "元素周期表" || s == "周期表") - { - ChemistryCommandLine.WriteTable(GetConsole(), ChemicalElementStyle); - return; - } - - if (s == "help" || s == "get-help" || s == "usages" || s == "?" || s == "帮助") - { - WriteHelp(Arguments.Verb.Key, Arguments.Verb.TryGet(1)); - return; - } - - if (s == "name") - { - console.WriteLine(ChemistryResource.Chemistry); - return; - } - - if (s == "element" || s == "get-element" || s == "z" || s == "元素" || (s == "Z" && Arguments.Verb.Count > 1)) - { - s = Arguments.Verb.TryGet(1); - if (s.Equals("help", StringComparison.Ordinal) || s.Equals("?", StringComparison.Ordinal)) - { - WriteHelp(Arguments.Verb?.Key, "element"); - return; - } - - if (s.Equals("name", StringComparison.Ordinal)) - { - console.WriteLine(ChemistryResource.ChemicalElement); - return; - } - } - else - { - s = null; - } - - if (string.IsNullOrEmpty(s)) - s = Arguments.Get("element", "number", "z", "e", "symbol", "s")?.MergedValue?.Trim(); - if (string.IsNullOrEmpty(s)) - s = Arguments.Verb?.TryGet(0); - if (string.IsNullOrEmpty(s)) - { - console.WriteLine(ChemistryResource.ChemicalElement); - var elements = ChemicalElement.Where(GetFilter(q)).ToList(); - if (elements.Count <= 64) - { - foreach (var i in elements) - { - WriteSimpleInfo(i, Arguments.Has("en")); - } - } - else if (Arguments.Has("en")) - { - var i = 0; - var style = ChemicalElementStyle ?? new(); - var numberStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var nameStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.NameConsoleColor, - ForegroundRgbColor = style.NameRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var col = new List(); - foreach (var element in elements) - { - if (element is null || element.AtomicNumber < 0) continue; - i++; - if (element.AtomicNumber < 1000) - { - ChemistryCommandLine.AppendNumber(col, element.AtomicNumber, numberStyle); - } - else - { - col.Add(element.AtomicNumber.ToString("g"), numberStyle); - col.Add(' ', 1, numberStyle); - } - - col.Add(element.EnglishName ?? element.Symbol ?? string.Empty, nameStyle); - if (i % 3 == 0) - { - col.AddNewLine(); - continue; - } - - col.Add(' ', Math.Max(1, 24 - col[col.Count - 1].Length - col[col.Count - 2].Length - col[col.Count - 3].Length), punctuationStyle); - } - - if (i % 3 > 0) col.AddNewLine(); - GetConsole().Write(col); - } - else - { - var start = false; - var style = ChemicalElementStyle ?? new(); - var numberStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.AtomicNumberConsoleColor, - ForegroundRgbColor = style.AtomicNumberRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var nameStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.NameConsoleColor, - ForegroundRgbColor = style.NameRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var symbolStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.SymbolConsoleColor, - ForegroundRgbColor = style.SymbolRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var punctuationStyle = new ConsoleTextStyle - { - ForegroundConsoleColor = style.PunctuationConsoleColor, - ForegroundRgbColor = style.PunctuationRgbColor, - BackgroundConsoleColor = style.BackgroundConsoleColor, - BackgroundRgbColor = style.BackgroundRgbColor - }; - var col = new List(); - foreach (var element in elements) - { - if (element is null) continue; - if (start) col.Add(" \t", punctuationStyle); - else start = true; - col.Add(element.Name, nameStyle); - col.Add(" (", punctuationStyle); - if (element.AtomicNumber < 1) - col.Add('?', 1, numberStyle); - else - col.Add(element.AtomicNumber.ToString("g"), numberStyle); - - if (!element.Name.Equals(element.Symbol, StringComparison.OrdinalIgnoreCase) - && !"?".Equals(element.Symbol, StringComparison.OrdinalIgnoreCase)) - { - col.Add(' ', 1, punctuationStyle); - col.Add(element.Symbol, symbolStyle); - } - - col.Add(')', 1, punctuationStyle); - } - - col.AddNewLine(); - GetConsole().Write(col); - } - return; - } - - var eles = s.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries).Distinct().Select(i => ChemicalElement.Get(i)).Where(i => i != null).Distinct().ToList(); - if (eles.Count < 1) - { - console.WriteLine(ConsoleColor.Red, NotFoundTips ?? "Not found."); - return; - } - - if (eles.Count == 1) - { - WriteInfo(eles[0], true); - return; - } - - if (eles.Count < 4) - { - WriteInfo(eles[0]); - GetConsole().WriteLine(); - WriteInfo(eles[1]); - if (eles.Count > 2) - { - GetConsole().WriteLine(); - WriteInfo(eles[2]); - } - - return; - } - - var filter3 = GetFilter(q); - foreach (var i in filter3 is null ? eles : eles.Where(filter3)) - { - WriteSimpleInfo(i, Arguments.Has("en")); - } - } - - /// - protected override void OnGetHelp() - { - WriteHelp(Arguments.Verb?.Key, Arguments.Verb?.TryGet(0)); - } - - private void WriteInfo(ChemicalElement element, bool containIsotopes = false) - { - var col = ChemistryCommandLine.ToConsoleText(ChemicalElementStyle, element, containIsotopes); - GetConsole().Write(col); - } - - private void WriteSimpleInfo(ChemicalElement element, bool writeEnglishName) - { - var col = ChemistryCommandLine.ToSimpleConsoleText(ChemicalElementStyle, element, writeEnglishName); - GetConsole().Write(col); - } - - private void WriteError(string message) - => GetConsole().WriteLine(new List - { - { - ErrorTips ?? "Error!", - new ConsoleTextStyle - { - ForegroundConsoleColor = ConsoleColor.Red - } - }, - message - }); - - private void WriteHelp(string verb, string key = null) - { - var console = GetConsole(); - verb = verb?.Trim(); - if (string.IsNullOrEmpty(verb)) verb = "~"; -#if NETFRAMEWORK - var lsKey = "dir"; -#else - var lsKey = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows) ? "dir" : "ls"; -#endif - switch (key?.Trim() ?? string.Empty) - { - case "": - break; - case "get-element": - case "element": - case "z": - case "Z": - case "元素": - WriteTips(verb, "element ", ElementTips, "Get details of the specific chemical element by symbol or atomic numbers."); - console.WriteLine(); - console.WriteLine(ExamplesTips ?? "EXAMPLES"); - console.WriteLine(); - console.WriteLine(verb + " element 6"); - console.WriteLine("{0} element {1}", verb, ChemicalElement.Au?.Symbol ?? ChemicalElement.Pt?.Symbol ?? ChemicalElement.O?.Symbol ?? "1"); - return; - case "periodic": - case "table": - case "周期表": - case "元素周期表": - WriteTips(verb, "table", PeriodicTableTips, "Output the periodic table."); - return; - case "period": - case "周期": - case "Period": - WriteTips(verb, "period ", PeriodTips, "List chemical elements in the specific period."); - console.WriteLine(); - console.WriteLine(ExamplesTips ?? "EXAMPLES"); - console.WriteLine(); - console.WriteLine(verb + " period 2"); - console.WriteLine(verb + " period 7"); - return; - case "*": - case "all": - WriteTips(verb, "all", AllElementsTips, "List all chemical elements."); - return; - case "ls": - case "list": - case "dir": - case "全部": - WriteTips(verb, lsKey + " -", ElementListTips, "List a speicific range of chemical elements."); - console.WriteLine(); - console.WriteLine(ExamplesTips ?? "EXAMPLES"); - console.WriteLine(); - console.WriteLine("{0} {1} 10-29", verb, lsKey); - console.WriteLine("{0} {1} 20", verb, lsKey); - console.WriteLine("{0} {1} 80 -q h", verb, lsKey); - return; - case "molecular": - case "formula": - case "分子": - WriteTips(verb, "molecular ", MolecularFormulaTips, "Get the information of the specific molecular formula."); - console.WriteLine(); - console.WriteLine(ExamplesTips ?? "EXAMPLES"); - console.WriteLine(); - console.WriteLine(verb + " molecular Fe3O4"); - console.WriteLine(verb + " molecular R-COOH"); - return; - case "about": - case "copyright": - if (!ChemistryResource.Chemistry.Equals("Chemistry", StringComparison.Ordinal)) - console.WriteLine(ChemistryResource.Chemistry); - var ver = System.Reflection.Assembly.GetExecutingAssembly()?.GetName()?.Version; - console.WriteLine(System.Drawing.Color.FromArgb(0xF0, 0xAA, 0xBB), "Trivial.Chemistry"); - var sb = new StringBuilder(); - if (ver != null) - { - sb.AppendFormat("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Build); - sb.AppendLine(); - } - - sb.AppendLine("Copyright (c) 2021 Kingcean Tuan. All rights reserved."); - sb.AppendLine("MIT licensed."); - console.Write(sb.ToString()); - return; - default: - break; - } - - var s = HelpInfo?.Trim(); - if (!string.IsNullOrEmpty(s)) - { - console.WriteLine(s); - console.WriteLine(); - } - - console.WriteLine(UsagesTips ?? "USAGES"); - console.WriteLine(); - WriteTips(verb, "element ", ElementTips, "Get details of the specific chemical element by symbol or atomic numbers."); - console.WriteLine(); - WriteTips(verb, "table", PeriodicTableTips, "Output the periodic table."); - console.WriteLine(); - WriteTips(verb, "period ", PeriodTips, "List chemical elements in the specific period."); - console.WriteLine(); - WriteTips(verb, "all", AllElementsTips, "List all chemical elements."); - console.WriteLine(); - WriteTips(verb, lsKey + " -", ElementListTips, "List a speicific range of chemical elements."); - console.WriteLine(); - WriteTips(verb, "molecular ", MolecularFormulaTips, "Get the information of the specific molecular formula."); - } - - private void WriteTips(string verb, string cmd, string desc, string descBackup) - { - GetConsole().WriteLine(VerbColorInHelp, $"{verb} {cmd}"); - GetConsole().WriteLine($" {desc ?? descBackup}"); - } - - private static Func GetFilter(string q) - { - if (string.IsNullOrEmpty(q)) return null; - return (ChemicalElement ele) => - { -#if NETFRAMEWORK - if (string.IsNullOrEmpty(ele?.EnglishName)) return false; - if (ele.EnglishName.Contains(q)) return true; - var name = ele.Name; - if (string.IsNullOrEmpty(name) || name == ele.EnglishName) return false; - return name.Contains(q); -#else - if (string.IsNullOrEmpty(ele?.EnglishName)) return false; - if (ele.EnglishName.Contains(q, StringComparison.OrdinalIgnoreCase)) return true; - var name = ele.Name; - if (string.IsNullOrEmpty(name) || name == ele.EnglishName) return false; - return name.Contains(q, StringComparison.OrdinalIgnoreCase); -#endif - }; - } -#pragma warning restore IDE0057 -} diff --git a/Chemistry/PeriodicTable.json b/Chemistry/PeriodicTable.json deleted file mode 100644 index 9c153b58..00000000 --- a/Chemistry/PeriodicTable.json +++ /dev/null @@ -1,710 +0,0 @@ -[ - { - "symbol": "H", - "name": "Hydrogen", - "weight": 1.008, - "isotopes": [ 1.00782503223, 2.01410177812, 3.0160492779, 4.02643, 5.035311, 6.04496, 7.0527 ] - }, - { - "symbol": "He", - "name": "Helium", - "weight": 4.002602, - "isotopes": [ 3.0160293201, 4.00260325413, 5.012057, 6.018885891, 7.0279907, 8.03393439, 9.043946, 10.05279 ] - }, - { - "symbol": "Li", - "name": "Lithium", - "weight": 6.94, - "isotopes": [ 3.0308, 4.02719, 5.012538, 6.0151228874, 7.0160034366, 8.022486246, 9.02679019, 10.035483, 11.04372358, 12.052517, 13.06263 ] - }, - { - "symbol": "Be", - "name": "Beryllium", - "weight": 9.0121831, - "isotopes": [ 5.0399, 6.0197264, 7.016928717, 8.005305102, 9.012183065, 10.013534695, 11.02166108, 12.0269221, 13.036135, 14.04289, 15.05342, 16.06167 ] - }, - { - "symbol": "B", - "name": "Boron", - "weight": 10.81, - "isotopes": [ 6.0508, 7.029712, 8.0246073, 9.01332965, 10.01293695, 11.00930536, 12.0143527, 13.0177802, 14.025404, 15.031088, 16.039842, 17.04699, 18.05566, 19.0631, 20.07207, 21.08129 ] - }, - { - "symbol": "C", - "name": "Carbon", - "weight": 12.011, - "isotopes": [ 8.037643, 9.0310372, 10.01685331, 11.0114336, 12, 13.00335483507, 14.0032419884, 15.01059926, 16.0147013, 17.022577, 18.026751, 19.0348, 20.04032, 21.049, 22.05753, 23.0689 ] - }, - { - "symbol": "N", - "name": "Nitrogen", - "weight": 14.007, - "isotopes": [ 10.04165, 11.026091, 12.0186132, 13.00573861, 14.00307400443, 15.00010889888, 16.0061019, 17.008449, 18.014078, 19.017022, 20.023366, 21.02711, 22.03439, 23.04114, 24.05039, 25.0601 ] - }, - { - "symbol": "O", - "name": "Oxygen", - "weight": 15.999, - "isotopes": [ 12.034262, 13.024815, 14.00859636, 15.00306562, 15.99491461957, 16.9991317565, 17.99915961286, 19.003578, 20.00407535, 21.008655, 22.009966, 23.015696, 24.01986, 25.02936, 26.03729, 27.04772, 28.05591 ] - }, - { - "symbol": "F", - "name": "Fluorine", - "weight": 18.998403163, - "isotopes": [ 14.034315, 15.018043, 16.0114657, 17.00209524, 18.00093733, 18.99840316273, 19.999981252, 20.9999489, 22.002999, 23.003557, 24.008115, 25.012199, 26.020038, 27.02644, 28.03534, 29.04254, 30.05165, 31.05971 ] - }, - { - "symbol": "Ne", - "name": "Neon", - "weight": 20.1797, - "isotopes": [ 16.02575, 17.01771396, 18.0057087, 19.00188091, 19.9924401762, 20.993846685, 21.991385114, 22.99446691, 23.99361065, 24.997789, 26.000515, 27.007553, 28.01212, 29.01975, 30.02473, 31.0331, 32.03972, 33.04938, 34.05673 ] - }, - { - "symbol": "Na", - "name": "Sodium", - "weight": 22.98976928, - "isotopes": [ 18.02688, 19.01388, 20.0073544, 20.99765469, 21.99443741, 22.989769282, 23.99096295, 24.989954, 25.9926346, 26.9940765, 27.998939, 29.0028771, 30.0090979, 31.013163, 32.02019, 33.02573, 34.03359, 35.04062, 36.04929, 37.05705 ] - }, - { - "symbol": "Mg", - "name": "Magnesium", - "weight": 24.305, - "isotopes": [ 19.034169, 20.01885, 21.011716, 21.99957065, 22.99412421, 23.985041697, 24.985836976, 25.982592968, 26.984340624, 27.9838767, 28.988617, 29.9904629, 30.996648, 31.9991102, 33.0053271, 34.008935, 35.01679, 36.02188, 37.03037, 38.03658, 39.04538, 40.05218 ] - }, - { - "symbol": "Al", - "name": "Aluminium", - "weight": 26.9815384, - "isotopes": [ 21.02897, 22.01954, 23.00724435, 23.9999489, 24.9904281, 25.986891904, 26.98153853, 27.98191021, 28.9804565, 29.98296, 30.983945, 31.988085, 32.990909, 33.996705, 34.999764, 36.00639, 37.01053, 38.0174, 39.02254, 40.03003, 41.03638, 42.04384, 43.05147 ] - }, - { - "symbol": "Si", - "name": "Silicon", - "weight": 28.085, - "isotopes": [ 22.03579, 23.02544, 24.011535, 25.004109, 25.99233384, 26.98670481, 27.97692653465, 28.9764946649, 29.973770136, 30.975363194, 31.97415154, 32.97797696, 33.978576, 34.984583, 35.986695, 36.992921, 37.995523, 39.002491, 40.00583, 41.01301, 42.01778, 43.0248, 44.03061, 45.03995 ] - }, - { - "symbol": "P", - "name": "Phosphorus", - "weight": 30.973761998, - "isotopes": [ 24.03577, 25.02119, 26.01178, 26.999224, 27.9923266, 28.98180079, 29.97831375, 30.97376199842, 31.973907643, 32.9717257, 33.97364589, 34.9733141, 35.97826, 36.979607, 37.984252, 38.986227, 39.99133, 40.994654, 42.00108, 43.00502, 44.01121, 45.01645, 46.02446, 47.03139 ] - }, - { - "symbol": "S", - "name": "Sulfur", - "weight": 32.06, - "isotopes": [ 26.02907, 27.01828, 28.00437, 28.996611, 29.98490703, 30.97955701, 31.9720711744, 32.9714589098, 33.967867004, 34.96903231, 35.96708071, 36.97112551, 37.9711633, 38.975134, 39.9754826, 40.9795935, 41.9810651, 42.9869076, 43.9901188, 44.99572, 46.00004, 47.00795, 48.0137, 49.02276 ] - }, - { - "symbol": "Cl", - "name": "Chlorine", - "weight": 35.45, - "isotopes": [ 28.02954, 29.01478, 30.00477, 30.992414, 31.98568464, 32.97745199, 33.973762485, 34.968852682, 35.968306809, 36.965902602, 37.96801044, 38.9680082, 39.970415, 40.970685, 41.97325, 42.97389, 43.97787, 44.98029, 45.98517, 46.98916, 47.99564, 49.00123, 50.00905, 51.01554 ] - }, - { - "symbol": "Ar", - "name": "Argon", - "weight": 39.95, - "isotopes": [ 30.02307, 31.01212, 31.9976378, 32.98992555, 33.98027009, 34.97525759, 35.967545105, 36.96677633, 37.96273211, 38.964313, 39.9623831237, 40.96450057, 41.9630457, 42.9656361, 43.9649238, 44.96803973, 45.968083, 46.972935, 47.97591, 48.9819, 49.98613, 50.9937, 51.99896, 53.00729 ] - }, - { - "symbol": "K", - "name": "Potassium", - "weight": 39.0983, - "isotopes": [ 32.02265, 33.00756, 33.99869, 34.98800541, 35.98130201, 36.97337589, 37.96908112, 38.9637064864, 39.963998166, 40.9618252579, 41.96240231, 42.9607347, 43.96158699, 44.96069149, 45.96198159, 46.9616616, 47.96534119, 48.96821075, 49.97238, 50.975828, 51.98224, 52.98746, 53.99463, 55.00076, 56.00851 ] - }, - { - "symbol": "Ca", - "name": "Calcium", - "weight": 40.078, - "isotopes": [ 34.01487, 35.00514, 35.993074, 36.98589785, 37.97631922, 38.97071081, 39.962590863, 40.96227792, 41.95861783, 42.95876644, 43.95548156, 44.95618635, 45.953689, 46.9545424, 47.95252276, 48.95566274, 49.9574992, 50.960989, 51.963217, 52.96945, 53.9734, 54.9803, 55.98508, 56.99262, 57.99794 ] - }, - { - "symbol": "Sc", - "name": "Scandium", - "weight": 44.955908, - "isotopes": [ 36.01648, 37.00374, 37.99512, 38.984785, 39.9779673, 40.969251105, 41.96551653, 42.9611505, 43.9594029, 44.95590828, 45.95516826, 46.9524037, 47.9522236, 48.9500146, 49.952176, 50.953592, 51.95688, 52.95909, 53.96393, 54.96782, 55.97345, 56.97777, 57.98403, 58.98894, 59.99565, 61.001 ] - }, - { - "symbol": "Ti", - "name": "Titanium", - "weight": 47.867, - "isotopes": [ 38.01145, 39.00236, 39.9905, 40.983148, 41.97304903, 42.9685225, 43.95968995, 44.95812198, 45.95262772, 46.95175879, 47.94794198, 48.94786568, 49.94478689, 50.94661065, 51.946893, 52.94973, 53.95105, 54.95527, 55.95791, 56.96364, 57.9666, 58.97247, 59.97603, 60.98245, 61.98651, 62.99375 ] - }, - { - "symbol": "V", - "name": "Vanadium", - "weight": 50.9415, - "isotopes": [ 40.01276, 41.00021, 41.99182, 42.980766, 43.97411, 44.9657748, 45.96019878, 46.95490491, 47.9522522, 48.9485118, 49.94715601, 50.94395704, 51.94477301, 52.9443367, 53.946439, 54.94724, 55.95048, 56.95252, 57.95672, 58.95939, 59.96431, 60.96725, 61.97265, 62.97639, 63.98264, 64.9875, 65.99398 ] - }, - { - "symbol": "Cr", - "name": "Chromium", - "weight": 51.9961, - "isotopes": [ 42.0067, 42.99753, 43.98536, 44.97905, 45.968359, 46.9628974, 47.9540291, 48.9513333, 49.94604183, 50.94476502, 51.94050623, 52.94064815, 53.93887916, 54.94083843, 55.9406531, 56.943613, 57.94435, 58.94859, 59.95008, 60.95442, 61.9561, 62.96165, 63.96408, 64.96996, 65.97366, 66.98016, 67.98403 ] - }, - { - "symbol": "Mn", - "name": "Manganese", - "weight": 54.938043, - "isotopes": [ 44.00715, 44.99449, 45.98609, 46.975775, 47.96852, 48.959595, 49.95423778, 50.94820847, 51.9455639, 52.94128889, 53.9403576, 54.93804391, 55.93890369, 56.9382861, 57.9400666, 58.9403911, 59.9431366, 60.9444525, 61.94795, 62.9496647, 63.9538494, 64.9560198, 65.960547, 66.96424, 67.96962, 68.97366, 69.97937, 70.98368 ] - }, - { - "symbol": "Fe", - "name": "Iron", - "weight": 55.845, - "isotopes": [ 45.01442, 46.00063, 46.99185, 47.98023, 48.973429, 49.962975, 50.956841, 51.9481131, 52.9453064, 53.93960899, 54.93829199, 55.93493633, 56.93539284, 57.93327443, 58.93487434, 59.9340711, 60.9367462, 61.9367918, 62.9402727, 63.9409878, 64.9450115, 65.94625, 66.95054, 67.95295, 68.95807, 69.96102, 70.96672, 71.96983, 72.97572, 73.97935 ] - }, - { - "symbol": "Co", - "name": "Cobalt", - "weight": 58.933194, - "isotopes": [ 47.01057, 48.00093, 48.98891, 49.98091, 50.970647, 51.96351, 52.9542041, 53.94845987, 54.9419972, 55.9398388, 56.93629057, 57.9357521, 58.93319429, 59.9338163, 60.93247662, 61.934059, 62.9336, 63.935811, 64.9364621, 65.939443, 66.9406096, 67.94426, 68.94614, 69.94963, 70.95237, 71.95729, 72.96039, 73.96515, 74.96876, 75.97413 ] - }, - { - "symbol": "Ni", - "name": "Nickel", - "weight": 58.6934, - "isotopes": [ 48.01769, 49.0077, 49.99474, 50.98611, 51.9748, 52.96819, 53.957892, 54.95133063, 55.94212855, 56.93979218, 57.93534241, 58.9343462, 59.93078588, 60.93105557, 61.92834537, 62.92966963, 63.92796682, 64.93008517, 65.9291393, 66.9315694, 67.9318688, 68.9356103, 69.9364313, 70.940519, 71.9417859, 72.9462067, 73.94798, 74.9525, 75.95533, 76.96055, 77.96336, 78.97025 ] - }, - { - "symbol": "Cu", - "name": "Copper", - "weight": 63.546, - "isotopes": [ 51.99671, 52.98459, 53.97666, 54.96604, 55.95895, 56.9492125, 57.94453305, 58.93949748, 59.9373645, 60.9334576, 61.93259541, 62.92959772, 63.92976434, 64.9277897, 65.92886903, 66.9277303, 67.9296109, 68.9294293, 69.9323921, 70.9326768, 71.9358203, 72.9366744, 73.9398749, 74.9415226, 75.945275, 76.94792, 77.95223, 78.95502, 79.96089, 80.96587, 81.97244 ] - }, - { - "symbol": "Zn", - "name": "Zinc", - "weight": 65.38, - "isotopes": [ 53.99204, 54.98398, 55.97254, 56.96506, 57.954591, 58.94931266, 59.9418421, 60.939507, 61.93433397, 62.9332115, 63.92914201, 64.92924077, 65.92603381, 66.92712775, 67.92484455, 68.9265507, 69.9253192, 70.9277196, 71.9268428, 72.9295826, 73.9294073, 74.9328402, 75.933115, 76.9368872, 77.9382892, 78.9426381, 79.9445529, 80.9504026, 81.95426, 82.96056, 83.96521, 84.97226 ] - }, - { - "symbol": "Ga", - "name": "Gallium", - "weight": 69.723, - "isotopes": [ 55.99536, 56.9832, 57.97478, 58.96353, 59.95729, 60.949399, 61.94419025, 62.9392942, 63.9368404, 64.93273459, 65.9315894, 66.9282025, 67.9279805, 68.9255735, 69.9260219, 70.92470258, 71.92636747, 72.9251747, 73.9269457, 74.9265002, 75.9288276, 76.9291543, 77.9316088, 78.9328523, 79.9364208, 80.9381338, 81.9431765, 82.9471203, 83.95246, 84.95699, 85.96301, 86.96824 ] - }, - { - "symbol": "Ge", - "name": "Germanium", - "weight": 72.63, - "isotopes": [ 57.99172, 58.98249, 59.97036, 60.96379, 61.95502, 62.949628, 63.9416899, 64.9393681, 65.9338621, 66.9327339, 67.9280953, 68.9279645, 69.92424875, 70.92495233, 71.922075826, 72.923458956, 73.921177761, 74.92285837, 75.921402726, 76.923549843, 77.9228529, 78.92536, 79.9253508, 80.9288329, 81.929774, 82.9345391, 83.9375751, 84.9429697, 85.94658, 86.95268, 87.95691, 88.96379, 89.96863 ] - }, - { - "symbol": "As", - "name": "Arsenic", - "weight": 74.921595, - "isotopes": [ 59.99388, 60.98112, 61.97361, 62.9639, 63.95743, 64.949611, 65.9441488, 66.93925111, 67.9367741, 68.932246, 69.930926, 70.9271138, 71.9267523, 72.9238291, 73.9239286, 74.92159457, 75.92239202, 76.9206476, 77.921828, 78.9209484, 79.9224746, 80.9221323, 81.9247412, 82.9252069, 83.9293033, 84.9321637, 85.9367015, 86.9402917, 87.94555, 88.94976, 89.95563, 90.96039, 91.96674 ] - }, - { - "symbol": "Se", - "name": "Selenium", - "weight": 78.971, - "isotopes": [ 63.97109, 64.9644, 65.95559, 66.949994, 67.94182524, 68.9394148, 69.9335155, 70.9322094, 71.9271405, 72.9267549, 73.922475934, 74.92252287, 75.919213704, 76.919914154, 77.91730928, 78.91849929, 79.9165218, 80.917993, 81.9166995, 82.9191186, 83.9184668, 84.9222608, 85.9243117, 86.9286886, 87.9314175, 88.9366691, 89.9401, 90.94596, 91.94984, 92.95629, 93.96049, 94.9673 ] - }, - { - "symbol": "Br", - "name": "Bromine", - "weight": 79.904, - "isotopes": [ 66.96465, 67.95873, 68.950497, 69.944792, 70.9393422, 71.9365886, 72.9316715, 73.9299102, 74.9258105, 75.924542, 76.9213792, 77.9211459, 78.9183376, 79.9185298, 80.9162897, 81.9168032, 82.9151756, 83.916496, 84.9156458, 85.9188054, 86.920674, 87.9240833, 88.9267046, 89.9312928, 90.9343986, 91.9396316, 92.94313, 93.9489, 94.95301, 95.95903, 96.96344, 97.96946 ] - }, - { - "symbol": "Kr", - "name": "Krypton", - "weight": 83.798, - "isotopes": [ 68.96518, 69.95604, 70.95027, 71.9420924, 72.9392892, 73.933084, 74.9309457, 75.9259103, 76.92467, 77.92036494, 78.9200829, 79.91637808, 80.9165912, 81.91348273, 82.91412716, 83.9114977282, 84.9125273, 85.9106106269, 86.91335476, 87.9144479, 88.9178355, 89.9195279, 90.9238063, 91.9261731, 92.9311472, 93.93414, 94.939711, 95.943017, 96.94909, 97.95243, 98.95839, 99.96237, 100.96873 ] - }, - { - "symbol": "Rb", - "name": "Rubidium", - "weight": 85.4678, - "isotopes": [ 70.96532, 71.95908, 72.95053, 73.9442659, 74.9385732, 75.935073, 76.9304016, 77.9281419, 78.9239899, 79.9225164, 80.9189939, 81.918209, 82.9151142, 83.9143752, 84.9117897379, 85.91116743, 86.909180531, 87.91131559, 88.9122783, 89.9147985, 90.9165372, 91.9197284, 92.9220393, 93.9263948, 94.92926, 95.9341334, 96.9371771, 97.9416869, 98.94503, 99.95003, 100.95404, 101.95952, 102.96392 ] - }, - { - "symbol": "Sr", - "name": "Strontium", - "weight": 87.62, - "isotopes": [ 72.9657, 73.95617, 74.94995, 75.941763, 76.9379455, 77.93218, 78.9297077, 79.9245175, 80.9232114, 81.9183999, 82.9175544, 83.9134191, 84.912932, 85.9092606, 86.9088775, 87.9056125, 88.9074511, 89.90773, 90.9101954, 91.9110382, 92.9140242, 93.9153556, 94.9193529, 95.9217066, 96.926374, 97.9286888, 98.9328907, 99.93577, 100.940352, 101.943791, 102.94909, 103.95265, 104.95855, 105.96265, 106.96897 ] - }, - { - "symbol": "Y", - "name": "Yttrium", - "weight": 88.90584, - "isotopes": [ 75.95856, 76.949781, 77.94361, 78.93735, 79.9343561, 80.9294556, 81.9269314, 82.922485, 83.9206721, 84.916433, 85.914886, 86.9108761, 87.9095016, 88.9058403, 89.9071439, 90.9072974, 91.9089451, 92.909578, 93.9115906, 94.9128161, 95.9158968, 96.9182741, 97.9223821, 98.924148, 99.927715, 100.9301477, 101.9343277, 102.937243, 103.94196, 104.94544, 105.95056, 106.95452, 107.95996, 108.96436 ] - }, - { - "symbol": "Zr", - "name": "Zirconium", - "weight": 91.224, - "isotopes": [ 77.95566, 78.94948, 79.9404, 80.93731, 81.93135, 82.9292421, 83.9233269, 84.9214444, 85.9162972, 86.914818, 87.9102213, 88.9088814, 89.9046977, 90.9056396, 91.9050347, 92.9064699, 93.9063108, 94.9080385, 95.9082714, 96.9109512, 97.9127289, 98.916667, 99.9180006, 100.921448, 101.9231409, 102.927191, 103.929436, 104.934008, 105.93676, 106.94174, 107.94487, 108.95041, 109.95396, 110.95968, 111.9637 ] - }, - { - "symbol": "Nb", - "name": "Niobium", - "weight": 92.90637, - "isotopes": [ 80.9496, 81.94396, 82.93729, 83.93449, 84.9288458, 85.9257828, 86.9206937, 87.918222, 88.913445, 89.9112584, 90.9069897, 91.9071881, 92.906373, 93.9072788, 94.9068324, 95.9080973, 96.9080959, 97.9103265, 98.911613, 99.9143276, 100.9153103, 101.9180772, 102.9194572, 103.9228925, 104.9249465, 105.9289317, 106.9315937, 107.9360748, 108.93922, 109.94403, 110.94753, 111.95247, 112.95651, 113.96201, 114.96634 ] - }, - { - "symbol": "Mo", - "name": "Molybdenum", - "weight": 95.95, - "isotopes": [ 82.94988, 83.94149, 84.938261, 85.9311748, 86.9281962, 87.9219678, 88.9194682, 89.9139309, 90.9117453, 91.90680796, 92.90680958, 93.9050849, 94.90583877, 95.90467612, 96.90601812, 97.90540482, 98.90770851, 99.9074718, 100.9103414, 101.9102834, 102.913079, 103.9137344, 104.916969, 105.918259, 106.922106, 107.924033, 108.928424, 109.930704, 110.935654, 111.93831, 112.94335, 113.94653, 114.95196, 115.95545, 116.96117 ] - }, - { - "symbol": "Tc", - "name": "Technetium", - "weight": 98, - "isotopes": [ 84.95058, 85.94493, 86.9380672, 87.93378, 88.9276487, 89.9240739, 90.9184254, 91.9152698, 92.910246, 93.9096536, 94.9076536, 95.907868, 96.9063667, 97.9072124, 98.9062508, 99.9076539, 100.907309, 101.9092097, 102.909176, 103.911425, 104.911655, 105.914358, 106.9154606, 107.9184957, 108.920256, 109.923744, 110.925901, 111.9299458, 112.932569, 113.93691, 114.93998, 115.94476, 116.94806, 117.95299, 118.95666, 119.96187 ] - }, - { - "symbol": "Ru", - "name": "Ruthenium", - "weight": 101.07, - "isotopes": [ 86.95069, 87.9416, 88.93762, 89.9303444, 90.9267419, 91.9202344, 92.9171044, 93.9113429, 94.910406, 95.90759025, 96.9075471, 97.9052868, 98.9059341, 99.9042143, 100.9055769, 101.9043441, 102.9063186, 103.9054275, 104.9077476, 105.9073291, 106.909972, 107.910188, 108.913326, 109.9140407, 110.91757, 111.918809, 112.922844, 113.9246136, 114.92882, 115.9312192, 116.9361, 117.93853, 118.94357, 119.94631, 120.95164, 121.95447, 122.95989, 123.96305 ] - }, - { - "symbol": "Rh", - "name": "Rhodium", - "weight": 102.90549, - "isotopes": [ 88.95058, 89.94422, 90.93688, 91.9323677, 92.9259128, 93.9217305, 94.9158979, 95.914453, 96.911329, 97.910708, 98.9081282, 99.908117, 100.9061606, 101.9068374, 102.905498, 103.9066492, 104.9056885, 105.9072868, 106.906748, 107.908714, 108.9087488, 109.911079, 110.9116423, 111.914403, 112.9154393, 113.918718, 114.9203116, 115.924059, 116.9260354, 117.93034, 118.932557, 119.93686, 120.93942, 121.94399, 122.94685, 123.95151, 124.95469, 125.95946 ] - }, - { - "symbol": "Pd", - "name": "Palladium", - "weight": 106.42, - "isotopes": [ 90.95032, 91.94088, 92.93651, 93.9290376, 94.9248898, 95.9182151, 96.916472, 97.9126983, 98.9117748, 99.908505, 100.9082864, 101.9056022, 102.9060809, 103.9040305, 104.9050796, 105.9034804, 106.9051282, 107.9038916, 108.9059504, 109.9051722, 110.90768968, 111.9073297, 112.910261, 113.9103686, 114.913659, 115.914297, 116.9179547, 117.9190667, 118.9233402, 119.9245511, 120.9289503, 121.930632, 122.93514, 123.93714, 124.94179, 125.94416, 126.94907, 127.95183 ] - }, - { - "symbol": "Ag", - "name": "Silver", - "weight": 107.8682, - "isotopes": [ 92.95033, 93.94373, 94.93602, 95.930744, 96.92397, 97.92156, 98.9176458, 99.9161154, 100.912684, 101.9117047, 102.9089631, 103.9086239, 104.9065256, 105.9066636, 106.9050916, 107.9059503, 108.9047553, 109.9061102, 110.9052959, 111.9070486, 112.906573, 113.908823, 114.908767, 115.9113868, 116.911774, 117.9145955, 118.91557, 119.9187848, 120.920125, 121.923664, 122.925337, 123.92893, 124.93105, 125.93475, 126.93711, 127.94106, 128.94395, 129.9507 ] - }, - { - "symbol": "Cd", - "name": "Cadmium", - "weight": 112.414, - "isotopes": [ 94.94994, 95.94034, 96.9351, 97.927389, 98.9249258, 99.9203488, 100.9185862, 101.914482, 102.9134165, 103.9098564, 104.9094639, 105.9064599, 106.9066121, 107.9041834, 108.9049867, 109.90300661, 110.90418287, 111.90276287, 112.90440813, 113.90336509, 114.90543751, 115.90476315, 116.907226, 117.906922, 118.909847, 119.9098681, 120.9129637, 121.9134591, 122.9168925, 123.9176574, 124.9212576, 125.9224291, 126.926472, 127.9278129, 128.93182, 129.93394, 130.9406, 131.94604, 132.95285 ] - }, - { - "symbol": "In", - "name": "Indium", - "weight": 114.818, - "isotopes": [ 96.94934, 97.94214, 98.93411, 99.93096, 100.92634, 101.9241071, 102.9198819, 103.9182145, 104.914502, 105.913464, 106.91029, 107.9096935, 108.9071514, 109.90717, 110.9051085, 111.9055377, 112.90406184, 113.90491791, 114.903878776, 115.90525999, 116.9045157, 117.9063566, 118.9058507, 119.907967, 120.907851, 121.910281, 122.910434, 123.913182, 124.913605, 125.916507, 126.917446, 127.9204, 128.9218053, 129.924977, 130.9269715, 131.933001, 132.93831, 133.94454, 134.95005 ] - }, - { - "symbol": "Sn", - "name": "Tin", - "weight": 118.71, - "isotopes": [ 98.94853, 99.9385, 100.93526, 101.93029, 102.928105, 103.9231052, 104.9212684, 105.9169574, 106.9157137, 107.9118943, 108.9112921, 109.907845, 110.9077401, 111.90482387, 112.9051757, 113.9027827, 114.903344699, 115.9017428, 116.90295398, 117.90160657, 118.90331117, 119.90220163, 120.9042426, 121.9034438, 122.9057252, 123.9052766, 124.9077864, 125.907659, 126.91039, 127.910507, 128.913465, 129.9139738, 130.917045, 131.9178267, 132.9239134, 133.9286821, 134.9349086, 135.93999, 136.94655, 137.95184 ] - }, - { - "symbol": "Sb", - "name": "Antimony", - "weight": 121.76, - "isotopes": [ 102.93969, 103.93648, 104.931276, 105.928638, 106.9241506, 107.9222267, 108.9181411, 109.9168543, 110.9132182, 111.9124, 112.909375, 113.90929, 114.906598, 115.9067931, 116.9048415, 117.9055321, 118.9039455, 119.9050794, 120.903812, 121.9051699, 122.9042132, 123.905935, 124.905253, 125.907253, 126.9069243, 127.909146, 128.909147, 129.911662, 130.9119888, 131.9145077, 132.9152732, 133.9205357, 134.9251851, 135.9307459, 136.93555, 137.94145, 138.94655, 139.95283 ] - }, - { - "symbol": "Te", - "name": "Tellurium", - "weight": 127.6, - "isotopes": [ 104.9433, 105.9375, 106.935012, 107.9293805, 108.9273045, 109.9224581, 110.9210006, 111.9167279, 112.915891, 113.912089, 114.911902, 115.90846, 116.908646, 117.905854, 118.9064071, 119.9040593, 120.904944, 121.9030435, 122.9042698, 123.9028171, 124.9044299, 125.9033109, 126.9052257, 127.90446128, 128.90659646, 129.906222748, 130.908522213, 131.9085467, 132.9109688, 133.911394, 134.9165557, 135.9201006, 136.9255989, 137.9294722, 138.9353672, 139.939499, 140.9458, 141.95022, 142.95676 ] - }, - { - "symbol": "I", - "name": "Iodine", - "weight": 126.90447, - "isotopes": [ 106.94678, 107.94348, 108.9380853, 109.935089, 110.9302692, 111.928005, 112.9236501, 113.92185, 114.918048, 115.91681, 116.913648, 117.913074, 118.910074, 119.910087, 120.9074051, 121.9075888, 122.9055885, 123.906209, 124.9046294, 125.9056233, 126.9044719, 127.9058086, 128.9049837, 129.9066702, 130.9061263, 131.9079935, 132.907797, 133.9097588, 134.9100488, 135.914604, 136.9180282, 137.9227264, 138.926506, 139.93173, 140.93569, 141.9412, 142.94565, 143.95139, 144.95605 ] - }, - { - "symbol": "Xe", - "name": "Xenon", - "weight": 131.293, - "isotopes": [ 108.95043, 109.94426, 110.941607, 111.935559, 112.9332217, 113.92798, 114.926294, 115.921581, 116.920359, 117.916179, 118.915411, 119.911784, 120.911453, 121.908368, 122.908482, 123.905892, 124.9063944, 125.9042983, 126.9051829, 127.903531, 128.9047808611, 129.903509349, 130.90508406, 131.9041550856, 132.9059108, 133.90539466, 134.9072278, 135.907214484, 136.91155778, 137.9141463, 138.9187922, 139.9216458, 140.9267872, 141.9299731, 142.9353696, 143.9389451, 144.94472, 145.948518, 146.95426, 147.95813 ] - }, - { - "symbol": "Cs", - "name": "Caesium", - "weight": 132.90545196, - "isotopes": [ 111.950309, 112.9444291, 113.941296, 114.93591, 115.93337, 116.928617, 117.92656, 118.922377, 119.920677, 120.917227, 121.916108, 122.912996, 123.9122578, 124.909728, 125.909446, 126.9074174, 127.9077487, 128.9060657, 129.9067093, 130.9054649, 131.9064339, 132.905451961, 133.906718503, 134.905977, 135.9073114, 136.90708923, 137.9110171, 138.9133638, 139.9172831, 140.9200455, 141.924296, 142.927349, 143.932076, 144.935527, 145.940344, 146.944156, 147.94923, 148.95302, 149.95833, 150.96258 ] - }, - { - "symbol": "Ba", - "name": "Barium", - "weight": 137.327, - "isotopes": [ 113.95066, 114.94737, 115.94128, 116.93814, 117.93306, 118.93066, 119.92605, 120.92405, 121.919904, 122.918781, 123.915094, 124.914472, 125.91125, 126.911091, 127.908342, 128.908681, 129.9063207, 130.906941, 131.9050611, 132.9060074, 133.90450818, 134.90568838, 135.90457573, 136.90582714, 137.905247, 138.9088411, 139.9106057, 140.9144033, 141.9164324, 142.9206253, 143.9229549, 144.9275184, 145.930284, 146.935304, 147.938171, 148.94308, 149.94605, 150.95127, 151.95481, 152.96036 ] - }, - { - "symbol": "La", - "name": "Lanthanum", - "weight": 138.90547, - "isotopes": [ 115.9563, 116.94999, 117.94673, 118.94099, 119.93807, 120.93315, 121.93071, 122.9263, 123.924574, 124.920816, 125.919513, 126.916375, 127.915592, 128.912694, 129.912369, 130.91007, 131.910119, 132.908218, 133.908514, 134.906984, 135.907635, 136.9064504, 137.9071149, 138.9063563, 139.9094806, 140.910966, 141.9140909, 142.9160795, 143.919646, 144.921808, 145.925875, 146.928418, 147.932679, 148.93535, 149.93947, 150.94232, 151.94682, 152.95036, 153.95517, 154.95901 ] - }, - { - "symbol": "Ce", - "name": "Cerium", - "weight": 140.116, - "isotopes": [ 118.95271, 119.94654, 120.94335, 121.93787, 122.93528, 123.93031, 124.92844, 125.923971, 126.922727, 127.918911, 128.918102, 129.914736, 130.914429, 131.911464, 132.91152, 133.908928, 134.909161, 135.90712921, 136.90776236, 137.905991, 138.9066551, 139.9054431, 140.9082807, 141.9092504, 142.9123921, 143.9136529, 144.917265, 145.918802, 146.9226899, 147.924424, 148.928427, 149.930384, 150.934272, 151.9366, 152.94093, 153.9438, 154.94855, 155.95183, 156.95705 ] - }, - { - "symbol": "Pr", - "name": "Praseodymium", - "weight": 140.90766, - "isotopes": [ 120.95532, 121.95175, 122.94596, 123.94294, 124.9377, 125.93524, 126.93071, 127.928791, 128.925095, 129.92359, 130.920235, 131.919255, 132.916331, 133.915697, 134.913112, 135.912677, 136.9106792, 137.910754, 138.9089408, 139.9090803, 140.9076576, 141.9100496, 142.9108228, 143.9133109, 144.9145182, 145.91768, 146.919008, 147.92213, 148.923736, 149.9266765, 150.928309, 151.931553, 152.933904, 153.93753, 154.940509, 155.94464, 156.94789, 157.95241, 158.95589 ] - }, - { - "symbol": "Nd", - "name": "Neodymium", - "weight": 144.242, - "isotopes": [ 123.9522, 124.9489, 125.94311, 126.94038, 127.93525, 128.9331, 129.928506, 130.927248, 131.923321, 132.922348, 133.91879, 134.918181, 135.914976, 136.914562, 137.91195, 138.911954, 139.90955, 140.9096147, 141.907729, 142.90982, 143.910093, 144.9125793, 145.9131226, 146.9161061, 147.9168993, 148.9201548, 149.9209022, 150.9238403, 151.924692, 152.927718, 153.92948, 154.9331357, 155.93508, 156.939386, 157.94197, 158.94653, 159.9494, 160.95428 ] - }, - { - "symbol": "Pm", - "name": "Promethium", - "weight": 145, - "isotopes": [ 125.95792, 126.95192, 127.9487, 128.94323, 129.94053, 130.93567, 131.93384, 132.929782, 133.928353, 134.924823, 135.923585, 136.92048, 137.919548, 138.9168, 139.91604, 140.913555, 141.91289, 142.9109383, 143.9125964, 144.9127559, 145.9147024, 146.915145, 147.9174819, 148.9183423, 149.920991, 150.9212175, 151.923506, 152.9241567, 153.926472, 154.928137, 155.9311175, 156.9331214, 157.936565, 158.939287, 159.9431, 160.94607, 161.95022, 162.95357 ] - }, - { - "symbol": "Sm", - "name": "Samarium", - "weight": 150.36, - "isotopes": [ 127.95842, 128.95476, 129.949, 130.94618, 131.94087, 132.93856, 133.93411, 134.93252, 135.928276, 136.926971, 137.923244, 138.922297, 139.918995, 140.9184816, 141.9152044, 142.9146353, 143.9120065, 144.9134173, 145.913047, 146.9149044, 147.9148292, 148.9171921, 149.9172829, 150.9199398, 151.9197397, 152.9221047, 153.9222169, 154.9246477, 155.925536, 156.9284187, 157.929951, 158.9332172, 159.9353353, 160.9391602, 161.94146, 162.94555, 163.94836, 164.95297 ] - }, - { - "symbol": "Eu", - "name": "Europium", - "weight": 151.964, - "isotopes": [ 129.96369, 130.95784, 131.95467, 132.94929, 133.9464, 134.94187, 135.93962, 136.93546, 137.933709, 138.929792, 139.928088, 140.924932, 141.923442, 142.920299, 143.91882, 144.9162726, 145.917211, 146.9167527, 147.918089, 148.9179378, 149.9197077, 150.9198578, 151.9217522, 152.921238, 153.922987, 154.9229011, 155.9247605, 156.9254334, 157.927799, 158.9291001, 159.931851, 160.933664, 161.936989, 162.939196, 163.94274, 164.94559, 165.94962, 166.95289 ] - }, - { - "symbol": "Gd", - "name": "Gadolinium", - "weight": 157.25, - "isotopes": [ 132.96133, 133.95566, 134.95245, 135.9473, 136.94502, 137.94025, 138.93813, 139.933674, 140.932126, 141.928116, 142.92675, 143.922963, 144.921713, 145.9183188, 146.9191014, 147.9181215, 148.9193481, 149.9186644, 150.920356, 151.9197995, 152.921758, 153.9208741, 154.9226305, 155.9221312, 156.9239686, 157.9241123, 158.926397, 159.9270624, 160.9296775, 161.930993, 162.9341769, 163.93583, 164.93936, 165.94146, 166.94545, 167.94808, 168.9526 ] - }, - { - "symbol": "Tb", - "name": "Terbium", - "weight": 158.925354, - "isotopes": [ 134.96476, 135.96129, 136.95602, 137.95312, 138.94833, 139.94581, 140.94145, 141.93928, 142.935137, 143.933045, 144.92882, 145.927253, 146.9240548, 147.924282, 148.9232535, 149.9236649, 150.9231096, 151.924083, 152.9234424, 153.924685, 154.923511, 155.9247552, 156.924033, 157.9254209, 158.9253547, 159.9271756, 160.9275778, 161.929495, 162.9306547, 163.93336, 164.93498, 165.93786, 166.93996, 167.9434, 168.94597, 169.94984, 170.95273 ] - }, - { - "symbol": "Dy", - "name": "Dysprosium", - "weight": 162.5, - "isotopes": [ 137.9625, 138.95959, 139.95402, 140.95128, 141.94619, 142.943994, 143.9392695, 144.937474, 145.9328445, 146.9310827, 147.927157, 148.927322, 149.9255933, 150.9261916, 151.9247253, 152.9257724, 153.9244293, 154.925759, 155.9242847, 156.9254707, 157.9244159, 158.925747, 159.9252046, 160.9269405, 161.9268056, 162.9287383, 163.9291819, 164.9317105, 165.9328139, 166.935661, 167.93713, 168.94031, 169.94239, 170.94612, 171.94846, 172.95283 ] - }, - { - "symbol": "Ho", - "name": "Holmium", - "weight": 164.930328, - "isotopes": [ 139.96859, 140.96311, 141.96001, 142.95486, 143.9521097, 144.9472674, 145.9449935, 146.9401423, 147.937744, 148.933803, 149.933498, 150.9316983, 151.931724, 152.9302064, 153.9306068, 154.929104, 155.929706, 156.928254, 157.928946, 158.9277197, 159.928737, 160.9278615, 161.9291023, 162.928741, 163.9302403, 164.9303288, 165.9322909, 166.9331385, 167.935522, 168.936878, 169.939625, 170.94147, 171.94473, 172.94702, 173.95095, 174.95362 ] - }, - { - "symbol": "Er", - "name": "Erbium", - "weight": 167.259, - "isotopes": [ 141.9701, 142.96662, 143.9607, 144.95805, 145.9524184, 146.949964, 147.944735, 148.942306, 149.937916, 150.937449, 151.935057, 152.93508, 153.9327908, 154.9332159, 155.931067, 156.931949, 157.929893, 158.9306918, 159.929077, 160.9300046, 161.9287884, 162.9300408, 163.9292088, 164.9307345, 165.9302995, 166.9320546, 167.9323767, 168.9345968, 169.9354702, 170.9380357, 171.9393619, 172.9424, 173.94423, 174.94777, 175.94994, 176.95399 ] - }, - { - "symbol": "Tm", - "name": "Thulium", - "weight": 168.934218, - "isotopes": [ 143.97628, 144.97039, 145.96684, 146.9613799, 147.958384, 148.95289, 149.95009, 150.945488, 151.944422, 152.94204, 153.94157, 154.93921, 155.938992, 156.936944, 157.93698, 158.934975, 159.935263, 160.933549, 161.934002, 162.9326592, 163.933544, 164.9324431, 165.933561, 166.9328562, 167.9341774, 168.9342179, 169.935806, 170.9364339, 171.9384055, 172.9396084, 173.942173, 174.943841, 175.947, 176.94904, 177.95264, 178.95534 ] - }, - { - "symbol": "Yb", - "name": "Ytterbium", - "weight": 173.045, - "isotopes": [ 147.96758, 148.96436, 149.95852, 150.9554, 151.95027, 152.94932, 153.946396, 154.945783, 155.942825, 156.942645, 157.9398705, 158.940055, 159.937557, 160.937907, 161.935774, 162.93634, 163.934495, 164.93527, 165.9338747, 166.934953, 167.9338896, 168.9351825, 169.9347664, 170.9363302, 171.9363859, 172.9382151, 173.9388664, 174.9412808, 175.9425764, 176.9452656, 177.946651, 178.95004, 179.95212, 180.95589 ] - }, - { - "symbol": "Lu", - "name": "Lutetium", - "weight": 174.9668, - "isotopes": [ 149.97355, 150.96768, 151.96412, 152.95875, 153.95736, 154.954321, 155.953033, 156.950127, 157.949316, 158.946636, 159.946033, 160.943572, 161.943283, 162.941179, 163.941339, 164.939407, 165.939859, 166.93827, 167.938736, 168.9376441, 169.938478, 170.937917, 171.9390891, 172.938934, 173.9403409, 174.9407752, 175.9426897, 176.9437615, 177.945958, 178.9473309, 179.949888, 180.95191, 181.95504, 182.957363, 183.96091, 184.96362 ] - }, - { - "symbol": "Hf", - "name": "Hafnium", - "weight": 178.49, - "isotopes": [ 152.97069, 153.96486, 154.96311, 155.95935, 156.95824, 157.954801, 158.953996, 159.950691, 160.950278, 161.9472148, 162.947113, 163.944371, 164.944567, 165.94218, 166.9426, 167.940568, 168.941259, 169.939609, 170.940492, 171.93945, 172.940513, 173.9400461, 174.9415092, 175.9414076, 176.9432277, 177.9437058, 178.9458232, 179.946557, 180.9491083, 181.9505612, 182.95353, 183.955446, 184.958862, 185.960897, 186.96477, 187.96685, 188.97084 ] - }, - { - "symbol": "Ta", - "name": "Tantalum", - "weight": 180.94788, - "isotopes": [ 154.97424, 155.97203, 156.96818, 157.96654, 158.963023, 159.961488, 160.958452, 161.957294, 162.954337, 163.953534, 164.950781, 165.950512, 166.948093, 167.948047, 168.946011, 169.946175, 170.944476, 171.944895, 172.94375, 173.944454, 174.943737, 175.944857, 176.9444795, 177.945678, 178.9459366, 179.9474648, 180.9479958, 181.9501519, 182.9513726, 183.954008, 184.955559, 185.958551, 186.960386, 187.963916, 188.96583, 189.96939, 190.97156, 191.97514 ] - }, - { - "symbol": "W", - "name": "Tungsten", - "weight": 183.84, - "isotopes": [ 156.97884, 157.97456, 158.97264, 159.96846, 160.9672, 161.963499, 162.962524, 163.958961, 164.958281, 165.955031, 166.954805, 167.951806, 168.951779, 169.949232, 170.949451, 171.947292, 172.947689, 173.946079, 174.946717, 175.945634, 176.946643, 177.945883, 178.947077, 179.9467108, 180.9481978, 181.94820394, 182.95022275, 183.95093092, 184.95341897, 185.9543628, 186.9571588, 187.9584862, 188.961763, 189.963091, 190.966531, 191.96817, 192.97178, 193.97367 ] - }, - { - "symbol": "Re", - "name": "Rhenium", - "weight": 186.207, - "isotopes": [ 158.98418, 159.98182, 160.97757, 161.97584, 162.97208, 163.970453, 164.967103, 165.965761, 166.962595, 167.961573, 168.958766, 169.95822, 170.955716, 171.95542, 172.953243, 173.953115, 174.951381, 175.951623, 176.950328, 177.950989, 178.949989, 179.950792, 180.950058, 181.95121, 182.9508196, 183.9525228, 184.9529545, 185.9549856, 186.9557501, 187.9581115, 188.959226, 189.961744, 190.963122, 191.966088, 192.967541, 193.97076, 194.97254, 195.9758, 196.97799, 197.9816 ] - }, - { - "symbol": "Os", - "name": "Osmium", - "weight": 190.23, - "isotopes": [ 160.98903, 161.98443, 162.98241, 163.97802, 164.9766, 165.972692, 166.971549, 167.967808, 168.967018, 169.963578, 170.963174, 171.960017, 172.959808, 173.957064, 174.956945, 175.954806, 176.954966, 177.953254, 178.953817, 179.952375, 180.953247, 181.95211, 182.953125, 183.9524885, 184.9540417, 185.953835, 186.9557474, 187.9558352, 188.9581442, 189.9584437, 190.9609264, 191.961477, 192.9641479, 193.9651772, 194.968318, 195.969641, 196.97283, 197.97441, 198.97801, 199.97984, 200.98364, 201.98595 ] - }, - { - "symbol": "Ir", - "name": "Iridium", - "weight": 192.217, - "isotopes": [ 163.99191, 164.9875, 165.98566, 166.981666, 167.979907, 168.976298, 169.974922, 170.97164, 171.970607, 172.967506, 173.966861, 174.96415, 175.96365, 176.961301, 177.961082, 178.95912, 179.959229, 180.957625, 181.958076, 182.95684, 183.957476, 184.956698, 185.957944, 186.957542, 187.958828, 188.958715, 189.9605412, 190.9605893, 191.9626002, 192.9629216, 193.9650735, 194.9659747, 195.968397, 196.969655, 197.97228, 198.973805, 199.9768, 200.97864, 201.98199, 202.98423, 203.9896 ] - }, - { - "symbol": "Pt", - "name": "Platinum", - "weight": 195.084, - "isotopes": [ 165.99486, 166.99269, 167.98813, 168.98657, 169.982496, 170.981245, 171.977351, 172.976443, 173.97282, 174.97241, 175.968938, 176.96847, 177.96565, 178.965359, 179.963032, 180.963098, 181.961172, 182.961597, 183.959915, 184.960614, 185.959351, 186.960617, 187.9593889, 188.960831, 189.9599297, 190.9616729, 191.9610387, 192.9629824, 193.9626809, 194.9647917, 195.96495209, 196.96734069, 197.9678949, 198.9705952, 199.971443, 200.974513, 201.975639, 202.97893, 203.98076, 204.98608, 205.98966 ] - }, - { - "symbol": "Au", - "name": "Gold", - "weight": 196.96657, - "isotopes": [ 168.99808, 169.99597, 170.991876, 171.989942, 172.986241, 173.984717, 174.981304, 175.98025, 176.97687, 177.976032, 178.973174, 179.972523, 180.970079, 181.969618, 182.967591, 183.967452, 184.96579, 185.965953, 186.964543, 187.965349, 188.963948, 189.964698, 190.963702, 191.964814, 192.9641373, 193.9654178, 194.9650352, 195.9665699, 196.96656879, 197.96824242, 198.96876528, 199.970756, 200.9716575, 201.973856, 202.9751544, 203.97783, 204.97985, 205.98474, 206.9884, 207.99345, 208.99735, 210.0025 ] - }, - { - "symbol": "Hg", - "name": "Mercury", - "weight": 200.592, - "isotopes": [ 171.00353, 171.99881, 172.99709, 173.992865, 174.991441, 175.987361, 176.986277, 177.982484, 178.981831, 179.97826, 180.977819, 181.974689, 182.9744448, 183.971714, 184.971899, 185.969362, 186.969814, 187.967567, 188.968195, 189.966323, 190.967157, 191.965635, 192.966653, 193.9654491, 194.966721, 195.9658326, 196.9672128, 197.9667686, 198.96828064, 199.96832659, 200.97030284, 201.9706434, 202.9728728, 203.97349398, 204.9760734, 205.977514, 206.9823, 207.985759, 208.99072, 209.99424, 210.99933, 212.00296, 213.00823, 214.012, 215.0174, 216.02132 ] - }, - { - "symbol": "Tl", - "name": "Thallium", - "weight": 204.38, - "isotopes": [ 176.000624, 176.996431, 177.99485, 178.991111, 179.990057, 180.98626, 181.985713, 182.982193, 183.981886, 184.978789, 185.978651, 186.9759063, 187.976021, 188.973588, 189.973828, 190.9717842, 191.972225, 192.970502, 193.971081, 194.969774, 195.970481, 196.969576, 197.970483, 198.969877, 199.9709633, 200.970822, 201.972102, 202.9723446, 203.9738639, 204.9744278, 205.9761106, 206.9774197, 207.982019, 208.9853594, 209.990074, 210.993475, 211.99834, 213.001915, 214.00694, 215.01064, 216.0158, 217.01966, 218.02479 ] - }, - { - "symbol": "Pb", - "name": "Lead", - "weight": 207.2, - "isotopes": [ 178.003831, 179.002201, 179.997928, 180.996653, 181.992672, 182.991872, 183.988136, 184.98761, 185.984238, 186.9839109, 187.980875, 188.980807, 189.978082, 190.978276, 191.975775, 192.976173, 193.974012, 194.974543, 195.972774, 196.9734312, 197.972034, 198.972913, 199.971819, 200.972883, 201.972152, 202.9733911, 203.973044, 204.9744822, 205.9744657, 206.9758973, 207.9766525, 208.9810905, 209.9841889, 210.9887371, 211.9918977, 212.9965629, 213.9998059, 215.00474, 216.00803, 217.01314, 218.01659, 219.02177, 220.02541 ] - }, - { - "symbol": "Bi", - "name": "Bismuth", - "weight": 208.9804, - "isotopes": [ 184.001275, 184.9976, 185.996644, 186.993147, 187.992287, 188.989195, 189.988622, 190.9857866, 191.985469, 192.98296, 193.982785, 194.9806488, 195.980667, 196.9788651, 197.979206, 198.977673, 199.978131, 200.97701, 201.977734, 202.976893, 203.9778361, 204.9773867, 205.9784993, 206.978471, 207.9797425, 208.9803991, 209.9841207, 210.9872697, 211.991286, 212.9943851, 213.998712, 215.00177, 216.006306, 217.009372, 218.014188, 219.01748, 220.02235, 221.02587, 222.03078, 223.0345, 224.03947 ] - }, - { - "symbol": "Po", - "name": "Polonium", - "weight": 209, - "isotopes": [ 186.004393, 187.003041, 187.999416, 188.998473, 189.995101, 190.9945585, 191.991336, 192.991026, 193.988186, 194.988126, 195.985526, 196.98566, 197.983389, 198.983667, 199.981799, 200.9822598, 201.980758, 202.9814161, 203.98031, 204.981203, 205.980474, 206.9815938, 207.9812461, 208.9824308, 209.9828741, 210.9866536, 211.9888684, 212.9928576, 213.9952017, 214.9994201, 216.0019152, 217.0063182, 218.0089735, 219.013614, 220.016386, 221.021228, 222.02414, 223.02907, 224.03211, 225.03707, 226.04031, 227.04539 ] - }, - { - "symbol": "At", - "name": "Astatine", - "weight": 210, - "isotopes": [ 191.004148, 192.003152, 192.999927, 193.999236, 194.9962685, 195.9958, 196.993189, 197.992784, 198.9905277, 199.990351, 200.9884171, 201.98863, 202.986943, 203.987251, 204.986076, 205.986657, 206.9858, 207.9866133, 208.9861702, 209.9871479, 210.9874966, 211.9907377, 212.992937, 213.9963721, 214.9986528, 216.0024236, 217.0047192, 218.008695, 219.0111618, 220.015433, 221.018017, 222.022494, 223.025151, 224.029749, 225.03263, 226.03716, 227.04024, 228.04475, 229.04812 ] - }, - { - "symbol": "Rn", - "name": "Radon", - "weight": 222, - "isotopes": [ 193.009708, 194.006144, 195.005422, 196.002116, 197.001585, 197.998679, 198.99839, 199.99569, 200.995628, 201.993264, 202.993388, 203.99143, 204.991719, 205.990214, 206.9907303, 207.989635, 208.990415, 209.9896891, 210.9906011, 211.9907039, 212.9938831, 213.995363, 214.9987459, 216.0002719, 217.003928, 218.0056016, 219.0094804, 220.0113941, 221.0155371, 222.0175782, 223.0218893, 224.024096, 225.028486, 226.030861, 227.035304, 228.037835, 229.042257, 230.04514, 231.04987 ] - }, - { - "symbol": "Fr", - "name": "Francium", - "weight": 223, - "isotopes": [ 199.007259, 200.006586, 201.003867, 202.00332, 203.0009407, 204.000652, 204.9985939, 205.998666, 206.996946, 207.997138, 208.995955, 209.996422, 210.995556, 211.9962257, 212.996186, 213.9989713, 215.0003418, 216.0031899, 217.0046323, 218.0075787, 219.0092524, 220.0123277, 221.0142552, 222.017552, 223.019736, 224.023398, 225.025573, 226.029566, 227.031869, 228.035823, 229.038298, 230.042416, 231.045158, 232.04937, 233.05264 ] - }, - { - "symbol": "Ra", - "name": "Radium", - "weight": 226, - "isotopes": [ 201.01271, 202.00976, 203.009304, 204.006492, 205.006268, 206.003828, 207.003799, 208.001841, 209.00199, 210.000494, 211.0008932, 211.999787, 213.000384, 214.0000997, 215.0027204, 216.0035334, 217.0063207, 218.007141, 219.0100855, 220.0110259, 221.0139177, 222.0153748, 223.0185023, 224.020212, 225.0236119, 226.0254103, 227.0291783, 228.0310707, 229.034942, 230.037055, 231.041027, 232.0434753, 233.047582, 234.050342, 235.05497 ] - }, - { - "symbol": "Ac", - "name": "Actinium", - "weight": 227, - "isotopes": [ 206.014452, 207.011966, 208.01155, 209.009495, 210.009436, 211.007732, 212.007813, 213.006609, 214.006918, 215.006475, 216.008743, 217.009344, 218.011642, 219.012421, 220.0147549, 221.015592, 222.0178442, 223.0191377, 224.0217232, 225.02323, 226.0260984, 227.0277523, 228.0310215, 229.032956, 230.036327, 231.038393, 232.042034, 233.044346, 234.048139, 235.05084, 236.054988, 237.05827 ] - }, - { - "symbol": "Th", - "name": "Thorium", - "weight": 232.0377, - "isotopes": [ 208.0179, 209.017753, 210.015094, 211.014929, 212.012988, 213.013009, 214.0115, 215.0117248, 216.011056, 217.013117, 218.013276, 219.015537, 220.015748, 221.018184, 222.018469, 223.0208119, 224.021464, 225.0239514, 226.0249034, 227.0277042, 228.0287413, 229.0317627, 230.0331341, 231.0363046, 232.0380558, 233.0415823, 234.0436014, 235.047255, 236.049657, 237.053629, 238.0565, 239.06077 ] - }, - { - "symbol": "Pa", - "name": "Protactinium", - "weight": 231.03588, - "isotopes": [ 212.023203, 213.021109, 214.020918, 215.019183, 216.019109, 217.018325, 218.020059, 219.019904, 220.021705, 221.021875, 222.023784, 223.023963, 224.0256176, 225.026131, 226.027948, 227.0288054, 228.0310517, 229.0320972, 230.034541, 231.0358842, 232.0385917, 233.0402472, 234.0433072, 235.045399, 236.048668, 237.051023, 238.054637, 239.05726, 240.06098, 241.06408 ] - }, - { - "symbol": "U", - "name": "Uranium", - "weight": 238.02891, - "isotopes": [ 217.02466, 218.023523, 219.024999, 220.02462, 221.02628, 222.026, 223.027739, 224.027605, 225.029391, 226.029339, 227.031157, 228.031371, 229.0335063, 230.0339401, 231.0362939, 232.0371563, 233.0396355, 234.0409523, 235.0439301, 236.0455682, 237.0487304, 238.0507884, 239.0542935, 240.0565934, 241.06033, 242.06293, 243.06699 ] - }, - { - "symbol": "Np", - "name": "Neptunium", - "weight": 237, - "isotopes": [ 219.03143, 220.03254, 221.03204, 222.0333, 223.03285, 224.03422, 225.033911, 226.035188, 227.034957, 228.036067, 229.036264, 230.037828, 231.038245, 232.04011, 233.040741, 234.0428953, 235.0440635, 236.04657, 237.0481736, 238.0509466, 239.0529392, 240.056165, 241.058253, 242.06164, 243.06428, 244.06785, 245.0708 ] - }, - { - "symbol": "Pu", - "name": "Plutonium", - "weight": 244, - "isotopes": [ 228.038732, 229.040144, 230.03965, 231.041102, 232.041185, 233.042998, 234.0433174, 235.045286, 236.0460581, 237.0484098, 238.0495601, 239.0521636, 240.0538138, 241.0568517, 242.0587428, 243.0620036, 244.0642053, 245.067826, 246.070205, 247.07419 ] - }, - { - "symbol": "Am", - "name": "Americium", - "weight": 243, - "isotopes": [ 230.04609, 231.04556, 232.04645, 233.04644, 234.04773, 235.047908, 236.04943, 237.049996, 238.051985, 239.0530247, 240.0553, 241.0568293, 242.0595494, 243.0613813, 244.0642851, 245.0664548, 246.069775, 247.07209, 248.07575, 249.07848 ] - }, - { - "symbol": "Cm", - "name": "Curium", - "weight": 247, - "isotopes": [ 232.04982, 233.05077, 234.05016, 235.05154, 236.051374, 237.052869, 238.053081, 239.05491, 240.0555297, 241.0576532, 242.058836, 243.0613893, 244.0627528, 245.0654915, 246.0672238, 247.0703541, 248.0723499, 249.0759548, 250.078358, 251.082286, 252.08487 ] - }, - { - "symbol": "Bk", - "name": "Berkelium", - "weight": 247, - "isotopes": [ 234.05727, 235.05658, 236.05748, 237.0571, 238.0582, 239.05824, 240.05976, 241.06016, 242.06198, 243.0630078, 244.065181, 245.0663618, 246.068673, 247.0703073, 248.073088, 249.0749877, 250.0783167, 251.080762, 252.08431, 253.08688, 254.0906 ] - }, - { - "symbol": "Cf", - "name": "Californium", - "weight": 251, - "isotopes": [ 237.062198, 238.06149, 239.06253, 240.062256, 241.06369, 242.063754, 243.06548, 244.0660008, 245.0680487, 246.0688055, 247.070965, 248.0721851, 249.0748539, 250.0764062, 251.0795886, 252.0816272, 253.0851345, 254.087324, 255.09105, 256.09344 ] - }, - { - "symbol": "Es", - "name": "Einsteinium", - "weight": 252, - "isotopes": [ 239.06823, 240.06892, 241.06856, 242.06957, 243.06951, 244.07088, 245.07125, 246.0729, 247.073622, 248.075471, 249.076411, 250.07861, 251.0799936, 252.08298, 253.0848257, 254.0880222, 255.090275, 256.0936, 257.09598, 258.09952 ] - }, - { - "symbol": "Fm", - "name": "Fermium", - "weight": 257, - "isotopes": [ 241.07421, 242.07343, 243.07446, 244.07404, 245.07535, 246.07535, 247.07694, 248.0771865, 249.0789275, 250.079521, 251.08154, 252.0824671, 253.0851846, 254.0868544, 255.089964, 256.0917745, 257.0951061, 258.09708, 259.1006, 260.10281 ] - }, - { - "symbol": "Md", - "name": "Mendelevium", - "weight": 258, - "isotopes": [ 245.08081, 246.08171, 247.08152, 248.08282, 249.08291, 250.08441, 251.084774, 252.08643, 253.087144, 254.08959, 255.0910841, 256.09389, 257.0955424, 258.0984315, 259.10051, 260.10365, 261.10583, 262.1091 ] - }, - { - "symbol": "No", - "name": "Nobelium", - "weight": 259, - "isotopes": [ 248.08655, 249.0878, 250.08756, 251.08894, 252.088967, 253.0905641, 254.090956, 255.093191, 256.0942829, 257.0968878, 258.09821, 259.10103, 260.10264, 261.1057, 262.10746, 263.11071, 264.11273 ] - }, - { - "symbol": "Lr", - "name": "Lawrencium", - "weight": 266, - "isotopes": [ 251.09418, 252.09526, 253.09509, 254.09648, 255.096562, 256.098494, 257.099418, 258.10176, 259.102902, 260.1055, 261.10688, 262.10961, 263.11136, 264.1142, 265.11619, 266.11983 ] - }, - { - "symbol": "Rf", - "name": "Rutherfordium", - "weight": 267, - "isotopes": [ 253.10044, 254.10005, 255.10127, 256.101152, 257.102918, 258.103428, 259.105596, 260.10644, 261.108773, 262.10992, 263.11249, 264.11388, 265.11668, 266.11817, 267.12179, 268.12397 ] - }, - { - "symbol": "Db", - "name": "Dubnium", - "weight": 268, - "isotopes": [ 255.10707, 256.10789, 257.10758, 258.10928, 259.109492, 260.1113, 261.11192, 262.11407, 263.11499, 264.11741, 265.11861, 266.12103, 267.12247, 268.12567, 269.12791, 270.13136 ] - }, - { - "symbol": "Sg", - "name": "Seaborgium", - "weight": 269, - "isotopes": [ 258.11298, 259.1144, 260.114384, 261.115949, 262.116337, 263.11829, 264.11893, 265.12109, 266.12198, 267.12436, 268.12539, 269.12863, 270.13043, 271.13393, 272.13589, 273.13958 ] - }, - { - "symbol": "Bh", - "name": "Bohrium", - "weight": 270, - "isotopes": [ 260.12166, 261.12145, 262.12297, 263.12292, 264.12459, 265.12491, 266.12679, 267.1275, 268.12969, 269.13042, 270.13336, 271.13526, 272.13826, 273.14024, 274.14355, 275.14567 ] - }, - { - "symbol": "Hs", - "name": "Hassium", - "weight": 270, - "isotopes": [ 263.12852, 264.128357, 265.129793, 266.130046, 267.13167, 268.13186, 269.13375, 270.13429, 271.13717, 272.1385, 273.14168, 274.1433, 275.14667, 276.14846, 277.1519 ] - }, - { - "symbol": "Mt", - "name": "Meitnerium", - "weight": 278, - "isotopes": [ 265.136, 266.13737, 267.13719, 268.13865, 269.13882, 270.14033, 271.14074, 272.14341, 273.1444, 274.14724, 275.14882, 276.15159, 277.15327, 278.15631, 279.15808 ] - }, - { - "symbol": "Ds", - "name": "Darmstadtium", - "weight": 281, - "isotopes": [ 267.14377, 268.14348, 269.144752, 270.144584, 271.14595, 272.14602, 273.14856, 274.14941, 275.15203, 276.15303, 277.15591, 278.15704, 279.1601, 280.16131, 281.16451 ] - }, - { - "symbol": "Rg", - "name": "Roentgenium", - "weight": 282, - "isotopes": [ 272.15327, 273.15313, 274.15525, 275.15594, 276.15833, 277.15907, 278.16149, 279.16272, 280.16514, 281.16636, 282.16912, 283.17054 ] - }, - { - "symbol": "Cn", - "name": "Copernicium", - "weight": 285, - "isotopes": [ 276.16141, 277.16364, 278.16416, 279.16654, 280.16715, 281.16975, 282.1705, 283.17327, 284.17416, 285.17712 ] - }, - { - "symbol": "Nh", - "name": "Nihonium", - "weight": 286, - "isotopes": [ 278.17058, 279.17095, 280.17293, 281.17348, 282.17567, 283.17657, 284.17873, 285.17973, 286.18221, 287.18339 ] - }, - { - "symbol": "Fl", - "name": "Flerovium", - "weight": 289, - "isotopes": [ 285.18364, 286.18423, 287.18678, 288.18757, 289.19042 ] - }, - { - "symbol": "Mc", - "name": "Moscovium", - "weight": 290, - "isotopes": [ 287.1907, 288.19274, 289.19363, 290.19598, 291.19707 ] - }, - { - "symbol": "Lv", - "name": "Livermorium", - "weight": 293, - "isotopes": [ 289.19816, 290.19864, 291.20108, 292.20174, 293.20449 ] - }, - { - "symbol": "Ts", - "name": "Tennessine", - "weight": 294, - "isotopes": [ 291.20553, 292.20746, 293.20824, 294.21046 ] - }, - { - "symbol": "Og", - "name": "Oganesson", - "weight": 294, - "isotopes": [ 293.21356, 294.21392, 295.21624 ] - } -] \ No newline at end of file diff --git a/Chemistry/README.md b/Chemistry/README.md deleted file mode 100644 index d0896291..00000000 --- a/Chemistry/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# [Trivial.Chemistry](https://trivial.kingcean.net/chemistry) - -This library includes the basic chemistry models. - -## Import - -Add following namespace to your code file to use. - -```csharp -using Trivial.Chemistry; -``` - -## Element - -Get element from periodic table by its symbol or atomic numbers. - -```csharp -var oxygen = ChemicalElement.Get(8); -var gold = ChemicalElement.Get("Au"); -var carbon = ChemicalElement.C; -``` - -Or list a set of element. - -```csharp -var some = ChemicalElement.Where(ele => ele.AtomicNumber < 20); -``` - -## Isotope - -Create an isotope from an element. - -```csharp -var diplogen = ChemicalElement.H.Isotope(2); -``` - -Or list all for a specific element. - -```csharp -var allCarbonIsotopes = ChemicalElement.C.Isotopes(); -``` - -## Molecular formula - -Parse a molecular formula. - -```csharp -var carbonicAcid = MolecularFormula.Parse("H2CO3"); -``` - -Or create a molecular formula by merging elements and other molecular formulas. - -```csharp -var sulfuricAcid = ChemicalElement.H * 2 + ChemicalElement.S + ChemicalElement.O * 4; -var ethanol = MolecularFormula.Parse("CH3") + MolecularFormula.Parse("CH2") + MolecularFormula.Parse("OH"); -var iron = ChemicalElement.Fe; -``` - -Test conservation of mass. - -```csharp -// 2 Na + 2 H₂O = 2 NaOH + H₂ -var mass = MolecularFormula.ConservationOfMass( - new List - { - { ChemicalElement.Na, 2 }, - { ChemicalElement.H * 2 + ChemicalElement.O, 2 } - }, - new List - { - { ChemicalElement.Na + ChemicalElement.H + ChemicalElement.O, 2 }, - ChemicalElement.H * 2 - } -); -Console.WriteLine(mass); // -> True -``` diff --git a/Console/CommandLine/Default.cs b/Console/CommandLine/Default.cs deleted file mode 100644 index 49f3ace1..00000000 --- a/Console/CommandLine/Default.cs +++ /dev/null @@ -1,1724 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Security; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Security; -using Trivial.Tasks; -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The command line interface. -/// -public static class DefaultConsole -{ - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The text content. - public static void Write(ConsoleText content) - => StyleConsole.Default.Write(content); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The text content 1. - /// The text content 2. - /// The additional text content collection. - public static void Write(ConsoleText content1, ConsoleText content2, params ConsoleText[] additionalContext) - => StyleConsole.Default.Write(content1, content2, additionalContext); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The text content collection. - public static void Write(IEnumerable content) - => StyleConsole.Default.Write(content); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(string s, params object[] args) - => StyleConsole.Default.Write(s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(ConsoleTextStyle style, string s, params object[] args) - => StyleConsole.Default.Write(style, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(ConsoleColor foreground, string s, params object[] args) - => StyleConsole.Default.Write(foreground, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, string s, params object[] args) - => StyleConsole.Default.Write(foreground, background, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(Color foreground, string s, params object[] args) - => StyleConsole.Default.Write(foreground, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(Color foreground, Color background, string s, params object[] args) - => StyleConsole.Default.Write(foreground, background, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The style. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void Write(IConsoleTextPrettier style, string s, params object[] args) - => StyleConsole.Default.Write(style, s, args); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// A composite format string to output. - public static void Write(StringBuilder s) - => StyleConsole.Default.Write(s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A composite format string to output. - public static void Write(ConsoleTextStyle style, StringBuilder s) - => StyleConsole.Default.Write(style, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void Write(ConsoleColor foreground, StringBuilder s) - => StyleConsole.Default.Write(foreground, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, StringBuilder s) - => StyleConsole.Default.Write(foreground, background, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void Write(Color foreground, StringBuilder s) - => StyleConsole.Default.Write(foreground, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void Write(Color foreground, Color background, StringBuilder s) - => StyleConsole.Default.Write(foreground, background, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The style. - /// A composite format string to output. - public static void Write(IConsoleTextPrettier style, StringBuilder s) - => StyleConsole.Default.Write(style, s); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// A composite format string to output. - public static void Write(SecureString s) - => StyleConsole.Default.Write(s.ToUnsecureString()); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A composite format string to output. - public static void Write(ConsoleTextStyle style, SecureString s) - => StyleConsole.Default.Write(style, s.ToUnsecureString()); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void Write(ConsoleColor foreground, SecureString s) - => StyleConsole.Default.Write(foreground, s.ToUnsecureString()); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, SecureString s) - => StyleConsole.Default.Write(foreground, background, s.ToUnsecureString()); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(int number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(int number, string format) - => StyleConsole.Default.Write(number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, int number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleTextStyle style, int number, string format) - => StyleConsole.Default.Write(style, number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, int number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleColor foreground, int number, string format) - => StyleConsole.Default.Write(foreground, number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, int number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, int number, string format) - => StyleConsole.Default.Write(foreground, background, number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(long number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, long number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, long number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, long number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(ulong number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, ulong number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, ulong number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, ulong number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(float number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, float number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, float number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, float number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(decimal number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, decimal number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, decimal number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, decimal number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - public static void Write(double number) - => StyleConsole.Default.Write(number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(double number, string format) - => StyleConsole.Default.Write(number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - public static void Write(ConsoleTextStyle style, double number) - => StyleConsole.Default.Write(style, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleTextStyle style, double number, string format) - => StyleConsole.Default.Write(style, number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void Write(ConsoleColor foreground, double number) - => StyleConsole.Default.Write(foreground, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleColor foreground, double number, string format) - => StyleConsole.Default.Write(foreground, number, format); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, double number) - => StyleConsole.Default.Write(foreground, background, number); - - /// - /// Writes the specified number to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, double number, string format) - => StyleConsole.Default.Write(foreground, background, number, format); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void Write(char[] value, int start = 0, int? count = null) - => StyleConsole.Default.Write(value, start, count); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void Write(ConsoleTextStyle style, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.Write(style, value, start, count); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void Write(ConsoleColor foreground, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.Write(foreground, value, start, count); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.Write(foreground, background, value, start, count); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void Write(IConsoleTextPrettier style, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.Write(style, value, start, count); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The value to write. - /// The number of times to append value. - public static void Write(char value, int repeatCount = 1) - => StyleConsole.Default.Write(value, repeatCount); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The content style. - /// The value to write. - /// The number of times to append value. - public static void Write(ConsoleTextStyle style, char value, int repeatCount = 1) - => StyleConsole.Default.Write(style, value, repeatCount); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The value to write. - /// The number of times to append value. - public static void Write(ConsoleColor foreground, char value, int repeatCount = 1) - => StyleConsole.Default.Write(foreground, value, repeatCount); - - /// - /// Writes the specified string value to the standard output stream. - /// Note it may not flush immediately. - /// - /// The style. - /// The value to write. - /// The number of times to append value. - public static void Write(IConsoleTextPrettier style, char value, int repeatCount = 1) - => StyleConsole.Default.Write(style, value, repeatCount); - - /// - /// Writes the specified data to the standard output stream. - /// Note it may not flush immediately. - /// - /// A representation model. - public static void Write(IConsoleTextCreator model) - => StyleConsole.Default.Write(model); - - /// - /// Writes the specified data to the standard output stream. - /// Note it may not flush immediately. - /// - /// The type of data model. - /// The style. - /// A data model. - public static void Write(IConsoleTextCreator style, T data) - => StyleConsole.Default.Write(style, data); - - /// - /// Writes the specified data to the standard output stream. - /// Note it may not flush immediately. - /// - /// The type of data model. - /// The additional options. - /// The style. - /// A data model. - /// The additional options. - public static void Write(IConsoleTextCreator style, TData data, TOptions options) - => StyleConsole.Default.Write(style, data, options); - - /// - /// Writes the specified characters to the standard output stream. - /// Note it may not flush immediately. - /// - /// The foreground color. - /// The background color. - /// The value to write. - /// The number of times to append value. - public static void Write(ConsoleColor? foreground, ConsoleColor? background, char value, int repeatCount = 1) - => StyleConsole.Default.Write(foreground, background, value, repeatCount); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The text content. - public static void WriteLine(ConsoleText content = null) - => StyleConsole.Default.WriteLine(content); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The text content 1. - /// The text content 2. - /// The additional text content collection. - public static void WriteLine(ConsoleText content1, ConsoleText content2, params ConsoleText[] additionalContext) - => StyleConsole.Default.WriteLine(content1, content2, additionalContext); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The text content collection. - public static void WriteLine(IEnumerable content) - => StyleConsole.Default.WriteLine(content); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(string s, params object[] args) - => StyleConsole.Default.WriteLine(s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// - /// The content style. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(ConsoleTextStyle style, string s, params object[] args) - => StyleConsole.Default.WriteLine(style, s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(ConsoleColor foreground, string s, params object[] args) - => StyleConsole.Default.WriteLine(foreground, s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, string s, params object[] args) - => StyleConsole.Default.WriteLine(foreground, background, s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(Color foreground, string s, params object[] args) - => StyleConsole.Default.WriteLine(foreground, s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(Color foreground, Color background, string s, params object[] args) - => StyleConsole.Default.WriteLine(foreground, background, s, args); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// A composite format string to output. - /// An object array that contains zero or more objects to format. - /// format is invalid. -or- The index of a format item is less than zero, or greater than or equal to the length of the args array. - public static void WriteLine(IConsoleTextPrettier style, string s, params object[] args) - => StyleConsole.Default.WriteLine(style, s, args); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A composite format string to output. - public static void WriteLine(StringBuilder s) - => StyleConsole.Default.WriteLine(s); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// - /// The content style. - /// A composite format string to output. - public static void WriteLine(ConsoleTextStyle style, StringBuilder s) - => StyleConsole.Default.WriteLine(style, s); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void WriteLine(ConsoleColor foreground, StringBuilder s) - => StyleConsole.Default.WriteLine(foreground, s); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, StringBuilder s) - => StyleConsole.Default.WriteLine(foreground, background, s); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void WriteLine(Color foreground, StringBuilder s) - => StyleConsole.Default.WriteLine(foreground, s); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void WriteLine(Color foreground, Color background, StringBuilder s) - => StyleConsole.Default.WriteLine(foreground, background, s); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// A composite format string to output. - public static void WriteLine(IConsoleTextPrettier style, StringBuilder s) - => StyleConsole.Default.WriteLine(style, s?.ToString()); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A composite format string to output. - public static void WriteLine(SecureString s) - => StyleConsole.Default.WriteLine(s?.ToUnsecureString()); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// - /// The content style. - /// A composite format string to output. - public static void WriteLine(ConsoleTextStyle style, SecureString s) - => StyleConsole.Default.WriteLine(style, s?.ToUnsecureString()); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A composite format string to output. - public static void WriteLine(ConsoleColor foreground, SecureString s) - => StyleConsole.Default.WriteLine(foreground, s?.ToUnsecureString()); - - /// - /// Writes the specified string value, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A composite format string to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, SecureString s) - => StyleConsole.Default.WriteLine(foreground, background, s.ToUnsecureString()); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(int number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(int number, string format) - => StyleConsole.Default.WriteLine(number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, int number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleTextStyle style, int number, string format) - => StyleConsole.Default.WriteLine(style, number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, int number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleColor foreground, int number, string format) - => StyleConsole.Default.WriteLine(foreground, number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, int number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, int number, string format) - => StyleConsole.Default.WriteLine(foreground, background, number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(long number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, long number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, long number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, long number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(ulong number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, ulong number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, ulong number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, ulong number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(float number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, float number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, float number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, float number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(decimal number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, decimal number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, decimal number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, decimal number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - public static void WriteLine(double number) - => StyleConsole.Default.WriteLine(number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(double number, string format) - => StyleConsole.Default.WriteLine(number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - public static void WriteLine(ConsoleTextStyle style, double number) - => StyleConsole.Default.WriteLine(style, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleTextStyle style, double number, string format) - => StyleConsole.Default.WriteLine(style, number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - public static void WriteLine(ConsoleColor foreground, double number) - => StyleConsole.Default.WriteLine(foreground, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleColor foreground, double number, string format) - => StyleConsole.Default.WriteLine(foreground, number, format); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, double number) - => StyleConsole.Default.WriteLine(foreground, background, number); - - /// - /// Writes the specified number, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// A number to output. - /// A standard or custom numeric format string. - /// format is invalid or not supported. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, double number, string format) - => StyleConsole.Default.WriteLine(foreground, background, number, format); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void WriteLine(char[] value, int start = 0, int? count = null) - => StyleConsole.Default.WriteLine(value, start, count); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void WriteLine(ConsoleTextStyle style, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.WriteLine(style, value, start, count); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void WriteLine(ConsoleColor foreground, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.WriteLine(foreground, value, start, count); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.WriteLine(foreground, background, value, start, count); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// The value to write. - /// The starting position in value. - /// The number of characters to write. - public static void WriteLine(IConsoleTextPrettier style, char[] value, int start = 0, int? count = null) - => StyleConsole.Default.WriteLine(style, value, start, count); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The value to write. - /// The number of times to append value. - public static void WriteLine(char value, int repeatCount = 1) - => StyleConsole.Default.WriteLine(value, repeatCount); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The content style. - /// The value to write. - /// The number of times to append value. - public static void WriteLine(ConsoleTextStyle style, char value, int repeatCount = 1) - => StyleConsole.Default.WriteLine(style, value, repeatCount); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The value to write. - /// The number of times to append value. - public static void WriteLine(ConsoleColor foreground, char value, int repeatCount = 1) - => StyleConsole.Default.WriteLine(foreground, value, repeatCount); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// The value to write. - /// The number of times to append value. - public static void WriteLine(IConsoleTextPrettier style, char value, int repeatCount = 1) - => StyleConsole.Default.WriteLine(style, value, repeatCount); - - /// - /// Writes the specified characters, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The foreground color. - /// The background color. - /// The value to write. - /// The number of times to append value. - public static void WriteLine(ConsoleColor? foreground, ConsoleColor? background, char value, int repeatCount = 1) - => StyleConsole.Default.WriteLine(foreground, background, value, repeatCount); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The exception. - /// true if output stack trace; otherwise, false. - public static void WriteLine(Exception ex, bool stackTrace = false) - => StyleConsole.Default.WriteLine(new ConsoleTextStyle(ConsoleColor.Red), null as ConsoleTextStyle, ex, stackTrace); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The exception. - /// The style of header. - /// The style of details. - /// true if output stack trace; otherwise, false. - public static void WriteLine(ConsoleTextStyle captionStyle, ConsoleTextStyle messageStyle, Exception ex, bool stackTrace = false) - => StyleConsole.Default.WriteLine(captionStyle, messageStyle, ex, stackTrace); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The error information. - public static void WriteLine(Data.ErrorMessageResult ex) - => StyleConsole.Default.WriteLine(new ConsoleTextStyle(ConsoleColor.Red), null as ConsoleTextStyle, ex); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The error information. - /// The style of header. - /// The style of details. - public static void WriteLine(ConsoleTextStyle captionStyle, ConsoleTextStyle messageStyle, Data.ErrorMessageResult ex) - => StyleConsole.Default.WriteLine(captionStyle, messageStyle, ex); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The JSON instance. - public static void WriteLine(IJsonDataNode json) - => StyleConsole.Default.WriteLine(new JsonConsoleStyle().CreateTextCollection(json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// The JSON instance. - public static void WriteLine(JsonConsoleStyle style, IJsonDataNode json) - => StyleConsole.Default.WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The JSON instance. - public static void WriteLine(System.Text.Json.Nodes.JsonObject json) - => StyleConsole.Default.WriteLine(new JsonConsoleStyle().CreateTextCollection(json == null ? null : (JsonObjectNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// The JSON instance. - public static void WriteLine(JsonConsoleStyle style, System.Text.Json.Nodes.JsonObject json) - => StyleConsole.Default.WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json == null ? null : (JsonObjectNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The JSON instance. - public static void WriteLine(IJsonObjectHost json) - => StyleConsole.Default.WriteLine(new JsonConsoleStyle().CreateTextCollection(json?.ToJson(), 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// The JSON instance. - public static void WriteLine(JsonConsoleStyle style, IJsonObjectHost json) - => StyleConsole.Default.WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json?.ToJson(), 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The JSON instance. - public static void WriteLine(System.Text.Json.Nodes.JsonArray json) - => StyleConsole.Default.WriteLine(new JsonConsoleStyle().CreateTextCollection(json == null ? null : (JsonArrayNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The style. - /// The JSON instance. - public static void WriteLine(JsonConsoleStyle style, System.Text.Json.Nodes.JsonArray json) - => StyleConsole.Default.WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json == null ? null : (JsonArrayNode)json, 0)); - - /// - /// Writes the specified data, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// A representation model. - public static void WriteLine(IConsoleTextCreator model) - => StyleConsole.Default.WriteLine(model); - - /// - /// Writes the specified data, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The type of data model. - /// The style. - /// A data model. - public static void WriteLine(IConsoleTextCreator style, T data) - => StyleConsole.Default.WriteLine(style, data); - - /// - /// Writes the specified data, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The type of data model. - /// The additional options. - /// The style. - /// A data model. - /// The additional options. - public static void WriteLine(IConsoleTextCreator style, TData data, TOptions options) - => StyleConsole.Default.WriteLine(style, data, options); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The options. - /// The progress result. - public static OneProgress WriteLine(ConsoleProgressStyle style) - => StyleConsole.Default.WriteLine(style, null); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The caption; or null if no caption. It will be better if it is less than 20 characters. - /// The progress size. - /// The progress kind. - /// The progress result. - public static OneProgress WriteLine(ConsoleProgressStyle.Sizes progressSize, string caption, ConsoleProgressStyle.Kinds kind = ConsoleProgressStyle.Kinds.Full) - => StyleConsole.Default.WriteLine(progressSize, caption, kind); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The progress size. - /// The progress kind. - /// The progress result. - public static OneProgress WriteLine(ConsoleProgressStyle.Sizes progressSize, ConsoleProgressStyle.Kinds kind = ConsoleProgressStyle.Kinds.Full) - => StyleConsole.Default.WriteLine(progressSize, kind); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The caption; or null if no caption. It will be better if it is less than 20 characters. - /// The style. - /// The progress result. - public static OneProgress WriteLine(ConsoleProgressStyle style, string caption) - => StyleConsole.Default.WriteLine(style, caption); - - /// - /// Writes the specific lines to the standard output stream. - /// - /// The count of line. - public static void WriteLines(int count) - => StyleConsole.Default.WriteLines(count); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The text content collection. - public static void WriteLines(IEnumerable content) - => StyleConsole.Default.WriteLines(content); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The text content. - /// The additional text content collection. - public static void WriteLines(ConsoleText content, params ConsoleText[] additionalContext) - => StyleConsole.Default.WriteLines(content, additionalContext); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The string collection to write. Each one in a line. - public static void WriteLines(IEnumerable col) - => StyleConsole.Default.WriteLines(col); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The content style. - /// The string collection to write. Each one in a line. - public static void WriteLines(ConsoleTextStyle style, IEnumerable col) - => StyleConsole.Default.WriteLines(style, col); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The foreground color of the console. - /// The string collection to write. Each one in a line. - public static void WriteLines(ConsoleColor foreground, IEnumerable col) - => StyleConsole.Default.WriteLines(foreground, col); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The foreground color of the console. - /// The background color. - /// The string collection to write. Each one in a line. - public static void WriteLines(ConsoleColor foreground, ConsoleColor background, IEnumerable col) - => StyleConsole.Default.WriteLines(foreground, background, col); - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The string collection to write. Each one in a line. - /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - public static void WriteLines(IEnumerable col, Func selector) - { - if (col == null) return; - if (selector == null) selector = (ele, i) => ele?.ToString(); - StyleConsole.Default.WriteLines(col.Select(selector)); - } - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The foreground color of the console. - /// The string collection to write. Each one in a line. - /// A transform function to apply to each source element; the second parameter of the function represents the index of the source element. - public static void WriteLines(ConsoleColor foreground, IEnumerable col, Func selector) - { - if (col == null) return; - if (selector == null) selector = (ele, i) => ele?.ToString(); - StyleConsole.Default.WriteLines(foreground, col.Select(selector)); - } - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The string collection to write. Each one in a line. - /// A transform function to apply to each element. - public static void WriteLines(IEnumerable col, Func selector) - { - if (col == null) return; - if (selector == null) selector = ele => ele?.ToString(); - StyleConsole.Default.WriteLines(col.Select(selector)); - } - - /// - /// Writes the current line terminator for each item, to the standard output stream. - /// - /// The foreground color of the console. - /// The string collection to write. Each one in a line. - /// A transform function to apply to each element. - public static void WriteLines(ConsoleColor foreground, IEnumerable col, Func selector) - { - if (col == null) return; - if (selector == null) selector = ele => ele?.ToString(); - StyleConsole.Default.WriteLines(foreground, col.Select(selector)); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(SelectionData collection, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(collection, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The collection data. - /// The converter. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(IEnumerable collection, Func> convert, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(collection, convert, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(IEnumerable> collection, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(collection, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The parent foler path. - /// The selection display options. - /// The search string to match against the names of directories and files. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions. - /// The result of selection. - /// searchPattern contains one or more invalid characters defined by the System.IO.Path.GetInvalidPathChars method. - /// The specified path is invalid (for example, it is on an unmapped drive). - /// The caller does not have the required permission. - public static SelectionResult Select(DirectoryInfo path, SelectionConsoleOptions options = null, string searchPattern = null) - => StyleConsole.Default.Select(path, options, searchPattern); - - /// - /// Writes a collection of item for selecting. - /// - /// The parent foler path. - /// A function to test each element for a condition. - /// The selection display options. - /// The result of selection. - /// The specified path is invalid (for example, it is on an unmapped drive). - /// The caller does not have the required permission. - public static SelectionResult Select(DirectoryInfo path, Func predicate, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(path, predicate, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The type of data. - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(SelectionData collection, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(collection, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(IEnumerable collection, SelectionConsoleOptions options = null) - => StyleConsole.Default.Select(collection, options); - - /// - /// Flushes all data. - /// - public static void Flush() - => StyleConsole.Default.Flush(); - - /// - /// Clears output cache. - /// - public static void ClearOutputCache() - => StyleConsole.Default.ClearOutputCache(); - - /// - /// Enters a backspace to console to remove the last charactor. - /// - /// The count of the charactor to remove from end. - /// true if just only move cursor back and keep output; otherwise, false. - public static void Backspace(int count = 1, bool doNotRemoveOutput = false) - => StyleConsole.Default.Backspace(count, doNotRemoveOutput); - - /// - /// Enters backspaces to console to remove the charactors to the beginning of the line. - /// - public static void BackspaceToBeginning() - => StyleConsole.Default.BackspaceToBeginning(); - - /// - /// Reads the next line of characters from the standard input stream. - /// - /// The next line of characters from the input stream, or null if no more lines are available. - /// An I/O error occurred. - /// There is insufficient memory to allocate a buffer for the returned string. - /// The number of characters in the next line of characters is greater than max value of 32-bit integer. - public static string ReadLine() - => StyleConsole.Default.ReadLine(); - - /// - /// Obtains the next character or function key pressed by the user. The pressed key is optionally displayed in the console window. - /// - /// Determines whether to display the pressed key in the console window. true to not display the pressed key; otherwise, false. - /// The next line of characters from the input stream, or null if no more lines are available. - /// An I/O error occurred. - /// The input stream is redirected from the one other than the console. - public static ConsoleKeyInfo ReadKey(bool intercept = false) - => StyleConsole.Default.ReadKey(intercept); - - /// - /// Obtains the password pressed by the user. - /// - /// - /// The password. - /// - public static SecureString ReadPassword() - => StyleConsole.Default.ReadPassword(null, null); - - /// - /// Obtains the password pressed by the user. - /// - /// The optional charactor to output to replace the original one, such as *. - /// true if do not follow the line terminator after typing the password; otherwise, false. - /// - /// The password. - /// - public static SecureString ReadPassword(char replaceChar, bool inline = false) - => StyleConsole.Default.ReadPassword(null, replaceChar, inline); - - /// - /// Obtains the password pressed by the user. - /// - /// The replace charactor color. - /// The optional charactor to output to replace the original one, such as *. - /// true if do not follow the line terminator after typing the password; otherwise, false. - /// - /// The password. - /// - public static SecureString ReadPassword(ConsoleColor? foreground, char? replaceChar, bool inline = false) - => StyleConsole.Default.ReadPassword(foreground, replaceChar, inline); - - /// - /// Moves cursor by a specific relative position. - /// - /// The horizontal translation size. - /// The vertical translation size. - public static void MoveCursorBy(int x, int y = 0) - => StyleConsole.Default.MoveCursorBy(x, y); - - /// - /// Moves cursor at a specific position in buffer. - /// - /// Column, the left from the edge of buffer. - /// Row, the top from the edge of buffer. - public static void MoveCursorTo(int x, int y) - => StyleConsole.Default.MoveCursorTo(x, y); - - /// - /// Removes the specific area. - /// - /// The area to remove. - public static void Clear(StyleConsole.RelativeAreas area) - => StyleConsole.Default.Clear(area); -} diff --git a/Console/CommandLine/HighlightConsoleStyle.cs b/Console/CommandLine/HighlightConsoleStyle.cs deleted file mode 100644 index bdb5e360..00000000 --- a/Console/CommandLine/HighlightConsoleStyle.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The highlight console text style. -/// -public class HighlightConsoleStyle : IConsoleTextPrettier -{ - /// - /// Initialzies a new instance of the HighlightConsoleStyle class. - /// - /// The normal style. - /// The highlight style. - /// The query string. - public HighlightConsoleStyle(ConsoleTextStyle normal, ConsoleTextStyle highlight, IEnumerable q) - { - Normal = normal; - Highlight = highlight; - if (q != null) Query.AddRange(q.Where(ele => !string.IsNullOrEmpty(ele))); - } - - /// - /// Initialzies a new instance of the HighlightConsoleStyle class. - /// - /// The normal style. - /// The highlight style. - /// The query string. - /// One of the enumeration values that specifies the rules for the search. - public HighlightConsoleStyle(ConsoleTextStyle normal, ConsoleTextStyle highlight, string q, StringComparison? comparisonType = null) - { - Normal = normal; - Highlight = highlight; - if (!string.IsNullOrEmpty(q)) Query.Add(q); - if (comparisonType.HasValue) ComparisonType = comparisonType.Value; - } - - /// - /// Gets or sets the fallback foreground color. - /// - [JsonPropertyName("normal")] - public ConsoleTextStyle Normal { get; } = new(); - - /// - /// Gets or sets the fallback background color. - /// - [JsonPropertyName("highlight")] - public ConsoleTextStyle Highlight { get; } = new(); - - /// - /// Gets or sets a value indicating whether the text is strikeout. - /// - [JsonPropertyName("q")] - public List Query { get; } = new(); - - /// - /// Gets or sets one of the enumeration values that specifies the rules for the search. - /// - [JsonPropertyName("compare")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] - public StringComparison ComparisonType { get; set; } - - /// - /// The search starting position to search. - /// - [JsonPropertyName("start")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] - public int StartPosition { get; set; } - -#pragma warning disable IDE0057 - /// - /// Creates the console text collection based on this style. - /// - /// The text. - /// A collection of console text. - IEnumerable IConsoleTextPrettier.CreateTextCollection(string s) - { - var col = new List(); - var q = Query.Where(ele => !string.IsNullOrEmpty(ele)).ToList(); - var pos = StartPosition > 0 ? StartPosition : 0; - while (true) - { - if (pos >= s.Length) break; - var i = -1; - var hl = string.Empty; - foreach (var item in q) - { - var j = s.IndexOf(item, pos, ComparisonType); - if (j < 0 || (i >= 0 && j > i) || (i == j && item.Length < hl.Length)) continue; - i = j; - hl = item; - } - - if (i < 0) break; - col.Add(s.Substring(pos, i - pos), Normal); - col.Add(hl, Highlight); - pos += hl.Length; - } - - if (pos < s.Length) col.Add(s.Substring(pos), Normal); - return col; - } -#pragma warning restore IDE0057 -} diff --git a/Console/CommandLine/InfoRender.cs b/Console/CommandLine/InfoRender.cs deleted file mode 100644 index 746abfcc..00000000 --- a/Console/CommandLine/InfoRender.cs +++ /dev/null @@ -1,360 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using System.Security; - -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The extensions for console renderer. -/// -public static partial class ConsoleRenderExtensions -{ - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The exception. - /// true if output stack trace; otherwise, false. - public static void WriteLine(this StyleConsole cli, Exception ex, bool stackTrace = false) - => WriteLine(cli, new ConsoleTextStyle - { - ForegroundConsoleColor = ConsoleColor.Red - }, null, ex, stackTrace); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The style of header. - /// The style of details. - /// The exception. - /// true if output stack trace; otherwise, false. - public static void WriteLine(this StyleConsole cli, ConsoleTextStyle captionStyle, ConsoleTextStyle messageStyle, Exception ex, bool stackTrace = false) - { - if (ex == null) return; - cli ??= StyleConsole.Default; - var header = new ConsoleText(Resource.Error, captionStyle); - if (!string.IsNullOrWhiteSpace(ex.Message)) header.Content.Append(ex.Message); - var message = new ConsoleText(Environment.NewLine, messageStyle); - if (!string.IsNullOrWhiteSpace(ex.HelpLink)) - message.Content.AppendLine(ex.HelpLink); - message.Content.Append(ex.GetType().FullName); - if (ex.InnerException != null) - { - message.Content.Append($" > {ex.InnerException.GetType().FullName}"); - if (ex.InnerException is AggregateException aggEx && aggEx.InnerExceptions != null) - { - foreach (var iEx in aggEx.InnerExceptions) - { - message.Content.AppendLine(); - message.Content.Append($"- {iEx.GetType().FullName}\t{iEx.Message}"); - } - } - else - { - if (!string.IsNullOrWhiteSpace(ex.InnerException.Message)) - { - message.Content.AppendLine(); - message.Content.Append(ex.InnerException.Message); - } - } - } - - if (stackTrace && !string.IsNullOrWhiteSpace(ex.StackTrace)) - { - message.Content.AppendLine(); - message.Content.AppendLine("Stack trace"); - message.Content.Append(ex.StackTrace); - } - - cli.WriteLine(header, message); - } - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The error information. - public static void WriteLine(this StyleConsole cli, Data.ErrorMessageResult ex) - => WriteLine(cli, new ConsoleTextStyle - { - ForegroundConsoleColor = ConsoleColor.Red - }, null, ex); - - /// - /// Writes an exception, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The style of header. - /// The style of details. - /// The error information. - public static void WriteLine(this StyleConsole cli, ConsoleTextStyle captionStyle, ConsoleTextStyle messageStyle, Data.ErrorMessageResult ex) - { - if (ex == null) return; - cli ??= StyleConsole.Default; - var header = new ConsoleText(Resource.Error, captionStyle); - if (!string.IsNullOrWhiteSpace(ex.Message)) header.Content.Append(ex.Message); - var message = new ConsoleText(Environment.NewLine, messageStyle); - if (!string.IsNullOrWhiteSpace(ex.ErrorCode)) - message.Content.Append($" [ErrCode] {ex.ErrorCode}"); - if (ex.Details != null) - { - foreach (var line in ex.Details) - { - message.Content.AppendLine(); - message.Content.Append($"- {line}"); - } - } - - cli.WriteLine(header, message); - } - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, IJsonDataNode json) - => (cli ?? StyleConsole.Default).WriteLine(new JsonConsoleStyle().CreateTextCollection(json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The style. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, JsonConsoleStyle style, IJsonDataNode json) - => (cli ?? StyleConsole.Default).WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, System.Text.Json.Nodes.JsonObject json) - => (cli ?? StyleConsole.Default).WriteLine(new JsonConsoleStyle().CreateTextCollection(json == null ? null : (JsonObjectNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The style. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, JsonConsoleStyle style, System.Text.Json.Nodes.JsonObject json) - => (cli ?? StyleConsole.Default).WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json == null ? null : (JsonObjectNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, System.Text.Json.Nodes.JsonArray json) - => (cli ?? StyleConsole.Default).WriteLine(new JsonConsoleStyle().CreateTextCollection(json == null ? null : (JsonArrayNode)json, 0)); - - /// - /// Writes a JSON object, followed by the current line terminator, to the standard output stream. - /// It will flush immediately. - /// - /// The command line interface proxy. - /// The style. - /// The JSON instance. - public static void WriteLine(this StyleConsole cli, JsonConsoleStyle style, System.Text.Json.Nodes.JsonArray json) - => (cli ?? StyleConsole.Default).WriteLine((style ?? new JsonConsoleStyle()).CreateTextCollection(json == null ? null : (JsonArrayNode)json, 0)); - - /// - /// Adds an empty line. - /// - /// The console text collection. - public static void AddEmptyLine(this IList list) - => list?.Add(new ConsoleText(Environment.NewLine)); - - /// - /// Writes a sentense to allow pressing a key to continue. - /// - /// The command line interface proxy. - /// The style. - public static void PressAnyKeyToContinue(StyleConsole cli, ConsoleTextStyle style = null) - { - cli ??= StyleConsole.Default; - cli.WriteLine(style, Resource.PressAnyKeyToCont); - try - { - cli.ReadKey(true); - } - catch (InvalidOperationException) - { - } - catch (IOException) - { - } - catch (NotSupportedException) - { - } - - try - { - cli.ReadLine(); - } - catch (InvalidOperationException) - { - } - catch (IOException) - { - } - catch (NotSupportedException) - { - } - catch (ArgumentException) - { - } - - return; - } - - /// - /// Removes rest content value. - /// - /// The console text instance to limit length. - /// The length at most. - public static void RemoveRest(this ConsoleText s, int length) - { - if (s == null) return; - var sb = s.Content; - if (sb.Length <= length / 2) return; - var count = 0; - var n = new StringBuilder(); - foreach (var c in sb.ToString()) - { - var needStop = false; - switch (c) - { - case '\t': - count += 4; - break; - case '\r': - case '\n': - case '\0': - needStop = true; - break; - case '\b': - break; - default: - count += GetLetterWidth(c); - break; - } - - if (needStop || count > length) break; - n.Append(c); - } - - sb.Clear(); -#if NETFRAMEWORK - sb.Append(n.ToString()); -#else - sb.Append(n); -#endif - } - - /// - /// Tries to gets the row position of the cursor within the buffer area. - /// - /// The command line interface. - /// The row position of the cursor within the buffer area; or null if failed. - public static int? TryGetCursorTop(this StyleConsole cli) - { - try - { - return cli.CursorTop; - } - catch (IOException) - { - } - catch (InvalidOperationException) - { - } - catch (NotSupportedException) - { - } - catch (SecurityException) - { - } - - return null; - } - - /// - /// Tries to gets the column position of the cursor within the buffer area; or null if failed. - /// - /// The command line interface. - /// The column position of the cursor within the buffer area; or null if failed. - public static int? TryGetCursorLeft(this StyleConsole cli) - { - try - { - return (cli ?? StyleConsole.Default).CursorLeft; - } - catch (IOException) - { - } - catch (InvalidOperationException) - { - } - catch (NotSupportedException) - { - } - catch (SecurityException) - { - } - catch (System.Runtime.InteropServices.ExternalException) - { - } - catch (ArgumentException) - { - } - - return null; - } - - private static int GetBufferSafeWidth(StyleConsole cli) - { - try - { - return (cli ?? StyleConsole.Default).BufferWidth - 1; - } - catch (IOException) - { - } - catch (InvalidOperationException) - { - } - catch (NotSupportedException) - { - } - catch (SecurityException) - { - } - catch (System.Runtime.InteropServices.ExternalException) - { - } - catch (ArgumentException) - { - } - - return 70; - } -} diff --git a/Console/CommandLine/JsonConsoleStyle.cs b/Console/CommandLine/JsonConsoleStyle.cs deleted file mode 100644 index dbc6ded8..00000000 --- a/Console/CommandLine/JsonConsoleStyle.cs +++ /dev/null @@ -1,326 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The style for JSON output. -/// -public class JsonConsoleStyle : ICloneable -{ - /// - /// Gets or sets the foreground color of property key. - /// - [JsonPropertyName("property")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PropertyForegroundRgbColor { get; set; } = Color.FromArgb(0xCE, 0x91, 0x78); - - /// - /// Gets or sets the foreground color of string value. - /// - [JsonPropertyName("string")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? StringForegroundRgbColor { get; set; } = Color.FromArgb(0xCE, 0x91, 0x78); - - /// - /// Gets or sets the foreground color of language keyword. - /// - [JsonPropertyName("keyword")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? KeywordForegroundRgbColor { get; set; } = Color.FromArgb(0x56, 0x9C, 0xD6); - - /// - /// Gets or sets the foreground color of number. - /// - [JsonPropertyName("number")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? NumberForegroundRgbColor { get; set; } = Color.FromArgb(0xB5, 0xCE, 0xA8); - - /// - /// Gets or sets the foreground color of punctuation. - /// - [JsonPropertyName("punctuation")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PunctuationForegroundRgbColor { get; set; } = Color.FromArgb(0xDC, 0xDC, 0xDC); - - /// - /// Gets or sets the background color. - /// - [JsonPropertyName("back")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? BackgroundRgbColor { get; set; } - - /// - /// Gets or sets the foreground color of property key. - /// - [JsonPropertyName("property2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PropertyForegroundConsoleColor { get; set; } = ConsoleColor.Gray; - - /// - /// Gets or sets the foreground color of string value. - /// - [JsonPropertyName("string2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? StringForegroundConsoleColor { get; set; } = ConsoleColor.Green; - - /// - /// Gets or sets the foreground color of keyword. - /// - [JsonPropertyName("keyword2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? KeywordForegroundConsoleColor { get; set; } = ConsoleColor.Cyan; - - /// - /// Gets or sets the foreground color of number. - /// - [JsonPropertyName("number2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? NumberForegroundConsoleColor { get; set; } = ConsoleColor.Yellow; - - /// - /// Gets or sets the foreground color of punctuation. - /// - [JsonPropertyName("punctuation2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PunctuationForegroundConsoleColor { get; set; } = ConsoleColor.Gray; - - /// - /// Gets or sets the background color. - /// - [JsonPropertyName("back2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? BackgroundConsoleColor { get; set; } - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - public ConsoleText CreateText(bool value) - => CreateByKeyword(value ? JsonBooleanNode.TrueString : JsonBooleanNode.FalseString); - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - public ConsoleText CreateText(int value) - => new( - value.ToString("g"), - NumberForegroundRgbColor, - NumberForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor); - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - public ConsoleText CreateText(string value) - { - return value == null ? CreateByKeyword(JsonValues.Null.ToString()) : new( - JsonStringNode.ToJson(value), - StringForegroundRgbColor, - StringForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor); - } - - /// - /// Clones an object. - /// - /// The object copied from this instance. - public virtual JsonConsoleStyle Clone() - => MemberwiseClone() as JsonConsoleStyle; - - /// - /// Clones an object. - /// - /// The object copied from this instance. - object ICloneable.Clone() - => MemberwiseClone(); - - /// - /// Creates a console text by this style. - /// - /// The JSON instance. - /// The current indent level. - /// A console text instance. - internal List CreateTextCollection(IJsonDataNode json, int indentLevel = 0) - { - var cmd = new List(); - if (json == null) - { - cmd.Add(CreateByKeyword(JsonValues.Null.ToString())); - return cmd; - } - - switch (json.ValueKind) - { - case JsonValueKind.Undefined: - case JsonValueKind.Null: - cmd.Add(CreateText(null)); - break; - case JsonValueKind.String: - cmd.Add(new(json.ToString(), - StringForegroundRgbColor, - StringForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor)); - break; - case JsonValueKind.Number: - cmd.Add(new(json.ToString(), - NumberForegroundRgbColor, - NumberForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor)); - break; - case JsonValueKind.True: - cmd.Add(CreateText(true)); - break; - case JsonValueKind.False: - cmd.Add(CreateText(false)); - break; - case JsonValueKind.Object: - cmd.AddRange(CreateTextCollection(json as JsonObjectNode, indentLevel)); - break; - case JsonValueKind.Array: - cmd.AddRange(CreateTextCollection(json as JsonArrayNode, indentLevel)); - break; - default: - break; - } - - return cmd; - } - - /// - /// Creates a console text by this style. - /// - /// The JSON instance. - /// The current indent level. - /// A console text instance. - private List CreateTextCollection(JsonObjectNode json, int indentLevel) - { - var cmd = new List(); - if (json == null) - { - cmd.Add(CreateByKeyword(JsonValues.Null.ToString())); - return cmd; - } - - var spaces = CreateByWhitespace(Environment.NewLine + new string(' ', (indentLevel + 1) * 2)); - cmd.Add(CreateByPunctuation("{")); - foreach (var prop in json) - { - cmd.Add(spaces); - cmd.Add(new( - JsonStringNode.ToJson(prop.Key), - PropertyForegroundRgbColor, - PropertyForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor)); - cmd.Add(CreateByPunctuation(": ")); - cmd.AddRange(CreateTextCollection(prop.Value, indentLevel + 1)); - cmd.Add(CreateByPunctuation(",")); - } - - if (cmd.Count > 1) cmd.RemoveAt(cmd.Count - 1); - cmd.Add(CreateByWhitespace(Environment.NewLine)); - cmd.Add(CreateByWhitespace(new string(' ', indentLevel * 2))); - cmd.Add(CreateByPunctuation("}")); - return cmd; - } - - /// - /// Creates a console text by this style. - /// - /// The JSON instance. - /// The current indent level. - /// A console text instance. - private List CreateTextCollection(JsonArrayNode json, int indentLevel) - { - var cmd = new List(); - if (json == null) - { - cmd.Add(CreateByKeyword(JsonValues.Null.ToString())); - return cmd; - } - - var spaces = CreateByWhitespace(Environment.NewLine + new string(' ', (indentLevel + 1) * 2)); - cmd.Add(CreateByPunctuation("[")); - foreach (var prop in json) - { - cmd.Add(spaces); - cmd.AddRange(CreateTextCollection(prop, indentLevel + 1)); - cmd.Add(CreateByPunctuation(",")); - } - - if (cmd.Count > 1) cmd.RemoveAt(cmd.Count - 1); - cmd.Add(CreateByWhitespace(Environment.NewLine)); - cmd.Add(CreateByWhitespace(new string(' ', indentLevel * 2))); - cmd.Add(CreateByPunctuation("]")); - return cmd; - } - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - private ConsoleText CreateByKeyword(string value) - => new( - value, - KeywordForegroundRgbColor, - KeywordForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor); - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - private ConsoleText CreateByPunctuation(string value) - => new( - value, - PunctuationForegroundRgbColor, - PunctuationForegroundConsoleColor, - BackgroundRgbColor, - BackgroundConsoleColor); - - /// - /// Creates a console text by this style. - /// - /// The value. - /// A console text instance. - private ConsoleText CreateByWhitespace(string value) - => new( - value, - null, - null, - BackgroundRgbColor, - BackgroundConsoleColor); -} diff --git a/Console/CommandLine/LinearGradientConsoleStyle.cs b/Console/CommandLine/LinearGradientConsoleStyle.cs deleted file mode 100644 index e6960aaa..00000000 --- a/Console/CommandLine/LinearGradientConsoleStyle.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The linear gradient console text style. -/// -public class LinearGradientConsoleStyle : IConsoleTextPrettier -{ - private readonly Color? fromFore; - private readonly Color? toFore; - private readonly Color? fromBack; - private readonly Color? toBack; - - /// - /// Initialzies a new instance of the LinearGradientConsoleStyle class. - /// - /// The fallback foreground color. - /// The from foreground color. - /// The to foreground color. - public LinearGradientConsoleStyle(ConsoleColor? fallbackForegroundColor, Color fromForegroundColor, Color toForegroundColor) - { - FallbackForegroundColor = fallbackForegroundColor; - fromFore = fromForegroundColor; - toFore = toForegroundColor; - } - - /// - /// Initialzies a new instance of the LinearGradientConsoleStyle class. - /// - /// The fallback foreground color. - /// The from foreground color. - /// The to foreground color. - /// The fallback background color. - /// The from background color. - /// The to background color. - public LinearGradientConsoleStyle(ConsoleColor? fallbackForegroundColor, Color fromForegroundColor, Color toForegroundColor, ConsoleColor? fallbackBackgroundColor, Color fromBackgroundColor, Color toBackgroundColor) - : this(fallbackForegroundColor, fromForegroundColor, toForegroundColor) - { - FallbackBackgroundColor = fallbackBackgroundColor; - fromBack = fromBackgroundColor; - toBack = toBackgroundColor; - } - - /// - /// Gets or sets the fallback foreground color. - /// - public ConsoleColor? FallbackForegroundColor { get; set; } - - /// - /// Gets or sets the fallback background color. - /// - public ConsoleColor? FallbackBackgroundColor { get; set; } - - /// - /// Gets or sets a value indicating whether the text is blink. - /// - public bool Blink { get; set; } - - /// - /// Gets or sets a value indicating whether the text is bold. - /// - public bool Bold { get; set; } - - /// - /// Gets or sets a value indicating whether the text is italic. - /// - public bool Italic { get; set; } - - /// - /// Gets or sets a value indicating whether the text is underlined. - /// - public bool Underline { get; set; } - - /// - /// Gets or sets a value indicating whether the text is strikeout. - /// - public bool Strikeout { get; set; } - - /// - /// Creates the console text collection based on this style. - /// - /// The text. - /// A collection of console text. - IEnumerable IConsoleTextPrettier.CreateTextCollection(string s) - { - var col = new List(); - if (string.IsNullOrEmpty(s)) return col; - col.Add(s[0], 1, new ConsoleTextStyle(fromFore, FallbackForegroundColor, fromBack, FallbackBackgroundColor) - { - Blink = Blink, - Bold = Bold, - Italic = Italic, - Underline = Underline, - Strikeout = Strikeout - }); - if (s.Length == 1) - { - if (fromFore.HasValue && toFore.HasValue) - col[0].Style.ForegroundRgbColor = Color.FromArgb((fromFore.Value.R + toFore.Value.R) / 2, (fromFore.Value.G + toFore.Value.G) / 2, (fromFore.Value.B + toFore.Value.B) / 2); - else if (!fromFore.HasValue) - col[0].Style.ForegroundRgbColor = toFore; - if (fromBack.HasValue && toBack.HasValue) - col[0].Style.BackgroundRgbColor = Color.FromArgb((fromBack.Value.R + toBack.Value.R) / 2, (fromBack.Value.G + toBack.Value.G) / 2, (fromBack.Value.B + toBack.Value.B) / 2); - else if (!fromBack.HasValue) - col[0].Style.BackgroundRgbColor = toBack; - return col; - } - - var steps = s.Length - 1; - var hasFore = fromFore.HasValue || toFore.HasValue; - var hasBack = fromBack.HasValue || toBack.HasValue; - var foreDelta = fromFore.HasValue && toFore.HasValue - ? ((toFore.Value.R - fromFore.Value.R) * 1.0 / steps, (toFore.Value.G - fromFore.Value.B) * 1.0 / steps, (toFore.Value.B - fromFore.Value.B) * 1.0 / steps) - : (0.0, 0.0, 0.0); - var backDelta = fromBack.HasValue && toBack.HasValue - ? ((toBack.Value.R - fromBack.Value.R) * 1.0 / steps, (toBack.Value.G - fromBack.Value.B) * 1.0 / steps, (toBack.Value.B - fromBack.Value.B) * 1.0 / steps) - : (0.0, 0.0, 0.0); - double foreR = fromFore?.R ?? toFore?.R ?? 0; - double foreG = fromFore?.G ?? toFore?.G ?? 0; - double foreB = fromFore?.B ?? toFore?.B ?? 0; - double backR = fromBack?.R ?? toBack?.R ?? 0; - double backG = fromBack?.G ?? toBack?.G ?? 0; - double backB = fromBack?.B ?? toBack?.B ?? 0; - for (var i = 1; i < steps; i++) - { - Color? fore = hasFore ? Color.FromArgb( - PlusChannel(ref foreR, foreDelta.Item1), - PlusChannel(ref foreG, foreDelta.Item2), - PlusChannel(ref foreB, foreDelta.Item3)) : null; - Color? back = hasBack ? Color.FromArgb( - PlusChannel(ref backR, backDelta.Item1), - PlusChannel(ref backG, backDelta.Item2), - PlusChannel(ref backB, backDelta.Item3)) : null; - col.Add(s[i], 1, new ConsoleTextStyle(fore, FallbackForegroundColor, back, FallbackBackgroundColor) - { - Blink = Blink, - Bold = Bold, - Italic = Italic, - Underline = Underline, - Strikeout = Strikeout - }); - } - - col.Add(s[s.Length - 1], 1, new ConsoleTextStyle(toFore, FallbackForegroundColor, toBack, FallbackBackgroundColor) - { - Blink = Blink, - Bold = Bold, - Italic = Italic, - Underline = Underline, - Strikeout = Strikeout - }); - return col; - } - - private static int PlusChannel(ref double c, double delta) - { - c = Math.Round(c + delta); - var r = (int)c; - if (r < 0) return 0; - else if (r > 255) return 255; - return r; - } -} diff --git a/Console/CommandLine/ProgressRender.cs b/Console/CommandLine/ProgressRender.cs deleted file mode 100644 index 8f59a609..00000000 --- a/Console/CommandLine/ProgressRender.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using System.Security; - -using Trivial.Collection; -using Trivial.Tasks; - -namespace Trivial.CommandLine; - -/// -/// The extensions for console renderer. -/// -public static partial class ConsoleRenderExtensions -{ - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The command line interface proxy. - /// The options. - /// The progress result. - public static OneProgress WriteLine(this StyleConsole cli, ConsoleProgressStyle style) - => WriteLine(cli, style, null); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The command line interface proxy. - /// The caption; or null if no caption. It will be better if it is less than 20 characters. - /// The progress size. - /// The progress kind. - /// The progress result. - public static OneProgress WriteLine(this StyleConsole cli, ConsoleProgressStyle.Sizes progressSize, string caption, ConsoleProgressStyle.Kinds kind = ConsoleProgressStyle.Kinds.Full) - => WriteLine(cli, progressSize != ConsoleProgressStyle.Sizes.None ? new ConsoleProgressStyle - { - Size = progressSize, - Kind = kind - } : null, caption); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The command line interface proxy. - /// The progress size. - /// The progress kind. - /// The progress result. - public static OneProgress WriteLine(this StyleConsole cli, ConsoleProgressStyle.Sizes progressSize, ConsoleProgressStyle.Kinds kind = ConsoleProgressStyle.Kinds.Full) - => WriteLine(cli, progressSize != ConsoleProgressStyle.Sizes.None ? new ConsoleProgressStyle - { - Size = progressSize, - Kind = kind - } : null, null); - - /// - /// Writes a progress component, followed by the current line terminator, to the standard output stream. - /// - /// The command line interface proxy. - /// The caption; or null if no caption. It will be better if it is less than 20 characters. - /// The style. - /// The progress result. - public static OneProgress WriteLine(this StyleConsole cli, ConsoleProgressStyle style, string caption) - { - if (cli == null) cli = StyleConsole.Default; - if (cli.Mode == StyleConsole.Modes.Text && cli.Handler == null) - { - var progress2 = new OneProgress(); - if (string.IsNullOrWhiteSpace(caption)) - { - cli.WriteLine(Resource.Loading); - progress2.ProgressChanged += (sender, ev) => - { - if (progress2.IsFailed || progress2.IsNotSupported) - cli.WriteLine($"{ev:#0%} {Resource.Error}"); - else if (progress2.IsCompleted) - cli.WriteLine($"√"); - }; - } - else - { - cli.WriteLine($"{caption} \t{Resource.Loading}"); - progress2.ProgressChanged += (sender, ev) => - { - if (progress2.IsFailed || progress2.IsNotSupported) - cli.WriteLine($"{caption} \t{ev:#0%} {Resource.Error}"); - else if (progress2.IsCompleted) - cli.WriteLine($"{caption} \t√"); - }; - } - - return progress2; - } - - if (style == null) style = new ConsoleProgressStyle(); - var status = RenderData(cli, style, caption, null, null); - var progress = new OneProgress(); - var top = TryGetCursorTop(cli) ?? -1; - progress.ProgressChanged += (sender, ev) => - { - var top2 = TryGetCursorTop(cli) ?? -1; - var left2 = TryGetCursorLeft(cli) ?? 0; - cli.Flush(); - if (cli.Mode == StyleConsole.Modes.Cmd && top >= 0 && top2 > top) - cli.MoveCursorBy(0, top - top2 - 1); - else - cli.MoveCursorBy(0, -1); - status = RenderData(cli, style, caption, progress, status); - if (cli.Mode == StyleConsole.Modes.Cmd && top >= 0 && top2 > top) - cli.MoveCursorTo(left2, top2); - }; - return progress; - } - - private static string RenderData(StyleConsole cli, ConsoleProgressStyle style, string caption, OneProgress value, string status) - { - var maxWidth = GetBufferSafeWidth(cli); - var width = style.Size switch - { - ConsoleProgressStyle.Sizes.None => 0, - ConsoleProgressStyle.Sizes.Short => maxWidth > 70 ? 20 : 10, - ConsoleProgressStyle.Sizes.Wide => maxWidth > 88 ? 60 : 40, - ConsoleProgressStyle.Sizes.Full => maxWidth - 5, - _ => maxWidth > 70 ? (maxWidth > 88 ? 40 : 30) : 20 - }; - var barChar = style.Kind switch - { - ConsoleProgressStyle.Kinds.AngleBracket => '>', - ConsoleProgressStyle.Kinds.Plus => '+', - ConsoleProgressStyle.Kinds.Sharp => '#', - ConsoleProgressStyle.Kinds.X => 'x', - ConsoleProgressStyle.Kinds.O => 'o', - _ => ' ', - }; - var pendingChar = style.Kind switch - { - ConsoleProgressStyle.Kinds.AngleBracket => '=', - ConsoleProgressStyle.Kinds.Plus => '-', - ConsoleProgressStyle.Kinds.Sharp => '-', - ConsoleProgressStyle.Kinds.X => '.', - ConsoleProgressStyle.Kinds.O => '.', - _ => ' ', - }; - var col = new List(); - if (!string.IsNullOrWhiteSpace(caption)) - { - var sb = new StringBuilder(); - var j = style.IgnoreCaptionSeparator ? 0 : 1; - foreach (var c in caption) - { - var c2 = c; - switch (c) - { - case '\t': - case '\r': - case '\n': - j++; - c2 = ' '; - break; - case '\0': - case '\b': - continue; - default: - j += GetLetterWidth(c); - break; - } - - sb.Append(c2); - } - - if (!style.IgnoreCaptionSeparator) sb.Append(' '); - col.Add(sb, new ConsoleTextStyle(style.CaptionRgbColor, style.CaptionConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); - if (style.Size == ConsoleProgressStyle.Sizes.Full) - width -= j; - } - - var v = value?.Value ?? -1; - if (v > 1) v = 1; - if (double.IsNaN(v)) - { - cli.WriteLine(col); - return null; - } - - var w = (int)Math.Round(width * v); - if (w < 0) w = 0; - var isError = value?.IsFailed == true || value?.IsNotSupported == true; - var isSucc = !isError && value?.IsSuccessful == true; - var newStatus = $"{(isError ? "e" : (isSucc ? "s" : "p"))}{w}/{maxWidth}"; - if (status == newStatus) - { - cli.Flush(); - cli.MoveCursorBy(0, 1); - return status; - } - - if (barChar == ' ') - { - col.Add(barChar, w, new ConsoleTextStyle(null, null, isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor)); - col.Add(pendingChar, width - w, new ConsoleTextStyle(null, null, style.PendingRgbColor, style.PendingConsoleColor)); - } - else - { - col.Add(barChar, w, new ConsoleTextStyle(isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); - col.Add(pendingChar, width - w, new ConsoleTextStyle(style.PendingRgbColor, style.PendingConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); - } - - if (v >= 0) - { - var s = v.ToString("#0%"); - if (s.Length > 3) s = isSucc ? " √" : "99%"; - col.Add(" " + s, new ConsoleTextStyle(style.ValueRgbColor, style.ValueConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); - } - - cli.Flush(); - cli.Clear(StyleConsole.RelativeAreas.Line); - cli.BackspaceToBeginning(); - cli.WriteLine(col); - return status; - } -} diff --git a/Console/CommandLine/ProgressStyle.cs b/Console/CommandLine/ProgressStyle.cs deleted file mode 100644 index 1586a73a..00000000 --- a/Console/CommandLine/ProgressStyle.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The style of progress line console component. -/// -public class ConsoleProgressStyle -{ - /// - /// Progress sizes (width). - /// - public enum Sizes : byte - { - /// - /// Normal size. - /// - Normal = 0, - - /// - /// Short size. - /// - Short = 1, - - /// - /// Wide size. - /// - Wide = 2, - - /// - /// The progress and its related text will stretch horizontal in the console. - /// - Full = 3, - - /// - /// No progress bar but only a value. - /// - None = 4 - } - - /// - /// The output text kinds filling in progress. - /// - public enum Kinds : byte - { - /// - /// Whitespace (rectangle). - /// - Full = 0, - - /// - /// Left angle bracket (less sign). - /// - AngleBracket = 1, - - /// - /// Plus sign. - /// - Plus = 2, - - /// - /// Sharp. - /// - Sharp = 3, - - /// - /// Character x. - /// - X = 4, - - /// - /// Character o. - /// - O = 5 - } - - /// - /// Gets or sets the background color of the component. - /// - [JsonPropertyName("back2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? BackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the background color of the component. - /// - [JsonPropertyName("back")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? BackgroundRgbColor { get; set; } - - /// - /// Gets or sets the progress background color. - /// - [JsonPropertyName("pending2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - public ConsoleColor PendingConsoleColor { get; set; } = ConsoleColor.DarkGray; - - /// - /// Gets or sets the progress background color. - /// - [JsonPropertyName("pending")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PendingRgbColor { get; set; } = Color.FromArgb(68, 68, 68); - - /// - /// Gets or sets the progress bar color. - /// - [JsonPropertyName("bar2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - public ConsoleColor BarConsoleColor { get; set; } = ConsoleColor.Green; - - /// - /// Gets or sets the progress bar color. - /// - [JsonPropertyName("bar")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? BarRgbColor { get; set; } = Color.FromArgb(48, 192, 128); - - /// - /// Gets or sets the error color. - /// - [JsonPropertyName("error2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - public ConsoleColor ErrorConsoleColor { get; set; } = ConsoleColor.Red; - - /// - /// Gets or sets the error color. - /// - [JsonPropertyName("error")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? ErrorRgbColor { get; set; } = Color.FromArgb(212, 48, 48); - - /// - /// Gets or sets the foreground color of caption. - /// - [JsonPropertyName("caption2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? CaptionConsoleColor { get; set; } - - /// - /// Gets or sets the foreground color of caption. - /// - [JsonPropertyName("caption")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? CaptionRgbColor { get; set; } - - /// - /// Gets or sets the foreground color of value. - /// - [JsonPropertyName("value2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? ValueConsoleColor { get; set; } = ConsoleColor.Gray; - - /// - /// Gets or sets the foreground color of value. - /// - [JsonPropertyName("value")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? ValueRgbColor { get; set; } - - /// - /// Gets or sets the progress size (width). - /// - [JsonPropertyName("size")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - public Sizes Size { get; set; } - - /// - /// Gets or sets the progress style. - /// - [JsonPropertyName("kind")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - public Kinds Kind { get; set; } - - /// - /// Gets or sets a value indicating whether remove the white space between caption and progress. - /// - [JsonPropertyName("slim")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] - public bool IgnoreCaptionSeparator { get; set; } -} diff --git a/Console/CommandLine/RepeatedColorConsoleStyle.cs b/Console/CommandLine/RepeatedColorConsoleStyle.cs deleted file mode 100644 index ec30ddcc..00000000 --- a/Console/CommandLine/RepeatedColorConsoleStyle.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The linear gradient console text style. -/// -public class RepeatedColorConsoleStyle : IConsoleTextPrettier -{ - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - public RepeatedColorConsoleStyle() - { - } - - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - /// The fallback foreground color. - /// The foreground colors. - public RepeatedColorConsoleStyle(ConsoleColor fallbackForegroundColor, IEnumerable foregroundColors) - { - ForegroundConsoleColors.Add(fallbackForegroundColor); - if (foregroundColors != null) ForegroundRgbColors.AddRange(foregroundColors); - } - - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - /// The foreground console colors. - /// The foreground RGB colors. - public RepeatedColorConsoleStyle(IEnumerable foregroundConsoleColors, IEnumerable foregroundRgbColors) - { - if (foregroundConsoleColors != null) ForegroundConsoleColors.AddRange(foregroundConsoleColors); - if (foregroundRgbColors != null) ForegroundRgbColors.AddRange(foregroundRgbColors); - } - - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - /// The foreground console colors. - /// The foreground RGB colors. - /// The background console colors. - /// The background RGB colors. - public RepeatedColorConsoleStyle(IEnumerable foregroundConsoleColors, IEnumerable foregroundRgbColors, ConsoleColor? backgroundConsoleColor, Color? backgroundRgbColor) - { - if (foregroundConsoleColors != null) ForegroundConsoleColors.AddRange(foregroundConsoleColors); - if (foregroundRgbColors != null) ForegroundRgbColors.AddRange(foregroundRgbColors); - if (backgroundConsoleColor.HasValue) BackgroundConsoleColors.Add(backgroundConsoleColor.Value); - if (backgroundRgbColor.HasValue) BackgroundRgbColors.Add(backgroundRgbColor.Value); - } - - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - /// The foreground console colors. - /// The foreground RGB colors. - /// The background console colors. - /// The background RGB colors. - public RepeatedColorConsoleStyle(IEnumerable foregroundConsoleColors, IEnumerable foregroundRgbColors, IEnumerable backgroundConsoleColors, IEnumerable backgroundRgbColors) - { - if (foregroundConsoleColors != null) ForegroundConsoleColors.AddRange(foregroundConsoleColors); - if (foregroundRgbColors != null) ForegroundRgbColors.AddRange(foregroundRgbColors); - if (backgroundConsoleColors != null) BackgroundConsoleColors.AddRange(backgroundConsoleColors); - if (backgroundRgbColors != null) BackgroundRgbColors.AddRange(backgroundRgbColors); - } - - /// - /// Initialzies a new instance of the RepeatedColorConsoleStyle class. - /// - /// The foreground console color. - /// The foreground RGB color. - /// The background console colors. - /// The background RGB colors. - public RepeatedColorConsoleStyle(ConsoleColor foregroundConsoleColor, Color foregroundRgbColor, IEnumerable backgroundConsoleColors, IEnumerable backgroundRgbColors) - { - ForegroundConsoleColors.Add(foregroundConsoleColor); - ForegroundRgbColors.Add(foregroundRgbColor); - if (backgroundConsoleColors != null) BackgroundConsoleColors.AddRange(backgroundConsoleColors); - if (backgroundRgbColors != null) BackgroundRgbColors.AddRange(backgroundRgbColors); - } - - /// - /// Gets or sets the foreground console colors. - /// - public List ForegroundConsoleColors { get; } = new(); - - /// - /// Gets or sets the foreground RGB colors. - /// - public List ForegroundRgbColors { get; } = new(); - - /// - /// Gets or sets the background console colors. - /// - public List BackgroundConsoleColors { get; } = new(); - - /// - /// Gets or sets the background RGB colors. - /// - public List BackgroundRgbColors { get; } = new(); - - /// - /// Gets or sets a value indicating whether the text is blink. - /// - public bool Blink { get; set; } - - /// - /// Gets or sets a value indicating whether the text is bold. - /// - public bool Bold { get; set; } - - /// - /// Gets or sets a value indicating whether the text is italic. - /// - public bool Italic { get; set; } - - /// - /// Gets or sets a value indicating whether the text is underlined. - /// - public bool Underline { get; set; } - - /// - /// Gets or sets a value indicating whether the text is strikeout. - /// - public bool Strikeout { get; set; } - - /// - /// Creates the console text collection based on this style. - /// - /// The text. - /// A collection of console text. - IEnumerable IConsoleTextPrettier.CreateTextCollection(string s) - { - var col = new List(); - if (string.IsNullOrEmpty(s)) return col; - if (ForegroundConsoleColors.Count < 2 && ForegroundRgbColors.Count < 2 && BackgroundConsoleColors.Count < 2 && BackgroundRgbColors.Count < 2) - { - col.Add(s, new ConsoleTextStyle( - ForegroundRgbColors.FirstOrDefault(), - ForegroundConsoleColors.FirstOrDefault(), - BackgroundRgbColors.FirstOrDefault(), - BackgroundConsoleColors.FirstOrDefault()) - { - Blink = Blink, - Bold = Bold, - Italic = Italic, - Underline = Underline, - Strikeout = Strikeout - }); - return col; - } - - var i = 0; - foreach (var c in s) - { - Color? foreRgb = ForegroundRgbColors.Count > 0 - ? ForegroundRgbColors[i % ForegroundRgbColors.Count] - : null; - ConsoleColor? foreConsole = ForegroundConsoleColors.Count > 0 - ? ForegroundConsoleColors[i % ForegroundConsoleColors.Count] - : null; - Color? backRgb = BackgroundRgbColors.Count > 0 - ? BackgroundRgbColors[i % BackgroundRgbColors.Count] - : null; - ConsoleColor? backConsole = BackgroundConsoleColors.Count > 0 - ? BackgroundConsoleColors[i % BackgroundConsoleColors.Count] - : null; - i++; - col.Add(c, 1, new ConsoleTextStyle(foreRgb, foreConsole, backRgb, backConsole) - { - Blink = Blink, - Bold = Bold, - Italic = Italic, - Underline = Underline, - Strikeout = Strikeout - }); - } - - return col; - } -} diff --git a/Console/CommandLine/Resource.Designer.cs b/Console/CommandLine/Resource.Designer.cs deleted file mode 100644 index ef0a6fca..00000000 --- a/Console/CommandLine/Resource.Designer.cs +++ /dev/null @@ -1,126 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -namespace Trivial.CommandLine { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resource { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resource() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Trivial.CommandLine.Resource", typeof(Resource).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性,对 - /// 使用此强类型资源类的所有资源查找执行重写。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找类似 End the current conversation. 的本地化字符串。 - /// - internal static string EndConversation { - get { - return ResourceManager.GetString("EndConversation", resourceCulture); - } - } - - /// - /// 查找类似 Error! 的本地化字符串。 - /// - internal static string Error { - get { - return ResourceManager.GetString("Error", resourceCulture); - } - } - - /// - /// 查找类似 Get help. 的本地化字符串。 - /// - internal static string GetHelp { - get { - return ResourceManager.GetString("GetHelp", resourceCulture); - } - } - - /// - /// 查找类似 Loading... 的本地化字符串。 - /// - internal static string Loading { - get { - return ResourceManager.GetString("Loading", resourceCulture); - } - } - - /// - /// 查找类似 Press any key to continue... 的本地化字符串。 - /// - internal static string PressAnyKeyToCont { - get { - return ResourceManager.GetString("PressAnyKeyToCont", resourceCulture); - } - } - - /// - /// 查找类似 Tips: [↑][↓][←][→] Select; [ENTER] OK. 的本地化字符串。 - /// - internal static string SelectionTips { - get { - return ResourceManager.GetString("SelectionTips", resourceCulture); - } - } - - /// - /// 查找类似 Select: 的本地化字符串。 - /// - internal static string ToSelect { - get { - return ResourceManager.GetString("ToSelect", resourceCulture); - } - } - } -} diff --git a/Console/CommandLine/Resource.de.resx b/Console/CommandLine/Resource.de.resx deleted file mode 100644 index f57cd5a8..00000000 --- a/Console/CommandLine/Resource.de.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Beenden Sie die aktuelle Sitzung. - - - Fehler! - - - Holen Sie sich Hilfe. - - - Laden... - - - Drücken Sie eine beliebige Taste, um fortzufahren... - - - Tipps: [↑][↓][←][→] Wählen; [ENTER] OKAY. - - - Wählen: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.en.resx b/Console/CommandLine/Resource.en.resx deleted file mode 100644 index 1a424888..00000000 --- a/Console/CommandLine/Resource.en.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - End the current conversation. - - - Error! - - - Get help. - - - Loading... - - - Press any key to continue... - - - Tips: [↑][↓][←][→] Select; [ENTER] OK. - - - Select: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.es.resx b/Console/CommandLine/Resource.es.resx deleted file mode 100644 index bb3cec0b..00000000 --- a/Console/CommandLine/Resource.es.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Termine la conversación actual. - - - Error! - - - Ayuda. - - - Cargando... - - - Pulsa cualquier tecla para continuar... - - - Tips: [↑][↓][←][→] Seleccione; [ENTER] OK. - - - Seleccione: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.fr.resx b/Console/CommandLine/Resource.fr.resx deleted file mode 100644 index 1d914f8d..00000000 --- a/Console/CommandLine/Resource.fr.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Mettez fin à la conversation en cours. - - - Erreur! - - - Obtenez de l’aide. - - - Chargement... - - - Appuyez sur n’importe quelle touche pour continuer... - - - Conseils: [↑][↓][←][→]=Sélectionnez; [ENTRÉE]=D’accord. - - - Choisir: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.ja.resx b/Console/CommandLine/Resource.ja.resx deleted file mode 100644 index 4bc25396..00000000 --- a/Console/CommandLine/Resource.ja.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 会話の終了。 - - - エラー! - - - 情報を取得します。 - - - 読み込み中…… - - - 任意のキーを押して続行します…… - - - 操作提示:[↑][↓][←][→]=選択;[ENTER]=確定。 - - - 選択してください: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.ko.resx b/Console/CommandLine/Resource.ko.resx deleted file mode 100644 index 9b827c75..00000000 --- a/Console/CommandLine/Resource.ko.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 현재 대화를 종료합니다. - - - 오류! - - - 정보를 가져옵니다. - - - 로드... - - - 계속하려면 키를 누릅니다. - - - 팁: [↑][↓][←][→]=선택;[ENTER]=오케이. - - - 선택: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.pt.resx b/Console/CommandLine/Resource.pt.resx deleted file mode 100644 index 760ee1c9..00000000 --- a/Console/CommandLine/Resource.pt.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Termine a conversa atual. - - - Erro! - - - Pedir ajuda. - - - Carregamento... - - - Pressione qualquer tecla para continuar... - - - Dicas: [↑][↓][←][→] Selecione; [ENTER] OK. - - - Selecione: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.resx b/Console/CommandLine/Resource.resx deleted file mode 100644 index 1a424888..00000000 --- a/Console/CommandLine/Resource.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - End the current conversation. - - - Error! - - - Get help. - - - Loading... - - - Press any key to continue... - - - Tips: [↑][↓][←][→] Select; [ENTER] OK. - - - Select: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.ru.resx b/Console/CommandLine/Resource.ru.resx deleted file mode 100644 index a75dd632..00000000 --- a/Console/CommandLine/Resource.ru.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Завершите текущую беседу. - - - Ошибка! - - - Справка. - - - Погрузка... - - - Нажмите любую клавишу, чтобы продолжить... - - - Советы: [↑][↓][←][→] Выбирать; [ENTER] Ок. - - - Выбирать: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.zh-Hans.resx b/Console/CommandLine/Resource.zh-Hans.resx deleted file mode 100644 index 78d59956..00000000 --- a/Console/CommandLine/Resource.zh-Hans.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 退出当前会话。 - - - 错误! - - - 获取帮助。 - - - 加载中…… - - - 按任意键继续…… - - - 请先按方向键进行选择,然后按回车键确定。 - - - 请选择: - - \ No newline at end of file diff --git a/Console/CommandLine/Resource.zh-Hant.resx b/Console/CommandLine/Resource.zh-Hant.resx deleted file mode 100644 index 92909c0f..00000000 --- a/Console/CommandLine/Resource.zh-Hant.resx +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 退出當前會話。 - - - 錯誤! - - - 獲取説明。 - - - 載入中…… - - - 按任意鍵繼續...... - - - 操作提示:[↑][↓][←][→]=選擇;[ENTER]=確定。 - - - 請選擇: - - \ No newline at end of file diff --git a/Console/CommandLine/SelectionOptions.cs b/Console/CommandLine/SelectionOptions.cs deleted file mode 100644 index 730e7d57..00000000 --- a/Console/CommandLine/SelectionOptions.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Trivial.Text; - -namespace Trivial.CommandLine; - -/// -/// The selection options. -/// -public class SelectionConsoleOptions : ICloneable -{ - /// - /// Gets or sets the minimum length for each item. - /// - [JsonPropertyName("minlen")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public int? MinLength { get; set; } - - /// - /// Gets or sets the maximum length for each item. - /// - [JsonPropertyName("maxlen")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public int? MaxLength { get; set; } - - /// - /// Gets or sets the maximum column count to display. - /// - [JsonPropertyName("columns")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public int? Column { get; set; } - - /// - /// Gets or sets maximum row count per page. - /// null for disable paging. - /// - [JsonPropertyName("rows")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public int? MaxRow { get; set; } - - /// - /// Gets or sets the tips. - /// null for disable tips. - /// - [JsonPropertyName("tip")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string Tips { get; set; } = Resource.SelectionTips; - - /// - /// Gets or sets the paging tips. - /// Or null to disable tips. - /// - [JsonPropertyName("pagetip")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string PagingTips { get; set; } = "← [PgUp] | {from} - {end} / {total} | [PgDn] →"; - - /// - /// Gets or sets the question message for keyboard selecting. - /// Or null to disable additional question line. - /// - [JsonPropertyName("q")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string Question { get; set; } = Resource.ToSelect; - - /// - /// Gets or sets the question message for manual typing. - /// Or null to disable manual mode. - /// - [JsonPropertyName("manualq")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string ManualQuestion { get; set; } - - /// - /// Gets or sets the question message displayed when it is not supported. - /// Or null to disable manual mode. - /// - [JsonPropertyName("notsupportq")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string QuestionWhenNotSupported { get; set; } - - /// - /// Gets or sets the foreground color for item. - /// - [JsonPropertyName("fore")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? ForegroundColor { get; set; } - - /// - /// Gets or sets the background color for item. - /// - [JsonPropertyName("back")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? BackgroundColor { get; set; } - - /// - /// Gets or sets the foreground color for item selected. - /// - [JsonPropertyName("selfore2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? SelectedForegroundConsoleColor { get; set; } = ConsoleColor.Black; - - /// - /// Gets or sets the foreground color for item selected. - /// - [JsonPropertyName("selfore")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? SelectedForegroundRgbColor { get; set; } - - /// - /// Gets or sets the foreground color for item selected. - /// - [JsonPropertyName("selback2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? SelectedBackgroundConsoleColor { get; set; } = ConsoleColor.Cyan; - - /// - /// Gets or sets the foreground color for item selected. - /// - [JsonPropertyName("selback")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? SelectedBackgroundRgbColor { get; set; } = Color.FromArgb(0x55, 0xCC, 0xEE); - - /// - /// Gets or sets the foreground color for question. - /// - [JsonPropertyName("qfore2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? QuestionForegroundConsoleColor { get; set; } - - /// - /// Gets or sets the foreground color for question. - /// - [JsonPropertyName("qfore")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? QuestionForegroundRgbColor { get; set; } - - /// - /// Gets or sets the background color for question. - /// - [JsonPropertyName("qback2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? QuestionBackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the background color for question. - /// - [JsonPropertyName("qback")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? QuestionBackgroundRgbColor { get; set; } - - /// - /// Gets or sets the foreground color for tips. - /// - [JsonPropertyName("tipfore2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? TipsForegroundConsoleColor { get; set; } = ConsoleColor.Yellow; - - /// - /// Gets or sets the foreground color for tips. - /// - [JsonPropertyName("tipfore")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? TipsForegroundRgbColor { get; set; } = Color.FromArgb(0xF9, 0xEE, 0x88); - - /// - /// Gets or sets the background color for tips. - /// - [JsonPropertyName("tipback2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? TipsBackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the background color for tips. - /// - [JsonPropertyName("tipback")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? TipsBackgroundRgbColor { get; set; } - - /// - /// Gets or sets the foreground color for paing tips. - /// - [JsonPropertyName("pagefore2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PagingForegroundConsoleColor { get; set; } - - /// - /// Gets or sets the foreground color for paing tips. - /// - [JsonPropertyName("pagefore")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PagingForegroundRgbColor { get; set; } - - /// - /// Gets or sets the background color for paging tips. - /// - [JsonPropertyName("pageback2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? PagingBackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the background color for paging tips. - /// - [JsonPropertyName("pageback")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? PagingBackgroundRgbColor { get; set; } - - /// - /// Gets or sets the foreground color for default value. - /// - [JsonPropertyName("itemfore2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? ItemForegroundConsoleColor { get; set; } - - /// - /// Gets or sets the foreground color for default value. - /// - [JsonPropertyName("itemfore")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? ItemForegroundRgbColor { get; set; } - - /// - /// Gets or sets the background color for default value. - /// - [JsonPropertyName("itemback2")] - [JsonConverter(typeof(JsonIntegerEnumCompatibleConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public ConsoleColor? ItemBackgroundConsoleColor { get; set; } - - /// - /// Gets or sets the background color for default value. - /// - [JsonPropertyName("itemback")] - [JsonConverter(typeof(JsonNumberConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public Color? ItemBackgroundRgbColor { get; set; } - - /// - /// Gets or sets the prefix for the item. - /// - [JsonPropertyName("prefix")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string Prefix { get; set; } - - /// - /// Gets or sets the prefix for the item selected. - /// - [JsonPropertyName("selprefix")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string SelectedPrefix { get; set; } - - /// - /// Clones an object. - /// - /// The object copied from this instance. - public virtual SelectionConsoleOptions Clone() - => MemberwiseClone() as SelectionConsoleOptions; - - /// - /// Clones an object. - /// - /// The object copied from this instance. - object ICloneable.Clone() - => MemberwiseClone(); -} diff --git a/Console/CommandLine/SelectionRender.cs b/Console/CommandLine/SelectionRender.cs deleted file mode 100644 index 38336d59..00000000 --- a/Console/CommandLine/SelectionRender.cs +++ /dev/null @@ -1,867 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using System.Security; - -using Trivial.Collection; - -namespace Trivial.CommandLine; - -/// -/// The extensions for console renderer. -/// -public static partial class ConsoleRenderExtensions -{ - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(this StyleConsole cli, SelectionData collection, SelectionConsoleOptions options = null) - => Select(cli, collection, options); - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The collection data. - /// The converter. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(this StyleConsole cli, IEnumerable collection, Func> convert, SelectionConsoleOptions options = null) - { - var c = new SelectionData(); - c.AddRange(collection.Select(convert)); - return Select(cli, c, options); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(this StyleConsole cli, IEnumerable> collection, SelectionConsoleOptions options = null) - { - var c = new SelectionData(); - c.AddRange(collection); - return Select(cli, c, options); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The parent foler path. - /// The selection display options. - /// The search string to match against the names of directories and files. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions. - /// The result of selection. - /// searchPattern contains one or more invalid characters defined by the System.IO.Path.GetInvalidPathChars method. - /// The specified path is invalid (for example, it is on an unmapped drive). - /// The caller does not have the required permission. - public static SelectionResult Select(this StyleConsole cli, DirectoryInfo path, SelectionConsoleOptions options = null, string searchPattern = null) - { - var c = new SelectionData(); - var col = string.IsNullOrEmpty(searchPattern) ? path.GetFileSystemInfos() : path.GetFileSystemInfos(searchPattern); - foreach (var f in col) - { - c.Add(f.Name, f); - } - - return Select(cli, c, options); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The parent foler path. - /// true if only display files; otherwise, false. - /// The selection display options. - /// The search string to match against the names of directories and files. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions. - /// The result of selection. - /// searchPattern contains one or more invalid characters defined by the System.IO.Path.GetInvalidPathChars method. - /// The specified path is invalid (for example, it is on an unmapped drive). - /// The caller does not have the required permission. - public static SelectionResult Select(this StyleConsole cli, DirectoryInfo path, bool onlyFiles, SelectionConsoleOptions options = null, string searchPattern = null) - { - if (!onlyFiles) return Select(cli, path, options, searchPattern); - var c = new SelectionData(); - var col = string.IsNullOrEmpty(searchPattern) ? path.GetFiles() : path.GetFiles(searchPattern); - foreach (var f in col) - { - c.Add(f.Name, f); - } - - return Select(cli, c, options); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The parent foler path. - /// A function to test each element for a condition. - /// The selection display options. - /// The result of selection. - /// The specified path is invalid (for example, it is on an unmapped drive). - /// The caller does not have the required permission. - public static SelectionResult Select(this StyleConsole cli, DirectoryInfo path, Func predicate, SelectionConsoleOptions options = null) - { - var c = new SelectionData(); - IEnumerable col = path.GetFileSystemInfos(); - if (predicate != null) col = col.Where(predicate); - foreach (var f in col) - { - c.Add(f.Name, f); - } - - return Select(cli, c, options); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The type of data. - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(this StyleConsole cli, SelectionData collection, SelectionConsoleOptions options = null) - { - if (collection == null) return null; - if (cli == null) cli = StyleConsole.Default; - if (options == null) options = new(); - else options = options.Clone(); - cli.Flush(); - if (cli.Handler == null && cli.Mode == StyleConsole.Modes.Text) - return SelectForText(cli, collection, options); - return Select(cli, collection, options, 0); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The result of selection. - public static SelectionResult Select(this StyleConsole cli, IEnumerable collection, SelectionConsoleOptions options = null) - { - if (collection == null) return null; - if (cli == null) cli = StyleConsole.Default; - if (options == null) options = new(); - else options = options.Clone(); - cli.Flush(); - var c = new SelectionData(); - c.AddRange(collection); - if (cli.Handler == null && cli.Mode == StyleConsole.Modes.Text) - return SelectForText(cli, c, options); - return Select(cli, c, options, 0); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The type of data. - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The index of item selected. - /// The result of selection. - private static SelectionResult Select(StyleConsole cli, SelectionData collection, SelectionConsoleOptions options, int select) - { - var temp = (0, 0, 0, 0, false, false, 0, 0); - var oldSelect = select; - while (true) - { - var list = collection.ToList(); - void resetSelect() - { - if (oldSelect < 0 || oldSelect >= list.Count) return; - var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); - var oldItem = list[oldSelect]; - var y2 = Math.DivRem(oldSelect % temp.Item7, temp.Item4, out var x2) - h; - x2 *= temp.Item8; - cli.MoveCursorBy(x2, y2); - RenderData(cli, oldItem, options, false, temp.Item8); - cli.MoveCursorBy(-x2 - temp.Item8, -y2); - }; - - if (temp.Item3 > 0 && select >= temp.Item1 && select < (temp.Item1 + temp.Item2)) - { - cli.BackspaceToBeginning(); - var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); - if (oldSelect != select) resetSelect(); - if (select < 0 || select >= list.Count) select = 0; - var item = list[select]; - var y = Math.DivRem(select % temp.Item7, temp.Item4, out var x) - h; - x *= temp.Item8; - cli.MoveCursorBy(x, y); - RenderData(cli, item, options, true, temp.Item8); - cli.MoveCursorBy(-x - temp.Item8, -y); - RenderSelectResult(cli, item?.Title, options); - } - else - { - if (temp.Item3 > 0) - { - cli.BackspaceToBeginning(); - var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); - for (var i = 0; i < h; i++) - { - cli.MoveCursorBy(0, -1); - cli.Clear(StyleConsole.RelativeAreas.Line); - } - } - - temp = RenderData(cli, list, options, select); - } - - oldSelect = select; - ConsoleKeyInfo key; - try - { - key = cli.ReadKey(); - } - catch (InvalidOperationException) - { - return SelectByManualTyping(cli, collection, options); - } - catch (IOException) - { - return SelectByManualTyping(cli, collection, options); - } - catch (SecurityException) - { - return SelectByManualTyping(cli, collection, options); - } - catch (NotSupportedException) - { - return SelectByManualTyping(cli, collection, options); - } - - switch (key.Key) - { - case ConsoleKey.Enter: - case ConsoleKey.Select: - case ConsoleKey.Spacebar: - if (select < 0 || select >= list.Count) - { - select = temp.Item1; - if (select < 0 || select >= list.Count) - select = 0; - break; - } - - var sel = list[select]; - RenderSelectResult(cli, sel?.Title, options); - cli.WriteLine(); - return new SelectionResult(sel.Title, select, sel.Data, sel.Title); - case ConsoleKey.Backspace: - case ConsoleKey.Delete: - case ConsoleKey.Clear: - cli.WriteImmediately(' '); - cli.BackspaceToBeginning(); - resetSelect(); - return SelectByManualTyping(cli, collection, options); - case ConsoleKey.Escape: - case ConsoleKey.Pause: - cli.WriteImmediately(' '); - cli.BackspaceToBeginning(); - resetSelect(); - RenderSelectResult(cli, null, options); - cli.WriteLine(); - return new SelectionResult(string.Empty, SelectionResultTypes.Canceled); - case ConsoleKey.Help: - case ConsoleKey.F1: - { - cli.BackspaceToBeginning(); - resetSelect(); - RenderSelectResult(cli, "?", options); - cli.WriteLine(); - var item = collection.Get('?', out select); - return item == null - ? new SelectionResult("?", SelectionResultTypes.Selected) - : new SelectionResult("?", select, item.Data, item.Title); - } - case ConsoleKey.F4: - if (temp.Item3 > 0) - { - cli.BackspaceToBeginning(); - var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); - for (var i = 0; i < h; i++) - { - cli.MoveCursorBy(0, -1); - cli.Clear(StyleConsole.RelativeAreas.Line); - } - } - - return SelectByManualTyping(cli, collection, options, true); - case ConsoleKey.F5: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = 0; - break; - case ConsoleKey.F6: - cli.BackspaceToBeginning(); - resetSelect(); - RenderSelectResult(cli, null, options); - cli.WriteLine(); - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = 0; - temp = RenderData(cli, list, options, select); - break; - case ConsoleKey.F12: - { - cli.BackspaceToBeginning(); - resetSelect(); - RenderSelectResult(cli, "?", options); - cli.WriteLine(); - var item = collection.Get('?', out select); - return item == null - ? new SelectionResult("?", SelectionResultTypes.Canceled) - : new SelectionResult("?", select, item.Data, item.Title); - } - case ConsoleKey.PageUp: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = 0; - else - select = Math.Max(0, temp.Item1 - temp.Item7); - break; - case ConsoleKey.PageDown: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = list.Count - 1; - else - select = Math.Min(list.Count - 1, temp.Item1 + temp.Item7); - break; - case ConsoleKey.UpArrow: - if (select < temp.Item4) - { - select += list.Count - (list.Count % temp.Item4); - if (select >= list.Count) select -= temp.Item4; - if (select >= list.Count) select = list.Count - 1; - else if (select < 0) select = 0; - } - else - { - select -= temp.Item4; - } - - break; - case ConsoleKey.DownArrow: - select += temp.Item4; - if (select >= list.Count) - { - select %= temp.Item4; - if (select >= list.Count) select = list.Count - 1; - } - - break; - case ConsoleKey.LeftArrow: - select--; - if (select < 0) select = list.Count - 1; - break; - case ConsoleKey.RightArrow: - select++; - if (select >= list.Count) select = 0; - break; - case ConsoleKey.Home: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = 0; - else - select = temp.Item1; - break; - case ConsoleKey.End: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - select = list.Count - 1; - else - select = temp.Item1 + temp.Item2 - 1; - break; - default: - { - var item = collection.Get(key.KeyChar, out select); - if (item == null) - { - select = oldSelect; - continue; - } - - cli.WriteImmediately(' '); - cli.BackspaceToBeginning(); - resetSelect(); - RenderSelectResult(cli, item.Title, options); - cli.WriteLine(); - return new SelectionResult(item.Title, select, item.Data, item.Title); - } - } - } - } - - /// - /// Tests if the input string is to get help. - /// - /// The input string. - /// true if to get help; otherwise, false. - public static bool IsAboutToGetHelp(string s) - => !string.IsNullOrEmpty(s) && s.Trim().ToLowerInvariant() switch - { - "?" or "help" or "gethelp" or "get-help" or "-?" or "/h" or "--?" or "-help" or "--help" or "/help" or "帮助" or "bangzhu" or "/bangzhu" or "--bangzhu" or "获取帮助" or "助け" or "❓" => true, - _ => false - }; - - /// - /// Tests if the input string is to exit. - /// - /// The input string. - /// true if to exit; otherwise, false. - public static bool IsAboutToExit(string s) - => !string.IsNullOrEmpty(s) && s.Trim().ToLowerInvariant() switch - { - "exit" or "quit" or "close" or "bye" or "byebye" or "goodbye" or "good-bye" or "end" or "shutdown" or "shut-down" or "关闭" or "退出" or "再见" or "guanbi" or "tuichu" or "zaijian" or "さようなら" => true, - _ => false - }; - - /// - /// Writes a collection of item for selecting. - /// - /// The type of data. - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The index of item selected. - /// The result of selection: offset, count, rows, columns, paging tips, customized tips, page size, item length. - private static (int, int, int, int, bool, bool, int, int) RenderData(this StyleConsole cli, List> collection, SelectionConsoleOptions options, int select) - { - var maxWidth = GetBufferSafeWidth(cli); - var itemLen = options.Column.HasValue ? (int)Math.Floor(maxWidth * 1.0 / options.Column.Value) : maxWidth; - if (options.MaxLength.HasValue) itemLen = Math.Min(options.MaxLength.Value, itemLen); - if (options.MinLength.HasValue) itemLen = Math.Max(options.MinLength.Value, itemLen); - if (itemLen > maxWidth) itemLen = maxWidth; - var columns = (int)Math.Floor(maxWidth * 1.0 / itemLen); - if (options.Column.HasValue && columns > options.Column.Value) columns = options.Column.Value; - var maxRows = 50; - try - { - maxRows = Console.BufferHeight - 5; - if (maxRows < 1) maxRows = 50; - } - catch (InvalidOperationException) - { - } - catch (IOException) - { - } - catch (SecurityException) - { - } - catch (NotSupportedException) - { - } - - if (options.MaxRow.HasValue && options.MaxRow.Value < maxRows) - maxRows = options.MaxRow.Value; - var pageSize = columns * maxRows; - var needPaging = collection.Count > pageSize; - if (select >= collection.Count) select = collection.Count - 1; - var list = collection; - var offset = 0; - if (select >= pageSize) - { - offset = (int)Math.Floor(select * 1.0 / pageSize) * pageSize; - list = list.Skip(offset).Take(pageSize).ToList(); - } - else if (needPaging) - { - list = list.Take(pageSize).ToList(); - } - - var i = offset; - var lastColIndex = columns - 1; - var rows = -1; - SelectionItem selItem = null; - foreach (var item in list) - { - if (string.IsNullOrEmpty(item.Title)) continue; - var isSel = i == select; - if (isSel) selItem = item; - RenderData(cli, item, options, isSel, itemLen); - var indexInRow = i % columns; - if (indexInRow == lastColIndex) - cli.Write(Environment.NewLine); - else if (indexInRow == 0) - rows++; - i++; - } - - if (list.Count % columns > 0) cli.Write(Environment.NewLine); - var hasPagingTips = false; - var tipsP = options.PagingTips; - if (needPaging && !string.IsNullOrEmpty(tipsP)) - { - cli.Write( - new ConsoleTextStyle( - options.PagingForegroundRgbColor, - options.PagingForegroundConsoleColor ?? options.ForegroundColor, - options.PagingBackgroundRgbColor, - options.PagingBackgroundConsoleColor ?? options.BackgroundColor), - tipsP - .Replace("{from}", (offset + 1).ToString()) - .Replace("{end}", (offset + list.Count).ToString()) - .Replace("{count}", list.Count.ToString("g")) - .Replace("{size}", pageSize.ToString("g")) - .Replace("{total}", collection.Count.ToString("g"))); - cli.Write(Environment.NewLine); - hasPagingTips = true; - } - - var hasTips = false; - if (!string.IsNullOrEmpty(options.Tips)) - { - cli.Write( - new ConsoleTextStyle( - options.TipsForegroundRgbColor, - options.TipsForegroundConsoleColor ?? options.ForegroundColor, - options.TipsBackgroundRgbColor, - options.TipsBackgroundConsoleColor ?? options.BackgroundColor), - options.Tips.Length < maxWidth - 1 - ? options.Tips - : (options.Tips.Substring(0, maxWidth - 5) + "...")); - cli.Write(Environment.NewLine); - hasTips = true; - } - - RenderSelectResult(cli, selItem?.Title, options); - return (offset, list.Count, rows, columns, hasPagingTips, hasTips, pageSize, itemLen); - } - - private static void RenderSelectResult(StyleConsole cli, string value, SelectionConsoleOptions options) - { - cli.Write( - new ConsoleTextStyle( - options.QuestionForegroundRgbColor, - options.QuestionForegroundConsoleColor ?? options.ForegroundColor, - options.QuestionBackgroundRgbColor, - options.QuestionBackgroundConsoleColor ?? options.BackgroundColor), - options.Question); - if (!string.IsNullOrWhiteSpace(value)) - cli.WriteImmediately(options.ForegroundColor, options.BackgroundColor, value); - else - cli.Flush(); - } - - private static void RenderData(StyleConsole cli, SelectionItem item, SelectionConsoleOptions options, bool isSelect, int len) - { - var style = isSelect ? new ConsoleTextStyle( - options.SelectedForegroundRgbColor, - options.SelectedForegroundConsoleColor ?? options.ForegroundColor, - options.SelectedBackgroundRgbColor, - options.SelectedBackgroundConsoleColor ?? options.BackgroundColor) : new ConsoleTextStyle( - options.ItemForegroundRgbColor, - options.ItemForegroundConsoleColor ?? options.ForegroundColor, - options.ItemBackgroundRgbColor, - options.ItemBackgroundConsoleColor ?? options.BackgroundColor); - var sb = new StringBuilder(); - var j = 0; - var maxLen = len - 1; - var curLeft = TryGetCursorLeft(cli) ?? -1; - foreach (var c in (isSelect ? options.SelectedPrefix : options.Prefix) ?? string.Empty) - { - var c2 = c; - switch (c) - { - case '\t': - case '\r': - case '\n': - j++; - c2 = ' '; - break; - case '\0': - case '\b': - continue; - default: - j += GetLetterWidth(c); - break; - } - - if (j >= maxLen) break; - sb.Append(c2); - } - - foreach (var c in item.Title) - { - var c2 = c; - switch (c) - { - case '\t': - case '\r': - case '\n': - j++; - c2 = ' '; - break; - case '\0': - case '\b': - continue; - default: - j += GetLetterWidth(c); - break; - } - - if (j >= maxLen) break; - sb.Append(c2); - } - - if (curLeft >= 0) - { - cli.WriteImmediately(style, sb); - var rest = curLeft + len - cli.CursorLeft; - if (rest > 0) - cli.WriteImmediately(style, ' ', rest); - else if (rest < 0) - cli.WriteImmediately( - new ConsoleTextStyle( - options.ItemForegroundRgbColor, - options.ItemForegroundConsoleColor ?? options.ForegroundColor, - options.ItemBackgroundRgbColor, - options.ItemBackgroundConsoleColor ?? options.BackgroundColor), - " \b"); - } - else - { - sb.Append(' ', len - j); - cli.WriteImmediately(style, sb); - } - - try - { - if (curLeft >= 0) - { - curLeft += len; - var rest = curLeft - cli.CursorLeft; - if (rest < 0) - { - cli.MoveCursorBy(rest, 0); - cli.WriteImmediately( - new ConsoleTextStyle( - options.ItemForegroundRgbColor, - options.ItemForegroundConsoleColor ?? options.ForegroundColor, - options.ItemBackgroundRgbColor, - options.ItemBackgroundConsoleColor ?? options.BackgroundColor), - " \b"); - } - else if (rest > 0) - { - cli.MoveCursorBy(rest, 0); - } - } - } - catch (InvalidOperationException) - { - } - catch (IOException) - { - } - catch (SecurityException) - { - } - catch (NotSupportedException) - { - } - } - - private static int GetLetterWidth(char c) - { - if (c < 0x2E80) return 1; - return c < 0xA500 || (c >= 0xF900 && c < 0xFB00) || (c >= 0xFE30 && c < 0xFE70) - ? 2 - : 1; - } - - /// - /// Asks to type the item keyword. - /// - /// The type of data. - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// true if list all data before typing; otherwise, false. - /// The result of selection. - private static SelectionResult SelectByManualTyping(StyleConsole cli, SelectionData collection, SelectionConsoleOptions options, bool listAllData = false) - { - cli.BackspaceToBeginning(); - int i; - if (listAllData) - { - var maxWidth = GetBufferSafeWidth(cli); - var itemLen = options.Column.HasValue ? (int)Math.Floor(maxWidth * 1.0 / options.Column.Value) : maxWidth; - if (options.MaxLength.HasValue) itemLen = Math.Min(options.MaxLength.Value, itemLen); - if (options.MinLength.HasValue) itemLen = Math.Max(options.MinLength.Value, itemLen); - if (itemLen > maxWidth) itemLen = maxWidth; - var columns = (int)Math.Floor(maxWidth * 1.0 / itemLen); - if (options.Column.HasValue && columns > options.Column.Value) columns = options.Column.Value; - var list = collection.ToList(); - i = 0; - var lastColIndex = columns - 1; - var rows = -1; - foreach (var ele in list) - { - if (string.IsNullOrEmpty(ele.Title)) continue; - RenderData(cli, ele, options, false, itemLen); - var indexInRow = i % columns; - if (indexInRow == lastColIndex) - cli.Write(Environment.NewLine); - else if (indexInRow == 0) - rows++; - i++; - } - - if (list.Count % columns > 0) cli.Write(Environment.NewLine); - return SelectByManualTyping(cli, collection, options); - } - - cli.WriteImmediately( - new ConsoleTextStyle( - options.QuestionForegroundRgbColor, - options.QuestionForegroundConsoleColor ?? options.ForegroundColor, - options.QuestionBackgroundRgbColor, - options.QuestionBackgroundConsoleColor ?? options.BackgroundColor), - options.ManualQuestion ?? options.Question); - string s; - try - { - s = cli.ReadLine(); - } - catch (IOException) - { - return new SelectionResult(string.Empty, SelectionResultTypes.NotSupported); - } - catch (InvalidOperationException) - { - return new SelectionResult(string.Empty, SelectionResultTypes.NotSupported); - } - catch (ArgumentException) - { - return new SelectionResult(string.Empty, SelectionResultTypes.NotSupported); - } - catch (NotSupportedException) - { - return new SelectionResult(string.Empty, SelectionResultTypes.NotSupported); - } - - if (string.IsNullOrEmpty(s)) - return new SelectionResult(s, SelectionResultTypes.Canceled); - SelectionItem item = null; - if (s.Trim().Length == 1) - { - item = collection.Get(s[0], out i); - if (item != null) - return new SelectionResult(s, i, item.Data, item.Title); - } - - i = -1; - foreach (var ele in collection.ToList()) - { - i++; - if (ele.Title != s) - continue; - item = ele; - break; - } - - return item == null - ? new SelectionResult(s, SelectionResultTypes.Typed) - : new SelectionResult(s, i, item.Data, item.Title, SelectionResultTypes.Typed); - } - - /// - /// Writes a collection of item for selecting. - /// - /// The type of data. - /// The command line interface proxy. - /// The collection data. - /// The selection display options. - /// The result of selection. - private static SelectionResult SelectForText(StyleConsole cli, SelectionData collection, SelectionConsoleOptions options) - { - var list = collection.ToList(); - cli.WriteLines(list.Select((ele, i) => $"#{i + 1}\t{ele.Title}")); - var style = new ConsoleTextStyle( - options.QuestionForegroundRgbColor, - options.QuestionForegroundConsoleColor ?? options.ForegroundColor, - options.QuestionBackgroundRgbColor, - options.QuestionBackgroundConsoleColor ?? options.BackgroundColor); - cli.Write(style, options.QuestionWhenNotSupported ?? options.ManualQuestion ?? options.Question); - string text; - try - { - text = cli.ReadLine(); - } - catch (NotSupportedException) - { - return new SelectionResult(null, SelectionResultTypes.NotSupported); - } - catch (InvalidOperationException) - { - return new SelectionResult(null, SelectionResultTypes.NotSupported); - } - catch (IOException) - { - return new SelectionResult(null, SelectionResultTypes.NotSupported); - } - catch (ArgumentException) - { - return new SelectionResult(null, SelectionResultTypes.NotSupported); - } - - if (string.IsNullOrEmpty(text)) - { - cli.Write(style, options.QuestionWhenNotSupported ?? options.ManualQuestion ?? options.Question); - text = cli.ReadLine(); - if (string.IsNullOrEmpty(text)) - return new SelectionResult(text, SelectionResultTypes.Canceled); - } - - SelectionItem item = null; - int i; - if (text.Trim().Length == 1) - { - item = collection.Get(text[0], out i); - if (item != null) - return new SelectionResult(text, i, item.Data, item.Title); - } - -#pragma warning disable IDE0057 - if (text.StartsWith("#") && int.TryParse(text.Substring(1).Trim(), out i) && i > 0 && i <= list.Count) - { - item = list[i]; - return new SelectionResult(text, i, item.Data, item.Title); - } -#pragma warning restore IDE0057 - - i = -1; - foreach (var ele in list) - { - i++; - if (ele.Title != text) - continue; - item = ele; - break; - } - - if (item != null) - return new SelectionResult(text, i, item.Data, item.Title, SelectionResultTypes.Typed); - - if (int.TryParse(text.Trim(), out i) && i > 0 && i <= list.Count) - { - item = list[i]; - return new SelectionResult(text, i, item.Data, item.Title); - } - - return new SelectionResult(text, SelectionResultTypes.Typed); - } -} diff --git a/Console/Console.csproj b/Console/Console.csproj deleted file mode 100644 index 3ddeff2c..00000000 --- a/Console/Console.csproj +++ /dev/null @@ -1,84 +0,0 @@ - - - - net8.0;net6.0;net48;net462;net461 - Trivial.Console - Trivial - Trivial.Console - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 - The rich user interface console controls and utilities. - Copyright (c) 2018 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/console - true - true - snupkg - https://github.com/nuscien/trivial - git - true - cmd.png - https://github.com/nuscien/trivial/raw/master/Materials/logo.png - console - README.md - 12.0 - True - ..\Trivial.snk - - - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Console.xml - - - - ..\bin\Release\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Console.xml - - - - NETOLDVER - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resource.resx - - - - - - ResXFileCodeGenerator - Resource.Designer.cs - - - - diff --git a/Console/README.md b/Console/README.md deleted file mode 100644 index fb73391d..00000000 --- a/Console/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# [Trivial.Console](https://trivial.kingcean.net/cmdline) - -This library includes a lot of useful rich command line controls. - -## Import - -Add following namespace to your code file to use. - -```csharp -using Trivial.CommandLine; -``` - -## Select - -A beautiful list or table with customized style to the standard output stream -so that user just need press the arrow buttons and `ENTER` in keyboard to select. - -```csharp -// Create an instance for adding items and setting options. -var col = new Trivial.Collection.SelectionData(); - -// Add some items. For each item, you can set a hotkey, a display name and the data. -col.Add('a', "char a", "a"); -col.Add('b', "char b", "b"); -for (var i = 0; i < 120; i++) -{ - col.Add("num " + i, i.ToString()); -} - -// Create an options for display. -var options = new SelectionOptions -{ - // You can define a question string after the list. - Question = "Please select one: ", - - // We can define the colors of the item selected. - SelectedForegroundConsoleColor = ConsoleColor.White, - SelectedBackgroundConsoleColor = ConsoleColor.Blue, - - // The selected item will also be displayed after the question string. - // So you can define its color. - ItemForegroundConsoleColor = ConsoleColor.Cyan, - - // At the end of the list, the tips will be displayed before user press any key. - // There is a default value and you can customize it. - // And you can disable it by set it as null. - Tips = "Tips: You can use arrow key to select and press ENTER key to continue.", - - // Then you can define its color. - TipsForegroundConsoleColor = ConsoleColor.Yellow, - - // You can define the prefix for the item and the one selected. - SelectedPrefix = "> ", - Prefix = " ", - - // You can define the column count for the list. - Column = 5, - - // You can define the maximum rows to displayed. - // A paging will be displayed if the count of the list is greater than it. - MaxRow = 10, - - // Press ESC can cancel this selection. - // But you can enable the manual way by set a manual question - // so that user can type the words directly. - ManualQuestion = "Type: " -}; - -// Write it to the standard output stream and wait for user selection. -var result = DefaultConsole.Select(col, options); - -// You can get the result. -DefaultConsole.WriteLine("The result is {0}.", result.Value); -``` - -## Progress - -A progress bar in terminal that can present the latest state during the specific task running. - -```csharp -// Define an options that you can custom the style. -var progressStyle = new ConsoleProgressStyle -{ - ValueConsoleColor = ConsoleColor.White -}; - -// Ouput the component in console and get the progress instance to update. -var progress = DefaultConsole.WriteLine(progressStyle, "Processing"); - -// A time-consuming work here. -for (var i = 0; i <= 50; i++) -{ - await Task.Delay(10); - - // And report the progress updated. - progress.Report(0.02 * i); -} -``` - -## JSON - -Following is a sample to format JSON into terminal. - -```csharp -var json = new Trivial.Text.JsonObjectNode(); -// and then add some properties to json. -DefaultConsole.WriteLine(json); -``` - -## Linear gradient - -Output a string with linear gradient. - -```csharp -DefaultConsole.WriteLine(new LinearGradientConsoleStyle( - ConsoleColor.Gray, // Fallback color. - Color.FromArgb(15, 250, 250), // From color. - Color.FromArgb(85, 168, 255)) // To color - { - Bold = true // Additional font style - },"Trivial Sample"); -``` diff --git a/Core/Core.csproj b/Core/Core.csproj index 0d7b7fa8..b92abb41 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -1,49 +1,27 @@  + + net8.0;net6.0;net48;net462;net461 Trivial Trivial Trivial - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 A library providing lots of useful utilities, models and services, including interceptor, retry policy, writable JSON DOM, PEM, JWT, stream combination, JSON HTTP web client, JSON converters, CSV parser, numerals, coordinates, angle, arithmetic, sets, colors, etc. - Copyright (c) 2018 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/core - true true snupkg - https://github.com/nuscien/trivial - git - true logo.png https://github.com/nuscien/trivial/raw/main/Materials/logo.png tasks interceptor numerals json oauth2-client jwt-token csv-parser stream pem coordinates uri - README.md - 12.0 - ..\Materials\Trivial.ico - True - ..\Trivial.snk - - - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.xml - - ..\bin\Release\ + + ..\bin\$(Configuration)\ ..\bin\$(Configuration)\$(TargetFramework)\Trivial.xml - @@ -51,9 +29,6 @@ - - - diff --git a/Maths/Basic/Helper.cs b/Maths/Basic/Helper.cs deleted file mode 100644 index a6dd499c..00000000 --- a/Maths/Basic/Helper.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -internal static class InternalHelper -{ - internal const double DoubleAccuracy = 1E-10; - internal const float SingleAccuracy = 1E-10F; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The instance. - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public static IEnumerable DrawPoints(ICoordinateSinglePoint graph, double left, double right, double accuracy) - { - if (left > right) - { - var temp = left; - left = right; - right = temp; - } - - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < DoubleAccuracy) accuracy = DoubleAccuracy; - var x2 = left; - for (var x = left; x < right; x += accuracy) - { - x2 = x; - var y = graph.GetY(x); - if (!double.IsNaN(y)) yield return new(x, y); - } - - if (x2 >= right) yield break; - var y2 = graph.GetY(right); - if (!double.IsNaN(y2)) yield return new(right, y2); - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The instance. - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public static IEnumerable DrawPoints(ICoordinateSinglePoint graph, float left, float right, float accuracy) - { - if (left > right) - { - var temp = left; - left = right; - right = temp; - } - - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < SingleAccuracy) accuracy = SingleAccuracy; - var x2 = left; - for (var x = left; x < right; x += accuracy) - { - x2 = x; - var y = graph.GetY(x); - if (!double.IsNaN(y)) yield return new(x, y); - } - - if (x2 >= right) yield break; - var y2 = graph.GetY(right); - if (!double.IsNaN(y2)) yield return new(right, y2); - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The instance. - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public static IEnumerable DrawPoints(ICoordinateTuplePoint graph, double left, double right, double accuracy) - { - if (left > right) - { - var temp = left; - left = right; - right = temp; - } - - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < DoubleAccuracy) accuracy = DoubleAccuracy; - var x2 = left; - for (var x = left; x < right; x += accuracy) - { - x2 = x; - var (y1, y2) = graph.GetY(x); - if (!double.IsNaN(y1)) yield return new(x, y1); - if (!double.IsNaN(y2) && y1 != y2) yield return new(x, y2); - } - - if (x2 >= right) yield break; - var (y3, y4) = graph.GetY(right); - if (!double.IsNaN(y3)) yield return new(right, y3); - if (!double.IsNaN(y4) && y3 != y4) yield return new(right, y4); - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The instance. - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public static IEnumerable DrawPoints(ICoordinateTuplePoint graph, float left, float right, float accuracy) - { - if (left > right) - { - var temp = left; - left = right; - right = temp; - } - - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < SingleAccuracy) accuracy = SingleAccuracy; - var x2 = left; - for (var x = left; x < right; x += accuracy) - { - x2 = x; - var (y1, y2) = graph.GetY(x); - if (!double.IsNaN(y1)) yield return new(x, y1); - if (!double.IsNaN(y2) && y1 != y2) yield return new(x, y2); - } - - if (x2 >= right) yield break; - var (y3, y4) = graph.GetY(right); - if (!double.IsNaN(y3)) yield return new(right, y3); - if (!double.IsNaN(y4) && y3 != y4) yield return new(right, y4); - } -} diff --git a/Maths/Collection/Balance.cs b/Maths/Collection/Balance.cs deleted file mode 100644 index aa341d79..00000000 --- a/Maths/Collection/Balance.cs +++ /dev/null @@ -1,334 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Trivial.Collection; - -namespace Trivial.Maths; - -public static partial class CollectionOperation -{ - /// - /// Balances 2 collections. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static void Balance(ref IEnumerable a, ref IEnumerable b, DifferentCollectionCountOptions options) - { - var aCol = a == null ? new List() : new List(a); - var bCol = b == null ? new List() : new List(b); - if (aCol.Count == bCol.Count) return; - var compare = aCol.Count > bCol.Count; - var shorter = compare ? bCol : aCol; - var longer = compare ? aCol : bCol; - var diff = compare ? aCol.Count - bCol.Count : bCol.Count - aCol.Count; - switch (options) - { - case DifferentCollectionCountOptions.PadEnd: - ListExtensions.PadEndTo(shorter, diff); - if (compare) b = bCol; - else a = aCol; - return; - case DifferentCollectionCountOptions.PadBegin: - ListExtensions.PadBeginTo(shorter, diff); - if (compare) b = bCol; - else a = aCol; - return; - case DifferentCollectionCountOptions.TrimEnd: - while (longer.Count > shorter.Count) - { - longer.RemoveAt(shorter.Count); - } - - if (compare) a = aCol; - else b = bCol; - return; - case DifferentCollectionCountOptions.TrimBegin: - while (longer.Count > shorter.Count) - { - longer.RemoveAt(0); - } - - if (compare) a = aCol; - else b = bCol; - return; - case DifferentCollectionCountOptions.Abort: - throw new InvalidOperationException("The count of 2 collections should be same."); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Balances 3 collections. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 3 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static void Balance(ref IEnumerable a, ref IEnumerable b, ref IEnumerable c, DifferentCollectionCountOptions options) - { - var aCol = a == null ? new List() : new List(a); - var bCol = b == null ? new List() : new List(b); - var cCol = c == null ? new List() : new List(c); - if (aCol.Count == bCol.Count && aCol.Count == cCol.Count) return; - var max = Math.Max(Math.Max(aCol.Count, bCol.Count), cCol.Count); - var min = Math.Max(Math.Max(aCol.Count, bCol.Count), cCol.Count); - switch (options) - { - case DifferentCollectionCountOptions.PadEnd: - if (aCol.Count < max) - { - ListExtensions.PadEndTo(aCol, max - aCol.Count); - a = aCol; - } - - if (bCol.Count < max) - { - ListExtensions.PadEndTo(bCol, max - bCol.Count); - b = bCol; - } - - if (cCol.Count < max) - { - ListExtensions.PadEndTo(cCol, max - cCol.Count); - c = cCol; - } - - return; - case DifferentCollectionCountOptions.PadBegin: - if (aCol.Count < max) - { - ListExtensions.PadBeginTo(aCol, max - aCol.Count); - a = aCol; - } - - if (bCol.Count < max) - { - ListExtensions.PadBeginTo(bCol, max - bCol.Count); - b = bCol; - } - - if (cCol.Count < max) - { - ListExtensions.PadBeginTo(cCol, max - cCol.Count); - c = cCol; - } - - return; - case DifferentCollectionCountOptions.TrimEnd: - if (aCol.Count > min) a = aCol; - while (aCol.Count > min) - { - aCol.RemoveAt(min); - } - - if (bCol.Count > min) b = bCol; - while (bCol.Count > min) - { - bCol.RemoveAt(min); - } - - if (cCol.Count > min) c = cCol; - while (cCol.Count > min) - { - cCol.RemoveAt(min); - } - - return; - case DifferentCollectionCountOptions.TrimBegin: - if (aCol.Count > min) a = aCol; - while (aCol.Count > min) - { - aCol.RemoveAt(0); - } - - if (bCol.Count > min) b = bCol; - while (bCol.Count > min) - { - bCol.RemoveAt(0); - } - - if (cCol.Count > min) c = cCol; - while (cCol.Count > min) - { - cCol.RemoveAt(0); - } - - return; - case DifferentCollectionCountOptions.Abort: - throw new InvalidOperationException("The count of 3 collections should be same."); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Applies a specified function to the corresponding elements of 2 collections, producing a sequence of the results. - /// - /// The item type of the first collection. - /// The item type of the second collection. - /// The first collection. - /// The second collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A new collection that contains merged elements of 2 input collections. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable<(T1, T2)> Zip(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - var aCol = a == null ? new List() : new List(a); - var bCol = b == null ? new List() : new List(b); - if (aCol.Count == bCol.Count) - { - for (var i = 0; i < aCol.Count; i++) - { - yield return (aCol[i], bCol[i]); - } - - yield break; - } - - var max = Math.Max(aCol.Count, bCol.Count); - var min = Math.Max(aCol.Count, bCol.Count); - switch (options) - { - case DifferentCollectionCountOptions.PadEnd: - for (var i = 0; i < max; i++) - { - yield return (i < aCol.Count ? aCol[i] : default, i < bCol.Count ? bCol[i] : default); - } - - break; - case DifferentCollectionCountOptions.PadBegin: - if (aCol.Count < max) ListExtensions.PadBeginTo(aCol, max - aCol.Count); - if (bCol.Count < max) ListExtensions.PadBeginTo(bCol, max - bCol.Count); - for (var i = 0; i < max; i++) - { - yield return (aCol[i], bCol[i]); - } - - break; - case DifferentCollectionCountOptions.TrimEnd: - for (var i = 0; i < min; i++) - { - yield return (aCol[i], bCol[i]); - } - - break; - case DifferentCollectionCountOptions.TrimBegin: - while (aCol.Count > min) - { - aCol.RemoveAt(0); - } - - while (bCol.Count > min) - { - bCol.RemoveAt(0); - } - - for (var i = 0; i < min; i++) - { - yield return (aCol[i], bCol[i]); - } - - break; - case DifferentCollectionCountOptions.Abort: - throw new InvalidOperationException("The count of 2 collections should be same."); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Applies a specified function to the corresponding elements of 3 collections, producing a sequence of the results. - /// - /// The item type of the first collection. - /// The item type of the second collection. - /// The item type of the third collection. - /// The first collection. - /// The second collection. - /// The third collection. - /// The preprocessing option for calculating between 3 collections with different count. - /// A new collection that contains merged elements of 3 input collections. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable<(T1, T2, T3)> Zip(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - var aCol = a == null ? new List() : new List(a); - var bCol = b == null ? new List() : new List(b); - var cCol = c == null ? new List() : new List(c); - if (aCol.Count == bCol.Count && aCol.Count == cCol.Count) - { - for (var i = 0; i < aCol.Count; i++) - { - yield return (aCol[i], bCol[i], cCol[i]); - } - - yield break; - } - - var max = Math.Max(Math.Max(aCol.Count, bCol.Count), cCol.Count); - var min = Math.Max(Math.Max(aCol.Count, bCol.Count), cCol.Count); - switch (options) - { - case DifferentCollectionCountOptions.PadEnd: - for (var i = 0; i < max; i++) - { - yield return (i < aCol.Count ? aCol[i] : default, i < bCol.Count ? bCol[i] : default, i < cCol.Count ? cCol[i] : default); - } - - break; - case DifferentCollectionCountOptions.PadBegin: - if (aCol.Count < max) ListExtensions.PadBeginTo(aCol, max - aCol.Count); - if (bCol.Count < max) ListExtensions.PadBeginTo(bCol, max - bCol.Count); - if (cCol.Count < max) ListExtensions.PadBeginTo(cCol, max - cCol.Count); - for (var i = 0; i < max; i++) - { - yield return (aCol[i], bCol[i], cCol[i]); - } - - break; - case DifferentCollectionCountOptions.TrimEnd: - for (var i = 0; i < min; i++) - { - yield return (aCol[i], bCol[i], cCol[i]); - } - - break; - case DifferentCollectionCountOptions.TrimBegin: - while (aCol.Count > min) - { - aCol.RemoveAt(0); - } - - while (bCol.Count > min) - { - bCol.RemoveAt(0); - } - - while (cCol.Count > min) - { - cCol.RemoveAt(0); - } - - for (var i = 0; i < min; i++) - { - yield return (aCol[i], bCol[i], cCol[i]); - } - - break; - case DifferentCollectionCountOptions.Abort: - throw new InvalidOperationException("The count of 3 collections should be same."); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } -} diff --git a/Maths/Collection/BooleansOperation.cs b/Maths/Collection/BooleansOperation.cs deleted file mode 100644 index 853a41db..00000000 --- a/Maths/Collection/BooleansOperation.cs +++ /dev/null @@ -1,310 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The operators for boolean collection. -/// -public enum BooleanCollectionOperators : byte -{ - /// - /// Always returns false. - /// - False = 0, - - /// - /// Always returns true. - /// - True = 1, - - /// - /// And operator. - /// That means to return true if all are true; otherwise, false. - /// - And = 2, - - /// - /// Or operator. - /// That means to return true if one or more are true; otherwise, false. - /// - Or = 3, - - /// - /// And operator first, not operator then. - /// - Nand = 4, - - /// - /// Or operator first, not operator then. - /// - Nor = 5, - - /// - /// As the most ones, including all the same. - /// - Most = 6, - - /// - /// As the most ones, including all the same; or as the first one, if half and half (including all are empty). - /// - MostOrFirst = 7, - - /// - /// As the most ones, including all the same; or as the last one, if half and half (including all are empty). - /// - MostOrLast = 8, - - /// - /// As the least one, or none in items. - /// - Least = 9, - - /// - /// As the least ones (or none); or as the first one, if half and half (including all are empty). - /// - LeastOrFirst = 10, - - /// - /// As the least ones (or none); or as the last one, if half and half (including all are empty). - /// - LeastOrLast = 11, - - /// - /// All are same. - /// - Same = 12, - - /// - /// Different. - /// - Different = 13, -} - -public static partial class CollectionOperation -{ - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static bool Merge(CriteriaBooleanOperator op, IEnumerable input, bool defaultValue) - { - var col = input?.ToList(); - return Merge(op, col) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static bool? Merge(CriteriaBooleanOperator op, IEnumerable input) - { - switch (op) - { - case CriteriaBooleanOperator.And: - foreach (var item in input) - { - if (!item) return false; - } - - return true; - case CriteriaBooleanOperator.Or: - foreach (var item in input) - { - if (item) return true; - } - - return false; - default: - throw NotSupported(op); - } - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static bool? Merge(CriteriaBooleanOperator op, params bool[] input) - => Merge(op, input as IEnumerable); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static bool Merge(BooleanCollectionOperators op, IEnumerable input, bool defaultValue) - { - var col = input?.ToList(); - return Merge(op, col) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The value for true. - /// The value for false. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static T Merge(BooleanCollectionOperators op, IEnumerable input, T trueValue, T falseValue, T defaultValue = default) - { - var col = input?.ToList(); - var b = Merge(op, col); - if (!b.HasValue) return defaultValue; - return b.Value ? trueValue : falseValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static bool? Merge(BooleanCollectionOperators op, IEnumerable input) - { - if (input == null) return Merge(op); - if (input is bool[] arr) - { - if (arr.Length < 1) return Merge(op); - } - else if (input is ICollection col) - { - if (col.Count < 1) return Merge(op); - } - else - { - col = input?.ToList(); - input = col; - if (col.Count < 1) return Merge(op); - } - - switch (op) - { - case BooleanCollectionOperators.False: - return false; - case BooleanCollectionOperators.True: - return true; - case BooleanCollectionOperators.And: - foreach (var item in input) - { - if (!item) return false; - } - - return true; - case BooleanCollectionOperators.Or: - foreach (var item in input) - { - if (item) return true; - } - - return false; - case BooleanCollectionOperators.Nand: - foreach (var item in input) - { - if (!item) return true; - } - - return false; - case BooleanCollectionOperators.Nor: - foreach (var item in input) - { - if (item) return false; - } - - return true; - case BooleanCollectionOperators.Most: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? null : t > f; - } - case BooleanCollectionOperators.MostOrFirst: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? input.First() : t > f; - } - case BooleanCollectionOperators.MostOrLast: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? input.Last() : t > f; - } - case BooleanCollectionOperators.Least: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? null : t < f; - } - case BooleanCollectionOperators.LeastOrFirst: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? input.First() : t < f; - } - case BooleanCollectionOperators.LeastOrLast: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == f ? input.Last() : t < f; - } - case BooleanCollectionOperators.Same: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t == 0 || f == 0; - } - case BooleanCollectionOperators.Different: - { - var t = input.Count(IsTrue); - var f = input.Count(IsFalse); - return t > 0 && f > 0; - } - default: - throw NotSupported(op); - } - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static bool? Merge(BooleanCollectionOperators op, params bool[] input) - => Merge(op, input as IEnumerable); - - private static bool? Merge(BooleanCollectionOperators op) - => op switch - { - BooleanCollectionOperators.True => true, - BooleanCollectionOperators.False => false, - _ => null - }; - - private static bool IsFalse(bool b) - => !b; - - private static bool IsTrue(bool b) - => b; -} diff --git a/Maths/Collection/Calculation.cs b/Maths/Collection/Calculation.cs deleted file mode 100644 index dc458318..00000000 --- a/Maths/Collection/Calculation.cs +++ /dev/null @@ -1,415 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml.Schema; -using Trivial.Collection; - -namespace Trivial.Maths; - -/// -/// The preprocessing options for calculating between 2 collections with different count. -/// -public enum DifferentCollectionCountOptions : byte -{ - /// - /// Pad end for shorter. - /// - PadEnd = 0, - - /// - /// Pad begin for shorter. - /// - PadBegin = 1, - - /// - /// Remove end for longer. - /// - TrimEnd = 2, - - /// - /// Remove begin for longer. - /// - TrimBegin = 3, - - /// - /// Abort and throw invalid operation exception. - /// - Abort = 4, -} - -public static partial class CollectionOperation -{ - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, int c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, long c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, float c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, double c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, decimal c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b); - } - - /// - /// Pluses each item in 3 collections by index. - /// - /// Left collection. - /// Middle collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, IEnumerable c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, ref c, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Pluses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// Additional number to plus. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items plused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Plus(IEnumerable a, IEnumerable b, TimeSpan c, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Plus(a, b, c); - } - - /// - /// Minuses each item in 2 collections by index. - /// - /// Left collection. - /// Right collection. - /// The preprocessing option for calculating between 2 collections with different count. - /// A collection with items minused. - /// The count of the collections are not same and the options is set to abort. - /// The options is not supported. - public static IEnumerable Minus(IEnumerable a, IEnumerable b, DifferentCollectionCountOptions options = DifferentCollectionCountOptions.PadEnd) - { - Balance(ref a, ref b, options); - return Arithmetic.Minus(a, b); - } -} diff --git a/Maths/Collection/CollectionOperation.cs b/Maths/Collection/CollectionOperation.cs deleted file mode 100644 index c23e9620..00000000 --- a/Maths/Collection/CollectionOperation.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - - -/// -/// The operators for number collection. -/// -public enum ComparerCollectionOperators : byte -{ - /// - /// Default value. - /// - None = 0, - - /// - /// The smallest number. - /// - Min = 1, - - /// - /// The largest number. - /// - Max = 2, - - /// - /// The first number. - /// - First = 3, - - /// - /// The last number. - /// - Last = 4, -} - -/// -/// The operations for data collection. -/// -public static partial class CollectionOperation -{ - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static T Merge(ComparerCollectionOperators op, IEnumerable input, T defaultValue = default) where T : IComparable - { - if (input == null) return defaultValue; - if (input is bool[] arr) - { - if (arr.Length < 1) return defaultValue; - } - else if (input is List col) - { - if (col.Count < 1) return defaultValue; - } - else - { - col = input?.ToList(); - input = col; - if (col.Count < 1) return defaultValue; - } - - return op switch - { - ComparerCollectionOperators.None => defaultValue, - ComparerCollectionOperators.Min => input.Min(), - ComparerCollectionOperators.Max => input.Max(), - ComparerCollectionOperators.First => input.First(), - ComparerCollectionOperators.Last => input.Last(), - _ => throw NotSupported(op), - }; - } - private static NotSupportedException NotSupported(T op) - => new($"The operation {op} is not supported.", new ArgumentException("op should be a valid one.", nameof(op))); -} diff --git a/Maths/Collection/FloatingPointCollection.cs b/Maths/Collection/FloatingPointCollection.cs deleted file mode 100644 index cec8aa56..00000000 --- a/Maths/Collection/FloatingPointCollection.cs +++ /dev/null @@ -1,724 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Trivial.Collection; - -namespace Trivial.Maths; - -/// -/// The options for converting a set of number to ratio collection. -/// -public enum RatioConvertionOptions : byte -{ - /// - /// Original. - /// - Scale = 0, - - /// - /// Calculated by soft max. - /// - SoftMax = 1, - - /// - /// Calculated by hard max. That means only the maximum ones only. - /// - HardMax = 2, - - /// - /// Only for the ones above average. - /// - AboveAverage = 3, - - /// - /// Only for the ones above zero (0). - /// - AboveZero = 4, - - /// - /// Equal division. - /// - EqualDivision = 7 -} - -public static partial class CollectionOperation -{ - /// - /// Converts to double-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with double-precision floating-point numbers. - public static IEnumerable ToDoubleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return item; - } - } - - /// - /// Converts to double-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with double-precision floating-point numbers. - public static IEnumerable ToDoubleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return item; - } - } - - /// - /// Converts to double-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with double-precision floating-point numbers. - public static IEnumerable ToDoubleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return item; - } - } - - /// - /// Converts to double-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with double-precision floating-point numbers. - public static IEnumerable ToDoubleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return (double)item; - } - } - - /// - /// Converts to double-precision floating-point number array. - /// - /// The source array to convert. - /// An array with double-precision floating-point numbers. - public static double[] ToDoubleFloatingPointArray(this int[] source) - { - if (source == null) return null; - var arr = new double[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = source[i]; - } - - return arr; - } - - - /// - /// Converts to double-precision floating-point number array. - /// - /// The source array to convert. - /// An array with double-precision floating-point numbers. - public static double[] ToDoubleFloatingPointArray(this long[] source) - { - if (source == null) return null; - var arr = new double[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = source[i]; - } - - return arr; - } - - /// - /// Converts to double-precision floating-point number array. - /// - /// The source array to convert. - /// An array with double-precision floating-point numbers. - public static double[] ToDoubleFloatingPointArray(this float[] source) - { - if (source == null) return null; - var arr = new double[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = source[i]; - } - - return arr; - } - - /// - /// Converts to double-precision floating-point number array. - /// - /// The source array to convert. - /// An array with double-precision floating-point numbers. - public static double[] ToDoubleFloatingPointArray(this decimal[] source) - { - if (source == null) return null; - var arr = new double[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = (double)source[i]; - } - - return arr; - } - - /// - /// Converts to single-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with single-precision floating-point numbers. - public static IEnumerable ToSingleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return item; - } - } - - /// - /// Converts to single-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with single-precision floating-point numbers. - public static IEnumerable ToSingleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return item; - } - } - - /// - /// Converts to single-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with single-precision floating-point numbers. - public static IEnumerable ToSingleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return (float)item; - } - } - - /// - /// Converts to single-precision floating-point number collection. - /// - /// The source sequence to convert. - /// A sequence with single-precision floating-point numbers. - public static IEnumerable ToSingleFloatingPointCollection(this IEnumerable source) - { - if (source == null) yield break; - foreach (var item in source) - { - yield return (float)item; - } - } - - /// - /// Converts to double-precision floating-point number array. - /// - /// The source array to convert. - /// An array with double-precision floating-point numbers. - public static float[] ToSingleFloatingPointArray(this int[] source) - { - if (source == null) return null; - var arr = new float[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = source[i]; - } - - return arr; - } - - - /// - /// Converts to single-precision floating-point number array. - /// - /// The source array to convert. - /// An array with single-precision floating-point numbers. - public static float[] ToSingleFloatingPointArray(this long[] source) - { - if (source == null) return null; - var arr = new float[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = source[i]; - } - - return arr; - } - - /// - /// Converts to single-precision floating-point number array. - /// - /// The source array to convert. - /// An array with single-precision floating-point numbers. - public static float[] ToSingleFloatingPointArray(this double[] source) - { - if (source == null) return null; - var arr = new float[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = (float)source[i]; - } - - return arr; - } - - /// - /// Converts to single-precision floating-point number array. - /// - /// The source array to convert. - /// An array with single-precision floating-point numbers. - public static float[] ToSingleFloatingPointArray(this decimal[] source) - { - if (source == null) return null; - var arr = new float[source.Length]; - for (var i = 0; i < source.Length; i++) - { - arr[i] = (float)source[i]; - } - - return arr; - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static List Ratios(IEnumerable source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - var col = new List(source); - if (col.Count < 1) return new(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(col, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(col); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(col, true); - case RatioConvertionOptions.AboveAverage: - { - var average = col.Average(); - return Ratios(col, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(col, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.Create(col.Count, 1d / col.Count).ToList(); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The converter to get number value from source. - /// The selector to generate result. - /// The convertion options. - /// An array of all ratios. - /// converter or selector is null. - /// The options is not supported. - public static List Ratios(IEnumerable source, Func converter, Func selector, RatioConvertionOptions options = RatioConvertionOptions.Scale) - => Ratios(source, converter, Ratios, options, selector); - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static double[] Ratios(int[] source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - if (source.Length < 1) return Array.Empty(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(source, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(source); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(source, true); - case RatioConvertionOptions.AboveAverage: - { - var average = source.Average(); - return Ratios(source, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(source, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.CreateArray(source.Length, 1d / source.Length); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static List Ratios(IEnumerable source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - var col = new List(source); - if (col.Count < 1) return new(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(col, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(col); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(col, true); - case RatioConvertionOptions.AboveAverage: - { - var average = col.Average(); - return Ratios(col, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(col, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.Create(col.Count, 1d / col.Count).ToList(); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The converter to get number value from source. - /// The selector to generate result. - /// The convertion options. - /// An array of all ratios. - /// converter or selector is null. - /// The options is not supported. - public static List Ratios(IEnumerable source, Func converter, Func selector, RatioConvertionOptions options = RatioConvertionOptions.Scale) - => Ratios(source, converter, Ratios, options, selector); - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static double[] Ratios(double[] source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - if (source.Length < 1) return Array.Empty(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(source, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(source); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(source, true); - case RatioConvertionOptions.AboveAverage: - { - var average = source.Average(); - return Ratios(source, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(source, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.CreateArray(source.Length, 1d / source.Length); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static List Ratios(IEnumerable source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - var col = new List(source); - if (col.Count < 1) return new(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(col, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(col); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(col, true); - case RatioConvertionOptions.AboveAverage: - { - var average = col.Average(); - return Ratios(col, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(col, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.Create(col.Count, 1f / col.Count).ToList(); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The convertion options. - /// An array of all ratios. - /// The options is not supported. - public static float[] Ratios(float[] source, RatioConvertionOptions options = RatioConvertionOptions.Scale) - { - if (source == null) return null; - if (source.Length < 1) return Array.Empty(); - switch (options) - { - case RatioConvertionOptions.Scale: - return Ratios(source, ele => true); - case RatioConvertionOptions.SoftMax: - return StatisticalMethod.Softmax(source); - case RatioConvertionOptions.HardMax: - return StatisticalMethod.Hardmax(source, true); - case RatioConvertionOptions.AboveAverage: - { - var average = source.Average(); - return Ratios(source, ele => ele > average); - } - case RatioConvertionOptions.AboveZero: - return Ratios(source, ele => ele > 0); - case RatioConvertionOptions.EqualDivision: - return ListExtensions.CreateArray(source.Length, 1f / source.Length); - default: - throw new NotSupportedException("The options was not supported.", new ArgumentException("options is invalid.", nameof(options))); - } - } - - /// - /// Computes ratios by given numbers. - /// - /// The source numbers. - /// The converter to get number value from source. - /// The convertion options. - /// The selector to generate result. - /// An array of all ratios. - /// converter or selector is null. - /// The options is not supported. - public static List Ratios(IEnumerable source, Func converter, Func selector, RatioConvertionOptions options = RatioConvertionOptions.Scale) - => Ratios(source, converter, Ratios, options, selector); - - private static List Ratios(IList source, Func predicate) - { - var list = new List(); - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Count; - if (total == 0) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? ((item * 1d - min) / total) : 0d); - } - } - else - { - if (total == 0) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? (item * 1d / total) : 0d); - } - } - - return list; - } - - private static double[] Ratios(int[] source, Func predicate) - { - var arr = new double[source.Length]; - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Length; - if (total == 0) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? ((item * 1d - min) / total) : 0d; - } - } - else - { - if (total == 0) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? (item * 1d / total) : 0d; - } - } - - return arr; - } - - private static List Ratios(IList source, Func predicate) - { - var list = new List(); - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Count; - if (total == 0d) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? ((item - min) / total) : 0d); - } - } - else - { - if (total == 0d) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? (item / total) : 0d); - } - } - - return list; - } - - private static double[] Ratios(double[] source, Func predicate) - { - var arr = new double[source.Length]; - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Length; - if (total == 0d) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? ((item - min) / total) : 0d; - } - } - else - { - if (total == 0d) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? (item / total) : 0d; - } - } - - return arr; - } - - private static List Ratios(IList source, Func predicate) - { - var list = new List(); - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Count; - if (total == 0f) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? ((item - min) / total) : 0f); - } - } - else - { - if (total == 0f) return list; - for (var i = 0; i < source.Count; i++) - { - var item = source[i]; - list.Add(predicate(item) ? (item / total) : 0f); - } - } - - return list; - } - - private static float[] Ratios(float[] source, Func predicate) - { - var arr = new float[source.Length]; - var min = source.Where(predicate).Min(); - var total = source.Where(predicate).Sum(); - if (min < 0) - { - total -= min * source.Length; - if (total == 0f) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? ((item - min) / total) : 0f; - } - } - else - { - if (total == 0f) return arr; - for (var i = 0; i < source.Length; i++) - { - var item = source[i]; - arr[i] = predicate(item) ? (item / total) : 0f; - } - } - - return arr; - } - - private static List Ratios(IEnumerable source, Func converter, Func, RatioConvertionOptions, List> ratios, RatioConvertionOptions options, Func selector) - { - if (source == null) return null; - if (converter == null) throw new ArgumentNullException(nameof(converter), "converter should not be null."); - if (selector == null) throw new ArgumentNullException(nameof(selector), "selector should not be null."); - var list = new List(source); - var col = list.Select(converter); - var r = ratios(col, options); - var result = new List(); - for (var i = 0; i < list.Count; i++) - { - var ratio = i < r.Count ? r[i] : default; - var value = selector(list[i], ratio, i); - result.Add(value); - } - - return result; - } -} diff --git a/Maths/Collection/NumbersOperation.cs b/Maths/Collection/NumbersOperation.cs deleted file mode 100644 index 987187ba..00000000 --- a/Maths/Collection/NumbersOperation.cs +++ /dev/null @@ -1,367 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The operators for number collection. -/// -public enum NumberCollectionOperators : byte -{ - /// - /// Always returns zero (0). - /// - Zero = 0, - - /// - /// The smallest number. - /// - Min = 1, - - /// - /// The largest number. - /// - Max = 2, - - /// - /// The first number. - /// - First = 3, - - /// - /// The last number. - /// - Last = 4, - - /// - /// Sum of the numbers. - /// - Sum = 5, - - /// - /// Average of the numbers. - /// - Average = 6, -} - -public static partial class CollectionOperation -{ - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static int Merge(NumberCollectionOperators op, IEnumerable input, int defaultValue) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static double Merge(NumberCollectionOperators op, IEnumerable input, double defaultValue) - { - var col = input?.ToList(); - var empty = col == null || col.Count < 1; - return op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? defaultValue : col.Sum(), - NumberCollectionOperators.Average => empty ? defaultValue : col.Average(), - NumberCollectionOperators.Min => empty ? defaultValue : col.Min(), - NumberCollectionOperators.Max => empty ? defaultValue : col.Max(), - NumberCollectionOperators.First => empty ? defaultValue : col.First(), - NumberCollectionOperators.Last => empty ? defaultValue : col.Last(), - _ => throw NotSupported(op), - }; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static int? Merge(NumberCollectionOperators op, IEnumerable input) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1); - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static int? Merge(NumberCollectionOperators op, params int[] input) - => Merge(op, input, input == null || input.Length < 1); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static long Merge(NumberCollectionOperators op, IEnumerable input, long defaultValue) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static long? Merge(NumberCollectionOperators op, IEnumerable input) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1); - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static long? Merge(NumberCollectionOperators op, params long[] input) - => Merge(op, input, input == null || input.Length < 1); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static float Merge(NumberCollectionOperators op, IEnumerable input, float defaultValue) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static float? Merge(NumberCollectionOperators op, IEnumerable input) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1); - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static float? Merge(NumberCollectionOperators op, params float[] input) - => Merge(op, input, input == null || input.Length < 1); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static double Merge(NumberCollectionOperators op, IEnumerable input, double defaultValue) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static double? Merge(NumberCollectionOperators op, IEnumerable input) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1); - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static double? Merge(NumberCollectionOperators op, params double[] input) - => Merge(op, input, input == null || input.Length < 1); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The default value for empty. - /// The result. - /// The operator is not supported. - public static decimal Merge(NumberCollectionOperators op, IEnumerable input, decimal defaultValue) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1) ?? defaultValue; - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static decimal? Merge(NumberCollectionOperators op, IEnumerable input) - { - var col = input?.ToList(); - return Merge(op, col, col == null || col.Count < 1); - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static decimal? Merge(NumberCollectionOperators op, params decimal[] input) - => Merge(op, input, input == null || input.Length < 1); - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// true if the input collection is empty or null; otherwise, false. - /// The result. - /// The operator is not supported. - private static int? Merge(NumberCollectionOperators op, IEnumerable input, bool empty) - => op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? null : input.Sum(), - NumberCollectionOperators.Average => empty ? null : (int)Math.Round(input.Average()), - NumberCollectionOperators.Min => empty ? null : input.Min(), - NumberCollectionOperators.Max => empty ? null : input.Max(), - NumberCollectionOperators.First => empty ? null : input.First(), - NumberCollectionOperators.Last => empty ? null : input.Last(), - _ => throw NotSupported(op), - }; - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// true if the input collection is empty or null; otherwise, false. - /// The result. - /// The operator is not supported. - private static long? Merge(NumberCollectionOperators op, IEnumerable input, bool empty) - => op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? null : input.Sum(), - NumberCollectionOperators.Average => empty ? null : (long)Math.Round(input.Average()), - NumberCollectionOperators.Min => empty ? null : input.Min(), - NumberCollectionOperators.Max => empty ? null : input.Max(), - NumberCollectionOperators.First => empty ? null : input.First(), - NumberCollectionOperators.Last => empty ? null : input.Last(), - _ => throw NotSupported(op), - }; - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// true if the input collection is empty or null; otherwise, false. - /// The result. - /// The operator is not supported. - private static float? Merge(NumberCollectionOperators op, IEnumerable input, bool empty) - => op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? null : input.Sum(), - NumberCollectionOperators.Average => empty ? null : input.Average(), - NumberCollectionOperators.Min => empty ? null : input.Min(), - NumberCollectionOperators.Max => empty ? null : input.Max(), - NumberCollectionOperators.First => empty ? null : input.First(), - NumberCollectionOperators.Last => empty ? null : input.Last(), - _ => throw NotSupported(op), - }; - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// true if the input collection is empty or null; otherwise, false. - /// The result. - /// The operator is not supported. - private static double? Merge(NumberCollectionOperators op, IEnumerable input, bool empty) - => op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? null : input.Sum(), - NumberCollectionOperators.Average => empty ? null : input.Average(), - NumberCollectionOperators.Min => empty ? null : input.Min(), - NumberCollectionOperators.Max => empty ? null : input.Max(), - NumberCollectionOperators.First => empty ? null : input.First(), - NumberCollectionOperators.Last => empty ? null : input.Last(), - _ => throw NotSupported(op), - }; - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// true if the input collection is empty or null; otherwise, false. - /// The result. - /// The operator is not supported. - private static decimal? Merge(NumberCollectionOperators op, IEnumerable input, bool empty) - => op switch - { - NumberCollectionOperators.Zero => 0, - NumberCollectionOperators.Sum => empty ? null : input.Sum(), - NumberCollectionOperators.Average => empty ? null : input.Average(), - NumberCollectionOperators.Min => empty ? null : input.Min(), - NumberCollectionOperators.Max => empty ? null : input.Max(), - NumberCollectionOperators.First => empty ? null : input.First(), - NumberCollectionOperators.Last => empty ? null : input.Last(), - _ => throw NotSupported(op), - }; -} diff --git a/Maths/Maths.csproj b/Maths/Maths.csproj deleted file mode 100644 index 4a5dfa62..00000000 --- a/Maths/Maths.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - net8.0;net6.0;net48;net462;net461 - Trivial.Maths - Trivial.Maths - Trivial.Maths - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 - The mathematics utilities. - Copyright (c) 2018 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/core - true - true - snupkg - https://github.com/nuscien/trivial - git - true - maths.png - https://github.com/nuscien/trivial/raw/master/Materials/logo.png - maths - README.md - 12.0 - True - ..\Trivial.snk - - - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Maths.xml - - - - ..\bin\Release\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Maths.xml - - - - NETOLDVER - - - - - - - - - - - - - - - - - - - - - diff --git a/Maths/README.md b/Maths/README.md deleted file mode 100644 index ab83da8e..00000000 --- a/Maths/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# [Trivial.Maths](https://trivial.kingcean.net/web/maths) - -Mathematics utilities. - -## Import - -Add following namespace to your code file to use. - -```csharp -using Trivial.Maths; -``` - -## Geometry - -Compute about point and line. - -```csharp -var angle = Geometry.Angle( - new DoublePoint2D(0, 0), - new DoublePoint2D(1, 0), - new DoublePoint2D(0, 1)); -``` diff --git a/Maths/Statistics/GaussianMixtureModel.cs b/Maths/Statistics/GaussianMixtureModel.cs deleted file mode 100644 index fba93cdf..00000000 --- a/Maths/Statistics/GaussianMixtureModel.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The item of Gaussian Mixture Model. -/// -public struct GaussianMixtureModelItem -{ - /// - /// Initializes a new instance of the GaussianMixtureModelItem class. - /// - /// The weight, - /// The mean. - /// The variance. - public GaussianMixtureModelItem(double weight, double mean, double variance) - { - Weight = weight; - Mean = mean; - Variance = variance; - } - - /// - /// Gets the weights. - /// - public double Weight { get; } - - /// - /// Gets the mean. - /// - public double Mean { get; } - - /// - /// Gets the variances. - /// - public double Variance { get; } - - /// - /// Calculates the Gaussian Mixture Model. - /// - /// The count of the component. - /// The input data. - /// The max count of iterations. - /// The tolerance. - /// An optional random object. - /// A collection of Gaussian Mixture Model. - public static List Calculate(int count, double[] data, int maxIterations = 100, double tolerance = 1e-6, Random random = null) - { - var n = data.Length; - random ??= new(); - var weights = Enumerable.Range(0, count).Select(_ => 1.0 / count).ToArray(); - var means = Enumerable.Range(0, count).Select(_ => data[random.Next(n)]).ToArray(); - var variances = Enumerable.Range(0, count).Select(_ => data.Select(x => Math.Pow(x - means[0], 2)).Average()).ToArray(); - var newWeights = new double[count]; - var newMeans = new double[count]; - var newVariances = new double[count]; - var responsibilities = new double[n, count]; - var prevLogLikelihood = double.NegativeInfinity; - for (var iter = 0; iter < maxIterations; iter++) - { - for (var i = 0; i < n; i++) - { - var probs = new double[count]; - for (var j = 0; j < count; j++) - { - probs[j] = weights[j] * StatisticalMethod.GaussianMixture(data[i], means[j], variances[j]); - } - var sumProbs = probs.Sum(); - for (var j = 0; j < count; j++) - { - responsibilities[i, j] = probs[j] / sumProbs; - } - } - - for (var j = 0; j < count; j++) - { - var respSum = 0.0; - for (var i = 0; i < n; i++) - { - respSum += responsibilities[i, j]; - } - - newWeights[j] = respSum / n; - newMeans[j] = 0; - for (var i = 0; i < n; i++) - { - newMeans[j] += responsibilities[i, j] * data[i]; - } - - newMeans[j] /= respSum; - newVariances[j] = 0; - for (var i = 0; i < n; i++) - { - newVariances[j] += responsibilities[i, j] * Math.Pow(data[i] - newMeans[j], 2); - } - - newVariances[j] /= respSum; - } - - weights = newWeights; - means = newMeans; - variances = newVariances; - var logLikelihood = 0.0; - for (var i = 0; i < n; i++) - { - var probSum = 0.0; - for (var j = 0; j < count; j++) - { - probSum += weights[j] * StatisticalMethod.GaussianMixture(data[i], means[j], variances[j]); - } - - logLikelihood += Math.Log(probSum); - } - - if (Math.Abs(logLikelihood - prevLogLikelihood) < tolerance) break; - prevLogLikelihood = logLikelihood; - } - - var list = new List(); - for (var i = 0; i < count; i++) - { - list.Add(new(weights[i], means[i], variances[i])); - } - - return list; - } -} - -#if NET6_0_OR_GREATER -/// -/// The item of Gaussian Mixture Model. -/// -public struct GaussianMixtureModelItemF -{ - /// - /// Initializes a new instance of the GaussianMixtureModelItemF class. - /// - /// The weight, - /// The mean. - /// The variance. - public GaussianMixtureModelItemF(float weight, float mean, float variance) - { - Weight = weight; - Mean = mean; - Variance = variance; - } - - /// - /// Gets the weights. - /// - public float Weight { get; } - - /// - /// Gets the mean. - /// - public float Mean { get; } - - /// - /// Gets the variances. - /// - public float Variance { get; } - - /// - /// Calculates the Gaussian Mixture Model. - /// - /// The count of the component. - /// The input data. - /// The max count of iterations. - /// The tolerance. - /// An optional random object. - /// A collection of Gaussian Mixture Model. - public static List Calculate(int count, float[] data, int maxIterations = 100, float tolerance = 1e-6f, Random random = null) - { - var n = data.Length; - random ??= new(); - var weights = Enumerable.Range(0, count).Select(_ => 1f / count).ToArray(); - var means = Enumerable.Range(0, count).Select(_ => data[random.Next(n)]).ToArray(); - var variances = Enumerable.Range(0, count).Select(_ => data.Select(x => MathF.Pow(x - means[0], 2)).Average()).ToArray(); - var newWeights = new float[count]; - var newMeans = new float[count]; - var newVariances = new float[count]; - var responsibilities = new float[n, count]; - var prevLogLikelihood = float.NegativeInfinity; - for (var iter = 0; iter < maxIterations; iter++) - { - for (var i = 0; i < n; i++) - { - var probs = new float[count]; - for (var j = 0; j < count; j++) - { - probs[j] = weights[j] * StatisticalMethod.GaussianMixture(data[i], means[j], variances[j]); - } - var sumProbs = probs.Sum(); - for (var j = 0; j < count; j++) - { - responsibilities[i, j] = probs[j] / sumProbs; - } - } - - for (var j = 0; j < count; j++) - { - var respSum = 0f; - for (var i = 0; i < n; i++) - { - respSum += responsibilities[i, j]; - } - - newWeights[j] = respSum / n; - newMeans[j] = 0; - for (var i = 0; i < n; i++) - { - newMeans[j] += responsibilities[i, j] * data[i]; - } - - newMeans[j] /= respSum; - newVariances[j] = 0; - for (var i = 0; i < n; i++) - { - newVariances[j] += responsibilities[i, j] * MathF.Pow(data[i] - newMeans[j], 2); - } - - newVariances[j] /= respSum; - } - - weights = newWeights; - means = newMeans; - variances = newVariances; - var logLikelihood = 0f; - for (var i = 0; i < n; i++) - { - var probSum = 0f; - for (var j = 0; j < count; j++) - { - probSum += weights[j] * StatisticalMethod.GaussianMixture(data[i], means[j], variances[j]); - } - - logLikelihood += MathF.Log(probSum); - } - - if (MathF.Abs(logLikelihood - prevLogLikelihood) < tolerance) break; - prevLogLikelihood = logLikelihood; - } - - var list = new List(); - for (var i = 0; i < count; i++) - { - list.Add(new(weights[i], means[i], variances[i])); - } - - return list; - } -} -#endif diff --git a/Maths/Statistics/SimpleLinearRegression.cs b/Maths/Statistics/SimpleLinearRegression.cs deleted file mode 100644 index 6b57e07f..00000000 --- a/Maths/Statistics/SimpleLinearRegression.cs +++ /dev/null @@ -1,320 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The result of simple linear regression. -/// -public struct SimpleLinearRegressionResult : IEquatable, IEquatable -{ - /// - /// Initializes a new instance of the SimpleLinearRegressionResult class. - /// - public SimpleLinearRegressionResult() - { - Slope = 0; - Intercept = 0; - } - - /// - /// Initializes a new instance of the SimpleLinearRegressionResult class. - /// - /// The intercept. - /// The slope. - [JsonConstructor] - public SimpleLinearRegressionResult(double intercept, double slope) - { - Intercept = intercept; - Slope = double.IsNaN(slope) ? 0 : slope; - } - - /// - /// Gets the intercept (beta 0). - /// - [JsonPropertyName("intercept")] - public double Intercept { get; } - - /// - /// Gets the slope (beta 1). - /// - [JsonPropertyName("slope")] - public double Slope { get; } - - /// - /// Gets a value indicating whether the result is not valid. - /// - [JsonIgnore] - public bool IsInvalid => Slope == 0 || double.IsNaN(Intercept); - - /// - /// Gets the value on X-axis. - /// - /// The value on Y-axis. - /// The value on X-axis. - public double GetX(double y) - => Slope == 0 ? double.NaN : ((y - Intercept) / Slope); - - /// - /// Gets the value on Y-axis. - /// - /// The value on X-axis. - /// The value on Y-axis. - public double GetY(double x) - => Slope == 0 ? double.NaN : (Intercept + Slope * x); - - /// - /// Serves as the default hash function. - /// - /// A hash code for the current object. - public override int GetHashCode() - => $"y = {Intercept} + {Slope} x".GetHashCode(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(SimpleLinearRegressionResult other) - => Intercept == other.Intercept && Slope == other.Slope; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(SimpleLinearRegressionResultF other) - => Intercept == other.Intercept && Slope == other.Slope; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is SimpleLinearRegressionResult r) return Equals(r); - if (other is SimpleLinearRegressionResultF f) return Equals(f); - return false; - } - - /// - /// Compares two multiple elements to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(SimpleLinearRegressionResult leftValue, SimpleLinearRegressionResult rightValue) - => leftValue.Equals(rightValue); - - /// - /// Compares two multiple elements to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(SimpleLinearRegressionResult leftValue, SimpleLinearRegressionResult rightValue) - => !leftValue.Equals(rightValue); - - /// - /// Gets the simple linear regression. - /// - /// The input data. - /// The result of simple linear regression. - public static SimpleLinearRegressionResult From(IEnumerable values) - { - if (values == null) return new(); - var list = values.Where(ele => ele != null).ToList(); - var meanX = list.Average(ele => ele.X); - var meanY = list.Average(ele => ele.Y); - var numerators = new List(); - var denominators = new List(); - foreach (var item in list) - { - var deltaX = item.X - meanX; - numerators.Add(deltaX * (item.Y - meanY)); - denominators.Add(deltaX * deltaX); - } - - var denominator = denominators.Average(); - if (denominator == 0) return new(); - var slope = numerators.Average() / denominator; - return new(meanY - slope * meanX, slope); - } - - /// - /// Gets the simple linear regression. - /// - /// The input data. - /// The result of simple linear regression. - public static SimpleLinearRegressionResult From(IEnumerable values) - { - if (values == null) return new(); - var list = values.Where(ele => ele != null).ToList(); - var meanX = list.Average(ele => ele.X); - var meanY = list.Average(ele => ele.Y); - var numerators = new List(); - var denominators = new List(); - foreach (var item in list) - { - var deltaX = item.X - meanX; - numerators.Add(deltaX * (item.Y - meanY)); - denominators.Add(deltaX * deltaX); - } - - var denominator = denominators.Average(); - if (denominator == 0) return new(); - var slope = numerators.Average() / denominator; - return new(meanY - slope * meanX, slope); - } -} - -/// -/// The result of simple linear regression. -/// -public class SimpleLinearRegressionResultF : IEquatable, IEquatable -{ - /// - /// Initializes a new instance of the SimpleLinearRegressionResultF class. - /// - public SimpleLinearRegressionResultF() - { - Slope = 0; - Intercept = 0; - } - - /// - /// Initializes a new instance of the SimpleLinearRegressionResultF class. - /// - /// The slope. - /// The intercept. - [JsonConstructor] - public SimpleLinearRegressionResultF(float slope, float intercept) - { - Slope = float.IsNaN(slope) ? 0 : slope; - Intercept = intercept; - } - - /// - /// Gets the slope (beta 1). - /// - [JsonPropertyName("slope")] - public float Slope { get; } - - /// - /// Gets the intercept (beta 0). - /// - [JsonPropertyName("intercept")] - public float Intercept { get; } - - /// - /// Gets a value indicating whether the result is not valid. - /// - [JsonIgnore] - public bool IsInvalid => Slope == 0 || float.IsNaN(Intercept); - - /// - /// Gets the value on X-axis. - /// - /// The value on Y-axis. - /// The value on X-axis. - public float GetX(float y) - => Slope == 0 ? float.NaN : ((y - Intercept) / Slope); - - /// - /// Gets the value on Y-axis. - /// - /// The value on X-axis. - /// The value on Y-axis. - public float GetY(float x) - => Slope == 0 ? float.NaN : (Intercept + Slope * x); - - /// - /// Serves as the default hash function. - /// - /// A hash code for the current object. - public override int GetHashCode() - => $"y = {Intercept} + {Slope} x".GetHashCode(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(SimpleLinearRegressionResult other) - => Intercept == other.Intercept && Slope == other.Slope; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(SimpleLinearRegressionResultF other) - => Intercept == other.Intercept && Slope == other.Slope; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object other) - { - if (other is null) return false; - if (other is SimpleLinearRegressionResultF r) return Equals(r); - if (other is SimpleLinearRegressionResult d) return Equals(d); - return false; - } - - /// - /// Compares two multiple elements to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(SimpleLinearRegressionResultF leftValue, SimpleLinearRegressionResultF rightValue) - => leftValue.Equals(rightValue); - - /// - /// Compares two multiple elements to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(SimpleLinearRegressionResultF leftValue, SimpleLinearRegressionResultF rightValue) - => !leftValue.Equals(rightValue); - - /// - /// Gets the simple linear regression. - /// - /// The input data. - /// The result of simple linear regression. - public static SimpleLinearRegressionResultF SimpleLinearRegression(IEnumerable values) - { - if (values == null) return new(); - var list = values as IList ?? values.ToList(); - var meanX = list.Average(ele => ele.X); - var meanY = list.Average(ele => ele.Y); - var numerators = new List(); - var denominators = new List(); - foreach (var item in list) - { - var deltaX = item.X - meanX; - numerators.Add(deltaX * (item.Y - meanY)); - denominators.Add(deltaX * deltaX); - } - - var denominator = denominators.Average(); - if (denominator == 0) return new(); - var slope = numerators.Average() / denominator; - return new(meanY - slope * meanX, slope); - } -} diff --git a/Maths/Text/StringCollectionOperator.cs b/Maths/Text/StringCollectionOperator.cs deleted file mode 100644 index d19922b8..00000000 --- a/Maths/Text/StringCollectionOperator.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Text; - -/// -/// The operators for boolean collection. -/// -public enum StringCollectionOperators : byte -{ - /// - /// Returns an empty string. - /// - Empty = 0, - - /// - /// Join each strings. - /// - Join = 1, - - /// - /// Join strings in each line. - /// - Lines = 2, - - /// - /// Join strings seperated by tab. - /// - Tabs = 3, - - /// - /// Join strings seperated by semicolon. - /// - Tags = 4, - - /// - /// Join strings seperated by comma. - /// - Commas = 5, - - /// - /// Join strings seperated by dot. - /// - Dots = 6, - - /// - /// Join strings seperated by slash. - /// - Slashes = 7, - - /// - /// Join strings seperated by vertical line. - /// - VerticalLines = 8, - - /// - /// Join strings seperated by white space. - /// - WhiteSpaces = 10, - - /// - /// Join strings seperated by white space. - /// - DoubleWhiteSpaces = 11, - - /// - /// Join strings seperated by white space. - /// - TripleWhiteSpaces = 12, - - /// - /// Join strings seperated by ampersand with white space around. - /// - And = 13, - - /// - /// Join strings seperated by spit poin with white space around. - /// - SplitPoints = 14, - - /// - /// JSON array string format. - /// - JsonArray = 15, - - /// - /// In bullet list. Each item is in a line with prefix of a split dot and a white space. - /// - Bullet = 16, - - /// - /// In numbering list. Each item is in a line with prefix of one-based index and a tab. - /// - Numbering = 17, - - /// - /// Returns the first one. - /// - First = 18, - - /// - /// Returns the last one. - /// - Last = 19, - - /// - /// Returns the first longest one. - /// - Longest = 20, - - /// - /// Returns the last longest one. - /// - LastLongest = 21, - - /// - /// Returns the first shortest one. - /// - Shortest = 22, - - /// - /// Returns the last shortest one. - /// - LastShortest = 23, -} diff --git a/Maths/Text/StringsOperation.cs b/Maths/Text/StringsOperation.cs deleted file mode 100644 index cc997c84..00000000 --- a/Maths/Text/StringsOperation.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Trivial.Text; - -namespace Trivial.Maths; - -public static partial class CollectionOperation -{ - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static string Merge(StringCollectionOperators op, IEnumerable input) - { - if (input == null) return null; - if (input is string[] arr) - { - if (arr.Length < 1) return null; - } - else if (input is ICollection col) - { - if (col.Count < 1) return null; - } - else - { - col = input?.ToList(); - input = col; - if (col.Count < 1) return null; - } - - switch (op) - { - case StringCollectionOperators.Empty: - return string.Empty; - case StringCollectionOperators.Join: - return string.Join(string.Empty, input); - case StringCollectionOperators.Lines: - return string.Join(Environment.NewLine, input); - case StringCollectionOperators.Tabs: - return Join('\t', input); - case StringCollectionOperators.Tags: - return Join(';', input); - case StringCollectionOperators.Commas: - return Join(',', input); - case StringCollectionOperators.Dots: - return Join('.', input); - case StringCollectionOperators.Slashes: - return Join('/', input); - case StringCollectionOperators.VerticalLines: - return Join('|', input); - case StringCollectionOperators.WhiteSpaces: - return Join(' ', input); - case StringCollectionOperators.DoubleWhiteSpaces: - return string.Join(" ", input); - case StringCollectionOperators.TripleWhiteSpaces: - return string.Join(" ", input); - case StringCollectionOperators.And: - return string.Join(" & ", input); - case StringCollectionOperators.SplitPoints: - return string.Join(" · ", input); - case StringCollectionOperators.JsonArray: - { - var json = new JsonArrayNode(); - json.AddRange(input); - return json.ToString(); - } - case StringCollectionOperators.Bullet: - input = input.Select(ele => string.Concat("· ", ele)); - return string.Join(Environment.NewLine, input); - case StringCollectionOperators.Numbering: - { - input = input.Select((ele, i) => string.Concat(i, ' ', '\t', ele)); - return string.Join(Environment.NewLine, input); - } - case StringCollectionOperators.First: - return input.First(); - case StringCollectionOperators.Last: - return input.Last(); - case StringCollectionOperators.Longest: - { - int i = 0; - string s = null; - foreach (var item in input) - { - if (item == null || item.Length < i) continue; - if (item.Length == i) - { - if (i == 0) s = string.Empty; - continue; - } - - s = item; - i = item.Length; - } - - return s; - } - case StringCollectionOperators.LastLongest: - { - int i = 0; - string s = null; - foreach (var item in input) - { - if (item == null || item.Length < i) continue; - if (i == 0) s = string.Empty; - s = item; - i = item.Length; - } - - return s; - } - case StringCollectionOperators.Shortest: - { - int i = -1; - string s = null; - foreach (var item in input) - { - if (item == null) return null; - if (i >= 0 && item.Length >= i) continue; - s = item; - i = item.Length; - } - - return s; - } - case StringCollectionOperators.LastShortest: - { - int i = -1; - string s = null; - foreach (var item in input) - { - if (item == null) return null; - if (i >= 0 && item.Length > i) continue; - s = item; - i = item.Length; - } - - return s; - } - default: - throw NotSupported(op); - } - } - - /// - /// Gets one item by specific operator. - /// - /// The operator. - /// The input collection to compute. - /// The result. - /// The operator is not supported. - public static string Merge(StringCollectionOperators op, params string[] input) - => Merge(op, input as IEnumerable); - - private static string Join(char seperator, IEnumerable input) -#if NET6_0_OR_GREATER - => string.Join(seperator, input); -#else - => string.Join(seperator.ToString(), input); -#endif -} diff --git a/Maths/ThreeDimentional/Geometry.cs b/Maths/ThreeDimentional/Geometry.cs deleted file mode 100644 index 9bd6819d..00000000 --- a/Maths/ThreeDimentional/Geometry.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The utility for geometry. -/// -public static partial class Geometry -{ - /// - /// Computes the distance between a point and a plane. - /// - /// The point. - /// The a parameter of plane. - /// The b parameter of plane. - /// The c parameter of plane. - /// The d parameter of plane. - /// The distance. - public static double Distance(DoublePoint3D point, double a, double b, double c, double d) - => Math.Abs(a * point.X + b * point.Y + c * point.Z + d) / Math.Sqrt(a * a + b * b + c * c); -} diff --git a/Maths/ThreeDimentional/Sphere.cs b/Maths/ThreeDimentional/Sphere.cs deleted file mode 100644 index d5ee911e..00000000 --- a/Maths/ThreeDimentional/Sphere.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The sphere in coordinate. -/// -[DataContract] -public class CoordinateSphere : ICloneable -{ - private DoublePoint3D center; - - /// - /// Initializes a new instance of the CoordinateSphere class. - /// - public CoordinateSphere() - { - center = new(); - Radius = 0; - } - - /// - /// Initializes a new instance of the CoordinateSphere class. - /// - /// The x of center point. - /// The y of center point. - /// The z of center point. - /// The radius. - public CoordinateSphere(double x, double y, double z, double r) - { - center = new(x, y, z); - Radius = double.IsNaN(r) ? 0 : r; - } - - /// - /// Initializes a new instance of the CoordinateSphere class. - /// - /// The center point. - /// The radius. - public CoordinateSphere(DoublePoint3D center, double r) - { - this.center = center ?? new(); - Radius = double.IsNaN(r) ? 0 : r; - } - - /// - /// Gets or sets the radius. - /// - [JsonPropertyName("r")] - [DataMember(Name = "r")] - public double Radius { get; set; } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint3D Center - { - get => center; - set => center = value ?? new(); - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public double X - { - get => Center.X; - set => Center.X = value; - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public double Y - { - get => Center.Y; - set => Center.Y = value; - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("z")] - [DataMember(Name = "z")] - public double Z - { - get => Center.Z; - set => Center.Z = value; - } - - /// - /// Gets the area. - /// - public double Area() - => Math.PI * Radius * Radius * 4; - - /// - /// Gets the perimeter. - /// - public double Volume() - => Math.PI * Math.Pow(Radius, 3) * 4 / 3; - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{X:0.########}, {Y:0.########}, {Z:0.########} (r {Radius:0.########})"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"{X}, {Y}, {Z} (r {Radius})"; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateSphere Clone() - => new(center, double.IsNaN(Radius) ? 0d : Radius); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); -} diff --git a/Maths/TwoDimentional/Circle.cs b/Maths/TwoDimentional/Circle.cs deleted file mode 100644 index 00363438..00000000 --- a/Maths/TwoDimentional/Circle.cs +++ /dev/null @@ -1,1222 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The relationship between 2 circles. -/// -public enum RelationshipBetweenCircles : byte -{ - /// - /// Congruence. - /// - Congruence = 0, - - /// - /// Separation. - /// - Separation = 1, - - /// - /// Externally tangent. - /// - ExternallyTangent = 2, - - /// - /// Intersection. - /// - Intersection = 3, - - /// - /// Inscribe. - /// - Inscribe = 4, - - /// - /// Inclusion - /// - Inclusion = 5 -} - -/// -/// The circle in coordinate. -/// -[DataContract] -public class CoordinateCircle : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private DoublePoint2D center; - private double radius; - - /// - /// Initializes a new instance of the CoordinateCircle class. - /// - public CoordinateCircle() - { - center = new(); - radius = 0; - } - - /// - /// Initializes a new instance of the CoordinateCircle class. - /// - /// The radius. - public CoordinateCircle(double r) - { - center = new(0, 0); - radius = double.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Initializes a new instance of the CoordinateCircle class. - /// - /// The x of center point. - /// The y of center point. - /// The radius. - public CoordinateCircle(double x, double y, double r) - { - center = new(x, y); - radius = double.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Initializes a new instance of the CoordinateCircle class. - /// - /// The center point. - /// The radius. - public CoordinateCircle(DoublePoint2D center, double r) - { - this.center = center ?? new(); - radius = double.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Initializes a new instance of the CoordinateCircle class. - /// - /// The circle. - public CoordinateCircle(CoordinateCircleF circle) - { - if (circle == null) circle = new(); - center = circle.Center; - radius = circle.Radius; - } - - /// - /// Gets or sets the radius. - /// - /// Radius was less than 0. - [JsonPropertyName("r")] - [DataMember(Name = "r")] - public double Radius - { - get => radius; - set => radius = !double.IsNaN(value) && value >= 0 ? value : throw new InvalidOperationException("Radius should equal to or be greater than 0."); - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint2D Center - { - get => center; - set => center = value ?? new(); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public double CenterX - { - get => Center.X; - set => Center.X = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public double CenterY - { - get => Center.Y; - set => Center.Y = value; - } - - /// - /// Gets the perimeter. - /// - public double Perimeter() - => 2 * Math.PI * Radius; - - /// - /// Gets the area. - /// - public double Area() - => Math.PI * Radius * Radius; - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (double, double) GetY(double x) - { - var delta = x - CenterX; - var r = delta == 0 ? Radius : Math.Sqrt(Radius * Radius - delta * delta); - if (double.IsNaN(r) || r > Radius) return (double.NaN, double.NaN); - if (r == 0) return (CenterY, double.NaN); - return (CenterY + r, CenterY - r); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (double, double) GetX(double y) - { - var delta = y - CenterY; - var r = delta == 0 ? Radius : Math.Sqrt(Radius * Radius - delta * delta); - if (double.IsNaN(r) || r > Radius) return (double.NaN, double.NaN); - if (r == 0) return (CenterY, double.NaN); - return (CenterX + r, CenterX - r); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs(Math.Pow(point.X - CenterX, 2) + Math.Pow(point.Y - CenterY, 2) - Radius * Radius) < InternalHelper.DoubleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double accuracy) - => InternalHelper.DrawPoints(this, CenterX - Radius, CenterX + Radius, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{CenterX:0.########}, {CenterY:0.########} (r {Radius:0.########})"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"⊙ {CenterX}, {CenterY} (r {Radius})"; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateCircle Clone() - => new(center, double.IsNaN(Radius) ? 0d : Radius); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateCircle other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && Radius == other.Radius; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateEllipse other) - => other is not null && CenterX == other.CenterX && CenterY == other.CenterY && Radius == other.A && Radius == other.B; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - if (obj is CoordinateEllipse ellipse) Equals(ellipse); - return Equals(obj as CoordinateCircle); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, Radius).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateCircle leftValue, CoordinateCircle rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateCircle leftValue, CoordinateCircle rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to angle. - /// - /// The line. - public static explicit operator CoordinateEllipse(CoordinateCircle value) - => value is null ? new() : new(value.Center, value.Radius, value.Radius); - - /// - /// Make a circle by 3 points on periphery. - /// - /// The first point. - /// The second point. - /// The third point. - /// The circle; or null, if failed. - public static CoordinateCircle ByPeriphery(DoublePoint2D a, DoublePoint2D b, DoublePoint2D c) - { - if (a == null) a = new(); - if (b == null) b = new(); - if (c == null) c = new(); - var x1 = b.X - a.X; - var y1 = b.Y - a.Y; - var x2 = c.X - a.X; - var y2 = c.Y - a.Y; - var z1 = x1 * (a.X + b.X) + y1 * (a.Y + b.Y); - var z2 = x2 * (a.X + c.X) + y2 * (a.Y + c.Y); - var d = 2.0 * (x1 * (c.Y - b.Y) - y1 * (c.X - b.X)); - if (Math.Abs(d) < InternalHelper.DoubleAccuracy) return null; - var center = new DoublePoint2D( - (y2 * z1 - y1 * z2) / d, - (x1 * z2 - x2 * z1) / d); - return new CoordinateCircle(center, Geometry.Distance(a, center)); - } - - /// - /// Make incircle. - /// - /// The first point. - /// The second point. - /// The third point. - /// The circle. - public static CoordinateCircle Incircle(DoublePoint2D a, DoublePoint2D b, DoublePoint2D c) - { - var dx31 = c.X - a.X; - var dy31 = c.Y - a.Y; - var dx21 = b.X - a.X; - var dy21 = b.Y - a.Y; - var d31 = Math.Sqrt(dx31 * dx31 + dy31 * dy31); - var d21 = Math.Sqrt(dx21 * dx21 + dy21 * dy21); - var a1 = dx31 * d21 - dx21 * d31; - var b1 = dy31 * d21 - dy21 * d31; - var c1 = a1 * a.X + b1 * a.Y; - var dx32 = c.X - b.X; - var dy32 = c.Y - b.Y; - var dx12 = -dx21; - var dy12 = -dy21; - var d32 = Math.Sqrt(dx32 * dx32 + dy32 * dy32); - var d12 = d21; - var a2 = dx12 * d32 - dx32 * d12; - var b2 = dy12 * d32 - dy32 * d12; - var c2 = a2 * b.X + b2 * b.Y; - var x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); - var y = (c2 * a1 - c1 * a2) / (a1 * b2 - a2 * b1); - return new CoordinateCircle(x, y, Math.Abs(dy21 * x - dx21 * y + dx21 * a.Y - dy21 * a.X) / d21); - } -} - -/// -/// Ellipse in coordinate. -/// -[DataContract] -public class CoordinateEllipse : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private DoublePoint2D center; - private double radiusA; - private double radiusB; - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - public CoordinateEllipse() - { - Alpha = new Angle(); - center = new(); - radiusA = 0; - radiusB = 0; - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The longer radius. - /// The shorter radius. - public CoordinateEllipse(double a, double b) - { - Alpha = new Angle(); - center = new(0, 0); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipse(double x, double y, double a, double b) - { - Alpha = new Angle(); - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipse(DoublePoint2D center, double a, double b) - { - Alpha = new Angle(); - this.center = center; - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The angle between X-axis and the line of focuses. - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipse(Angle alpha, double x, double y, double a, double b) - { - Alpha = alpha; - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The angle between X-axis and the line of focuses. - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipse(Angle alpha, DoublePoint2D center, double a, double b) - { - Alpha = alpha; - this.center = center; - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipse class. - /// - /// The Ellipse. - public CoordinateEllipse(CoordinateEllipseF ellipse) - { - if (ellipse == null) ellipse = new(); - Alpha = ellipse.Alpha; - center = ellipse.Center; - } - - /// - /// Gets or sets the angle between X-axis and the line of focuses. - /// - [JsonPropertyName("alpha")] - [DataMember(Name = "alpha")] - public Angle Alpha { get; set; } - - /// - /// Gets or sets the longer radius. - /// - /// The value was less than 0. - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public double A - { - get - { - return radiusA; - } - - set - { - if (double.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value >= radiusB) - { - radiusA = value; - return; - } - - radiusA = radiusB; - radiusB = value; - } - } - - /// - /// Gets or sets the shorter radius. - /// - /// The value was less than 0. - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public double B - { - get - { - return radiusB; - } - - set - { - if (double.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value <= radiusA) - { - radiusB = value; - return; - } - - radiusB = radiusA; - radiusA = value; - } - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint2D Center - { - get => center; - set => center = value ?? new(); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public double CenterX - { - get => Center.X; - set => Center.X = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public double CenterY - { - get => Center.Y; - set => Center.Y = value; - } - - /// - /// Gets the eccentricity. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double Eccentricity => Math.Sqrt(1 - Math.Pow(B / A, 2)); - - /// - /// Gets the middle value h. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double H => Math.Pow(A - B, 2) / Math.Pow(A + B, 2); - - /// - /// Gets the focal distance. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double C => Math.Sqrt(A * A - B * B); - - /// - /// Gets the perimeter. - /// - public double Perimeter() - { - var h3 = H * 3; - return Math.PI * (A + B) * (1 + h3 / (10 + Math.Sqrt(4 - h3))); - } - - /// - /// Gets the area. - /// - public double Area() - => Math.PI * A * B; - - /// - /// Gets focuses. - /// - /// The focuses. - public (DoublePoint2D, DoublePoint2D) Focuses() - { - var c = C; - if (Alpha.Degrees == 0 || Alpha.Degrees == 360) - return (new(center.X - c, center.Y), new(center.X + c, center.Y)); - if (Alpha.Degrees == 90 || Alpha.Degrees == 270) - return (new(center.X, center.Y - c), new(center.X, center.Y + c)); - return ( - Geometry.Rotate(new DoublePoint2D(center.X - c, center.Y), null, Alpha), - Geometry.Rotate(new DoublePoint2D(center.X + c, center.Y), null, Alpha)); - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (double, double) GetY(double x) - { - x = Geometry.Rotate(new DoublePoint2D(x, 0), center, Alpha).X; - var width = x - CenterX; - var y = Math.Sqrt((1 - width * width / A * A) * B * B); - if (double.IsNaN(y)) return (double.NaN, double.NaN); - if (y == 0) return (y, double.NaN); - return (-y, y); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (double, double) GetX(double y) - { - y = Geometry.Rotate(new DoublePoint2D(0, y), center, Alpha).Y; - var height = y - CenterY; - var x = Math.Sqrt((1 - height * height / B * B) * A * A); - if (double.IsNaN(x)) return (double.NaN, double.NaN); - if (x == 0) return (x, double.NaN); - return (-x, x); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - { - if (point == null) return false; - if (Alpha.AbsDegrees > 0) - point = Geometry.Rotate(point, center, Alpha); - var width = point.X - CenterX; - var height = point.Y - CenterY; - return Math.Abs(width * width + height * height - 1) < InternalHelper.DoubleAccuracy; - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double accuracy) - { - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < InternalHelper.DoubleAccuracy) accuracy = InternalHelper.DoubleAccuracy; - for (var x = -A; x <= A; x += accuracy) - { - var width = x - CenterX; - var y = Math.Sqrt((1 - width * width / A * A) * B * B); - if (double.IsNaN(y)) continue; - if (y == 0) yield return Geometry.Rotate(new Point2D(x, y), center, Alpha); - yield return Geometry.Rotate(new Point2D(x, -y), center, Alpha); - yield return Geometry.Rotate(new Point2D(x, y), center, Alpha); - } - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - var sb = new StringBuilder(); - if (CenterX == 0 || double.IsNaN(CenterX)) sb.Append("x²"); - else sb.AppendFormat("(x - {0})²", CenterX); - sb.AppendFormat("/ {0}² + ", A); - if (CenterY == 0 || double.IsNaN(CenterY)) sb.Append("y²"); - else sb.AppendFormat("(y - {0})²", CenterY); - sb.AppendFormat("/ {0}² = 1", B); - if (Alpha.AbsDegrees >= InternalHelper.DoubleAccuracy) sb.AppendFormat(" (rotate {0})", Alpha); - return sb.ToString(); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateEllipse Clone() - => new(Alpha, center, A, B); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateEllipse other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && A == other.A && B == other.B; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateCircle other) - => other is not null && CenterX == other.CenterX && CenterY == other.CenterY && A == other.Radius && B == other.Radius; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - if (obj is CoordinateCircle ellipse) return Equals(ellipse); - return Equals(obj as CoordinateEllipse); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, A, B).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateEllipse leftValue, CoordinateEllipse rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateEllipse leftValue, CoordinateEllipse rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Sets A and B. - /// - /// The longer radius. - /// The shorter radius. - public void SetRadius(double a, double b) - { - a = double.IsNaN(a) ? 0 : Math.Abs(a); - b = double.IsNaN(b) ? 0 : Math.Abs(b); - if (b > a) - { - var c = a; - a = b; - b = c; - } - - radiusA = a; - radiusB = b; - } -} - -/// -/// Hyperbola in coordinate. -/// -[DataContract] -public class CoordinateHyperbola : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private DoublePoint2D center; - private double radiusA; - private double radiusB; - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - public CoordinateHyperbola() - { - Alpha = new Angle(); - center = new(0, 0); - radiusA = 0; - radiusB = 0; - } - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbola(double a, double b) - { - Alpha = new Angle(); - center = new(0, 0); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbola(double x, double y, double a, double b) - { - Alpha = new Angle(); - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbola(DoublePoint2D center, double a, double b) - { - Alpha = new Angle(); - this.center = center ?? new(0, 0); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - /// The angle between X-axis and the line of focuses. - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbola(Angle alpha, double x, double y, double a, double b) - { - Alpha = alpha; - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbola class. - /// - /// The angle between X-axis and the line of focuses. - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbola(Angle alpha, DoublePoint2D center, double a, double b) - { - Alpha = alpha; - this.center = center; - SetRadius(a, b); - } - - /// - /// Gets or sets the angle between X-axis and the line of focuses. - /// - [JsonPropertyName("alpha")] - [DataMember(Name = "alpha")] - public Angle Alpha { get; set; } - - /// - /// Gets or sets the longer radius. - /// - /// The value was less than 0. - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public double A - { - get - { - return radiusA; - } - - set - { - if (double.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value >= radiusB) - { - radiusA = value; - return; - } - - radiusA = radiusB; - radiusB = value; - } - } - - /// - /// Gets or sets the shorter radius. - /// - /// The value was less than 0. - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public double B - { - get - { - return radiusB; - } - - set - { - if (double.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value <= radiusA) - { - radiusB = value; - return; - } - - radiusB = radiusA; - radiusA = value; - } - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint2D Center - { - get => center; - set => center = value ?? new(); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public double CenterX - { - get => Center.X; - set => Center.X = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public double CenterY - { - get => Center.Y; - set => Center.Y = value; - } - - /// - /// Gets the eccentricity. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double Eccentricity => Math.Sqrt(1 + Math.Pow(B / A, 2)); - - /// - /// Gets the focal distance. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double C => Math.Sqrt(A * A + B * B); - - /// - /// Gets focuses. - /// - /// The focuses. - public (DoublePoint2D, DoublePoint2D) Focuses() - { - var c = C; - if (Alpha.Degrees == 0 || Alpha.Degrees == 360) - return (new(center.X - c, center.Y), new(center.X + c, center.Y)); - if (Alpha.Degrees == 90 || Alpha.Degrees == 270) - return (new(center.X, center.Y - c), new(center.X, center.Y + c)); - return ( - Geometry.Rotate(new DoublePoint2D(center.X - c, center.Y), null, Alpha), - Geometry.Rotate(new DoublePoint2D(center.X + c, center.Y), null, Alpha)); - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (double, double) GetY(double x) - { - x = Geometry.Rotate(new DoublePoint2D(x, 0), center, Alpha).X; - var width = x - CenterX; - var y = Math.Sqrt((width * width / A * A - 1) * B * B); - if (double.IsNaN(y)) return (double.NaN, double.NaN); - if (y == 0) return (y, double.NaN); - return (-y, y); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (double, double) GetX(double y) - { - y = Geometry.Rotate(new DoublePoint2D(0, y), center, Alpha).Y; - var height = y - CenterY; - var x = Math.Sqrt((height * height / B * B + 1) * A * A); - if (double.IsNaN(x)) return (double.NaN, double.NaN); - if (x == 0) return (x, double.NaN); - return (-x, x); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - { - if (point == null) return false; - if (Alpha.AbsDegrees > 0) - point = Geometry.Rotate(point, center, Alpha); - var width = point.X - CenterX; - var height = point.Y - CenterY; - return Math.Abs(width * width - height * height - 1) < InternalHelper.DoubleAccuracy; - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - var sb = new StringBuilder(); - if (CenterX == 0 || double.IsNaN(CenterX)) sb.Append("x²"); - else sb.AppendFormat("(x - {0})²", CenterX); - sb.AppendFormat("/ {0}² - ", A); - if (CenterY == 0 || double.IsNaN(CenterY)) sb.Append("y²"); - else sb.AppendFormat("(y - {0})²", CenterY); - sb.AppendFormat("/ {0}² = 1", B); - if (Alpha.AbsDegrees >= InternalHelper.DoubleAccuracy) sb.AppendFormat(" (rotate {0})", Alpha); - return sb.ToString(); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateHyperbola Clone() - => new(Alpha, center, A, B); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateHyperbola other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && A == other.A && B == other.B; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as CoordinateHyperbola); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, A, B).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateHyperbola leftValue, CoordinateHyperbola rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateHyperbola leftValue, CoordinateHyperbola rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Sets A and B. - /// - /// The longer radius. - /// The shorter radius. - public void SetRadius(double a, double b) - { - a = double.IsNaN(a) ? 0 : Math.Abs(a); - b = double.IsNaN(b) ? 0 : Math.Abs(b); - if (b > a) - { - var c = a; - a = b; - b = c; - } - - radiusA = a; - radiusB = b; - } -} diff --git a/Maths/TwoDimentional/CircleF.cs b/Maths/TwoDimentional/CircleF.cs deleted file mode 100644 index d99dd6fa..00000000 --- a/Maths/TwoDimentional/CircleF.cs +++ /dev/null @@ -1,1236 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The circle in coordinate. -/// -[DataContract] -public class CoordinateCircleF : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private PointF center; - private float radius; - - /// - /// Initializes a new instance of the CoordinateCircleF class. - /// - public CoordinateCircleF() - { - center = new(); - radius = 0; - } - - /// - /// Initializes a new instance of the CoordinateCircleF class. - /// - /// The radius. - public CoordinateCircleF(float r) - { - center = new(0, 0); - radius = float.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Initializes a new instance of the CoordinateCircleF class. - /// - /// The x of center point. - /// The y of center point. - /// The radius. - public CoordinateCircleF(float x, float y, float r) - { - center = new(x, y); - radius = float.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Initializes a new instance of the CoordinateCircleF class. - /// - /// The center point. - /// The radius. - public CoordinateCircleF(PointF center, float r) - { - this.center = center; - radius = float.IsNaN(r) ? 0 : Math.Abs(r); - } - - /// - /// Gets or sets the radius. - /// - /// Radius was less than 0. - [JsonPropertyName("r")] - [DataMember(Name = "r")] - public float Radius - { - get => radius; - set => radius = !float.IsNaN(value) && value >= 0 ? value : throw new InvalidOperationException("Radius should equal to or be greater than 0."); - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public PointF Center - { - get => center; - set => center = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public float CenterX - { - get => Center.X; - set => Center = new PointF(float.IsNaN(value) ? 0f : value, Center.Y); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public float CenterY - { - get => Center.Y; - set => Center = new PointF(Center.X, float.IsNaN(value) ? 0f : value); - } - - /// - /// Gets the perimeter. - /// - public float Perimeter() - => (float)(2 * Math.PI * Radius); - - /// - /// Gets the area. - /// - public float Area() - => (float)(Math.PI * Radius * Radius); - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (float, float) GetY(float x) - { - var delta = x - CenterX; -#if NETFRAMEWORK - var r = delta == 0 ? Radius : (float)Math.Sqrt(Radius * Radius - delta * delta); -#else - var r = delta == 0 ? Radius : MathF.Sqrt(Radius * Radius - delta * delta); -#endif - if (float.IsNaN(r) || r > Radius) return (float.NaN, float.NaN); - if (r == 0) return (CenterY, float.NaN); - return (CenterY + r, CenterY - r); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (float, float) GetX(float y) - { - var delta = y - CenterY; -#if NETFRAMEWORK - var r = delta == 0 ? Radius : (float)Math.Sqrt(Radius * Radius - delta * delta); -#else - var r = delta == 0 ? Radius : MathF.Sqrt(Radius * Radius - delta * delta); -#endif - if (float.IsNaN(r) || r > Radius) return (float.NaN, float.NaN); - if (r == 0) return (CenterY, float.NaN); - return (CenterX + r, CenterX - r); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs(Math.Pow(point.X - CenterX, 2) + Math.Pow(point.Y - CenterY, 2) - Radius * Radius) < InternalHelper.SingleAccuracy; - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(PointF point) - => Math.Abs(Math.Pow(point.X - CenterX, 2) + Math.Pow(point.Y - CenterY, 2) - Radius * Radius) < InternalHelper.SingleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float accuracy) - => InternalHelper.DrawPoints(this, CenterX - Radius, CenterX + Radius, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy).Select(ele => new Point2D(ele.X, ele.Y)); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{CenterX:0.########}, {CenterY:0.########} (r {Radius:0.########})"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"⊙ {CenterX}, {CenterY} (r {Radius})"; - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateCircle Clone() - => new(center, float.IsNaN(Radius) ? 0d : Radius); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateCircleF other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && Radius == other.Radius; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateEllipseF other) - => other is not null && CenterX == other.CenterX && CenterY == other.CenterY && Radius == other.A && Radius == other.B; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - if (obj is CoordinateEllipseF ellipse) Equals(ellipse); - return Equals(obj as CoordinateCircleF); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, Radius).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateCircleF leftValue, CoordinateCircleF rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateCircleF leftValue, CoordinateCircleF rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to angle. - /// - /// The line. - public static explicit operator CoordinateEllipseF(CoordinateCircleF value) - => value is null ? new() : new(value.Center, value.Radius, value.Radius); - - /// - /// Make a circle by 3 points on periphery. - /// - /// The first point. - /// The second point. - /// The third point. - /// The circle; or null, if failed. - public static CoordinateCircleF ByPeriphery(PointF a, PointF b, PointF c) - { - var x1 = b.X - a.X; - var y1 = b.Y - a.Y; - var x2 = c.X - a.X; - var y2 = c.Y - a.Y; - var z1 = x1 * (a.X + b.X) + y1 * (a.Y + b.Y); - var z2 = x2 * (a.X + c.X) + y2 * (a.Y + c.Y); - var d = 2F * (x1 * (c.Y - b.Y) - y1 * (c.X - b.X)); - if (Math.Abs(d) < InternalHelper.SingleAccuracy) return null; - var center = new PointF( - (y2 * z1 - y1 * z2) / d, - (x1 * z2 - x2 * z1) / d); - return new CoordinateCircleF(center, Geometry.Distance(a, center)); - } - - /// - /// Make incircle. - /// - /// The first point. - /// The second point. - /// The third point. - /// The circle. - public static CoordinateCircleF Incircle(PointF a, PointF b, PointF c) - { - var dx31 = c.X - a.X; - var dy31 = c.Y - a.Y; - var dx21 = b.X - a.X; - var dy21 = b.Y - a.Y; - var d31 = (float)Math.Sqrt(dx31 * dx31 + dy31 * dy31); - var d21 = (float)Math.Sqrt(dx21 * dx21 + dy21 * dy21); - var a1 = dx31 * d21 - dx21 * d31; - var b1 = dy31 * d21 - dy21 * d31; - var c1 = a1 * a.X + b1 * a.Y; - var dx32 = c.X - b.X; - var dy32 = c.Y - b.Y; - var dx12 = -dx21; - var dy12 = -dy21; - var d32 = (float)Math.Sqrt(dx32 * dx32 + dy32 * dy32); - var d12 = d21; - var a2 = dx12 * d32 - dx32 * d12; - var b2 = dy12 * d32 - dy32 * d12; - var c2 = a2 * b.X + b2 * b.Y; - var x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); - var y = (c2 * a1 - c1 * a2) / (a1 * b2 - a2 * b1); - return new CoordinateCircleF(x, y, (float)Math.Abs(dy21 * x - dx21 * y + dx21 * a.Y - dy21 * a.X) / d21); - } -} - -/// -/// Ellipse in coordinate. -/// -[DataContract] -public class CoordinateEllipseF : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private PointF center; - private float radiusA; - private float radiusB; - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - public CoordinateEllipseF() - { - Alpha = new Angle(); - center = new(); - radiusA = 0; - radiusB = 0; - } - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - /// The longer radius. - /// The shorter radius. - public CoordinateEllipseF(float a, float b) - { - Alpha = new Angle(); - center = new(0, 0); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipseF(float x, float y, float a, float b) - { - Alpha = new Angle(); - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipseF(PointF center, float a, float b) - { - Alpha = new Angle(); - this.center = center; - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - /// The angle between X-axis and the line of focuses. - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipseF(Angle alpha, float x, float y, float a, float b) - { - Alpha = alpha; - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateEllipseF class. - /// - /// The angle between X-axis and the line of focuses. - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateEllipseF(Angle alpha, PointF center, float a, float b) - { - Alpha = alpha; - this.center = center; - SetRadius(a, b); - } - - /// - /// Gets or sets the angle between X-axis and the line of focuses. - /// - [JsonPropertyName("alpha")] - [DataMember(Name = "alpha")] - public Angle Alpha { get; set; } - - /// - /// Gets or sets the longer radius. - /// - /// The value was less than 0. - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public float A - { - get - { - return radiusA; - } - - set - { - if (float.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value >= radiusB) - { - radiusA = value; - return; - } - - radiusA = radiusB; - radiusB = value; - } - } - - /// - /// Gets or sets the shorter radius. - /// - /// The value was less than 0. - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public float B - { - get - { - return radiusB; - } - - set - { - if (float.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value <= radiusA) - { - radiusB = value; - return; - } - - radiusB = radiusA; - radiusA = value; - } - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public PointF Center - { - get => center; - set => center = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public float CenterX - { - get => Center.X; - set => Center = new PointF(float.IsNaN(value) ? 0f : value, Center.Y); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public float CenterY - { - get => Center.Y; - set => Center = new PointF(Center.X, float.IsNaN(value) ? 0f : value); - } - - /// - /// Gets the eccentricity. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float Eccentricity => (float)Math.Sqrt(1 - Math.Pow(B / A, 2)); -#else - public float Eccentricity => MathF.Sqrt(1 - MathF.Pow(B / A, 2)); -#endif - - /// - /// Gets the middle value h. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float H => (float)Math.Pow(A - B, 2) / (float)Math.Pow(A + B, 2); -#else - public float H => MathF.Pow(A - B, 2) / MathF.Pow(A + B, 2); -#endif - - /// - /// Gets the focal distance. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float C => (float)Math.Sqrt(A * A - B * B); -#else - public float C => MathF.Sqrt(A * A - B * B); -#endif - - /// - /// Gets the perimeter. - /// - public float Perimeter() - { - var h3 = H * 3; -#if NETFRAMEWORK - return (float)Math.PI * (A + B) * (1 + h3 / (10 + (float)Math.Sqrt(4 - h3))); -#else - return MathF.PI * (A + B) * (1 + h3 / (10 + MathF.Sqrt(4 - h3))); -#endif - } - - /// - /// Gets the area. - /// - public float Area() -#if NETFRAMEWORK - => (float)Math.PI * A * B; -#else - => MathF.PI * A * B; -#endif - - /// - /// Gets focuses. - /// - /// The focuses. - public (PointF, PointF) Focuses() - { - var c = C; - if (Alpha.Degrees == 0 || Alpha.Degrees == 360) - return (new(center.X - c, center.Y), new(center.X + c, center.Y)); - if (Alpha.Degrees == 90 || Alpha.Degrees == 270) - return (new(center.X, center.Y - c), new(center.X, center.Y + c)); - return ( - Geometry.Rotate(new PointF(center.X - c, center.Y), new PointF(0F, 0F), Alpha), - Geometry.Rotate(new PointF(center.X + c, center.Y), new PointF(0F, 0F), Alpha)); - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (float, float) GetY(float x) - { - x = Geometry.Rotate(new PointF(x, 0), center, Alpha).X; - var width = x - CenterX; -#if NETFRAMEWORK - var y = (float)Math.Sqrt((1 - width * width / A * A) * B * B); -#else - var y = MathF.Sqrt((1 - width * width / A * A) * B * B); -#endif - if (float.IsNaN(y)) return (float.NaN, float.NaN); - if (y == 0) return (y, float.NaN); - return (-y, y); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (float, float) GetX(float y) - { - y = Geometry.Rotate(new PointF(0, y), center, Alpha).Y; - var height = y - CenterY; -#if NETFRAMEWORK - var x = (float)Math.Sqrt((1 - height * height / B * B) * A * A); -#else - var x = MathF.Sqrt((1 - height * height / B * B) * A * A); -#endif - if (float.IsNaN(x)) return (float.NaN, float.NaN); - if (x == 0) return (x, float.NaN); - return (-x, x); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point is not null && Contains(new PointF(point.X, point.Y)); - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(PointF point) - { - if (Alpha.AbsDegrees > 0) - point = Geometry.Rotate(point, center, Alpha); - var width = point.X - CenterX; - var height = point.Y - CenterY; - return Math.Abs(width * width + height * height - 1) < InternalHelper.SingleAccuracy; - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float accuracy) - { - if (accuracy < 0) accuracy = Math.Abs(accuracy); - if (accuracy < InternalHelper.SingleAccuracy) accuracy = InternalHelper.SingleAccuracy; - for (var x = -A; x <= A; x += accuracy) - { - var width = x - CenterX; - var y = (float)Math.Sqrt((1 - width * width / A * A) * B * B); - if (float.IsNaN(y)) continue; - if (y == 0) yield return Geometry.Rotate(new PointF(x, y), center, Alpha); - yield return Geometry.Rotate(new PointF(x, -y), center, Alpha); - yield return Geometry.Rotate(new PointF(x, y), center, Alpha); - } - } - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy).Select(ele => new Point2D(ele.X, ele.Y)); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - var sb = new StringBuilder(); - if (CenterX == 0 || float.IsNaN(CenterX)) sb.Append("x²"); - else sb.AppendFormat("(x - {0})²", CenterX); - sb.AppendFormat("/ {0}² + ", A); - if (CenterY == 0 || float.IsNaN(CenterY)) sb.Append("y²"); - else sb.AppendFormat("(y - {0})²", CenterY); - sb.AppendFormat("/ {0}² = 1", B); - if (Alpha.AbsDegrees >= InternalHelper.SingleAccuracy) sb.AppendFormat(" (rotate {0})", Alpha); - return sb.ToString(); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateEllipse Clone() - => new(Alpha, center, A, B); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateEllipseF other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && A == other.A && B == other.B; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateCircleF other) - => other is not null && CenterX == other.CenterX && CenterY == other.CenterY && A == other.Radius && B == other.Radius; - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - if (obj is CoordinateCircleF ellipse) return Equals(ellipse); - return Equals(obj as CoordinateEllipseF); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, A, B).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateEllipseF leftValue, CoordinateEllipseF rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateEllipseF leftValue, CoordinateEllipseF rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Sets A and B. - /// - /// The longer radius. - /// The shorter radius. - public void SetRadius(float a, float b) - { - a = float.IsNaN(a) ? 0 : Math.Abs(a); - b = float.IsNaN(b) ? 0 : Math.Abs(b); - if (b > a) - { - var c = a; - a = b; - b = c; - } - - radiusA = a; - radiusB = b; - } -} - -/// -/// Hyperbola in coordinate. -/// -[DataContract] -public class CoordinateHyperbolaF : IPixelOutline, ICoordinateTuplePoint, ICloneable, IEquatable -{ - private PointF center; - private float radiusA; - private float radiusB; - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - public CoordinateHyperbolaF() - { - Alpha = new Angle(); - center = new(0, 0); - radiusA = 0; - radiusB = 0; - } - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbolaF(float a, float b) - { - Alpha = new Angle(); - center = new(0, 0); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbolaF(float x, float y, float a, float b) - { - Alpha = new Angle(); - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbolaF(PointF center, float a, float b) - { - Alpha = new Angle(); - this.center = center; - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - /// The angle between X-axis and the line of focuses. - /// The x of center point. - /// The y of center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbolaF(Angle alpha, float x, float y, float a, float b) - { - Alpha = alpha; - center = new(x, y); - SetRadius(a, b); - } - - /// - /// Initializes a new instance of the CoordinateHyperbolaF class. - /// - /// The angle between X-axis and the line of focuses. - /// The center point. - /// The longer radius. - /// The shorter radius. - public CoordinateHyperbolaF(Angle alpha, PointF center, float a, float b) - { - Alpha = alpha; - this.center = center; - SetRadius(a, b); - } - - /// - /// Gets or sets the angle between X-axis and the line of focuses. - /// - [JsonPropertyName("alpha")] - [DataMember(Name = "alpha")] - public Angle Alpha { get; set; } - - /// - /// Gets or sets the longer radius. - /// - /// The value was less than 0. - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public float A - { - get - { - return radiusA; - } - - set - { - if (float.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value >= radiusB) - { - radiusA = value; - return; - } - - radiusA = radiusB; - radiusB = value; - } - } - - /// - /// Gets or sets the shorter radius. - /// - /// The value was less than 0. - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public float B - { - get - { - return radiusB; - } - - set - { - if (float.IsNaN(value) || value < 0) throw new InvalidOperationException("The value should equal to or be greater than 0."); - if (value <= radiusA) - { - radiusB = value; - return; - } - - radiusB = radiusA; - radiusA = value; - } - } - - /// - /// Gets or sets the center point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public PointF Center - { - get => center; - set => center = value; - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("x")] - [DataMember(Name = "x")] - public float CenterX - { - get => Center.X; - set => Center = new PointF(float.IsNaN(value) ? 0f : value, Center.Y); - } - - /// - /// Gets the x of the center point. - /// - [JsonPropertyName("y")] - [DataMember(Name = "y")] - public float CenterY - { - get => Center.Y; - set => Center = new PointF(Center.X, float.IsNaN(value) ? 0f : value); - } - - /// - /// Gets the eccentricity. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float Eccentricity => (float)Math.Sqrt(1 + Math.Pow(B / A, 2)); -#else - public float Eccentricity => MathF.Sqrt(1 + MathF.Pow(B / A, 2)); -#endif - - /// - /// Gets the focal distance. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float C => (float)Math.Sqrt(A * A + B * B); -#else - public float C => MathF.Sqrt(A * A + B * B); -#endif - - /// - /// Gets focuses. - /// - /// The focuses. - public (PointF, PointF) Focuses() - { - var c = C; - if (Alpha.Degrees == 0 || Alpha.Degrees == 360) - return (new(center.X - c, center.Y), new(center.X + c, center.Y)); - if (Alpha.Degrees == 90 || Alpha.Degrees == 270) - return (new(center.X, center.Y - c), new(center.X, center.Y + c)); - return ( - Geometry.Rotate(new PointF(center.X - c, center.Y), new PointF(0F, 0F), Alpha), - Geometry.Rotate(new PointF(center.X + c, center.Y), new PointF(0F, 0F), Alpha)); - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public (float, float) GetY(float x) - { - x = Geometry.Rotate(new PointF(x, 0), center, Alpha).X; - var width = x - CenterX; -#if NETFRAMEWORK - var y = (float)Math.Sqrt((width * width / A * A - 1) * B * B); -#else - var y = MathF.Sqrt((width * width / A * A - 1) * B * B); -#endif - if (float.IsNaN(y)) return (float.NaN, float.NaN); - if (y == 0) return (y, float.NaN); - return (-y, y); - } - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public (float, float) GetX(float y) - { - y = Geometry.Rotate(new PointF(0, y), center, Alpha).Y; - var height = y - CenterY; -#if NETFRAMEWORK - var x = (float)Math.Sqrt((height * height / B * B + 1) * A * A); -#else - var x = MathF.Sqrt((height * height / B * B + 1) * A * A); -#endif - if (float.IsNaN(x)) return (float.NaN, float.NaN); - if (x == 0) return (x, float.NaN); - return (-x, x); - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(PointF point) - { - if (Alpha.AbsDegrees > 0) - point = Geometry.Rotate(point, center, Alpha); - var width = point.X - CenterX; - var height = point.Y - CenterY; - return Math.Abs(width * width - height * height - 1) < InternalHelper.SingleAccuracy; - } - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point is not null && Contains(new PointF(point.X, point.Y)); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy).Select(ele => new Point2D(ele.X, ele.Y)); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - var sb = new StringBuilder(); - if (CenterX == 0 || float.IsNaN(CenterX)) sb.Append("x²"); - else sb.AppendFormat("(x - {0})²", CenterX); - sb.AppendFormat("/ {0}² - ", A); - if (CenterY == 0 || float.IsNaN(CenterY)) sb.Append("y²"); - else sb.AppendFormat("(y - {0})²", CenterY); - sb.AppendFormat("/ {0}² = 1", B); - if (Alpha.AbsDegrees >= InternalHelper.SingleAccuracy) sb.AppendFormat(" (rotate {0})", Alpha); - return sb.ToString(); - } - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public CoordinateHyperbola Clone() - => new(Alpha, center, A, B); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(CoordinateHyperbolaF other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return CenterX == other.CenterX && CenterY == other.CenterY && A == other.A && B == other.B; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as CoordinateHyperbolaF); - } - - /// - public override int GetHashCode() - => Tuple.Create(CenterX, CenterY, A, B).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(CoordinateHyperbolaF leftValue, CoordinateHyperbolaF rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(CoordinateHyperbolaF leftValue, CoordinateHyperbolaF rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Sets A and B. - /// - /// The longer radius. - /// The shorter radius. - public void SetRadius(float a, float b) - { - a = float.IsNaN(a) ? 0 : Math.Abs(a); - b = float.IsNaN(b) ? 0 : Math.Abs(b); - if (b > a) - { - var c = a; - a = b; - b = c; - } - - radiusA = a; - radiusB = b; - } -} diff --git a/Maths/TwoDimentional/Geometry.cs b/Maths/TwoDimentional/Geometry.cs deleted file mode 100644 index c6d6363e..00000000 --- a/Maths/TwoDimentional/Geometry.cs +++ /dev/null @@ -1,1899 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The utility for geometry. -/// -public static partial class Geometry -{ - /// - /// Computes euclidean metric. - /// - /// The start point. - /// The end point. - /// The distance. - public static double Distance(Point2D start, Point2D end) - { - if (start == null) start = new(); - if (end == null) end = new(); - var width = end.X - start.X; - var height = end.Y - start.Y; - return Math.Sqrt(width * width + height * height); - } - - /// - /// Computes euclidean metric. - /// - /// The start point. - /// The end point. - /// The distance. - public static float Distance(PointF start, PointF end) - { - var width = end.X - start.X; - var height = end.Y - start.Y; -#if NETFRAMEWORK - return (float)Math.Sqrt(width * width + height * height); -#else - return MathF.Sqrt(width * width + height * height); -#endif - } - - /// - /// Computes vector cross product. - /// - /// A point. - /// Another point. - /// The vertex/origin point. - /// The vector cross product. Greater than 0 if anticlockwise; equals to 0 if collineation; less than 0 if clockwise. - public static double CrossProduct(Point2D a, Point2D b, Point2D o = null) - { - if (a == null) a = new(); - if (b == null) b = new(); - if (o == null) o = new(); - return (a.X - o.X) * (b.Y - o.Y) - (b.X - o.X) * (a.Y - o.Y); - } - - /// - /// Computes vector cross product. - /// - /// A point. - /// Another point. - /// The vertex/origin point. - /// The vector cross product. Greater than 0 if anticlockwise; equals to 0 if collineation; less than 0 if clockwise. - public static float CrossProduct(PointF a, PointF b, PointF o) - => (a.X - o.X) * (b.Y - o.Y) - (b.X - o.X) * (a.Y - o.Y); - - /// - /// Computes vector cross product. - /// - /// A point. - /// Another point. - /// The vector cross product. Greater than 0 if anticlockwise; equals to 0 if collineation; less than 0 if clockwise. - public static float CrossProduct(PointF a, PointF b) - => CrossProduct(a, b, new PointF(0, 0)); - - /// - /// Computes vector dot (scalar) product. - /// - /// A point. - /// Another point. - /// The vertex/origin point. - /// The vector dot (scalar) product. Greater than 0 if it is obtuse angle; equals to 0 if it is right angle; less than 0 if it is acute angle. - public static double DotProduct(Point2D a, Point2D b, Point2D o = null) - { - if (a == null) a = new(); - if (b == null) b = new(); - if (o == null) o = new(); - return (a.X - o.X) * (b.X - o.X) + (a.Y - o.Y) * (b.Y - o.Y); - } - - /// - /// Computes vector dot (scalar) product. - /// - /// A point. - /// Another point. - /// The vertex/origin point. - /// The vector dot (scalar) product. Greater than 0 if it is obtuse angle; equals to 0 if it is right angle; less than 0 if it is acute angle. - public static float DotProduct(PointF a, PointF b, PointF o) - => (a.X - o.X) * (b.X - o.X) + (a.Y - o.Y) * (b.Y - o.Y); - - /// - /// Computes vector dot (scalar) product. - /// - /// A point. - /// Another point. - /// The vector dot (scalar) product. Greater than 0 if it is obtuse angle; equals to 0 if it is right angle; less than 0 if it is acute angle. - public static float DotProduct(PointF a, PointF b) - => DotProduct(a, b, new PointF(0, 0)); - - /// - /// Gets the point after counter clockwise rotation. - /// - /// The point. - /// The origin point. - /// The angle to counter clockwise rotate. - /// The point after rotation. - public static DoublePoint2D Rotate(Point2D point, Point2D origin, Angle alpha) - { - if (point == null) point = new(); - if (alpha.Degrees == 0) return new DoublePoint2D(point.X, point.Y); - if (origin == null) origin = new(); - var radian = alpha.Radians; - var x = origin.X - point.X; - var y = origin.Y - point.Y; - return new DoublePoint2D( - x * Math.Cos(radian) - y * Math.Sin(radian) + x, - y * Math.Cos(radian) + x * Math.Sin(radian) + y); - } - - /// - /// Gets the point after counter clockwise rotation. - /// - /// The point. - /// The origin point. - /// The angle to counter clockwise rotate. - /// The point after rotation. - public static PointF Rotate(PointF point, PointF origin, Angle alpha) - { - if (alpha.Degrees == 0) return point; - var radian = (float)alpha.Radians; - var x = origin.X - point.X; - var y = origin.Y - point.Y; -#if NETFRAMEWORK - return new PointF( - x * (float)Math.Cos(radian) - y * (float)Math.Sin(radian) + x, - y * (float)Math.Cos(radian) + x * (float)Math.Sin(radian) + y); -#else - return new PointF( - x * MathF.Cos(radian) - y * MathF.Sin(radian) + x, - y * MathF.Cos(radian) + x * MathF.Sin(radian) + y); -#endif - } - - /// - /// Computes included angle. - /// - /// The vertex point. - /// The start point. - /// The end point. - /// The included angle radian of line vertex-start and line vertex-end. - internal static double AngleRadian(Point2D vertex, Point2D start, Point2D end) - { - if (vertex == null) vertex = new(); - if (start == null) start = new(); - if (end == null) end = new(); - var dsx = start.X - vertex.X; - var dsy = start.Y - vertex.Y; - var dex = end.X - vertex.X; - var dey = end.Y - vertex.Y; - if (Math.Abs(dex) < InternalHelper.DoubleAccuracy && Math.Abs(dey) < InternalHelper.DoubleAccuracy) return 0; - var cosfi = dsx * dex + dsy * dey; - var norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey); - cosfi /= Math.Sqrt(norm); - if (cosfi >= 1.0) return 0; - if (cosfi <= -1.0) return -Math.PI; - var fi = Math.Acos(cosfi); - if (dsx * dey - dsy * dex > 0) return fi; - return -fi; - } - - /// - /// Computes included angle. - /// - /// The vertex point. - /// The start point. - /// The end point. - /// The included angle radian of line vertex-start and line vertex-end. - internal static float AngleRadian(PointF vertex, PointF start, PointF end) - { - var dsx = start.X - vertex.X; - var dsy = start.Y - vertex.Y; - var dex = end.X - vertex.X; - var dey = end.Y - vertex.Y; - if (Math.Abs(dex) < InternalHelper.DoubleAccuracy && Math.Abs(dey) < InternalHelper.DoubleAccuracy) return 0; - var cosfi = dsx * dex + dsy * dey; - var norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey); - cosfi /= (float)Math.Sqrt(norm); - if (cosfi >= 1.0) return 0; - if (cosfi <= -1.0) return -(float)Math.PI; - var fi = (float)Math.Acos(cosfi); - if (dsx * dey - dsy * dex > 0) return fi; - return -fi; - } - - /// - /// Computes included angle. - /// - /// The vertex point. - /// The start point. - /// The end point. - /// The included angle of line vertex-start and line vertex-end. - public static Angle Angle(Point2D vertex, Point2D start, Point2D end) - => Maths.Angle.FromRadian(AngleRadian(vertex, start, end)); - - /// - /// Computes included angle. - /// - /// The vertex point. - /// The start point. - /// The end point. - /// The included angle of line vertex-start and line vertex-end. - public static Angle Angle(PointF vertex, PointF start, PointF end) - => Maths.Angle.FromRadian(AngleRadian(vertex, start, end)); - - /// - /// Gets the position of a point that relative to a specific line. - /// - /// The point to get the relative position. - /// The line to compare. - /// The relative position ratio. Less than 0 if the point is on the backward extension of the line segment; greater than 1 if forward; equals to 0 if on the start point of the line segment; equals to 1 if on the end point; between 0 and 1 if on the line segment. - /// line was null. - public static double Relation(Point2D point, LineSegment line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should not be null."); - if (point == null) point = new(); - return DotProduct(point is DoublePoint2D p ? p : new DoublePoint2D(point.X, point.Y), line.End, line.Start) / (Distance(line.Start, line.End) * Distance(line.Start, line.End)); - } - - /// - /// Gets the position of a point that relative to a specific line. - /// - /// The point to get the relative position. - /// The line to compare. - /// The relative position ratio. Less than 0 if the point is on the backward extension of the line segment; greater than 1 if forward; equals to 0 if on the start point of the line segment; equals to 1 if on the end point; between 0 and 1 if on the line segment. - /// line was null. - public static float Relation(PointF point, LineSegmentF line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should not be null."); - return DotProduct(new PointF(point.X, point.Y), line.End, line.Start) / (Distance(line.Start, line.End) * Distance(line.Start, line.End)); - } - - /// - /// Gets the foot point. - /// - /// The point. - /// The line. - /// The foot point. - /// line was null. - public static DoublePoint2D GetFootPoint(Point2D point, LineSegment line) - { - var r = Relation(point, line); - return new( - line.Start.X + r * (line.End.X - line.Start.X), - line.Start.Y + r * (line.End.Y - line.Start.Y)); - } - - /// - /// Gets the foot point. - /// - /// The point. - /// The line. - /// The foot point. - /// line was null. - public static PointF GetFootPoint(PointF point, LineSegmentF line) - { - var r = Relation(point, line); - return new( - line.Start.X + r * (line.End.X - line.Start.X), - line.Start.Y + r * (line.End.Y - line.Start.Y)); - } - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// The foot point or the closest point. - /// The distance. - /// line was null. - public static double Distance(Point2D point, LineSegment line, out DoublePoint2D closest) - { - if (point == null) point = new(); - var r = Relation(point, line); - if (r < 0) - { - closest = line.Start; - return Distance(point, line.Start); - } - if (r > 1) - { - closest = line.End; - return Distance(point, line.End); - } - - closest = new( - line.Start.X + r * (line.End.X - line.Start.X), - line.Start.Y + r * (line.End.Y - line.Start.Y)); - return Distance(point, closest); - } - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// The distance. - /// line was null. - public static double Distance(Point2D point, LineSegment line) - => Distance(point, line, out _); - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// true if extend the line segment to a line; otherwise, false. - /// The distance. - /// line was null. - public static double Distance(Point2D point, LineSegment line, bool extendToLine) - => extendToLine - ? Math.Abs(CrossProduct(point, line.End, line.Start)) / Distance(line.Start, line.End) - : Distance(point, line, out _); - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// The foot point or the closest point. - /// The distance. - /// line was null. - public static float Distance(PointF point, LineSegmentF line, out PointF closest) - { - var r = Relation(point, line); - if (r < 0) - { - closest = line.Start; - return Distance(point, line.Start); - } - if (r > 1) - { - closest = line.End; - return Distance(point, line.End); - } - - closest = new( - line.Start.X + r * (line.End.X - line.Start.X), - line.Start.Y + r * (line.End.Y - line.Start.Y)); - return Distance(point, closest); - } - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// The distance. - /// line was null. - public static double Distance(PointF point, LineSegmentF line) - => Distance(point, line, out _); - - /// - /// Computes the distance between the point and the line. - /// - /// The point. - /// The line. - /// true if extend the line segment to a line; otherwise, false. - /// The distance. - /// line was null. - public static float Distance(PointF point, LineSegmentF line, bool extendToLine) - => extendToLine - ? Math.Abs(CrossProduct(point, line.End, line.Start)) / Distance(line.Start, line.End) - : Distance(point, line, out _); - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The foot point or the closest point. - /// The distance. - public static double Distance(Point2D point, DoublePoint2D[] polyline, out DoublePoint2D closest) - { - var cd = double.PositiveInfinity; - double td; - LineSegment l = new(); - DoublePoint2D cq = new(); - var count = polyline.Length - 1; - for (var i = 0; i < count; i++) - { - l.Start = polyline[i]; - l.End = polyline[i + 1]; - td = Distance(point, l, out var tq); - if (td < cd) - { - cd = td; - cq = tq; - } - } - - closest = cq; - return cd; - } - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The distance. - public static double Distance(Point2D point, DoublePoint2D[] polyline) - => Distance(point, polyline, out _); - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The foot point or the closest point. - /// The distance. - public static double Distance(Point2D point, IList polyline, out DoublePoint2D closest) - { - var cd = double.PositiveInfinity; - double td; - LineSegment l = new(); - DoublePoint2D cq = new(); - var count = polyline.Count - 1; - for (var i = 0; i < count; i++) - { - l.Start = polyline[i]; - l.End = polyline[i + 1]; - td = Distance(point, l, out var tq); - if (td < cd) - { - cd = td; - cq = tq; - } - } - closest = cq; - return cd; - } - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The distance. - public static double Distance(Point2D point, IList polyline) - => Distance(point, polyline, out _); - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The foot point or the closest point. - /// The distance. - public static double Distance(PointF point, PointF[] polyline, out PointF closest) - { - var cd = double.PositiveInfinity; - double td; - LineSegmentF l = new(); - PointF cq = new(); - var count = polyline.Length - 1; - for (var i = 0; i < count; i++) - { - l.Start = polyline[i]; - l.End = polyline[i + 1]; - td = Distance(point, l, out var tq); - if (td < cd) - { - cd = td; - cq = tq; - } - } - - closest = cq; - return cd; - } - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The distance. - public static double Distance(PointF point, PointF[] polyline) - => Distance(point, polyline, out _); - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The foot point or the closest point. - /// The distance. - public static double Distance(PointF point, IList polyline, out PointF closest) - { - var cd = double.PositiveInfinity; - double td; - LineSegmentF l = new(); - PointF cq = new(); - var count = polyline.Count - 1; - for (var i = 0; i < count; i++) - { - l.Start = polyline[i]; - l.End = polyline[i + 1]; - td = Distance(point, l, out var tq); - if (td < cd) - { - cd = td; - cq = tq; - } - } - closest = cq; - return cd; - } - - /// - /// Computes the distance between the point and the polyline. - /// - /// The point. - /// The polyline. - /// The distance. - public static double Distance(PointF point, IList polyline) - => Distance(point, polyline, out _); - - /// - /// Tests if the circle is in the polygon or is intersected with the polygon. - /// - /// The circle. - /// The polygon. - /// true if the circle is in the polygon or is intersected with the polygon; otherwise, false. - /// radius was null. - public static bool IsInOrIntersected(CoordinateCircle circle, DoublePoint2D[] polygon) - { - if (circle == null || double.IsNaN(circle.Radius)) throw new ArgumentNullException(nameof(circle), "circle should not be null."); - var d = Distance(circle.Center, polygon, out _); - return d < circle.Radius || Math.Abs(d - circle.Radius) < InternalHelper.DoubleAccuracy; - } - - /// - /// Tests if the circle is in the polygon or is intersected with the polygon. - /// - /// The circle. - /// The polygon. - /// true if the circle is in the polygon or is intersected with the polygon; otherwise, false. - /// radius was null. - public static bool IsInOrIntersected(CoordinateCircle circle, IList polygon) - { - if (circle == null || double.IsNaN(circle.Radius)) throw new ArgumentNullException(nameof(circle), "circle should not be null."); - var d = Distance(circle.Center, polygon, out _); - return d < circle.Radius || Math.Abs(d - circle.Radius) < InternalHelper.DoubleAccuracy; - } - - /// - /// Tests if the circle is in the polygon or is intersected with the polygon. - /// - /// The circle. - /// The polygon. - /// true if the circle is in the polygon or is intersected with the polygon; otherwise, false. - /// radius was null. - public static bool IsInOrIntersected(CoordinateCircleF circle, PointF[] polygon) - { - if (circle == null || double.IsNaN(circle.Radius)) throw new ArgumentNullException(nameof(circle), "circle should not be null."); - var d = Distance(circle.Center, polygon, out _); - return d < circle.Radius || Math.Abs(d - circle.Radius) < InternalHelper.DoubleAccuracy; - } - - /// - /// Tests if the circle is in the polygon or is intersected with the polygon. - /// - /// The circle. - /// The polygon. - /// true if the circle is in the polygon or is intersected with the polygon; otherwise, false. - /// radius was null. - public static bool IsInOrIntersected(CoordinateCircleF circle, IList polygon) - { - if (circle == null || double.IsNaN(circle.Radius)) throw new ArgumentNullException(nameof(circle), "circle should not be null."); - var d = Distance(circle.Center, polygon, out _); - return d < circle.Radius || Math.Abs(d - circle.Radius) < InternalHelper.DoubleAccuracy; - } - - /// - /// Gets the handed rotation state. - /// - /// The first line. - /// The second line. - /// The state. Less than 0 if left handed rotation; equals to 0 if the same; Greater than 0 if right handed rotation. - public static double HandedRotation(LineSegment a, LineSegment b) - { - var dx1 = a.Start.X - a.End.X; - var dy1 = a.Start.Y - a.End.Y; - var dx2 = b.Start.X - b.End.X; - var dy2 = b.Start.Y - b.End.Y; - return dx2 * dy1 - dx1 * dy2; - } - - /// - /// Gets the handed rotation state. - /// - /// The first line. - /// The second line. - /// The state. Less than 0 if left handed rotation; equals to 0 if the same; Greater than 0 if right handed rotation. - public static float HandedRotation(LineSegmentF a, LineSegmentF b) - { - var dx1 = a.Start.X - a.End.X; - var dy1 = a.Start.Y - a.End.Y; - var dx2 = b.Start.X - b.End.X; - var dy2 = b.Start.Y - b.End.Y; - return dx2 * dy1 - dx1 * dy2; - } - - /// - /// Computes sine of 2 vectors. - /// - /// The first vector. - /// The second vector. - /// The sine. - /// a or b was null. - public static double Sin(LineSegment a, LineSegment b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return (Distance(a.End, a.Start) * Distance(b.End, b.Start)) / ((a.End.X - a.Start.X) * (b.End.X - b.Start.X) + (a.End.Y - a.Start.Y) * (b.End.Y - b.Start.Y)); - } - - /// - /// Computes cosine of 2 vectors. - /// - /// The first vector. - /// The second vector. - /// The cosine. - /// a or b was null. - public static double Cos(LineSegment a, LineSegment b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return ((a.End.X - a.Start.X) * (b.End.X - b.Start.X) + (a.End.Y - a.Start.Y) * (b.End.Y - b.Start.Y)) / (Distance(a.End, a.Start) * Distance(b.End, b.Start)); - } - - /// - /// Computes sine of 2 vectors. - /// - /// The first vector. - /// The second vector. - /// The sine. - /// a or b was null. - public static double Sin(LineSegmentF a, LineSegmentF b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return (Distance(a.End, a.Start) * Distance(b.End, b.Start)) / ((a.End.X - a.Start.X) * (b.End.X - b.Start.X) + (a.End.Y - a.Start.Y) * (b.End.Y - b.Start.Y)); - } - - /// - /// Computes cosine of 2 vectors. - /// - /// The first vector. - /// The second vector. - /// The cosine. - /// a or b was null. - public static double Cos(LineSegmentF a, LineSegmentF b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return ((a.End.X - a.Start.X) * (b.End.X - b.Start.X) + (a.End.Y - a.Start.Y) * (b.End.Y - b.Start.Y)) / (Distance(a.End, a.Start) * Distance(b.End, b.Start)); - } - - /// - /// Tests if 2 line segments are intersected. - /// - /// The first line. - /// The second line. - /// true if the 2 lines are intersected, including connect with vertex; otherwise, false. - public static bool IsIntersected(LineSegment a, LineSegment b) - { - if (a == null || b == null) return false; - return (Math.Max(a.Start.X, a.End.X) >= Math.Min(b.Start.X, b.End.X)) && - (Math.Max(b.Start.X, b.End.X) >= Math.Min(a.Start.X, a.End.X)) && - (Math.Max(a.Start.Y, a.End.Y) >= Math.Min(b.Start.Y, b.End.Y)) && - (Math.Max(b.Start.Y, b.End.Y) >= Math.Min(a.Start.Y, a.End.Y)) && - (CrossProduct(b.Start, a.End, a.Start) * CrossProduct(a.End, b.End, a.Start) >= 0) && - (CrossProduct(a.Start, b.End, b.Start) * CrossProduct(b.End, a.End, b.Start) >= 0); - } - - /// - /// Tests if 2 line segments are intersected. - /// - /// The first line. - /// The second line. - /// true if the 2 lines are intersected, including connect with vertex; otherwise, false. - public static bool IsIntersected(LineSegmentF a, LineSegmentF b) - { - if (a == null || b == null) return false; - return (Math.Max(a.Start.X, a.End.X) >= Math.Min(b.Start.X, b.End.X)) && - (Math.Max(b.Start.X, b.End.X) >= Math.Min(a.Start.X, a.End.X)) && - (Math.Max(a.Start.Y, a.End.Y) >= Math.Min(b.Start.Y, b.End.Y)) && - (Math.Max(b.Start.Y, b.End.Y) >= Math.Min(a.Start.Y, a.End.Y)) && - (CrossProduct(b.Start, a.End, a.Start) * CrossProduct(a.End, b.End, a.Start) >= 0) && - (CrossProduct(a.Start, b.End, b.Start) * CrossProduct(b.End, a.End, b.Start) >= 0); - } - - /// - /// Computes included angle. - /// - /// The first line segment. - /// The second line segment. - /// The included angle of line vertex-start and line vertex-end. - /// a or b was null. - public static Angle Angle(LineSegment a, LineSegment b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return Angle(new DoublePoint2D(0, 0), new DoublePoint2D(a.End.X - a.Start.X, a.End.Y - a.Start.Y), new DoublePoint2D(b.End.X - b.Start.X, b.End.Y - b.Start.Y)); - } - - /// - /// Computes included angle. - /// - /// The first line segment. - /// The second line segment. - /// The included angle of line vertex-start and line vertex-end. - /// a or b was null. - public static Angle Angle(LineSegmentF a, LineSegmentF b) - { - if (a == null) throw new ArgumentNullException(nameof(a), "a should not be null"); - if (b == null) throw new ArgumentNullException(nameof(b), "b should not be null"); - return Angle(new DoublePoint2D(0, 0), new DoublePoint2D(a.End.X - a.Start.X, a.End.Y - a.Start.Y), new DoublePoint2D(b.End.X - b.Start.X, b.End.Y - b.Start.Y)); - } - - /// - /// Gets the angle of the line. - /// - /// The line. - /// The angle. - /// line was null. - internal static double AngleRadian(StraightLine line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - if (Math.Abs(line.A) < InternalHelper.DoubleAccuracy) - return 0; - if (Math.Abs(line.B) < InternalHelper.DoubleAccuracy) - return Math.PI / 2; - if (line.Slope > 0) - return Math.Atan(line.Slope); - else - return Math.PI + Math.Atan(line.Slope); - } - - /// - /// Gets the angle of the line. - /// - /// The line. - /// The angle. - /// line was null. - internal static double AngleRadian(StraightLineF line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - if (Math.Abs(line.A) < InternalHelper.SingleAccuracy) - return 0; - if (Math.Abs(line.B) < InternalHelper.SingleAccuracy) - return Math.PI / 2; - if (line.Slope > 0) - return Math.Atan(line.Slope); - else - return Math.PI + Math.Atan(line.Slope); - } - - /// - /// Gets the angle of the line. - /// - /// The line. - /// The angle. - /// line was null. - public static Angle Angle(StraightLine line) - => Maths.Angle.FromRadian(AngleRadian(line)); - - /// - /// Gets the angle of the line. - /// - /// The line. - /// The angle. - /// line was null. - public static Angle Angle(StraightLineF line) - => Maths.Angle.FromRadian(AngleRadian(line)); - - /// - /// Computes symmetry point from a line. - /// - /// The point. - /// The line. - /// The symmetry point. - /// line was null. - public static DoublePoint2D Symmetry(DoublePoint2D point, StraightLine line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - if (point == null) point = new(); - return new( - ((line.B * line.B - line.A * line.A) * point.X - 2 * line.A * line.B * point.Y - 2 * line.A * line.C) / (line.A * line.A + line.B * line.B), - ((line.A * line.A - line.B * line.B) * point.Y - 2 * line.A * line.B * point.X - 2 * line.B * line.C) / (line.A * line.A + line.B * line.B)); - } - - /// - /// Computes symmetry point from a line. - /// - /// The point. - /// The line. - /// The symmetry point. - /// line was null. - public static PointF Symmetry(PointF point, StraightLineF line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - return new( - ((line.B * line.B - line.A * line.A) * point.X - 2 * line.A * line.B * point.Y - 2 * line.A * line.C) / (line.A * line.A + line.B * line.B), - ((line.A * line.A - line.B * line.B) * point.Y - 2 * line.A * line.B * point.X - 2 * line.B * line.C) / (line.A * line.A + line.B * line.B)); - } - - /// - /// Tests the specific 2 point are in same side. - /// - /// The first point. - /// The second point. - /// The line. - /// true if they are in same side; otherwise, false. - /// line was null. - public static bool AreSameSide(DoublePoint2D a, DoublePoint2D b, StraightLine line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - if (a == null) a = new(); - if (b == null) b = new(); - return (line.A * a.X + line.B * a.Y + line.C) * (line.A * b.X + line.B * b.Y + line.C) > 0; - } - - /// - /// Tests the specific 2 point are in same side. - /// - /// The first point. - /// The second point. - /// The line. - /// true if they are in same side; otherwise, false. - /// line was null. - public static bool AreSameSide(PointF a, PointF b, StraightLineF line) - { - if (line == null) throw new ArgumentNullException(nameof(line), "line should noe be null."); - return (line.A * a.X + line.B * a.Y + line.C) * (line.A * b.X + line.B * b.Y + line.C) > 0; - } - - /// - /// Tests if 2 line are intersection. - /// - /// The first line. - /// The second line. - /// The point intersected. - /// true if they are intersected; otherwise, false. - public static bool IsIntersected(StraightLine a, StraightLine b, out DoublePoint2D p) - { - var d = a.A * b.B - b.A * a.B; - if (Math.Abs(d) < InternalHelper.DoubleAccuracy) - { - p = new(); - return false; - } - - p = new( - (b.C * a.B - a.C * b.B) / d, - (b.A * a.C - a.A * b.C) / d); - return true; - } - - /// - /// Tests if 2 line are intersected. - /// - /// The first line. - /// The second line. - /// true if they are intersected; otherwise, false. - public static bool IsIntersected(StraightLine a, StraightLine b) - => IsIntersected(a, b, out _); - - /// - /// Tests if 2 line are intersection. - /// - /// The first line. - /// The second line. - /// The point intersected. - /// true if they are intersected; otherwise, false. - public static bool IsIntersected(StraightLineF a, StraightLineF b, out PointF p) - { - var d = a.A * b.B - b.A * a.B; - if (Math.Abs(d) < InternalHelper.DoubleAccuracy) - { - p = new(); - return false; - } - - p = new( - (b.C * a.B - a.C * b.B) / d, - (b.A * a.C - a.A * b.C) / d); - return true; - } - - /// - /// Tests if 2 line are intersected. - /// - /// The first line. - /// The second line. - /// true if they are intersected; otherwise, false. - public static bool IsIntersected(StraightLineF a, StraightLineF b) - => IsIntersected(a, b, out _); - - /// - /// Gets the line relected. - /// - /// Mirror. - /// Incoming light. - /// The output light. - public static StraightLine Reflect(StraightLine a, StraightLine b) - { - var i = a.B * b.B + a.A * b.A; - var j = b.A * a.B - a.A * b.B; - var m = (i * a.B + j * a.A) / (a.B * a.B + a.A * a.A); - var n = (j * a.B - i * a.A) / (a.B * a.B + a.A * a.A); - if (Math.Abs(a.A * b.B - b.A * a.B) < InternalHelper.DoubleAccuracy) - return new(b.A, b.B, b.C); - var x = (a.B * b.C - b.B * a.C) / (a.A * b.B - b.A * a.B); - var y = (b.A * a.C - a.A * b.C) / (a.A * b.B - b.A * a.B); - return new(n, -m, m * y - x * n); - } - - /// - /// Gets the line relected. - /// - /// Mirror. - /// Incoming light. - /// The output light. - public static StraightLineF Reflect(StraightLineF a, StraightLineF b) - { - var i = a.B * b.B + a.A * b.A; - var j = b.A * a.B - a.A * b.B; - var m = (i * a.B + j * a.A) / (a.B * a.B + a.A * a.A); - var n = (j * a.B - i * a.A) / (a.B * a.B + a.A * a.A); - if (Math.Abs(a.A * b.B - b.A * a.B) < InternalHelper.DoubleAccuracy) - return new(b.A, b.B, b.C); - var x = (a.B * b.C - b.B * a.C) / (a.A * b.B - b.A * a.B); - var y = (b.A * a.C - a.A * b.C) / (a.A * b.B - b.A * a.B); - return new(n, -m, m * y - x * n); - } - - /// - /// Tests if the polygon is simple. - /// - /// The polygon. Requires to input by anticlockwise. - /// true if it is a simple polygon; otherwise, false. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - public static bool IsSimple(DoublePoint2D[] polygon) - { - if (polygon == null) throw new ArgumentNullException(nameof(polygon), "polygon should not be null."); - if (polygon.Length < 3) throw new ArgumentException("polygon is invalid because the points are less than 3.", nameof(polygon)); - int cn; - LineSegment l1 = new(); - LineSegment l2 = new(); - var count = polygon.Length; - for (var i = 0; i < count; i++) - { - l1.Start = polygon[i]; - l1.End = polygon[(i + 1) % count]; - cn = count - 3; - while (cn != 0) - { - l2.Start = polygon[(i + 2) % count]; - l2.End = polygon[(i + 3) % count]; - if (IsIntersected(l1, l2)) - break; - cn--; - } - - if (cn != 0) return false; - } - - return true; - } - - /// - /// Tests if the polygon is simple. - /// - /// The polygon. Requires to input by anticlockwise. - /// true if it is a simple polygon; otherwise, false. - public static bool IsSimple(IList polygon) - { - int cn; - LineSegment l1 = new(); - LineSegment l2 = new(); - var count = polygon.Count; - for (var i = 0; i < count; i++) - { - l1.Start = polygon[i]; - l1.End = polygon[(i + 1) % count]; - cn = count - 3; - while (cn != 0) - { - l2.Start = polygon[(i + 2) % count]; - l2.End = polygon[(i + 3) % count]; - if (IsIntersected(l1, l2)) - break; - cn--; - } - - if (cn != 0) return false; - } - - return true; - } - - /// - /// Tests if the polygon is simple. - /// - /// The polygon. Requires to input by anticlockwise. - /// true if it is a simple polygon; otherwise, false. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - public static bool IsSimple(PointF[] polygon) - { - if (polygon == null) throw new ArgumentNullException(nameof(polygon), "polygon should not be null."); - if (polygon.Length < 3) throw new ArgumentException("polygon is invalid because the points are less than 3.", nameof(polygon)); - int cn; - LineSegmentF l1 = new(); - LineSegmentF l2 = new(); - var count = polygon.Length; - for (var i = 0; i < count; i++) - { - l1.Start = polygon[i]; - l1.End = polygon[(i + 1) % count]; - cn = count - 3; - while (cn != 0) - { - l2.Start = polygon[(i + 2) % count]; - l2.End = polygon[(i + 3) % count]; - if (IsIntersected(l1, l2)) - break; - cn--; - } - - if (cn != 0) return false; - } - - return true; - } - - /// - /// Tests if the polygon is simple. - /// - /// The polygon. Requires to input by anticlockwise. - /// true if it is a simple polygon; otherwise, false. - public static bool IsSimple(IList polygon) - { - int cn; - LineSegmentF l1 = new(); - LineSegmentF l2 = new(); - var count = polygon.Count; - for (var i = 0; i < count; i++) - { - l1.Start = polygon[i]; - l1.End = polygon[(i + 1) % count]; - cn = count - 3; - while (cn != 0) - { - l2.Start = polygon[(i + 2) % count]; - l2.End = polygon[(i + 3) % count]; - if (IsIntersected(l1, l2)) - break; - cn--; - } - - if (cn != 0) return false; - } - - return true; - } - - /// - /// Gets convexity for each point in the polygon. - /// - /// The polygon. - /// The boolean array about if each point is convexity. - public static IList Convexity(DoublePoint2D[] polygon) - { - var index = 0; - var len = polygon.Length; - var point = polygon[0]; - var list = new List(); - for (var i = 1; i < len; i++) - { - list.Add(false); - if (polygon[i].Y < point.Y || (polygon[i].Y == point.Y && polygon[i].X < point.X)) - { - point = polygon[i]; - index = i; - } - } - - var count = len - 1; - list[index] = true; - while (count > 0) - { - if (CrossProduct(polygon[(index + 1) % len], polygon[(index + 2) % len], polygon[index]) >= 0) - list[(index + 1) % len] = true; - else - list[(index + 1) % len] = false; - index++; - count--; - } - - return list; - } - - /// - /// Tests if the polygon is convex. - /// - /// The polygon. - /// true if it is a convex polygon. - public static bool IsConvex(DoublePoint2D[] polygon) - => !Convexity(polygon).Any(ele => !ele); - - /// - /// Computes the area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static double Area(DoublePoint2D[] polygon) - { - var count = polygon.Length; - if (count < 3) return 0; - var s = polygon[0].Y * (polygon[count - 1].X - polygon[1].X); - for (var i = 1; i < count; i++) - { - s += polygon[i].Y * (polygon[i - 1].X - polygon[(i + 1) % count].X); - } - - return s / 2; - } - - /// - /// Computes the area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static double Area(IList polygon) - { - var count = polygon.Count; - if (count < 3) return 0; - var s = polygon[0].Y * (polygon[count - 1].X - polygon[1].X); - for (var i = 1; i < count; i++) - { - s += polygon[i].Y * (polygon[i - 1].X - polygon[(i + 1) % count].X); - } - - return s / 2; - } - - /// - /// Computes the absolute area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static double AbsArea(DoublePoint2D[] polygon) - => Math.Abs(Area(polygon)); - - /// - /// Computes the absolute area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static double AbsArea(IList polygon) - => Math.Abs(Area(polygon)); - - - /// - /// Computes the area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static float Area(PointF[] polygon) - { - var count = polygon.Length; - if (count < 3) return 0; - var s = polygon[0].Y * (polygon[count - 1].X - polygon[1].X); - for (var i = 1; i < count; i++) - { - s += polygon[i].Y * (polygon[i - 1].X - polygon[(i + 1) % count].X); - } - - return s / 2; - } - - /// - /// Computes the area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static float Area(IList polygon) - { - var count = polygon.Count; - if (count < 3) return 0; - var s = polygon[0].Y * (polygon[count - 1].X - polygon[1].X); - for (var i = 1; i < count; i++) - { - s += polygon[i].Y * (polygon[i - 1].X - polygon[(i + 1) % count].X); - } - - return s / 2; - } - - /// - /// Computes the absolute area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static float AbsArea(PointF[] polygon) - => Math.Abs(Area(polygon)); - - /// - /// Computes the absolute area of the polygon. - /// - /// The polygon. - /// The area of the polygon. Greater than 0 if anticlockwise; less than 0 if clockwise. - public static float AbsArea(IList polygon) - => Math.Abs(Area(polygon)); - - /// - /// Tests if the points in polygon is anticlockwise. - /// - /// The polygon. - /// true if it is anticlockwise; otherwise, false. - public static bool IsAnticlockwise(DoublePoint2D[] polygon) - => Area(polygon) > 0; - - /// - /// Tests if the points in polygon is anticlockwise. - /// - /// The polygon. - /// true if it is anticlockwise; otherwise, false. - public static bool IsAnticlockwise(IList polygon) - => Area(polygon) > 0; - - /// - /// Tests if the points in polygon is anticlockwise. - /// - /// The polygon. - /// true if it is anticlockwise; otherwise, false. - public static bool IsAnticlockwise(PointF[] polygon) - => Area(polygon) > 0; - - /// - /// Tests if the points in polygon is anticlockwise. - /// - /// The polygon. - /// true if it is anticlockwise; otherwise, false. - public static bool IsAnticlockwise(IList polygon) - => Area(polygon) > 0; - - /// - /// Gets the center of gravity of the polygon. - /// - /// The polygon. - /// The center of gravity of the polygon. - /// Only supports simple polygon. - public static DoublePoint2D CenterOfGravity(DoublePoint2D[] polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - DoublePoint2D p1; - DoublePoint2D p2; - double xtr, ytr, wtr, xtl, ytl, wtl; - xtr = ytr = wtr = xtl = ytl = wtl = 0d; - var count = polygon.Length; - for (int i = 0; i < count; i++) - { - p1 = polygon[i]; - p2 = polygon[(i + 1) % count]; - AddRegion(p1.X, p1.Y, p2.X, p2.Y, ref xtr, ref ytr, ref wtr, ref xtl, ref ytl, ref wtl); - } - - return new( - (wtr * xtr + wtl * xtl) / (wtr + wtl), - (wtr * ytr + wtl * ytl) / (wtr + wtl)); - } - - /// - /// Gets the center of gravity of the polygon. - /// - /// The polygon. - /// The center of gravity of the polygon. - /// Only supports simple polygon. - public static DoublePoint2D CenterOfGravity(IList polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - double xtr, ytr, wtr, xtl, ytl, wtl; - xtr = ytr = wtr = xtl = ytl = wtl = 0d; - DoublePoint2D p1; - DoublePoint2D p2; - var count = polygon.Count; - for (int i = 0; i < count; i++) - { - p1 = polygon[i]; - p2 = polygon[(i + 1) % count]; - AddRegion(p1.X, p1.Y, p2.X, p2.Y, ref xtr, ref ytr, ref wtr, ref xtl, ref ytl, ref wtl); - } - - return new( - (wtr * xtr + wtl * xtl) / (wtr + wtl), - (wtr * ytr + wtl * ytl) / (wtr + wtl)); - } - - /// - /// Gets the center of gravity of the polygon. - /// - /// The polygon. - /// The center of gravity of the polygon. - /// Only supports simple polygon. - public static PointF CenterOfGravity(PointF[] polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - PointF p1; - PointF p2; - double xtr, ytr, wtr, xtl, ytl, wtl; - xtr = ytr = wtr = xtl = ytl = wtl = 0f; - var count = polygon.Length; - for (int i = 0; i < count; i++) - { - p1 = polygon[i]; - p2 = polygon[(i + 1) % count]; - AddRegion(p1.X, p1.Y, p2.X, p2.Y, ref xtr, ref ytr, ref wtr, ref xtl, ref ytl, ref wtl); - } - - return new( - (float)(wtr * xtr + wtl * xtl) / (float)(wtr + wtl), - (float)(wtr * ytr + wtl * ytl) / (float)(wtr + wtl)); - } - - /// - /// Gets the center of gravity of the polygon. - /// - /// The polygon. - /// The center of gravity of the polygon. - /// Only supports simple polygon. - public static PointF CenterOfGravity(IList polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - double xtr, ytr, wtr, xtl, ytl, wtl; - xtr = ytr = wtr = xtl = ytl = wtl = 0f; - PointF p1; - PointF p2; - var count = polygon.Count; - for (int i = 0; i < count; i++) - { - p1 = polygon[i]; - p2 = polygon[(i + 1) % count]; - AddRegion(p1.X, p1.Y, p2.X, p2.Y, ref xtr, ref ytr, ref wtr, ref xtl, ref ytl, ref wtl); - } - - return new( - (float)(wtr * xtr + wtl * xtl) / (float)(wtr + wtl), - (float)(wtr * ytr + wtl * ytl) / (float)(wtr + wtl)); - } - - private static void AddPosPart(double x, double y, double w, ref double xtr, ref double ytr, ref double wtr) - { - if (Math.Abs(wtr + w) < InternalHelper.DoubleAccuracy) return; - xtr = (wtr * xtr + w * x) / (wtr + w); - ytr = (wtr * ytr + w * y) / (wtr + w); - wtr = w + wtr; - } - - private static void AddNegPart(double x, double y, double w, ref double xtl, ref double ytl, ref double wtl) - { - if (Math.Abs(wtl + w) < InternalHelper.DoubleAccuracy) return; - xtl = (wtl * xtl + w * x) / (wtl + w); - ytl = (wtl * ytl + w * y) / (wtl + w); - wtl = w + wtl; - } - - private static void AddRegion(double x1, double y1, double x2, double y2, ref double xtr, ref double ytr, ref double wtr, ref double xtl, ref double ytl, ref double wtl) - { - if (Math.Abs(x1 - x2) < InternalHelper.DoubleAccuracy) return; - if (x2 > x1) - { - AddPosPart((x2 + x1) / 2, y1 / 2, (x2 - x1) * y1, ref xtr, ref ytr, ref wtr); - AddPosPart((x1 + x2 + x2) / 3, (y1 + y1 + y2) / 3, (x2 - x1) * (y2 - y1) / 2, ref xtr, ref ytr, ref wtr); - } - else - { - AddNegPart((x2 + x1) / 2, y1 / 2, (x2 - x1) * y1, ref xtl, ref ytl, ref wtl); - AddNegPart((x1 + x2 + x2) / 3, (y1 + y1 + y2) / 3, (x2 - x1) * (y2 - y1) / 2, ref xtl, ref ytl, ref wtl); - } - } - - /// - /// Gets the points of contact from the specific point to the polygon. - /// - /// The point. - /// The polygon. - /// The right point of contact. - /// The left point of contact. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - /// polygon was not simple. - public static void PointTangentPoly(DoublePoint2D point, DoublePoint2D[] polygon, out DoublePoint2D right, out DoublePoint2D left) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - if (point == null) point = new(); - bool isLeft, isRight; - var count = polygon.Length; - LineSegment leftSegment = new(); - LineSegment rightSegment = new(); - right = polygon[0]; - left = polygon[0]; - for (int i = 1; i < count; i++) - { - leftSegment.Start = polygon[(i + count - 1) % count]; - leftSegment.End = polygon[i]; - rightSegment.Start = polygon[i]; - rightSegment.End = polygon[(i + 1) % count]; - isLeft = CrossProduct(leftSegment.End, point, leftSegment.Start) >= 0; - isRight = CrossProduct(rightSegment.End, point, rightSegment.Start) >= 0; - if (!isLeft && isRight) - { - if (CrossProduct(polygon[i], right, point) > 0) right = polygon[i]; - } - - if (isLeft && !isRight) - { - if (CrossProduct(left, polygon[i], point) > 0) left = polygon[i]; - } - } - - return; - } - - /// - /// Gets the points of contact from the specific point to the polygon. - /// - /// The point. - /// The polygon. - /// The right point of contact. - /// The left point of contact. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - /// polygon was not simple. - public static void PointTangentPoly(DoublePoint2D point, IList polygon, out DoublePoint2D right, out DoublePoint2D left) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - if (point == null) point = new(); - bool isLeft, isRight; - var count = polygon.Count; - LineSegment leftSegment = new(); - LineSegment rightSegment = new(); - right = polygon[0]; - left = polygon[0]; - for (int i = 1; i < count; i++) - { - leftSegment.Start = polygon[(i + count - 1) % count]; - leftSegment.End = polygon[i]; - rightSegment.Start = polygon[i]; - rightSegment.End = polygon[(i + 1) % count]; - isLeft = CrossProduct(leftSegment.End, point, leftSegment.Start) >= 0; - isRight = CrossProduct(rightSegment.End, point, rightSegment.Start) >= 0; - if (!isLeft && isRight) - { - if (CrossProduct(polygon[i], right, point) > 0) right = polygon[i]; - } - - if (isLeft && !isRight) - { - if (CrossProduct(left, polygon[i], point) > 0) left = polygon[i]; - } - } - - return; - } - - /// - /// Tests if the polygon has a core. - /// - /// The polygon. - /// A point of core; or null, if non-exists. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - /// polygon was not simple. - public static DoublePoint2D GetCore(DoublePoint2D[] polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - LineSegment l = new(); - var lineset = new List(); - var count = polygon.Length; - DoublePoint2D p = null; - int i, j, k; - for (i = 0; i < count; i++) - { - lineset.Add(new StraightLine(polygon[i], polygon[(i + 1) % count])); - } - - for (i = 0; i < count; i++) - { - for (j = 0; j < count; j++) - { - if (i == j) continue; - if (IsIntersected(lineset[i], lineset[j], out p)) - { - for (k = 0; k < count; k++) - { - l.Start = polygon[k]; - l.End = polygon[(k + 1) % count]; - if (CrossProduct(p, l.End, l.Start) > 0) break; - } - - if (k == count) break; - } - } - - if (j < count) break; - } - - if (i >= count) return null; - return p; - } - - /// - /// Tests if the polygon has a core. - /// - /// The polygon. - /// A point of core; or null, if non-exists. - /// polygon was invalid because its points are less than 3. - /// polygon was null. - /// polygon was not simple. - public static DoublePoint2D GetCore(IList polygon) - { - if (!IsSimple(polygon)) throw new InvalidOperationException("Only supports simple polygon.", new NotImplementedException("Only supports simple polygon.")); - LineSegment l = new(); - var lineset = new List(); - var count = polygon.Count; - DoublePoint2D p = null; - int i, j, k; - for (i = 0; i < count; i++) - { - lineset.Add(new StraightLine(polygon[i], polygon[(i + 1) % count])); - } - - for (i = 0; i < count; i++) - { - for (j = 0; j < count; j++) - { - if (i == j) continue; - if (IsIntersected(lineset[i], lineset[j], out p)) - { - for (k = 0; k < count; k++) - { - l.Start = polygon[k]; - l.End = polygon[(k + 1) % count]; - if (CrossProduct(p, l.End, l.Start) > 0) break; - } - - if (k == count) break; - } - } - - if (j < count) break; - } - - if (i >= count) return null; - return p; - } - - /// - /// Tests if the polygon has a core. - /// - /// The polygon. - /// true if has core; otherwise, false. - public static bool HasCore(DoublePoint2D[] polygon) - => GetCore(polygon) != null; - - /// - /// Tests if the polygon has a core. - /// - /// The polygon. - /// true if has core; otherwise, false. - public static bool HasCore(IList polygon) - => GetCore(polygon) != null; - - /// - /// Tests if the point is in the circle. - /// - /// The point to test. - /// The point of center of the circle. - /// The radius of the circle. - /// true if the point is in the circle; otherwise, false. - /// radius was invalid. - public static bool IsIn(DoublePoint2D point, DoublePoint2D center, double radius) - { - if (point == null) point = new(); - if (center == null) center = new(); - if (double.IsNaN(radius)) throw new ArgumentException("radius should be a valid number.", nameof(radius), new InvalidOperationException("radius is invalid.")); - var d = (point.X - center.X) * (point.X - center.X) + (point.Y - center.Y) * (point.Y - center.Y); - var r = radius * radius; - return d < r || Math.Abs(d - r) < InternalHelper.DoubleAccuracy; - } - - /// - /// Gets the rest point of the rectangle. The rectange is made by given 3 points. - /// - /// The first point. - /// The second point. - /// The third point. - /// The forth point; or null if failed. - public static DoublePoint2D GetRestPoint(DoublePoint2D a, DoublePoint2D b, DoublePoint2D c) - { - if (a == null) a = new(); - if (b == null) b = new(); - if (c == null) c = new(); - if (Math.Abs(DotProduct(a, b, c)) < InternalHelper.DoubleAccuracy) - return new DoublePoint2D(a.X + b.X - c.X, a.Y + b.Y - c.Y); - if (Math.Abs(DotProduct(a, c, b)) < InternalHelper.DoubleAccuracy) - return new DoublePoint2D(a.X + c.X - b.X, a.Y + c.Y - b.X); - if (Math.Abs(DotProduct(c, b, a)) < InternalHelper.DoubleAccuracy) - return new DoublePoint2D(c.X + b.X - a.X, c.Y + b.Y - a.Y); - return null; - } - - /// - /// Gets the relationship between 2 circles. - /// - /// The first circle. - /// The second circle. - /// The relationship between 2 circles. - /// a or b was invalid. - public static RelationshipBetweenCircles Relation(CoordinateCircle a, CoordinateCircle b) - { - if (a == null) a = new(); - if (b == null) b = new(); - var center1 = a.Center; - var center2 = b.Center; - var radius1 = a.Radius; - var radius2 = b.Radius; - if (double.IsNaN(radius1)) throw new ArgumentException("a radius should be a valid number.", nameof(a), new InvalidOperationException("radius1 is invalid.")); - if (double.IsNaN(radius2)) throw new ArgumentException("b radius should be a valid number.", nameof(b), new InvalidOperationException("radius2 is invalid.")); - var d = Math.Sqrt((center1.X - center2.X) * (center1.X - center2.X) + (center1.Y - center2.Y) * (center1.Y - center2.Y)); - if (d < InternalHelper.DoubleAccuracy && Math.Abs(radius1 - radius2) < InternalHelper.DoubleAccuracy) - return RelationshipBetweenCircles.Congruence; - if (Math.Abs(d - radius1 - radius2) < InternalHelper.DoubleAccuracy) - return RelationshipBetweenCircles.ExternallyTangent; - if (Math.Abs(d - Math.Abs(radius1 - radius2)) < InternalHelper.DoubleAccuracy) - return RelationshipBetweenCircles.Inscribe; - if (d > radius1 + radius2) - return RelationshipBetweenCircles.Separation; - if (d < Math.Abs(radius1 - radius2)) - return RelationshipBetweenCircles.Inclusion; - if (Math.Abs(radius1 - radius2) < d && d < radius1 + radius2) - return RelationshipBetweenCircles.Intersection; - return (RelationshipBetweenCircles)7; // Error! - } - - /// - /// Gets the relationship between 2 circles. - /// - /// The first circle. - /// The second circle. - /// The relationship between 2 circles. - /// a or b was invalid. - public static RelationshipBetweenCircles Relation(CoordinateCircleF a, CoordinateCircleF b) - { - if (a == null) a = new(); - if (b == null) b = new(); - var center1 = a.Center; - var center2 = b.Center; - var radius1 = a.Radius; - var radius2 = b.Radius; - if (float.IsNaN(radius1)) throw new ArgumentException("a radius should be a valid number.", nameof(a), new InvalidOperationException("radius1 is invalid.")); - if (float.IsNaN(radius2)) throw new ArgumentException("b radius should be a valid number.", nameof(b), new InvalidOperationException("radius2 is invalid.")); - var d = Math.Sqrt((center1.X - center2.X) * (center1.X - center2.X) + (center1.Y - center2.Y) * (center1.Y - center2.Y)); - if (d < InternalHelper.SingleAccuracy && Math.Abs(radius1 - radius2) < InternalHelper.SingleAccuracy) - return RelationshipBetweenCircles.Congruence; - if (Math.Abs(d - radius1 - radius2) < InternalHelper.SingleAccuracy) - return RelationshipBetweenCircles.ExternallyTangent; - if (Math.Abs(d - Math.Abs(radius1 - radius2)) < InternalHelper.SingleAccuracy) - return RelationshipBetweenCircles.Inscribe; - if (d > radius1 + radius2) - return RelationshipBetweenCircles.Separation; - if (d < Math.Abs(radius1 - radius2)) - return RelationshipBetweenCircles.Inclusion; - if (Math.Abs(radius1 - radius2) < d && d < radius1 + radius2) - return RelationshipBetweenCircles.Intersection; - return (RelationshipBetweenCircles)7; // Error! - } - - private static (DoublePoint2D, DoublePoint2D) Pointcuts(CoordinateCircle circle, DoublePoint2D point, double radius) - { - var a = point.X - circle.CenterX; - var b = point.Y - circle.CenterY; - var r = (a * a + b * b + circle.Radius * circle.Radius - radius * radius) / 2; - var left = new DoublePoint2D(); - var right = new DoublePoint2D(); - if (a == 0 && b != 0) - { - left.Y = right.Y = r / b; - left.X = Math.Sqrt(circle.Radius * circle.Radius - left.Y * left.Y); - right.X = -left.X; - } - else if (a != 0 && b == 0) - { - left.X = right.X = r / a; - left.Y = Math.Sqrt(circle.Radius * circle.Radius - left.X * right.X); - right.Y = -left.Y; - } - else if (a != 0 && b != 0) - { - double delta; - delta = b * b * r * r - (a * a + b * b) * (r * r - circle.Radius * circle.Radius * a * a); - left.Y = (b * r + Math.Sqrt(delta)) / (a * a + b * b); - right.Y = (b * r - Math.Sqrt(delta)) / (a * a + b * b); - left.X = (r - b * left.Y) / a; - right.X = (r - b * right.Y) / a; - } - - left.X += left.X; - left.Y += left.Y; - right.X += left.X; - right.Y += left.Y; - return (left, right); - } - - /// - /// Computes the areas. - /// - /// The first circle. - /// The second circle. - /// The area. - /// a or b was invalid. - public static double Area(CoordinateCircle a, CoordinateCircle b) - { - var rela = Relation(a, b); - switch (rela) - { - case RelationshipBetweenCircles.Inclusion: - return Math.Max(a.Area(), b.Area()); - case RelationshipBetweenCircles.Separation: - case RelationshipBetweenCircles.ExternallyTangent: - case RelationshipBetweenCircles.Inscribe: - return a.Area() + b.Area(); - case RelationshipBetweenCircles.Congruence: - return a.Area(); - } - - var (left, right) = Pointcuts(a, b.Center, b.Radius); - var p1 = a.Center; - var r1 = a.Radius; - var p2 = b.Center; - var r2 = b.Radius; - if (r1 > r2) - { - var p3 = p1; - p1 = p2; - p2 = p3; - var r3 = r1; - r1 = r2; - r2 = r3; - } - - var width = p1.X - p2.X; - var height = p1.Y - p2.Y; - var rr = Math.Sqrt(width * width + height * height); - var dx1 = left.X - p1.X; - var dy1 = left.Y - p1.Y; - var dx2 = right.X - p1.X; - var dy2 = right.Y - p1.Y; - var sita1 = Math.Acos((dx1 * dx2 + dy1 * dy2) / r1 / r1); - dx1 = left.X - p2.X; - dy1 = left.Y - p2.Y; - dx2 = right.X - p2.X; - dy2 = right.Y - p2.Y; - var sita2 = Math.Acos((dx1 * dx2 + dy1 * dy2) / r2 / r2); - return rr < r2 - ? r1 * r1 * (Math.PI - sita1 / 2 + Math.Sin(sita1) / 2) + r2 * r2 * (sita2 - Math.Sin(sita2)) / 2 - : (r1 * r1 * (sita1 - Math.Sin(sita1)) + r2 * r2 * (sita2 - Math.Sin(sita2))) / 2; - } - - /// - /// Gets the pointcuts. - /// - /// The circle. - /// The point. - /// The 2 pointcuts. - public static (DoublePoint2D, DoublePoint2D) Pointcuts(CoordinateCircle circle, DoublePoint2D point) - { - var p = new DoublePoint2D((circle.CenterX + point.X) / 2, (circle.CenterY + point.Y) / 2); - var dx = p.X - circle.CenterX; - var dy = p.Y - circle.CenterY; - var r = Math.Sqrt(dx * dx + dy * dy); - return Pointcuts(circle, p, r); - } - - /// - /// Gets the pointcuts. - /// - /// The circle. - /// The straight line. - /// The pointcuts. It may only contains 1 or even none. - public static (DoublePoint2D, DoublePoint2D) Pointcuts(CoordinateCircle circle, StraightLine line) - { - int res; - var a = line.A; - var b = line.B; - var c = line.C + a * circle.CenterX + b * circle.CenterY; - var left = new DoublePoint2D(); - var right = new DoublePoint2D(); - var r2 = circle.Radius * circle.Radius; - if (a == 0 && b != 0) - { - var tmp = -c / b; - if (r2 < tmp * tmp) return (null, null); - if (r2 == tmp * tmp) - { - res = 1; - left.Y = tmp; - left.X = 0; - } - else - { - res = 2; - left.Y = right.Y = tmp; - left.X = Math.Sqrt(r2 - tmp * tmp); - right.X = -left.X; - } - } - else if (a != 0 && b == 0) - { - var tmp = -c / a; - if (r2 < tmp * tmp) return (null, null); - if (r2 == tmp * tmp) - { - res = 1; - left.X = tmp; - left.Y = 0; - } - else - { - res = 2; - left.X = right.X = tmp; - left.Y = Math.Sqrt(r2 - tmp * tmp); - right.Y = -left.Y; - } - } - else if (a != 0 && b != 0) - { - double delta; - delta = b * b * c * c - (a * a + b * b) * (c * c - a * a * r2); - if (delta < 0) return (null, null); - if (delta == 0) - { - res = 1; - left.Y = -b * c / (a * a + b * b); - left.X = (-c - b * left.Y) / a; - } - else - { - res = 2; - left.Y = (-b * c + Math.Sqrt(delta)) / (a * a + b * b); - right.Y = (-b * c - Math.Sqrt(delta)) / (a * a + b * b); - left.X = (-c - b * left.Y) / a; - right.X = (-c - b * right.Y) / a; - } - } - else - { - return (null, null); - } - - left.X += circle.CenterX; - left.Y += circle.CenterY; - if (res == 1) return (left, null); - right.X += circle.CenterX; - right.Y += circle.CenterY; - return (left, right); - } -} diff --git a/Maths/TwoDimentional/Line.cs b/Maths/TwoDimentional/Line.cs deleted file mode 100644 index c8241701..00000000 --- a/Maths/TwoDimentional/Line.cs +++ /dev/null @@ -1,567 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The line segment in coordinate. -/// -[DataContract] -public class LineSegment : IPixelOutline, ICoordinateSinglePoint, ICloneable, IEquatable -{ - private DoublePoint2D start; - private DoublePoint2D end; - - /// - /// Initializes a new instance of the LineSegment class. - /// - public LineSegment() - { - start = new(); - end = new(); - } - - /// - /// Initializes a new instance of the LineSegment class. - /// - /// X of the start point. - /// Y of the start point. - /// X of the end point. - /// Y of the end point. - public LineSegment(double x1, double y1, double x2, double y2) - { - start = new(x1, y1); - end = new(x2, y2); - } - - /// - /// Initializes a new instance of the LineSegment class. - /// - /// The start point. - /// The end point. - public LineSegment(DoublePoint2D start, DoublePoint2D end) - { - this.start = start ?? new(); - this.end = end ?? new(); - } - - /// - /// Initializes a new instance of the LineSegment class. - /// - /// The line segment. - public LineSegment(LineSegmentF line) - { - if (line == null) line = new(); - start = line.Start; - end = line.End; - } - - /// - /// Gets or sets the start point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint2D Start - { - get => start; - set => start = value ?? new(); - } - - /// - /// Gets or sets the end point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public DoublePoint2D End - { - get => end; - set => end = value ?? new(); - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("x1")] - [DataMember(Name = "x1")] - public double StartX - { - get => Start.X; - set => Start.X = value; - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("y1")] - [DataMember(Name = "y1")] - public double StartY - { - get => Start.Y; - set => Start.Y = value; - } - - /// - /// Gets the x of end point. - /// - [JsonPropertyName("x2")] - [DataMember(Name = "x2")] - public double EndX - { - get => End.X; - set => End.X = value; - } - - /// - /// Gets the x of end point. - /// - [JsonPropertyName("y2")] - [DataMember(Name = "y2")] - public double EndY - { - get => End.Y; - set => End.Y = value; - } - - /// - /// Gets the length. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double Length => Math.Sqrt(Math.Pow(End.X - Start.X, 2) + Math.Pow(End.Y - Start.Y, 2)); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{StartX:0.########}, {StartY:0.########} → {EndX:0.########}, {EndY:0.########}"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"{StartX}, {StartY} → {EndX}, {EndY}"; - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public double GetY(double x) - => (x - StartX) / (StartX - EndX) * (StartY - EndY) + StartY; - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public double GetX(double y) - => (y - StartY) / (StartY - EndY) * (StartX - EndX) + StartX; - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs((point.Y - StartY) / (StartY - EndY) - (point.X - StartX) / (StartX - EndX)) < InternalHelper.DoubleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public LineSegment Clone() - => new(start, end); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(LineSegment other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return StartX == other.StartX && StartY == other.StartY && EndX == other.EndX && EndY == other.EndY; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as LineSegment); - } - - /// - public override int GetHashCode() - => Tuple.Create(StartX, StartY, EndX, EndY).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(LineSegment leftValue, LineSegment rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(LineSegment leftValue, LineSegment rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to a line. - /// - /// The line segment. - public static explicit operator StraightLine(LineSegment value) - { - if (value is null) return null; - var width = value.Start.X - value.End.X; - var height = value.Start.Y - value.End.Y; - return new StraightLine(width, -height, value.Start.Y / height - value.Start.X / width); - } -} - -/// -/// The straight line in coordinate. -/// -[DataContract] -public class StraightLine : IPixelOutline, ICoordinateSinglePoint, IEquatable -{ - /// - /// Initializes a new instance of the StraightLine class. - /// General form: ax+by+c=0 (a≥0). - /// - public StraightLine() - { - A = 1; - B = -1; - C = 0; - Slope = 1; - Intercept = 0; - } - - /// - /// Initializes a new instance of the StraightLine class. - /// General form: ax+by+c=0 (a≥0). - /// - /// Parameter a. - /// Parameter b. - /// Parameter c. - public StraightLine(double a, double b, double c) - { - A = a; - B = b; - C = c; - Slope = GetSlope(a, b); - Intercept = b == 0 || double.IsNaN(b) ? double.NaN : -c / b; - } - - /// - /// Initializes a new instance of the StraightLine class. - /// Slope intercept form: y=kx+b. - /// - /// Parameter k. - /// Parameter b. - public StraightLine(double k, double b) - { - Slope = k; - Intercept = b; - B = -1; - A = k; - C = b; - } - - /// - /// Initializes a new instance of the StraightLine class. - /// - /// The line segment to extend. - public StraightLine(LineSegment line) - : this(line.Start, line.End) - { - } - - /// - /// Initializes a new instance of the StraightLine class. - /// - /// The first point. - /// The second point. - public StraightLine(DoublePoint2D a, DoublePoint2D b) - { - if (a == null) a = new(); - if (b == null) b = new(); - if (a.X == b.X && a.Y == b.Y) - { - A = 1; - B = -1; - C = 0; - Slope = 1; - Intercept = 0; - return; - } - - var sign = 1; - A = b.Y - a.Y; - if (A < 0) - { - sign = -1; - A = sign * A; - } - - B = sign * (a.X - b.X); - C = sign * (a.Y * b.X - a.X * b.Y); - Slope = GetSlope(A, B); - Intercept = B == 0 || double.IsNaN(B) ? double.NaN : -C / B; - } - - /// - /// Initializes a new instance of the StraightLine class. - /// - /// The line. - public StraightLine(StraightLineF line) - { - if (line == null) line = new(); - Slope = line.Slope; - Intercept = line.Intercept; - B = line.B; - A = line.A; - C = line.C; - } - - /// - /// Gets or sets parameter a in general form. - /// - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public double A { get; } - - /// - /// Gets or sets parameter b in general form. - /// - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public double B { get; } - - /// - /// Gets or sets parameter c in general form. - /// - [JsonPropertyName("c")] - [DataMember(Name = "c")] - public double C { get; } - - /// - /// Gets or sets the slope. Parameter k in slope intercept form. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double Slope { get; } - - /// - /// Gets or sets the intercept. Parameter b in slope intercept form. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public double Intercept { get; } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public double GetY(double x) - => -(A * x + C) / B; - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public double GetX(double y) - => -(B * y + C) / A; - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs(A * point.X + B * point.Y + C) < InternalHelper.DoubleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(double left, double right, double accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{A:0.########} x + {B:0.########} y + {C:0.########} = 0"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"{A} x + {B} y + {C} = 0"; - } - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(StraightLine other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return A == other.A && B == other.B && C == other.C; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as StraightLine); - } - - /// - public override int GetHashCode() - => Tuple.Create(A, B, C).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(StraightLine leftValue, StraightLine rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(StraightLine leftValue, StraightLine rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to angle. - /// - /// The line. - public static explicit operator Angle(StraightLine value) - => value is null ? new Angle(0) : Geometry.Angle(value); - - private static double GetSlope(double a, double b) - { - if (b == 0 || double.IsNaN(b) || (b <= InternalHelper.DoubleAccuracy && b >= -InternalHelper.DoubleAccuracy)) - { - if (a > InternalHelper.DoubleAccuracy) return double.PositiveInfinity; - if (a < -InternalHelper.DoubleAccuracy) return double.NegativeInfinity; - return double.NaN; - } - - return -a / b; - } -} diff --git a/Maths/TwoDimentional/LineF.cs b/Maths/TwoDimentional/LineF.cs deleted file mode 100644 index b4c482e9..00000000 --- a/Maths/TwoDimentional/LineF.cs +++ /dev/null @@ -1,545 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The line segment in coordinate. -/// -[DataContract] -public class LineSegmentF : IPixelOutline, ICoordinateSinglePoint, ICloneable, IEquatable -{ - private PointF start; - private PointF end; - - /// - /// Initializes a new instance of the LineSegmentF class. - /// - public LineSegmentF() - { - start = new(); - end = new(); - } - - /// - /// Initializes a new instance of the LineSegmentF class. - /// - /// X of the start point. - /// Y of the start point. - /// X of the end point. - /// Y of the end point. - public LineSegmentF(float x1, float y1, float x2, float y2) - { - start = new(x1, y1); - end = new(x2, y2); - } - - /// - /// Initializes a new instance of the LineSegmentF class. - /// - /// The start point. - /// The end point. - public LineSegmentF(PointF start, PointF end) - { - this.start = start; - this.end = end; - } - - /// - /// Gets or sets the start point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public PointF Start - { - get => start; - set => start = value; - } - - /// - /// Gets or sets the end point. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public PointF End - { - get => end; - set => end = value; - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("x1")] - [DataMember(Name = "x1")] - public float StartX - { - get => Start.X; - set => Start = new PointF(float.IsNaN(value) ? 0f : value, Start.Y); - } - - /// - /// Gets the x of start point. - /// - [JsonPropertyName("y1")] - [DataMember(Name = "y1")] - public float StartY - { - get => Start.Y; - set => Start = new PointF(Start.X, float.IsNaN(value) ? 0f : value); - } - - /// - /// Gets the x of end point. - /// - [JsonPropertyName("x2")] - [DataMember(Name = "x2")] - public float EndX - { - get => End.X; - set => End = new PointF(float.IsNaN(value) ? 0f : value, End.Y); - } - - /// - /// Gets the x of end point. - /// - [JsonPropertyName("y2")] - [DataMember(Name = "y2")] - public float EndY - { - get => End.Y; - set => End = new PointF(Start.X, float.IsNaN(value) ? 0f : value); - } - - /// - /// Gets the length. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] -#if NETFRAMEWORK - public float Length => (float)Math.Sqrt((float)Math.Pow(End.X - Start.X, 2) + (float)Math.Pow(End.Y - Start.Y, 2)); -#else - public float Length => MathF.Sqrt(MathF.Pow(End.X - Start.X, 2) + MathF.Pow(End.Y - Start.Y, 2)); -#endif - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{StartX:0.########}, {StartY:0.########} → {EndX:0.########}, {EndY:0.########}"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"{StartX}, {StartY} → {EndX}, {EndY}"; - } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public float GetY(float x) - => (x - StartX) / (StartX - EndX) * (StartY - EndY) + StartY; - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public float GetX(float y) - => (y - StartY) / (StartY - EndY) * (StartX - EndX) + StartX; - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs((point.Y - StartY) / (StartY - EndY) - (point.X - StartX) / (StartX - EndX)) < InternalHelper.SingleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy).Select(ele => new Point2D(ele.X, ele.Y)); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - public LineSegment Clone() - => new(start, end); - - /// - /// Creates a new object that is a copy of the current instance. - /// - /// An instance copied from current one. - object ICloneable.Clone() - => Clone(); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(LineSegmentF other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return StartX == other.StartX && StartY == other.StartY && EndX == other.EndX && EndY == other.EndY; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as LineSegmentF); - } - - /// - public override int GetHashCode() - => Tuple.Create(StartX, StartY, EndX, EndY).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(LineSegmentF leftValue, LineSegmentF rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(LineSegmentF leftValue, LineSegmentF rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to a line. - /// - /// The line segment. - public static explicit operator StraightLineF(LineSegmentF value) - { - if (value is null) return null; - var width = value.Start.X - value.End.X; - var height = value.Start.Y - value.End.Y; - return new(width, -height, value.Start.Y / height - value.Start.X / width); - } -} - -/// -/// The straight line in coordinate. -/// -[DataContract] -public class StraightLineF : IPixelOutline, ICoordinateSinglePoint, IEquatable -{ - /// - /// Initializes a new instance of the StraightLineF class. - /// General form: ax+by+c=0 (a≥0). - /// - public StraightLineF() - { - A = 1; - B = -1; - C = 0; - Slope = 1; - Intercept = 0; - } - - /// - /// Initializes a new instance of the StraightLineF class. - /// General form: ax+by+c=0 (a≥0). - /// - /// Parameter a. - /// Parameter b. - /// Parameter c. - public StraightLineF(float a, float b, float c) - { - A = a; - B = b; - C = c; - Slope = GetSlope(a, b); - Intercept = b == 0 || float.IsNaN(b) ? float.NaN : -c / b; - } - - /// - /// Initializes a new instance of the StraightLineF class. - /// Slope intercept form: y=kx+b. - /// - /// Parameter k. - /// Parameter b. - public StraightLineF(float k, float b) - { - Slope = k; - Intercept = b; - B = -1; - A = k; - C = b; - } - - /// - /// Initializes a new instance of the StraightLineF class. - /// - /// The line segment to extend. - public StraightLineF(LineSegmentF line) - : this(line.Start, line.End) - { - } - - /// - /// Initializes a new instance of the StraightLineF class. - /// - /// The first point. - /// The second point. - public StraightLineF(PointF a, PointF b) - { - if (a.X == b.X && a.Y == b.Y) - { - A = 1; - B = -1; - C = 0; - Slope = 1; - Intercept = 0; - return; - } - - var sign = 1; - A = b.Y - a.Y; - if (A < 0) - { - sign = -1; - A = sign * A; - } - - B = sign * (a.X - b.X); - C = sign * (a.Y * b.X - a.X * b.Y); - Slope = GetSlope(A, B); - Intercept = B == 0 || float.IsNaN(B) ? float.NaN : -C / B; - } - - /// - /// Gets or sets parameter a in general form. - /// - [JsonPropertyName("a")] - [DataMember(Name = "a")] - public float A { get; } - - /// - /// Gets or sets parameter b in general form. - /// - [JsonPropertyName("b")] - [DataMember(Name = "b")] - public float B { get; } - - /// - /// Gets or sets parameter c in general form. - /// - [JsonPropertyName("c")] - [DataMember(Name = "c")] - public float C { get; } - - /// - /// Gets or sets the slope. Parameter k in slope intercept form. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public float Slope { get; } - - /// - /// Gets or sets the intercept. Parameter b in slope intercept form. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public float Intercept { get; } - - /// - /// Gets y by x. - /// - /// X. - /// Y. - public float GetY(float x) - => -(A * x + C) / B; - - /// - /// Gets x by y. - /// - /// Y. - /// X. - public float GetX(float y) - => -(B * y + C) / A; - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - public bool Contains(Point2D point) - => point != null && Math.Abs(A * point.X + B * point.Y + C) < InternalHelper.SingleAccuracy; - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - public IEnumerable DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy); - - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> IPixelOutline.DrawPoints(float left, float right, float accuracy) - => InternalHelper.DrawPoints(this, left, right, accuracy).Select(ele => new Point2D(ele.X, ele.Y)); - - /// - /// Returns a string that represents the line. - /// - /// A string that represents the line. - public override string ToString() - { - try - { - return $"{A:0.########} x + {B:0.########} y + {C:0.########} = 0"; - } - catch (ArgumentException) - { - } - catch (InvalidOperationException) - { - } - catch (FormatException) - { - } - catch (NullReferenceException) - { - } - - return $"{A} x + {B} y + {C} = 0"; - } - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(StraightLineF other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return A == other.A && B == other.B && C == other.C; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - if (obj is null) return false; - return Equals(obj as StraightLineF); - } - - /// - public override int GetHashCode() - => Tuple.Create(A, B, C).GetHashCode(); - - /// - /// Compares two angles to indicate if they are same. - /// leftValue == rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are same; otherwise, false. - public static bool operator ==(StraightLineF leftValue, StraightLineF rightValue) - { - if (leftValue is null && rightValue is null) return true; - if (leftValue is null || rightValue is null) return false; - return leftValue.Equals(rightValue); - } - - /// - /// Compares two angles to indicate if they are different. - /// leftValue != rightValue - /// - /// The left value to compare. - /// The right value to compare. - /// true if they are different; otherwise, false. - public static bool operator !=(StraightLineF leftValue, StraightLineF rightValue) - { - if (leftValue is null && rightValue is null) return false; - if (leftValue is null || rightValue is null) return true; - return !leftValue.Equals(rightValue); - } - - /// - /// Converts to angle. - /// - /// The line. - public static explicit operator Angle(StraightLineF value) - => value is null ? new Angle(0) : Geometry.Angle(value); - - private static float GetSlope(float a, float b) - { - if (b == 0 || float.IsNaN(b) || (b <= InternalHelper.SingleAccuracy && b >= -InternalHelper.SingleAccuracy)) - { - if (a > InternalHelper.SingleAccuracy) return float.PositiveInfinity; - if (a < -InternalHelper.SingleAccuracy) return float.NegativeInfinity; - return float.NaN; - } - - return -a / b; - } -} diff --git a/Maths/TwoDimentional/PointOutline.cs b/Maths/TwoDimentional/PointOutline.cs deleted file mode 100644 index 190c3218..00000000 --- a/Maths/TwoDimentional/PointOutline.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Trivial.Maths; - -/// -/// The interface for outline as point collection. -/// -public interface IPixelOutline where TUnit : struct, IComparable, IEquatable -{ - /// - /// Generates point collection in the specific zone and accuracy. - /// - /// The left boundary. - /// The right boundary. - /// The step in x. - /// A point collection. - IEnumerable> DrawPoints(TUnit left, TUnit right, TUnit accuracy); -} - -/// -/// The interface for outline as point collection. -/// -public interface ICoordinateSinglePoint where TUnit : struct, IComparable, IEquatable -{ - /// - /// Gets y by x. - /// - /// X. - /// Y. - TUnit GetY(TUnit x); - - /// - /// Gets x by y. - /// - /// Y. - /// X. - TUnit GetX(TUnit y); - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - bool Contains(Point2D point); -} - -/// -/// The interface for outline as point collection. -/// -public interface ICoordinateTuplePoint where TUnit : struct, IComparable, IEquatable -{ - /// - /// Gets y by x. - /// - /// X. - /// Y. - (TUnit, TUnit) GetY(TUnit x); - - /// - /// Gets x by y. - /// - /// Y. - /// X. - (TUnit, TUnit) GetX(TUnit y); - - /// - /// Test if a point is on the line. - /// - /// The point to test. - /// true if the point is on the line; otherwise, false. - bool Contains(Point2D point); -} diff --git a/Messages/Data/Code128.cs b/Messages/Data/Code128.cs new file mode 100644 index 00000000..ddf18da0 --- /dev/null +++ b/Messages/Data/Code128.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Data; + +/// +/// The code-128, which is a high-density linear barcode symbology defined in ISO/IEC 15417:2007. +/// It is used for alphanumeric or numeric-only barcodes. +/// +public partial class Code128 +{ + /// + /// The sub-types. + /// + public enum Subtypes : byte + { + /// + /// Code A. + /// + A = 1, + + /// + /// Code B. + /// + B = 2, + + /// + /// Code C. + /// + C = 3 + } + + /// + /// The output string format. + /// + public enum Formats : byte + { + /// + /// Regular format. + /// + Regular = 0, + + /// + /// Text only. + /// + Text = 1, + + /// + /// Symbol values. + /// + Values = 2, + + /// + /// Hex values. + /// + Hex = 3, + + /// + /// The barcode areas that white represented as 0 and black represented as 1. + /// + Barcode = 4, + + /// + /// The stroke path data used in SVG and XAML. + /// + Path = 5 + } + + /// + /// All patterns. + /// + private readonly static List patterns = new() { "11011001100", "11001101100", "11001100110", "10010011000", "10010001100", "10001001100", "10011001000", "10011000100", "10001100100", "11001001000", "11001000100", "11000100100", "10110011100", "10011011100", "10011001110", "10111001100", "10011101100", "10011100110", "11001110010", "11001011100", "11001001110", "11011100100", "11001110100", "11101101110", "11101001100", "11100101100", "11100100110", "11101100100", "11100110100", "11100110010", "11011011000", "11011000110", "11000110110", "10100011000", "10001011000", "10001000110", "10110001000", "10001101000", "10001100010", "11010001000", "11000101000", "11000100010", "10110111000", "10110001110", "10001101110", "10111011000", "10111000110", "10001110110", "11101110110", "11010001110", "11000101110", "11011101000", "11011100010", "11011101110", "11101011000", "11101000110", "11100010110", "11101101000", "11101100010", "11100011010", "11101111010", "11001000010", "11110001010", "10100110000", "10100001100", "10010110000", "10010000110", "10000101100", "10000100110", "10110010000", "10110000100", "10011010000", "10011000010", "10000110100", "10000110010", "11000010010", "11001010000", "11110111010", "11000010100", "10001111010", "10100111100", "10010111100", "10010011110", "10111100100", "10011110100", "10011110010", "11110100100", "11110010100", "11110010010", "11011011110", "11011110110", "11110110110", "10101111000", "10100011110", "10001011110", "10111101000", "10111100010", "11110101000", "11110100010", "10111011110", "10111101110", "11101011110", "11110101110", "11010000100", "11010010000", "11010011100", "11000111010" }; + + /// + /// Gets the pattern of the specific symbol value. + /// White represented as false, black represented as true. + /// + /// The symbol value. + /// The areas in boolean collection. + /// The value was greater than 106. + public static List GetPattern(byte value) + => GetPatternInternal(value).ToList(); + + /// + /// Gets the pattern of the specific symbol value. + /// + /// The symbol value. + /// The barcode string. + /// The value was greater than 106. + public static string GetPatternString(byte value) + => value < 107 ? patterns[value] : throw new ArgumentOutOfRangeException(nameof(value), "value should be less than 107."); + + /// + /// Gets the pattern of the specific symbol value. + /// + /// The symbol value. + /// The value of black represented. + /// The value of white represented. + /// The barcode string. + /// The value was greater than 106. + public static string ToBarcodeString(byte value, char black, char white) + => ToBarcodeString(value, ele => ele ? black : white); + + /// + /// Gets the pattern of the specific symbol value. + /// + /// The symbol value. + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + /// The value was greater than 106. + public static string ToBarcodeString(byte value, Func selector) + => string.Join(string.Empty, GetPatternInternal(value).Select(selector)); + + /// + /// Gets the pattern of the specific symbol value. + /// + /// The symbol value. + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + /// The value was greater than 106. + public static string ToBarcodeString(byte value, Func selector) + => string.Join(string.Empty, GetPatternInternal(value).Select(selector)); + + /// + /// Converts a symbol value to string. + /// + /// The sub-type. + /// The symbol value. + /// A string represented. + /// + public static string ToString(Subtypes subtype, byte value) + { + if (value > 101) return value switch + { + 102 => "[FNC1]", + 103 => "[Start A]", + 104 => "[Start B]", + 105 => "[Start C]", + 106 => "[Stop]", + _ => string.Empty + }; + if (subtype == Subtypes.C) + return value < 100 ? value.ToString("g") : value switch + { + 100 => "[Code B]", + 101 => "[Code A]", + _ => string.Empty + }; + + var isA = subtype == Subtypes.A; + if (!isA && subtype != Subtypes.B) + throw new InvalidOperationException("subtype is not valid."); + if (value < 64 || (!isA && value < 96)) + return new string((char)(value + 32), 1); + if (value < 96) + return new string((char)(value - 64), 1); + return value switch + { + 96 => "[FNC3]", + 97 => "[FNC2]", + 98 => isA ? "[Shift B]" : "[Shift A]", + 99 => "[Code C]", + 100 => isA ? "[Code B]" : "[FNC4]", + 101 => isA ? "[FNC4]" : "[Code A]", + _ => string.Empty + }; + } + + /// + /// Gets the pattern of the specific symbol value. + /// + /// The symbol value. + /// + /// The value was greater than 106. + private static IEnumerable GetPatternInternal(byte value) + { + if (value > 106) throw new ArgumentOutOfRangeException(nameof(value), "value should be less than 107."); + var item = patterns[value]; + return item.Select(c => c switch + { + '0' => false, + _ => true + }); + } +} diff --git a/Messages/Data/Code128AI.cs b/Messages/Data/Code128AI.cs new file mode 100644 index 00000000..ea5792c0 --- /dev/null +++ b/Messages/Data/Code128AI.cs @@ -0,0 +1,770 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Data; + +/// +/// The code-128, which is a high-density linear barcode symbology defined in ISO/IEC 15417:2007. +/// It is used for alphanumeric or numeric-only barcodes. +/// +public partial class Code128 +{ +#pragma warning disable IDE0056 + /// + /// Commonly used GS1-128 generator which identifies data with Application Identifiers. + /// + public static class Gs1Generator + { + /* https://www.gs1.org/standards/barcodes/application-identifiers */ + + /// + /// Creates serial shipping container code. + /// + /// The data without AI, length should be 18. + /// The code 128 instance. + public static Code128 Sscc(string data) + => CreateGs1(0, data); + + /// + /// Creates global trade item number. + /// + /// The data without AI, length should be 14. + /// The code 128 instance. + public static Code128 Gtin(string data) + => CreateGs1(1, data); + + /// + /// Creates global trade item number of contained trade items. + /// + /// The data without AI, length should be 14. + /// The code 128 instance. + public static Code128 GtinOfContainedTradeItems(string data) + => CreateGs1(2, data); + + /// + /// Creates batch number or lot number. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 Batch(string data) + => CreateGs1(10, data); + + /// + /// Creates production date. + /// + /// The data without AI. + /// The code 128 instance. + public static Code128 Production(DateTime data) + => CreateGs1Date(11, data); + + /// + /// Creates due date. + /// + /// The data without AI. + /// The code 128 instance. + public static Code128 Due(DateTime data) + => CreateGs1Date(12, data); + + /// + /// Creates packaging date. + /// + /// The data without AI. + /// The code 128 instance. + public static Code128 Packaging(DateTime data) + => CreateGs1Date(13, data); + + /// + /// Creates best before date. + /// + /// The data without AI. + /// The code 128 instance. + public static Code128 BestBefore(DateTime data) + => CreateGs1Date(15, data); + + /// + /// Creates expiration date. + /// + /// The data without AI. + /// The code 128 instance. + public static Code128 Expiration(DateTime data) + => CreateGs1Date(17, data); + + /// + /// Creates internal product variant. + /// + /// The data without AI, should be less than 100. + /// The code 128 instance. + public static Code128 ProductVariant(byte data) + => CreateGs1(20, data.ToString("g")); + + /// + /// Creates serial number. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 Sn(string data) + => CreateGs1(21, data); + + /// + /// Creates secondary data fields. + /// + /// The data without AI, length should be 29. + /// The code 128 instance. + public static Code128 SecondaryData(string data) + => CreateGs1(22, data); + + /// + /// Creates additional product identification. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 AdditionalProductIdentification(string data) + => CreateGs1(240, data); + + /// + /// Creates customer part number. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 CustomerPart(string data) + => CreateGs1(241, data); + + /// + /// Creates Made-to-Order Variation Number. + /// + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + public static Code128 MadeToOrderVariation(int data) + => CreateGs1(242, data.ToString("g")); + + /// + /// Creates packaging component number. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 PackagingComponent(string data) + => CreateGs1(243, data); + + /// + /// Creates secondary serial number. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 Sn2(string data) + => CreateGs1(250, data); + + /// + /// Creates reference to source entity. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 SourceEntity(string data) + => CreateGs1(251, data); + + /// + /// Creates global document type identifier. + /// + /// The data without AI, length is variable from 13 to 17. + /// The code 128 instance. + public static Code128 DocumentTypeId(string data) + => CreateGs1(253, data); + + /// + /// Creates GLN extension component. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 GlnExtensionComponent(string data) + => CreateGs1(254, data); + + /// + /// Creates global coupon number. + /// + /// The data without AI, length is variable from 13 to 25. + /// The code 128 instance. + public static Code128 Gcn(string data) + => CreateGs1(255, data); + + /// + /// Creates count of items. + /// + /// The data without AI, should be less than 1_000_000_000. + /// The code 128 instance. + public static Code128 Count(int data) + => CreateGs1(30, data.ToString("g")); + + /// + /// Creates product net weight in kilo gram (kg). + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductWeight(byte y, int data) + => CreateGs1Decimal(3100, y, data); + + /// + /// Creates container gross weight in kilo gram (kg). + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerWeight(byte y, int data) + => CreateGs1Decimal(3300, y, data); + + /// + /// Creates product length in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductLength(byte y, int data) + => CreateGs1Decimal(3110, y, data); + + /// + /// Creates container length in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerLength(byte y, int data) + => CreateGs1Decimal(3310, y, null, data); + + /// + /// Creates product width/diamete in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductWidth(byte y, int data) + => CreateGs1Decimal(3120, y, data); + + /// + /// Creates container width/diamete in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerWidth(byte y, int data) + => CreateGs1Decimal(3320, y, data); + + /// + /// Creates product depth/thickness/height in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductDepth(byte y, int data) + => CreateGs1Decimal(3130, y, data); + + /// + /// Creates container depth/thickness/height in meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerDepth(byte y, int data) + => CreateGs1Decimal(3330, y, data); + + /// + /// Creates product area in square meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductArea(byte y, int data) + => CreateGs1Decimal(3140, y, data); + + /// + /// Creates container area in square meters. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerArea(byte y, int data) + => CreateGs1Decimal(3340, y, data); + + /// + /// Creates product net volume in liters. + /// + /// A number of decimal places in the following value. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ProductVolume(byte y, int data) + => y > 9 ? CreateGs1Decimal(3160, (byte)(y - 10), data) : CreateGs1Decimal(3150, y, data); + + /// + /// Creates container gross volume in liters. + /// + /// A number of decimal places in the following value. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 ContainerVolume(byte y, int data) + => y > 9 ? CreateGs1Decimal(3360, (byte)(y - 10), data) : CreateGs1Decimal(3350, y, data); + + /// + /// Creates count of units contained. + /// + /// The data without AI, should be less than 1,000,000,000. + /// The code 128 instance. + public static Code128 UnitCount(int data) + => CreateGs1(37, data.ToString("g")); + + /// + /// Creates applicable amount payable. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 AmountPayable(byte y, long data) + => CreateGs1Decimal(3900, y, null, data); + + /// + /// Creates applicable amount payable with optional ISO currency code. + /// + /// A number of decimal places in the following value, should be less than 10. + /// The ISO currency code. + /// The data without AI, should be less than 1,000,000,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 AmountPayable(byte y, string currencyCode, long data) + => CreateGs1Decimal(string.IsNullOrEmpty(currencyCode) ? 3900 : 3910, y, currencyCode, data); + + /// + /// Creates applicable amount payable (variable measure trade item). + /// + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 TradeItemAmountPayable(byte y, long data) + => CreateGs1Decimal(3920, y, null, data); + + /// + /// Creates applicable amount payable with optional ISO currency code (variable measure trade item). + /// + /// A number of decimal places in the following value, should be less than 10. + /// The ISO currency code. + /// The data without AI, should be less than 1,000,000,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + public static Code128 TradeItemAmountPayable(byte y, string currencyCode, long data) + => CreateGs1Decimal(string.IsNullOrEmpty(currencyCode) ? 3920 : 3930, y, currencyCode, data); + + /// + /// Creates customer purchase order number. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 Order(string data) + => CreateGs1(400, data); + + /// + /// Creates consignment number. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 Consignment(string data) + => CreateGs1(401, data); + + /// + /// Creates bill of lading number. + /// + /// The data without AI, length should be 17. + /// The code 128 instance. + public static Code128 LadingBill(string data) + => CreateGs1(402, data); + + /// + /// Creates routing code. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 Routing(string data) + => CreateGs1(403, data); + + /// + /// Creates ship/deliver to postal code (single postal authority). + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 ToSinglePostalAuthorityCode(string data) + => CreateGs1(420, data); + + /// + /// Creates ship/deliver to postal code (with ISO country code). + /// + /// The data without AI, length is variable from 3 to 15. + /// The code 128 instance. + public static Code128 ToPostalCode(string data) + => CreateGs1(421, data); + + /// + /// Creates ISO country code of origin. + /// + /// The data without AI, length should be 3. + /// The code 128 instance. + public static Code128 OriginCountry(string data) + => CreateGs1(422, data); + + /// + /// Creates one or more ISO country code of initial processing. + /// + /// The data without AI, length is variable from 3 to 15. + /// The code 128 instance. + public static Code128 InitialProcessingCountries(string data) + => CreateGs1(423, data); + + /// + /// Creates ISO country code of processing. + /// + /// The data without AI, length should be 3. + /// The code 128 instance. + public static Code128 ProcessingCountry(string data) + => CreateGs1(424, data); + + /// + /// Creates ISO country code of disassembly. + /// + /// The data without AI, length should be 3. + /// The code 128 instance. + public static Code128 DisassemblyCountry(string data) + => CreateGs1(425, data); + + /// + /// Creates ISO country code of full process chain. + /// + /// The data without AI, length should be 3. + /// The code 128 instance. + public static Code128 FullProcessChainCountry(string data) + => CreateGs1(426, data); + + /// + /// Creates service code description. + /// + /// The data without AI, length is up to 35. + /// The code 128 instance. + public static Code128 ServiceCodeDescription(string data) + => CreateGs1(3420, data); + + /// + /// Creates dangerous goods flag. + /// + /// true if the data without AI is yes (as 1); otherwise, false. + /// The code 128 instance. + public static Code128 Dangerous(bool data) + => CreateGs1(3421, data ? "1" : "0"); + + /// + /// Creates authority to leave. + /// + /// true if the data without AI is yes (as 1); otherwise, false. + /// The code 128 instance. + public static Code128 AuthorityToLeave(bool data) + => CreateGs1(3422, data ? "1" : "0"); + + /// + /// Creates signature required flag. + /// + /// true if the data without AI is yes (as 1); otherwise, false. + /// The code 128 instance. + public static Code128 SignatureRequired(bool data) + => CreateGs1(3423, data ? "1" : "0"); + + /// + /// Creates release date. + /// + /// The data without AI, length should be 13. + /// The code 128 instance. + public static Code128 Release(DateTime data) + => CreateGs1Date(3426, data); + + /// + /// Creates NATO stock number. + /// + /// The data without AI, length should be 13. + /// The code 128 instance. + public static Code128 Nsn(string data) + => CreateGs1(7001, data); + + /// + /// Creates active potency. + /// + /// The data without AI, length is up to 4. + /// The code 128 instance. + public static Code128 ActivePotency(int data) + => CreateGs1(7004, data.ToString("g")); + + /// + /// Creates catch area. + /// + /// The data without AI, length is up to 12. + /// The code 128 instance. + public static Code128 CatchArea(string data) + => CreateGs1(7005, data); + + /// + /// Creates first freeze date. + /// + /// The data without AI, length should be 13. + /// The code 128 instance. + public static Code128 FirstFreeze(DateTime data) + => CreateGs1Date(7006, data); + + /// + /// Creates harvest date. + /// + /// The data without AI, length should be 13. + /// The code 128 instance. + public static Code128 Harvest(DateTime data) + => CreateGs1Date(7007, data); + + /// + /// Creates production method. + /// + /// The data without AI, length is up to 2. + /// The code 128 instance. + public static Code128 ProductionMethod(string data) + => CreateGs1(7010, data); + + /// + /// Creates certification reference. + /// + /// The certification number, should be 0-9. + /// The data without AI, length is up to 30. + /// The code 128 instance. + /// y ws greater than 9. + public static Code128 Certification(byte y, string data) + => y < 10 ? CreateGs1(7230 + y, data) : throw new ArgumentOutOfRangeException(nameof(y), "y should be less than 10."); + + /// + /// Creates protocol ID. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 Protocol(string data) + => CreateGs1(7240, data); + + /// + /// Creates roll products: width/length/core diameter/direction/splices. + /// + /// The data without AI, length should be 14. + /// The code 128 instance. + public static Code128 RollProducts(string data) + => CreateGs1(8001, data); + + /// + /// Creates mobile phone identifier. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 PhoneId(string data) + => CreateGs1(8002, data); + + /// + /// Creates global returnable asset identifier. + /// + /// The data without AI, length is variable from 14 to 30. + /// The code 128 instance. + public static Code128 GlobalReturnableAsset(string data) + => CreateGs1(8003, data); + + /// + /// Creates global individual asset identifier. + /// + /// The data without AI, length should be 30. + /// The code 128 instance. + public static Code128 GlobalIndividualAsset(string data) + => CreateGs1(8004, data); + + /// + /// Creates international bank account number. + /// + /// The data without AI, length should be 30. + /// The code 128 instance. + public static Code128 BankAccount(string data) + => CreateGs1(8007, data); + + /// + /// Creates software version. + /// + /// The data without AI, length is up to 20. + /// The code 128 instance. + public static Code128 SoftwareVersion(string data) + => CreateGs1(8012, data); + + /// + /// Creates global model number. + /// + /// The data without AI, length is up to 25. + /// The code 128 instance. + public static Code128 Gmn(string data) + => CreateGs1(8013, data); + + /// + /// Creates global service relationship number. + /// + /// true if identify the relationship between an organisation offering services and the recipient of services; otherwise, false, provider. + /// The data without AI, length should be 18. + /// The code 128 instance. + public static Code128 GlobalServiceRelationship(bool recipient, string data) + => CreateGs1(recipient ? 8018 : 8017, data); + + /// + /// Creates service relation instance number. + /// + /// The data without AI, length is up to 10. + /// The code 128 instance. + public static Code128 Srin(string data) + => CreateGs1(8019, data); + + /// + /// Creates payment slip reference number. + /// + /// The data without AI, length is variable from 13 to 25. + /// The code 128 instance. + public static Code128 PaymentSlip(string data) + => CreateGs1(8020, data); + + /// + /// Creates extended packaging URL. + /// + /// The data without AI, length tp to 70. + /// The code 128 instance. + public static Code128 ExtendedPackagingURL(string data) + => CreateGs1(8200, data); + + /// + /// Creates mutually agreed between trading partners. + /// + /// The data without AI, length is up to 30. + /// The code 128 instance. + public static Code128 MutuallyAgreedBetweenTradingPartners(string data) + => CreateGs1(90, data); + + /// + /// Creates internal company codes (AI 91). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes1(string data) + => CreateGs1(91, data); + + /// + /// Creates internal company codes (AI 92). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes2(string data) + => CreateGs1(92, data); + + /// + /// Creates internal company codes (AI 93). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes3(string data) + => CreateGs1(93, data); + + /// + /// Creates internal company codes (AI 94). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes4(string data) + => CreateGs1(94, data); + + /// + /// Creates internal company codes (AI 95). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes5(string data) + => CreateGs1(95, data); + + /// + /// Creates internal company codes (AI 96). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes6(string data) + => CreateGs1(96, data); + + /// + /// Creates internal company codes (AI 97). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes7(string data) + => CreateGs1(97, data); + + /// + /// Creates internal company codes (AI 98). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes8(string data) + => CreateGs1(98, data); + + /// + /// Creates internal company codes (AI 99). + /// + /// The data without AI, length is up to 90. + /// The code 128 instance. + public static Code128 InternalCompanyCodes9(string data) + => CreateGs1(99, data); + + /// + /// Creates for decimal. + /// + /// The application identifier. + /// A number of decimal places in the following value, should be less than 10. + /// The data without AI, should be less than 1,000,000. + /// The code 128 instance. + /// y or data was out of range. + private static Code128 CreateGs1Decimal(int ai, byte y, int data) + { + if (y > 9) throw new ArgumentOutOfRangeException(nameof(y), "y should be less than 10."); + if (data < 0) throw new ArgumentOutOfRangeException(nameof(data), "data should be in 0-999,999 but it is negative currently."); + if (data > 999_999) throw new ArgumentOutOfRangeException(nameof(data), "data should be in 0-999,999 but it is greater than 999,999 currently."); + return CreateGs1(ai + y, data.ToString("000000")); + } + + /// + /// Creates for decimal. + /// + /// The application identifier. + /// A number of decimal places in the following value, should be less than 10. + /// The prefix of data. + /// The data without AI, should be less than 1,000,000,000. + /// The code 128 instance. + /// y or data was out of range. + private static Code128 CreateGs1Decimal(int ai, byte y, string prefix, long data) + { + if (y > 9) throw new ArgumentOutOfRangeException(nameof(y), "y should be less than 10."); + if (data < 0) throw new ArgumentOutOfRangeException(nameof(data), "data should be in 0-999,999,999,999,999 but it is negative currently."); + if (data > 999_999_999_999_999) throw new ArgumentOutOfRangeException(nameof(data), "data should be in 0-999,999,999,999,999, but it is greater than 999,999,999,999,999 currently."); + return CreateGs1(ai + y, string.IsNullOrEmpty(prefix) ? data.ToString("g") : $"{prefix}{data:g}"); + } + } +#pragma warning restore IDE0056 + + private static Code128 CreateGs1Date(int ai, DateTime date) + => CreateGs1(ai, date.ToString("yyMMdd")); +} diff --git a/Messages/Data/Code128Builder.cs b/Messages/Data/Code128Builder.cs new file mode 100644 index 00000000..32595c36 --- /dev/null +++ b/Messages/Data/Code128Builder.cs @@ -0,0 +1,1063 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Data; + +/// +/// The code-128, which is a high-density linear barcode symbology defined in ISO/IEC 15417:2007. +/// It is used for alphanumeric or numeric-only barcodes. +/// +public partial class Code128 : IReadOnlyList +{ +#pragma warning disable IDE0056 + private readonly List v; + + /// + /// Initializes a new instance of Code128 class. + /// + /// The byte array of symbol. + private Code128(List values) + { + v = values ?? new List(); + } + + /// + /// Gets the count of symbol. + /// + public int Count => v.Count; + + /// + /// Gets the start sub-type. + /// + public Subtypes Subtype => v.Count > 3 ? v[0] switch + { + 103 => Subtypes.A, + 104 => Subtypes.B, + 105 => Subtypes.C, + _ => (Subtypes)0 + } : 0; + + /// + /// Gets the checksum; or 255, if not available. + /// + public byte Checksum => v.Count > 3 ? v[v.Count - 2] : (byte)255; + + /// + /// Gets the value of the specific symbol. + /// + /// The index of symbol. + /// The value of the symbol. + /// The index was out of range. + public byte this[int index] => v[index]; + + /// + /// Returns symbol values without start code, checksum, and stop code. + /// + /// A collection of symbol value without start code, checksum, and stop code. + public IEnumerable TakeData() + => v.Count > 3 ? v.Skip(1).Take(v.Count - 3) : new List(); + + /// + /// Converts to boolean list. + /// White represented as false, black represented as true. + /// + /// The boolean list of barcode. + public List ToBarcode() + { + var list = v.SelectMany(GetPattern).ToList(); + if (list.Count > 10) + { + list.Add(true); + list.Add(true); + } + + return list; + } + + /// + /// Gets all information of application identifier and its data value. + /// + /// A collection with application identifiers and their data value. + public IEnumerable GetAiData() + { + if (v.Count < 4) yield break; + var subtype = v[0] switch + { + 103 => Subtypes.A, + 104 => Subtypes.B, + 105 => Subtypes.C, + _ => (Subtypes)0 + }; + if (subtype == 0) yield break; + var sb = new StringBuilder(); + var subtype2 = subtype; + var high = false; + var rec = false; + foreach (var b in v.Skip(1).Take(v.Count - 3)) + { + if (b > 101) + { + if (b > 102) break; + rec = true; + if (sb.Length > 0) + { + yield return sb.ToString(); + sb.Clear(); + } + + continue; + } + + var st = subtype; + subtype = subtype2; + if (st == Subtypes.C) + { + high = false; + if (b < 100 || b == 102) + { + if (rec) sb.Append(b.ToString("00")); + continue; + } + + switch (b) + { + case 100: + subtype = subtype2 = Subtypes.B; + break; + case 101: + subtype = subtype2 = Subtypes.A; + break; + } + + continue; + } + + var isA = st == Subtypes.A; + if (!isA && st != Subtypes.B) + { + high = false; + continue; + } + + if (b < 96) + { + if (high) + { + high = false; + var c = (char)(ToString(st, b).FirstOrDefault() + 128); + if (rec) sb.Append(c); + } + else + { + if (rec) sb.Append(ToString(st, b)); + } + + continue; + } + + switch (b) + { + case 96: + rec = false; + if (sb.Length > 0) + { + yield return sb.ToString(); + sb.Clear(); + } + + break; + case 97: + rec = false; + if (sb.Length > 0) + { + yield return sb.ToString(); + sb.Clear(); + } + + break; + case 98: + subtype = isA ? Subtypes.B : Subtypes.A; + continue; + case 99: + subtype = subtype2 = Subtypes.C; + break; + case 100: + if (!isA) + { + high = !high; + continue; + } + + subtype = subtype2 = Subtypes.B; + break; + case 101: + if (isA) + { + high = !high; + continue; + } + + subtype = subtype2 = Subtypes.A; + break; + } + + high = false; + } + + if (sb.Length > 0) yield return sb.ToString(); + } + + /// + /// Returns a string that represents the barcode in stroke path for SVG or XAML. + /// + /// The bar height. + /// A stroke path string that represents the barcode. + public string ToPathString(int height = 40) + { + var sb = new StringBuilder(); + var i = 9; + sb.Append("M0,0 "); + foreach (var b in v) + { + if (b > 106) continue; + var binary = patterns[b]; + foreach (var c in binary) + { + i++; + if (c == '1') + sb.Append($"M{i},0 L{i},{height} "); + } + } + + sb.Append($"M{i + 1},{0} L{i + 1},{height} M{i + 2},{0} L{i + 2},{height} M{i + 12},0"); + return sb.ToString(); + } + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + public override string ToString() + => ToString(Formats.Regular); + + /// + /// Returns a string that represents the current object. + /// + /// The output string format. + /// A string that represents the current object. + public string ToString(Formats format) + { + if (v.Count < 4) return string.Empty; + var subtype = v[0] switch + { + 103 => Subtypes.A, + 104 => Subtypes.B, + 105 => Subtypes.C, + _ => (Subtypes)0 + }; + if (subtype == 0) return string.Empty; + var sb = new StringBuilder(); + switch (format) + { + case Formats.Regular: + case Formats.Text: + break; + case Formats.Hex: + foreach (var b in v) + { + sb.Append(b.ToString("x2")); + } + + return sb.ToString(); + case Formats.Values: + foreach (var b in v.Take(v.Count - 2)) + { + if (subtype == Subtypes.C && b < 100) + { + sb.Append(b); + sb.Append(' '); + continue; + } + + switch (b) + { + case 96: + sb.Append("[FNC3] "); + break; + case 97: + sb.Append("[FNC2] "); + break; + case 98: + sb.Append(subtype == Subtypes.A ? "[Shift B] " : "[Shift A] "); + break; + case 99: + subtype = Subtypes.C; + sb.Append("[Code C] "); + break; + case 100: + if (subtype == Subtypes.B) + { + sb.Append("[FNC4] "); + } + else + { + subtype = Subtypes.B; + sb.Append("[Code B] "); + } + + break; + case 101: + if (subtype == Subtypes.A) + { + sb.Append("[FNC4] "); + } + else + { + subtype = Subtypes.A; + sb.Append("[Code A] "); + } + + break; + case 102: + sb.Append("[FNC1] "); + break; + case 103: + sb.Append("[Start A] "); + break; + case 104: + sb.Append("[Start B] "); + break; + case 105: + sb.Append("[Start C] "); + break; + default: + sb.Append(b); + sb.Append(' '); + break; + } + } + + sb.Append($"[Check symbol {v[v.Count - 2]:g}] [Stop]"); + return sb.ToString().Trim(); + case Formats.Barcode: + return ToBarcodeString(); + case Formats.Path: + return ToPathString(40); + } + + var appendFunc = format == Formats.Regular; + var subtype2 = subtype; + var high = false; + var high2 = false; + foreach (var b in v.Skip(1).Take(v.Count - 3)) + { + if (b > 101) + { + if (b > 102) break; + if (appendFunc) sb.Append("[FNC1]"); + high = high2 = false; + continue; + } + + var st = subtype; + subtype = subtype2; + if (st == Subtypes.C) + { + high = high2 = false; + if (b < 100 || b == 102) + { + sb.Append(b.ToString("00")); + continue; + } + + switch (b) + { + case 100: + subtype = subtype2 = Subtypes.B; + break; + case 101: + subtype = subtype2 = Subtypes.A; + break; + } + + continue; + } + + var isA = st == Subtypes.A; + if (!isA && st != Subtypes.B) + { + high = high2 = false; + continue; + } + + if (b < 96) + { + if (high) + { + high = high2; + var c = (char)(ToString(st, b).FirstOrDefault() + 128); + sb.Append(c); + } + else + { + high = high2; + sb.Append(ToString(st, b)); + } + + continue; + } + + switch (b) + { + case 96: + if (appendFunc) sb.Append("[FNC3]"); + break; + case 97: + if (appendFunc) sb.Append("[FNC2]"); + break; + case 98: + subtype = isA ? Subtypes.B : Subtypes.A; + continue; + case 99: + subtype = subtype2 = Subtypes.C; + break; + case 100: + if (!isA) + { + if (high != high2) high2 = high; + else high = !high; + continue; + } + + subtype = subtype2 = Subtypes.B; + break; + case 101: + if (isA) + { + if (high != high2) high2 = high; + else high = !high; + continue; + } + + subtype = subtype2 = Subtypes.A; + break; + } + + high = high2; + } + + return sb.ToString(); + } + + /// + /// Converts to a string. + /// + /// The barcode string. + public string ToBarcodeString() + { + var sb = new StringBuilder(); + foreach (var b in v) + { + sb.Append(GetPattern(b)); + } + + if (sb.Length > 10) sb.Append("11"); + return sb.ToString(); + } + + /// + /// Converts to a string. + /// + /// The value of black represented. + /// The value of white represented. + /// The barcode string. + public string ToBarcodeString(char black, char white) + => string.Join(string.Empty, ToBarcode().Select(ele => ele ? black : white)); + + /// + /// Converts to a string. + /// + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + public string ToBarcodeString(Func selector) + => selector != null ? string.Join(string.Empty, ToBarcode().Select(selector)) : ToBarcodeString(); + + /// + /// Converts to a string. + /// + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + public string ToBarcodeString(Func selector) + => selector != null ? string.Join(string.Empty, ToBarcode().Select(selector)) : ToBarcodeString(); + + /// + /// Gets all sub-types used in value. + /// + /// A collection of sub-type. + public IEnumerable GetSubtypesUsed() + { + var subtype = Subtype; + yield return subtype; + foreach (var b in v.Skip(1).Take(v.Count - 3)) + { + if (b < 98) continue; + if (b > 102) break; + switch (b) + { + case 99: + if (subtype == Subtypes.C) break; + subtype = Subtypes.C; + yield return subtype; + break; + case 100: + if (subtype == Subtypes.B) break; + subtype = Subtypes.B; + yield return subtype; + break; + case 101: + if (subtype == Subtypes.A) break; + subtype = Subtypes.A; + yield return subtype; + break; + } + } + } + + /// + /// Returns an enumerator that iterates through the symbol collection. + /// + /// A enumerator of the symbol collection. + public IEnumerator GetEnumerator() + => v.GetEnumerator(); + + /// + /// Returns an enumerator that iterates through the symbol collection. + /// + /// A enumerator of the symbol collection. + IEnumerator IEnumerable.GetEnumerator() + => ((IEnumerable)v).GetEnumerator(); + + /// + /// Creates with Start Code A. + /// + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateA(IEnumerable values) + => Create(values, 103); + + /// + /// Creates with Start Code A. + /// + /// The string value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateA(string s) + => Create(Subtypes.A, s); + + /// + /// Creates with Start Code B. + /// + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateB(IEnumerable values) + => Create(values, 104); + + /// + /// Creates with Start Code B. + /// + /// The string value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateB(string s) + => Create(Subtypes.B, s); + + /// + /// Creates with Start Code C. + /// + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateC(IEnumerable values) + => Create(values, 105); + + /// + /// Creates with Start Code C. + /// + /// The string value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateC(string s) + => Create(Subtypes.C, s); + + /// + /// Creates with Start Code C. + /// + /// The integer value of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateC(long s) + => Create(Subtypes.C, s.ToString("g")); + + /// + /// Creates GS1-128 code. + /// + /// The application identifier. + /// The data value. + /// The Code 128 instance. + /// values was null. + /// ai was less than 0. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateGs1(int ai, string data) + { + if (ai < 0) throw new ArgumentOutOfRangeException(nameof(ai), "ai should not be less than zero."); + var col = new List { 102 }; + Fill(col, Subtypes.C, $"{ai:00}{data}"); + return Create(Subtypes.C, col); + } + + /// + /// Creates GS1-128 code. + /// + /// The string 1 with application identifier and its data value. + /// The string 2 with application identifier and its data value. + /// The string 3 with application identifier and its data value. + /// The string 4 with application identifier and its data value. + /// The string 5 with application identifier and its data value. + /// The string 6 with application identifier and its data value. + /// The string 7 with application identifier and its data value. + /// The string 8 with application identifier and its data value. + /// The Code 128 instance. + /// values was null. + /// ai was less than 0. + /// values was empty. + /// Any value is invalid. + public static Code128 CreateGs1(string part1, string part2, string part3 = null, string part4 = null, string part5 = null, string part6 = null, string part7 = null, string part8 = null) + { + var col = new List(); + var subtype = Subtypes.C; + if (!string.IsNullOrEmpty(part1)) + { + col.Add(102); + subtype = Fill(col, Subtypes.C, part1); + } + + if (!string.IsNullOrEmpty(part2)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part2); + } + + if (!string.IsNullOrEmpty(part3)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part3); + } + + if (!string.IsNullOrEmpty(part4)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part4); + } + + if (!string.IsNullOrEmpty(part5)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part5); + } + + if (!string.IsNullOrEmpty(part6)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part6); + } + + if (!string.IsNullOrEmpty(part7)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + subtype = Fill(col, Subtypes.C, part7); + } + + if (!string.IsNullOrEmpty(part8)) + { + if (subtype != Subtypes.C) col.Add(99); + col.Add(102); + Fill(col, Subtypes.C, part8); + } + + return Create(Subtypes.C, col); + } + + /// + /// Creates with the specific sub-type. + /// + /// The sub-type to use. + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 Create(Subtypes subtype, IEnumerable values) + => Create(values, subtype switch + { + Subtypes.A => 103, + Subtypes.B => 104, + Subtypes.C => 105, + _ => throw new InvalidOperationException("subtype is not valid.") + }); + + /// + /// Creates by boolean collection that white represented as false and black represented as true.. + /// + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 Create(IEnumerable values) + { + if (values == null) throw new ArgumentNullException(nameof(values), "values should not be null."); + var s = string.Join(string.Empty, values.Select(b => b ? '1' : '0')).Trim('0'); + if (s.Length < 25) throw new ArgumentException("The count of values is too less.", nameof(values)); + if (s.StartsWith("1100011101011")) s = new string(s.Reverse().ToArray()); + var col = new List(); + var first = s.Substring(0, 7) switch + { + "11010000100" => 103, + "11010010000" => 104, + "11010011100" => 105, + _ => throw new InvalidOperationException("The start code is not valid.") + }; + for (var i = 1; i < s.Length; i += 7) + { + try + { + var item = s.Substring(i, 7); + var j = patterns.IndexOf(item); + if (j < 0) throw new InvalidOperationException($"Contains invalid symbol at position {i}."); + if (j > 102) + { + if (j == 106) break; + throw new InvalidOperationException($"Contains invalid symbol at position {i}."); + } + } + catch (ArgumentException) + { + } + } + + return Create(col, (byte)first); + } + + /// + /// Creates by symbols. + /// + /// The value collection of symbol. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 Create(IEnumerable values) + { + if (values == null) throw new ArgumentNullException(nameof(values), "values should not be null."); + var first = values.First(); + if (first < 103 || first > 105) throw new InvalidOperationException("The start code is not valid."); + return Create(values.Skip(1), first); + } + + /// + /// Creates with the specific sub-type. + /// + /// The sub-type of start code. + /// The string to encode. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + public static Code128 Create(Subtypes subtype, string s) + { + var col = new List(); + Fill(col, subtype, s); + return Create(subtype, col); + } + + /// + /// Fills symbols. + /// + /// The byte array of symbol value to fill. + /// The sub-type of start code. + /// The string to encode. + /// The subtype of last one. + /// values was null. + /// values was empty. + /// Any value is invalid. + private static Subtypes Fill(List col, Subtypes subtype, string s) + { + if (s == null) return subtype; + var bytes = Encoding.ASCII.GetBytes(s); + byte? reserved = null; + foreach (var b in bytes) + { + if (subtype == Subtypes.A) + { + if (reserved.HasValue) + { + col.Add((byte)(reserved.Value + 16)); + reserved = null; + } + + if (b > 31 && b < 96) + { + col.Add((byte)(b - 32)); + } + else if (b < 32) + { + col.Add((byte)(b + 64)); + } + else if (b > 127) + { + col.Add(101); + var b2 = b - 128; + if (b2 > 31 && b2 < 96) + { + col.Add((byte)(b2 - 32)); + } + else if (b2 < 32) + { + col.Add((byte)(b2 + 64)); + } + else + { + subtype = Subtypes.B; + col.Add(100); + col.Add((byte)(b2 - 32)); + } + } + else + { + subtype = Subtypes.B; + col.Add(100); + col.Add((byte)(b - 32)); + } + } + else if (subtype == Subtypes.B) + { + if (reserved.HasValue) + { + col.Add((byte)(reserved.Value + 16)); + reserved = null; + } + + if (b > 31 && b < 128) + { + col.Add((byte)(b - 32)); + } + else if (b > 127) + { + col.Add(100); + var b2 = b - 128; + if (b2 > 31) + { + col.Add((byte)(b - 32)); + } + else + { + subtype = Subtypes.A; + col.Add(101); + col.Add((byte)(b2 + 64)); + } + } + else + { + subtype = Subtypes.A; + col.Add(101); + col.Add((byte)(b + 64)); + } + } + else if (subtype == Subtypes.C) + { + if (b < 48) + { + if (b < 32) + { + subtype = Subtypes.A; + col.Add(101); + col.Add((byte)(b + 64)); + } + else + { + subtype = Subtypes.B; + col.Add(100); + col.Add((byte)(b - 32)); + } + } + else if (b > 57) + { + if (b > 159) + { + subtype = Subtypes.A; + col.Add(100); + col.Add(100); + col.Add((byte)(b - 160)); + } + else if (b > 127) + { + subtype = Subtypes.A; + col.Add(101); + col.Add(101); + col.Add((byte)(b - 64)); + } + else + { + subtype = Subtypes.B; + col.Add(100); + col.Add((byte)(b - 32)); + } + } + else if (reserved.HasValue) + { + col.Add((byte)(reserved.Value * 10 + b - 48)); + reserved = null; + } + else + { + reserved = (byte)(b - 48); + } + } + else + { + throw new InvalidOperationException($"The subtype is not valid."); + } + } + + if (reserved.HasValue) + { + if (subtype == Subtypes.C) + col.Add(101); + col.Add((byte)(reserved.Value + 16)); + } + + return subtype; + } + + /// + /// Creates with the specific start code. + /// + /// The value collection of symbol. + /// The value of start code. + /// The Code 128 instance. + /// values was null. + /// values was empty. + /// Any value is invalid. + private static Code128 Create(IEnumerable values, byte startCode) + { + if (values == null) throw new ArgumentNullException(nameof(values), "values should not be null."); + var col = values.ToList(); + if (col.Count < 1) throw new ArgumentException("values should not be empty.", nameof(values)); + if (col[0] != startCode) + { + if (col[0] > 102) throw new InvalidOperationException($"The first value {col[0]} is not valid."); + col.Insert(0, startCode); + } + + if (col[col.Count - 1] != 106) + { + long check = startCode; + for (var i = 1; i < col.Count; i++) + { + check += col[i] * i; + } + + col.Add((byte)(check % 103)); + col.Add(106); + } + + var count = col.Count - 1; + for (var i = 1; i < count; i++) + { + if (col[i] > 102) throw new InvalidOperationException($"The value {col[i]} at position {i} is not valid."); + } + + return new Code128(col); + } + + /// + /// Adds all code 128 instances into one. + /// + /// The collection to combine. + /// A code 128 instance combined. + public static Code128 Join(IEnumerable col) + { + if (col is null) return null; + var list = col.Where(ele => ele != null && ele.Count > 3).ToList(); + if (list.Count < 2) return list.Count == 1 ? list[0] : null; + var first = list[0]; + var subtype = first.GetSubtypesUsed().Last(); + var bytes = first.TakeData().ToList(); + foreach (var c in list.Skip(1)) + { + var rightSubtype = c.Subtype; + if (subtype != rightSubtype) bytes.Add(rightSubtype switch + { + Subtypes.A => 101, + Subtypes.B => 100, + _ => 99 + }); + bytes.AddRange(c.TakeData()); + subtype = c.GetSubtypesUsed().Last(); + } + + return Create(first.Subtype, bytes); + } + + /// + /// Adds. + /// leftValue + rightValue + /// + /// The left value. + /// The right value. + /// A result after Add operation. + public static Code128 operator +(Code128 leftValue, Code128 rightValue) + { + if (rightValue is null) return leftValue; + if (leftValue is null) return rightValue; + var subtype = leftValue.GetSubtypesUsed().Last(); + var bytes = leftValue.TakeData().ToList(); + var rightSubtype = rightValue.Subtype; + if (subtype != rightSubtype) bytes.Add(rightSubtype switch + { + Subtypes.A => 101, + Subtypes.B => 100, + _ => 99 + }); + bytes.AddRange(rightValue.TakeData()); + return Create(leftValue.Subtype, bytes); + } +#pragma warning restore IDE0056 +} diff --git a/Messages/Data/Ean.cs b/Messages/Data/Ean.cs new file mode 100644 index 00000000..31fd4d90 --- /dev/null +++ b/Messages/Data/Ean.cs @@ -0,0 +1,706 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Data; + +/// +/// The International Article Number, a.k.a. European Article Number or EAN. +/// +public partial class InternationalArticleNumber +{ + /// + /// All digits. + /// + private string value; + + /// + /// Converts the value of the current object to its equivalent string representation. + /// + /// The string representation of the value of this object, which consists of a sequence of 7 digits of 0 and 1. + public override string ToString() + => value ?? string.Empty; + + /// + /// Gets the checksum of EAN13. + /// + /// The checksum. + /// The digits was not valid. + public byte Checksum() + { + if (string.IsNullOrEmpty(value)) + throw new InvalidOperationException("The value should not be null."); + return Checksum(value); + } + + /// + /// Converts to code list. + /// + /// The code list. + public List ToList() + { + if (value == null) return new(); + return value.Select(ele => ele switch + { + '0' => Zero, + '1' => One, + '2' => Two, + '3' => Three, + '4' => Four, + '5' => Five, + '6' => Six, + '7' => Seven, + '8' => Eight, + '9' => Nine, + _ => null + }).Where(ele => ele != null).ToList(); + } + + /// + /// Returns a string that represents the barcode in stroke path for SVG or XAML. + /// + /// The bar height. + /// A stroke path string that represents the barcode. + public string ToPathString(int height = 40) + { + var sb = new StringBuilder(); + var i = 6; + sb.Append("M0,0 "); + foreach (var b in ToBarcode()) + { + i++; + if (b) sb.Append($"M{i},0 L{i},{height} "); + } + + sb.Append($"M{i + 6},0"); + return sb.ToString(); + } + + /// + /// Converts to boolean list. + /// White represented as false, black represented as true. + /// + /// The boolean list of barcode. + /// It was not an EAN-13 ro EAN-8 code. + public List ToBarcode() + { + var codes = ToList(); + var col = new List(); + if (codes.Count == 13) + { + col.Add(true); + col.Add(false); + col.Add(true); + switch (value.FirstOrDefault()) + { + case '0': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.L)); + col.AddRange(codes[3].ToList(Encodings.L)); + col.AddRange(codes[4].ToList(Encodings.L)); + col.AddRange(codes[5].ToList(Encodings.L)); + col.AddRange(codes[6].ToList(Encodings.L)); + break; + case '1': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.L)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.L)); + col.AddRange(codes[5].ToList(Encodings.G)); + col.AddRange(codes[6].ToList(Encodings.G)); + break; + case '2': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.L)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.G)); + col.AddRange(codes[5].ToList(Encodings.L)); + col.AddRange(codes[6].ToList(Encodings.G)); + break; + case '3': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.L)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.G)); + col.AddRange(codes[5].ToList(Encodings.G)); + col.AddRange(codes[6].ToList(Encodings.L)); + break; + case '4': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.L)); + col.AddRange(codes[4].ToList(Encodings.L)); + col.AddRange(codes[5].ToList(Encodings.G)); + col.AddRange(codes[6].ToList(Encodings.G)); + break; + case '5': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.L)); + col.AddRange(codes[5].ToList(Encodings.L)); + col.AddRange(codes[6].ToList(Encodings.G)); + break; + case '6': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.G)); + col.AddRange(codes[5].ToList(Encodings.L)); + col.AddRange(codes[6].ToList(Encodings.L)); + break; + case '7': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.L)); + col.AddRange(codes[4].ToList(Encodings.G)); + col.AddRange(codes[5].ToList(Encodings.L)); + col.AddRange(codes[6].ToList(Encodings.G)); + break; + case '8': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.L)); + col.AddRange(codes[4].ToList(Encodings.G)); + col.AddRange(codes[5].ToList(Encodings.G)); + col.AddRange(codes[6].ToList(Encodings.L)); + break; + case '9': + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.G)); + col.AddRange(codes[3].ToList(Encodings.G)); + col.AddRange(codes[4].ToList(Encodings.L)); + col.AddRange(codes[5].ToList(Encodings.G)); + col.AddRange(codes[6].ToList(Encodings.L)); + break; + } + + col.Add(false); + col.Add(true); + col.Add(false); + col.Add(true); + col.Add(false); + col.AddRange(codes[7].ToList(Encodings.R)); + col.AddRange(codes[8].ToList(Encodings.R)); + col.AddRange(codes[9].ToList(Encodings.R)); + col.AddRange(codes[10].ToList(Encodings.R)); + col.AddRange(codes[11].ToList(Encodings.R)); + col.AddRange(codes[12].ToList(Encodings.R)); + col.Add(true); + col.Add(false); + col.Add(true); + return col; + } + else if (codes.Count == 8) + { + col.Add(true); + col.Add(false); + col.Add(true); + col.AddRange(codes[0].ToList(Encodings.L)); + col.AddRange(codes[1].ToList(Encodings.L)); + col.AddRange(codes[2].ToList(Encodings.L)); + col.AddRange(codes[3].ToList(Encodings.L)); + col.Add(false); + col.Add(true); + col.Add(false); + col.Add(true); + col.Add(false); + col.AddRange(codes[4].ToList(Encodings.R)); + col.AddRange(codes[5].ToList(Encodings.R)); + col.AddRange(codes[6].ToList(Encodings.R)); + col.AddRange(codes[7].ToList(Encodings.R)); + col.Add(true); + col.Add(false); + col.Add(true); + return col; + } + else if (codes.Count == 5) + { + var checksum = Checksum(); + col.Add(false); + col.Add(true); + col.Add(false); + col.Add(true); + col.Add(true); + col.AddRange(codes[0].ToList(checksum < 4 ? Encodings.G : Encodings.L)); + col.Add(false); + col.Add(true); + col.AddRange(codes[1].ToList(checksum == 0 || checksum == 4 || checksum == 7 || checksum == 8 ? Encodings.G : Encodings.L)); + col.Add(false); + col.Add(true); + col.AddRange(codes[2].ToList(checksum == 1 || checksum == 4 || checksum == 5 || checksum == 9 ? Encodings.G : Encodings.L)); + col.Add(false); + col.Add(true); + col.AddRange(codes[3].ToList(checksum == 2 || checksum == 5 || checksum == 6 || checksum == 7 ? Encodings.G : Encodings.L)); + col.Add(false); + col.Add(true); + col.AddRange(codes[4].ToList(checksum == 3 || checksum == 6 || checksum == 8 || checksum == 9 ? Encodings.G : Encodings.L)); + return col; + } + else if (codes.Count == 2) + { + var checksum = Checksum(); + col.Add(false); + col.Add(true); + col.Add(false); + col.Add(true); + col.Add(true); + col.AddRange(codes[0].ToList(checksum % 4 < 2 ? Encodings.L : Encodings.G)); + col.Add(false); + col.Add(true); + col.AddRange(codes[1].ToList(checksum % 2 == 0 ? Encodings.L : Encodings.G)); + return col; + } + + throw new InvalidOperationException("The count of digit is not any of 7, 8, 12 or 13."); + } + + /// + /// Converts to a string. + /// + /// The barcode string. + /// It was not an EAN-13 ro EAN-8 code. + public string ToBarcodeString() + => string.Join(string.Empty, ToBarcode().Select(ele => ele ? '1' : '0')); + + /// + /// Converts to a string. + /// + /// The value of black represented. + /// The value of white represented. + /// The barcode string. + /// It was not an EAN-13 ro EAN-8 code. + public string ToBarcodeString(char black, char white) + => string.Join(string.Empty, ToBarcode().Select(ele => ele ? black : white)); + + /// + /// Converts to a string. + /// + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + /// It was not an EAN-13 ro EAN-8 code. + public string ToBarcodeString(Func selector) + => selector != null ? string.Join(string.Empty, ToBarcode().Select(selector)) : ToBarcodeString(); + + /// + /// Converts to a string. + /// + /// The selector to convert boolean array to a string. Per boolean value, white represented as false, black represented as true. + /// The barcode string. + /// It was not an EAN-13 ro EAN-8 code. + public string ToBarcodeString(Func selector) + => selector != null ? string.Join(string.Empty, ToBarcode().Select(selector)) : ToBarcodeString(); + + /// + /// Creates an EAN. + /// + /// The digits. + /// An instance of the EAN. + /// The input sequence was null. + /// The digits was not valid. + public static InternationalArticleNumber Create(params byte[] digits) + { + if (digits.Length < 6) + { + foreach (var d in digits) + { + if (d > 9) throw new InvalidOperationException("The digit should be less than 10."); + } + + if (digits.Length == 5 || digits.Length == 2) + return new InternationalArticleNumber + { + value = string.Join(string.Empty, digits) + }; + + throw new InvalidOperationException("The count of digit is too less."); + } + + var check = Checksum(digits); + var col = digits.Length switch + { + 13 => digits[12] == check ? digits.Take(12) : null, + 8 => digits[7] == check ? digits.Take(7) : null, + 18 => digits[17] == check ? digits.Take(17) : null, + _ => digits + }; + if (col == null) + throw new InvalidOperationException($"Check failed. Expects {check} but {digits.LastOrDefault()}."); + return new InternationalArticleNumber + { + value = string.Join(string.Empty, col) + check + }; + } + + /// + /// Creates an EAN. + /// + /// The digits. + /// An instance of the EAN. + /// The input sequence was null. + /// The digits was not valid. + public static InternationalArticleNumber Create(IEnumerable digits) + => Create(digits?.ToArray()); + + /// + /// Creates an EAN. + /// + /// The EAN digits; or barcode areas that white represented as 0 and black represented as 1. + /// An instance of the EAN. + /// The input sequence was null. + /// The digits was not valid. + public static InternationalArticleNumber Create(string sequence) + { + if (sequence == null) throw new ArgumentNullException(nameof(sequence), "sequence should not be null."); + sequence = sequence.Trim(); + if (sequence.Length < 21 || sequence.Contains('9') || sequence.Replace("0", string.Empty).Replace("1", string.Empty).Replace("-", string.Empty).Trim().Length > 0) + return Create(ToList(sequence)); + var col = new List(); + foreach (var c in sequence) + { + if (c == '0') col.Add(false); + else if (c == '1') col.Add(true); + } + + return Create(col); + } + + /// + /// Creates an EAN. + /// + /// The barcode. White represented as false, black represented as true. + /// An instance of the EAN. + /// The barcode was null. + /// The barcode was not valid. + public static InternationalArticleNumber Create(IEnumerable barcode) + { +#pragma warning disable IDE0056 + if (barcode == null) throw new ArgumentNullException(nameof(barcode), "barcode should not be null."); + var col = barcode?.ToList(); + var sb = new StringBuilder(); + if (col.Count < 49) + { + if (col.Count != 21 && col.Count != 48) + throw new InvalidOperationException("The count of barcode area is too less."); + if (col[0] || !col[1] || col[2] || !col[3] || !col[4]) + throw new InvalidOperationException("The start marker is not invalid."); + for (var i = 5; i < col.Count; i += 9) + { + var n = GetLeftDigitNumber(col, i, out _); + sb.Append(n); + } + + return Create(sb.ToString()); + } + + if (!col[0] || col[1] || !col[2] || col[3]) + throw new InvalidOperationException("The start marker is not invalid."); + if (!col[col.Count - 1] || col[col.Count - 2] || !col[col.Count - 3] || col[col.Count - 4]) + throw new InvalidOperationException("The end marker is not invalid."); + if (col.Count == 95) + { + { + var n = GetLeftDigitNumber(col, 3, out var e); + if (e == Encodings.G) + { + col.Reverse(); + n = GetLeftDigitNumber(col, 3, out e); + } + + if (e != Encodings.L) throw new InvalidOperationException("The format of the first digit is invalid."); + sb.Append(n); + } + + var left = new List { false }; + for (var i = 10; i < 45; i += 7) + { + var n = GetLeftDigitNumber(col, i, out var e); + left.Add(e == Encodings.G); + sb.Append(n); + } + + sb.Insert(0, GetFirstDigitNumber(left)); + for (var i = 50; i < 92; i += 7) + { + var n = GetRightDigitNumber(col, i); + sb.Append(n); + } + } + else if (col.Count == 67) + { + { + var n = GetLeftDigitNumber(col, 3, out var e); + if (e == Encodings.G) + { + col.Reverse(); + n = GetLeftDigitNumber(col, 3, out e); + } + + if (e != Encodings.L) throw new InvalidOperationException("The format of the first digit is invalid."); + sb.Append(n); + } + + for (var i = 10; i < 31; i += 7) + { + var n = GetLeftDigitNumber(col, i, out _); + sb.Append(n); + } + + for (var i = 36; i < 64; i += 7) + { + var n = GetRightDigitNumber(col, i); + sb.Append(n); + } + } + else if (col.Count == 84) + { + { + var n = GetLeftDigitNumber(col, 0, out var e); + if (e == Encodings.G) + { + col.Reverse(); + n = GetLeftDigitNumber(col, 0, out e); + } + + if (e != Encodings.L) throw new InvalidOperationException("The format of the first digit is invalid."); + sb.Append(n); + } + + var left = new List { false }; + for (var i = 7; i < 42; i += 7) + { + var n = GetLeftDigitNumber(col, i, out var e); + left.Add(e == Encodings.G); + sb.Append(n); + } + + sb.Insert(0, GetFirstDigitNumber(left)); + for (var i = 42; i < 84; i += 7) + { + var n = GetRightDigitNumber(col, i); + sb.Append(n); + } + } + else + { + throw new InvalidOperationException("The count of barcode is invalid. Should be 95 or 67."); + } + + return Create(sb.ToString()); +#pragma warning restore IDE0056 + } + + /// + /// Gets the checksum. + /// + /// The digits. + /// The checksum. + /// The input sequence was null. + /// The digits was not valid. + public static byte Checksum(params byte[] digits) + { + if (digits == null) throw new ArgumentNullException(nameof(digits), "digits should not be null."); + foreach (var d in digits) + { + if (d > 9) throw new InvalidOperationException("The digit should be less than 10."); + } + + return (byte)(digits.Length switch + { + 12 or 13 => (10 - ((digits[0] + digits[2] + digits[4] + digits[6] + digits[8] + digits[10] + (digits[1] + digits[3] + digits[5] + digits[7] + digits[9] + digits[11]) * 3) % 10)) % 10, + 7 or 8 => (10 - ((digits[1] + digits[3] + digits[5] + (digits[0] + digits[2] + digits[4] + digits[6]) * 3) % 10)) % 10, + 17 or 18 => (10 - ((digits[1] + digits[3] + digits[5] + digits[7] + digits[9] + digits[11] + digits[13] + digits[15] + (digits[0] + digits[2] + digits[4] + digits[6] + digits[8] + digits[10] + digits[12] + digits[14] + digits[16]) * 3) % 10)) % 10, + 5 => ((digits[0] + digits[2] + digits[4]) * 3 + (digits[1] + digits[3]) * 9) % 10, + 2 => (digits[0] * 2 + digits[1]) % 4, + _ => throw new InvalidOperationException("The count of digit is not any of 7, 8, 12 or 13.") + }); + } + + /// + /// Gets the checksum. + /// + /// The digits. + /// The checksum. + /// The input sequence was null. + /// The digits was not valid. + public static byte Checksum(IEnumerable digits) + => Checksum(digits?.ToArray()); + + /// + /// Gets the checksum. + /// + /// The EAN digits. + /// The checksum. + /// The input sequence was null. + /// The input sequence was not valid. + public static byte Checksum(string sequence) + => Checksum(ToList(sequence)); + + /// + /// Validates the checksum. + /// + /// The digits. + /// true if checksum is correct; otherwise, false. + public static bool Validate(params byte[] digits) + => digits != null && digits.Length switch + { + 13 => (10 - ((digits[0] + digits[2] + digits[4] + digits[6] + digits[8] + digits[10] + (digits[1] + digits[3] + digits[5] + digits[7] + digits[9] + digits[11]) * 3) % 10)) % 10 == digits[12], + 8 => (10 - ((digits[1] + digits[3] + digits[5] + (digits[0] + digits[2] + digits[4] + digits[6]) * 3) % 10)) % 10 == digits[7], + 18 => (10 - ((digits[1] + digits[3] + digits[5] + digits[7] + digits[9] + digits[11] + digits[13] + digits[15] + (digits[0] + digits[2] + digits[4] + digits[6] + digits[8] + digits[10] + digits[12] + digits[14] + digits[16]) * 3) % 10)) % 10 == digits[17], + 5 or 2 => true, + _ => false + }; + + /// + /// Validates the checksum. + /// + /// The digits. + /// true if checksum is correct; otherwise, false. + public static bool Validate(IEnumerable digits) + => Validate(digits?.ToArray()); + + /// + /// Validates the checksum. + /// + /// The EAN digits. + /// true if checksum is correct; otherwise, false. + public static bool Validate(string sequence) + { + if (string.IsNullOrEmpty(sequence)) return false; + try + { + return Validate(ToList(sequence)); + } + catch (InvalidOperationException) + { + } + + return false; + } + + private static byte GetFirstDigitNumber(List col) + => string.Join(string.Empty, col.Select(ele => ele ? 'G' : 'L')) switch + { + "LLLLLL" => 0, + "LLGLGG" => 1, + "LLGGLG" => 2, + "LLGGGL" => 3, + "LGLLGG" => 4, + "LGGLLG" => 5, + "LGGGLL" => 6, + "LGLGLG" => 7, + "LGLGGL" => 8, + "LGGLGL" => 9, + _ => throw new InvalidOperationException("The encoding of first group is invalid.") + }; + + private static byte GetLeftDigitNumber(List col, int i, out Encodings encoding) + { + if (col[i]) throw new InvalidOperationException($"Position {i} should be white (false or 0) but is black in fact."); + if (!col[i + 6]) throw new InvalidOperationException($"Position {i + 6} should be black (true or 1) but is white in fact."); + var b = (byte)(0b1 + + (col[i + 1] ? 0b100000 : 0) + + (col[i + 2] ? 0b10000 : 0) + + (col[i + 3] ? 0b1000 : 0) + + (col[i + 4] ? 0b100 : 0) + + (col[i + 5] ? 0b10 : 0)); + try + { + return GetDigitNumber(b, out encoding); + } + catch (InvalidOperationException) + { + throw new InvalidOperationException($"Code {Code.ToString(b)} at position {i} is not a valid digit."); + } + } + + private static byte GetRightDigitNumber(List col, int i) + { + if (!col[i]) throw new InvalidOperationException($"Position {i} should be black (true or 1) but is white in fact."); + if (col[i + 6]) throw new InvalidOperationException($"Position {i + 6} should be white (false or 0) but is black in fact."); + var b = (byte)(0b1000000 + + (col[i + 1] ? 0b100000 : 0) + + (col[i + 2] ? 0b10000 : 0) + + (col[i + 3] ? 0b1000 : 0) + + (col[i + 4] ? 0b100 : 0) + + (col[i + 5] ? 0b10 : 0)); + byte r; + Encodings encoding; + try + { + r = GetDigitNumber(b, out encoding); + } + catch (InvalidOperationException) + { + throw new InvalidOperationException($"Code {Code.ToString(b)} at position {i} is not a valid digit."); + } + + if (encoding != Encodings.R) + throw new InvalidOperationException($"Code {Code.ToString(b)} ({r}) at position {i} is not R-column."); + return r; + } + + /// + /// Creates a byte list. + /// + /// The EAN digits. + /// The byte list. + /// The input sequence was null. + /// The input sequence was not valid. + private static List ToList(string sequence) + { + if (sequence == null) throw new ArgumentNullException(nameof(sequence), "sequence should not be null."); + var arr = new List(); + var i = -1; + foreach (var c in sequence) + { + i++; + switch (c) + { + case '-': + case ' ': + case '(': + case ')': + continue; + case '0': + arr.Add(0); + break; + case '1': + arr.Add(1); + break; + case '2': + arr.Add(2); + break; + case '3': + arr.Add(3); + break; + case '4': + arr.Add(4); + break; + case '5': + arr.Add(5); + break; + case '6': + arr.Add(6); + break; + case '7': + arr.Add(7); + break; + case '8': + arr.Add(8); + break; + case '9': + arr.Add(9); + break; + default: + throw new InvalidOperationException( + $"The input sequence is not valid. Character at index {i} is {c} but expects a digit.", + new ArgumentException("sequence format is not valid.", nameof(sequence))); + } + } + + return arr; + } +} diff --git a/Messages/Data/EanCli.cs b/Messages/Data/EanCli.cs new file mode 100644 index 00000000..f4eeef4d --- /dev/null +++ b/Messages/Data/EanCli.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Trivial.Collection; +using Trivial.CommandLine; + +namespace Trivial.Data; + +/// +/// The International Article Number, a.k.a. European Article Number or EAN. +/// +public partial class InternationalArticleNumber +{ + /// + /// Converts to boolean list and writes to the standard output stream. + /// White represented as false, black represented as true. + /// + /// The command line interface proxy. + /// The style that foreground represents black and background represents white. + /// The boolean list. + /// It was not an EAN-13 ro EAN-8 code. + public List ToBarcode(StyleConsole cli, ConsoleTextStyle style = null) + { + List barcode; + try + { + barcode = ToBarcode(); + } + catch (InvalidOperationException) + { + cli.WriteLine(style, value); + throw; + } + + var col = new List(); + if (style == null) style = new ConsoleTextStyle(System.Drawing.Color.FromArgb(16, 16, 16), ConsoleColor.Black, System.Drawing.Color.FromArgb(206, 206, 206), ConsoleColor.Gray); + var black = new ConsoleTextStyle(style.ForegroundRgbColor, style.ForegroundConsoleColor, style.ForegroundRgbColor, style.ForegroundConsoleColor); + var white = new ConsoleTextStyle(style.BackgroundRgbColor, style.BackgroundConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor); + var bg = new string(' ', 12 + barcode.Count); + col.Add(bg, white); + col.Add(Environment.NewLine); + var s = value; + cli.Flush(); + if (cli.Mode == StyleConsole.Modes.Text && cli.Handler == null) + { + cli.WriteLine(style, s); + return barcode; + } + else if (barcode.Count + 12 > GetBufferSafeWidth(cli)) + { + col.Clear(); + foreach (var b in barcode) + { + col.Add(' ', 1, b ? black : white); + } + + col.Add(Environment.NewLine); + col.Add(s, style); + cli.WriteLine(col); + return barcode; + } + else if (barcode.Count == 95 && s.Length == 13) + { + for (var i = 0; i < 4; i++) + { + col.Add(' ', 7, white); + foreach (var b in barcode) + { + col.Add(' ', 1, b ? black : white); + } + + col.Add(' ', 5, white); + col.Add(Environment.NewLine); + } + + var isbn = false; + if (s.StartsWith("97")) + { + if (s.StartsWith("9790")) + { + isbn = true; + col.Add("ISMN 9 ", style); + } + else if (s.StartsWith("978") || s.StartsWith("979")) + { + isbn = true; + col.Add("ISBN 9 ", style); + } + else if (s.StartsWith("977")) + { + isbn = true; + col.Add("ISSN 9 ", style); + } + } + + if (!isbn) + { + col.Add(' ', 4, white); + col.Add(s[0], 1, style); + col.Add(' ', 2, white); + } + + for (var i = 0; i < 3; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + for (var i = 1; i < 7; i++) + { + col.Add(' ', 3, white); + col.Add(s[i], 1, style); + col.Add(' ', 3, white); + } + + for (var i = 45; i < 50; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + for (var i = 7; i < 13; i++) + { + col.Add(' ', 3, white); + col.Add(s[i], 1, style); + col.Add(' ', 3, white); + } + + for (var i = 92; i < 95; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + col.Add(' ', 5, white); + col.Add(Environment.NewLine); + } + else if (barcode.Count == 67 && s.Length == 8) + { + for (var i = 0; i < 4; i++) + { + col.Add(' ', 6, white); + foreach (var b in barcode) + { + col.Add(' ', 1, b ? black : white); + } + + col.Add(' ', 6, white); + col.Add(Environment.NewLine); + } + + col.Add(' ', 6, white); + for (var i = 0; i < 3; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + for (var i = 0; i < 4; i++) + { + col.Add(' ', 3, white); + col.Add(s[i], 1, style); + col.Add(' ', 3, white); + } + + for (var i = 31; i < 36; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + for (var i = 4; i < 8; i++) + { + col.Add(' ', 3, white); + col.Add(s[i], 1, style); + col.Add(' ', 3, white); + } + + for (var i = 64; i < 67; i++) + { + col.Add(' ', 1, barcode[i] ? black : white); + } + + col.Add(' ', 6, white); + col.Add(Environment.NewLine); + } + else if ((barcode.Count == 48 && s.Length == 5) || (barcode.Count == 21 && s.Length == 2)) + { + col.Add(' ', 14, white); + foreach (var c in s) + { + col.Add(c, 1, style); + col.Add(' ', 8, white); + } + + col.Add(' ', 1, white); + col.Add(Environment.NewLine); + for (var i = 0; i < 4; i++) + { + col.Add(' ', 6, white); + foreach (var b in barcode) + { + col.Add(' ', 1, b ? black : white); + } + + col.Add(' ', 6, white); + col.Add(Environment.NewLine); + } + } + else + { + for (var i = 0; i < 4; i++) + { + col.Add(' ', 6, white); + foreach (var b in barcode) + { + col.Add(' ', 1, b ? black : white); + } + + col.Add(' ', 6, white); + col.Add(Environment.NewLine); + } + } + + col.Add(bg, white); + (cli ?? StyleConsole.Default).WriteLine(col); + return barcode; + } + + private static int GetBufferSafeWidth(StyleConsole cli) + { + try + { + return (cli ?? StyleConsole.Default).BufferWidth - 1; + } + catch (System.IO.IOException) + { + } + catch (InvalidOperationException) + { + } + catch (NotSupportedException) + { + } + catch (System.Security.SecurityException) + { + } + catch (System.Runtime.InteropServices.ExternalException) + { + } + catch (ArgumentException) + { + } + + return 70; + } +} diff --git a/Messages/Data/EanCode.cs b/Messages/Data/EanCode.cs new file mode 100644 index 00000000..1eae7942 --- /dev/null +++ b/Messages/Data/EanCode.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Data; + +/// +/// The International Article Number, a.k.a. European Article Number or EAN. +/// +public partial class InternationalArticleNumber +{ + /// + /// The encoding for Code. + /// + public enum Encodings : byte + { + /// + /// Odd parity for first group. + /// + L = 1, + + /// + /// Even parity for first group. + /// + G = 2, + + /// + /// Last group. + /// + R = 3 + } + + /// + /// The code of a Code. + /// + public class Code : IEquatable, IEquatable + { + /// + /// Initializes a new instance of the InternationalArticleNumber.Code class. + /// + /// The code. + public Code(byte code) + { + int r; + int rg; + if (code > 0b111111) + { + if (code > 0b1111111) + R = (byte)(code >> 1); + else + R = code; + rg = ((~code) + 128) % 128; + L = (byte)(rg); + r = code; + } + else + { + L = code; + r = ((~code) + 128) % 128; + R = (byte)r; + rg = code; + } + + G = Reverse(r); + RG = Reverse(rg); + } + + /// + /// Gets the binary (last 7 bits) of the Code encoded using odd parity for first group. + /// + public byte L { get; } + + /// + /// Gets the binary (last 7 bits) of the Code encoded using even parity for first group. + /// + public byte G { get; } + + /// + /// Gets the binary (last 7 bits) of the Code encoded for last group. + /// + public byte R { get; } + + internal byte RG { get; } + + /// + /// Gets the value. + /// + /// The encoding. + /// The value in byte (last 7 bit). + /// encoding is not valid. + public byte Get(Encodings encoding) + => encoding switch + { + Encodings.L => L, + Encodings.R => R, + Encodings.G => G, + (Encodings)4 => RG, + _ => throw new InvalidOperationException("encoding is invalid.", new ArgumentOutOfRangeException(nameof(encoding), "encoding is not the one of supported.")) + }; + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// + /// true if the current object is equal to the parameter; otherwise, false. + /// + public bool Equals(byte other) + { + return other == L || other == R || other == G || other == RG; + } + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// + /// true if the current object is equal to the parameter; otherwise, false. + /// + public bool Equals(Code other) + { + return other != null && L == other.L && G == other.G; + } + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// + /// true if the current object is equal to the parameter; otherwise, false. + /// + public override bool Equals(object obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj is byte b) return Equals(b); + return Equals(obj as Code); + } + + /// + public override int GetHashCode() + => L.GetHashCode(); + + /// + /// Gets the encoding if the specific value is the current object; otherwise, 0. + /// + /// An object to compare with this object. + /// The enocding used in this object. + public Encodings GetEncoding(byte other) + { + if (other == L) return Encodings.L; + if (other == R) return Encodings.R; + if (other == G) return Encodings.G; + if (other == RG) return (Encodings)4; + return 0; + } + + /// + /// Converts to a list of boolean about areas. + /// + /// The encoding. + /// The areas. White represented as false, black represented as true. + /// encoding is not valid. + public List ToList(Encodings encoding) + => encoding switch + { + Encodings.L => ToList(L), + Encodings.R => ToList(R), + Encodings.G => ToList(G), + (Encodings)4 => ToList(RG), + _ => throw new InvalidOperationException("encoding is invalid.", new ArgumentOutOfRangeException(nameof(encoding), "encoding is not the one of supported.")) + }; + + /// + /// Converts to a list of boolean. + /// + /// The encoding. + /// The boolean array. + /// encoding is not valid. + public string ToString(Encodings encoding) + => encoding switch + { + Encodings.L => ToString(L), + Encodings.R => ToString(R), + Encodings.G => ToString(G), + (Encodings)4 => ToString(RG), + _ => throw new InvalidOperationException("encoding is invalid.", new ArgumentOutOfRangeException(nameof(encoding), "encoding is not the one of supported.")) + }; + + /// + /// Converts the value of the current object to its equivalent string representation. + /// + /// The string representation of the value of this object, which consists of a sequence of 7 digits of 0 and 1. + public override string ToString() + { + return ToString(Encodings.L); + } + + internal static string ToString(byte value) + { + var s = Maths.Numbers.ToPositionalNotationString((long)value, 2); + return s.Length < 7 ? s.PadLeft(7 - s.Length, '0') : s; + } + + private static List ToList(int value) + => new() + { + (value & 0b1000000) > 0, + (value & 0b100000) > 0, + (value & 0b10000) > 0, + (value & 0b1000) > 0, + (value & 0b100) > 0, + (value & 0b10) > 0, + (value & 0b1) > 0, + }; + + private static byte Reverse(int value) + => (byte)(((value & 0b1000000) > 0 ? 0b1 : 0) + + ((value & 0b100000) > 0 ? 0b10 : 0) + + ((value & 0b10000) > 0 ? 0b100 : 0) + + ((value & 0b1000) > 0 ? 0b1000 : 0) + + ((value & 0b100) > 0 ? 0b10000 : 0) + + ((value & 0b10) > 0 ? 0b100000 : 0) + + ((value & 0b1) > 0 ? 0b1000000 : 0)); + } + + /// + /// Gets the Code 0. + /// + public static Code Zero { get; } = new(0b0001101); + + /// + /// Gets the Code 1. + /// + public static Code One { get; } = new(0b0011001); + + /// + /// Gets the Code 2. + /// + public static Code Two { get; } = new(0b0010011); + + /// + /// Gets the Code 3. + /// + public static Code Three { get; } = new(0b0111101); + + /// + /// Gets the Code 4. + /// + public static Code Four { get; } = new(0b0100011); + + /// + /// Gets the Code 5. + /// + public static Code Five { get; } = new(0b0110001); + + /// + /// Gets the Code 6. + /// + public static Code Six { get; } = new(0b0101111); + + /// + /// Gets the Code 7. + /// + public static Code Seven { get; } = new(0b0111011); + + /// + /// Gets the Code 8. + /// + public static Code Eight { get; } = new(0b0110111); + + /// + /// Gets the Code 9. + /// + public static Code Nine { get; } = new(0b0001011); + + /// + /// Gets the digit code. + /// + /// The number from 0 to 9. + /// The Code. + /// The number was negative or greater than 9. + public static Code GetDigitCode(byte number) + { + return number switch + { + 0 => Zero, + 1 => One, + 2 => Two, + 3 => Three, + 4 => Four, + 5 => Five, + 6 => Six, + 7 => Seven, + 9 => Eight, + _ => throw (number > 10 + ? new ArgumentOutOfRangeException(nameof(number), "number is out of range because it is greater than 9.") + : new ArgumentOutOfRangeException(nameof(number), "number is out of range because it is negative.")) + }; + } + + /// + /// Gets the digit number + /// + /// The code in byte (last 7 bits). + /// The encoding. + /// The digit number. + /// The code is not mapped to a digit. + public static byte GetDigitNumber(byte code, out Encodings encoding) + { + var e = Zero.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 0; + } + + e = One.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 1; + } + + e = Two.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 2; + } + + e = Three.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 3; + } + + e = Four.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 4; + } + + e = Five.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 5; + } + + e = Six.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 6; + } + + e = Seven.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 7; + } + + e = Eight.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 8; + } + + e = Nine.GetEncoding(code); + if (e > 0) + { + encoding = e; + return 9; + } + + throw new InvalidOperationException("The code was invalid since it does not mapped to a digit."); + } + + /// + /// Gets the digit number + /// + /// The code in byte (last 7 bits). + /// The digit number. + public static byte GetDigitNumber(byte code) + => GetDigitNumber(code, out _); + + /// + /// Gets the digit number + /// + /// The code in byte (last 7 bits). + /// The digit number. + /// The code is not mapped to a digit. + public static byte GetDigitNumber(Code code) + { + if (Zero.Equals(code)) return 0; + if (One.Equals(code)) return 1; + if (Two.Equals(code)) return 2; + if (Three.Equals(code)) return 3; + if (Four.Equals(code)) return 4; + if (Five.Equals(code)) return 5; + if (Six.Equals(code)) return 6; + if (Seven.Equals(code)) return 7; + if (Eight.Equals(code)) return 8; + if (Nine.Equals(code)) return 9; + throw new InvalidOperationException("The code was invalid since it does not mapped to a digit."); + } +} diff --git a/Messages/IO/FileAssociationInfo.cs b/Messages/IO/FileAssociationInfo.cs new file mode 100644 index 00000000..f6883021 --- /dev/null +++ b/Messages/IO/FileAssociationInfo.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Trivial.IO; + +/// +/// The file association information. +/// +[DataContract] +public class FileAssociationInfo +{ + /// + /// Gets or sets the file extension part. + /// + [JsonPropertyName("ext")] + [DataMember(Name = "ext")] + public string FileExtension { get; set; } + + /// + /// Gets or sets the MIME content type. + /// + [JsonPropertyName("mime")] + [DataMember(Name = "mime")] + public string ContentType { get; set; } + + /// + /// Gets or sets the default icon path. + /// + [JsonPropertyName("icon")] + [DataMember(Name = "icon")] + public string Icon { get; set; } + + /// + /// Ges or sets the friendly name of the content type. + /// + [JsonPropertyName("name")] + [DataMember(Name = "name")] + public string Name { get; set; } + + /// + /// Gets or sets the defaul command. + /// + [JsonPropertyName("defaultcmd")] + [DataMember(Name = "defaultcmd")] + public FileOpenCommandInfo DefaultCommand { get; set; } + + /// + /// Gets or sets the commands. + /// + [JsonPropertyName("cmds")] + [DataMember(Name = "cmds")] + public List Commands { get; set; } = new(); +} + +/// +/// The file open command information. +/// +[DataContract] +public class FileOpenCommandInfo +{ + /// + /// Gets or sets the command key. + /// + [JsonPropertyName("key")] + [DataMember(Name = "key")] + public string Key { get; set; } = "Open"; + + /// + /// Gets or sets the command. + /// + [JsonPropertyName("cmd")] + [DataMember(Name = "cmd")] + public string Command { get; set; } + + /// + /// Ges or sets the friendly name of the command. + /// + [JsonPropertyName("name")] + [DataMember(Name = "name")] + public string Name { get; set; } +} diff --git a/Messages/Maths/BitgNumeralBitmap.cs b/Messages/Maths/BitgNumeralBitmap.cs new file mode 100644 index 00000000..de868f2f --- /dev/null +++ b/Messages/Maths/BitgNumeralBitmap.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Trivial.Reflection; + +namespace Trivial.Maths; + +/// +/// The numeral bitmap collection of Beacon in the Galaxy. +/// +public static class BitgNumeralBitmap +{ + /// + /// The bitmap width. + /// + public const int WIDTH = 5; + + /// + /// The bitmap height. + /// + public const int HEIGHT = 7; + + /// + /// The radix. + /// + public const int RADIX = 10; + + /// + /// Gets the boolean array of zero. + /// + public readonly static bool[] Zero = new[] { false, false, true, false, false, false, false, true, false, false, true, true, true, true, true, true, false, false,false, false, true, true, true, true, true, true, false, false, true, false, false, false, false, true, false, false }; + + /// + /// Gets the boolean array of one. + /// + public readonly static bool[] One = new[] { true, true, true, true, true, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false }; + + /// + /// Gets the boolean array of two. + /// + public readonly static bool[] Two = new[] { true, true, true, false, false, false, false, true, false, false, true, false, true, false, false, true, false, false ,false, false, true, false, true, true, true, true, false, false, false, false, true, true, true, false, false }; + + /// + /// Gets the boolean array of three. + /// + public readonly static bool[] Three = new[] { true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, false, false, false, false, true, false, true, true, true, true, false, false, false, false, true, false, false, false, false}; + + /// + /// Gets the boolean array of four. + /// + public readonly static bool[] Four = new[] { true, false, true, true, true, true, false, false, false, false, true, true, true, false, false, true, false, false, false, false, true, true, true, false, false, true, false, false, false, false, true, true, true, false, false }; + + /// + /// Gets the boolean array of five. + /// + public readonly static bool[] Five = new[] { true, true, true, false, true, true, true, true, false, true, true, false, true, false, true, true, false, false, false, false, true, true, true, false, false, false, false, true, false, false, true, true, true, true, true }; + + /// + /// Gets the boolean array of six. + /// + public readonly static bool[] Six = new[] { false, false, false, false, true, false, true, false, true, true, true, true, true, false, true, false, false, true, false, false, true, true, true, false, false, true, false, true, false, false, true, true, true, false, false }; + + /// + /// Gets the boolean array of seven. + /// + public readonly static bool[] Seven = new[] { true, true, true, false, true, false, false, true, true, true, false, false, true, false, true, false, true, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false }; + + /// + /// Gets the boolean array of eight. + /// + public readonly static bool[] Eight = new[] { true, false, true, true, true, true, true, false, false, false, true, true, true, false, false, true, false, true, false, false, true, true, true, true, true, true, false, true, false, false, true, true, true, true, true }; + + /// + /// Gets the boolean array of nine. + /// + public readonly static bool[] Nine = new[] { false, false, false, false, true, false, true, false, false, true, true, false, true, false, true, true, false, true, false, true, true, true, true, true, true, false, false, true, false, false, true, true, true, false, false }; + + /// + /// Gets the boolean array of equal sign. + /// + public readonly static bool[] EqualSign = new[] { false, false, true, true, true, false, false, true, false, false, true, true, true, true, true, false, false, true, false, false, true, true, true, true, true, false, false, true, false, false, true, true, true, false, false }; + + /// + /// Gets the boolean array of negative sign. + /// + public readonly static bool[] NegativeSign = new[] { false, false, true, true, true, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true, true, true }; + + /// + /// Gets the boolean array of plus sign. + /// + public readonly static bool[] PlusSign = new[] { true, false, true, true, true, true, false, false, false, false, true, false, true, false, false, true, true, true, true, false, true, false, true, false, false, true, false, false, false, false, true, false, true, false, false }; + + /// + /// Gets the boolean array of equal sign. + /// + public readonly static bool[] MinusSign = new[] { true, true, true, true, true, false, true, false, true, false, true, false, false, false, false, true, false, false, false, false, true, true, true, true, true, true, false, false, false, false, true, false, false, false, false }; + + /// + /// Gets the boolean array of dot. + /// + public readonly static bool[] Dot = new[] { false, false, true, true, true, false, false, false, false, true, false, false, false, false, true, false, true, false, false, false, true, false, false, false, false, true, false, false, false, false, true, true, true, false, false }; +} diff --git a/Messages/Messages.csproj b/Messages/Messages.csproj index 5ed5cd69..cd58b0b7 100644 --- a/Messages/Messages.csproj +++ b/Messages/Messages.csproj @@ -1,65 +1,32 @@  + + net8.0;net6.0;net48;net462;net461 Trivial.Messages Trivial Trivial.Messages - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 The library with model of users and messages. - Copyright (c) 2023 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/core true true snupkg - https://github.com/nuscien/trivial - git - true - mime.png + messages.png https://github.com/nuscien/trivial/raw/master/Materials/logo.png users messages gpt - README.md - 12.0 - True - ..\Trivial.snk - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Messages.xml - + + + - - ..\bin\Release\ + + ..\bin\$(Configuration)\ ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Messages.xml - - NETOLDVER - - - - - - - - - - - - - - - - - + diff --git a/Messages/Text/JsonProperty.cs b/Messages/Text/JsonProperty.cs new file mode 100644 index 00000000..82576f6f --- /dev/null +++ b/Messages/Text/JsonProperty.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Trivial.Text; + +/// +/// The locale property resolver of JSON object. +/// +public class LocaleJsonPropertyResolver : IJsonPropertyResolver +{ + /// + /// Gets or sets the optional current market code. + /// + public string Market { get; set; } + + /// + /// Gets or sets the optional prefix of property key. + /// + public string Prefix { get; set; } + + /// + /// Gets or sets the optional suffix of property key. + /// + public string Suffix { get; set; } + + /// + /// Gets or sets the optional fallback market code. + /// + public string Fallback { get; set; } + + /// + /// Gets the property value. + /// + /// The source node. + /// The value of the property. + /// true if has the property and the type is the one expected; otherwise, false. + public bool TryGetValue(JsonObjectNode node, out string result) + { + var mkt = string.IsNullOrWhiteSpace(Market) ? Market.Trim() : CultureInfo.CurrentUICulture?.Name?.Trim(); + if (node == null || string.IsNullOrEmpty(mkt)) + { + result = null; + return false; + } + + string key; + string name; + while (true) + { + key = $"{Prefix}{mkt}{Suffix}"; + name = node.TryGetStringValue(key)?.Trim(); + if (!string.IsNullOrEmpty(name)) + { + result = name; + return true; + } + + key = $"{Prefix}{mkt.ToLowerInvariant()}{Suffix}"; + name = node.TryGetStringValue(key)?.Trim(); + if (!string.IsNullOrEmpty(name)) + { + result = name; + return true; + } + + var i = mkt.LastIndexOf('-'); + #pragma warning disable IDE0057 + if (i > 0) mkt = mkt.Substring(0, i); + #pragma warning restore IDE0057 + else break; + } + + key = $"{Prefix}{Fallback ?? "ww"}{Suffix}"; + result = node.TryGetStringValue(key)?.Trim(); + return string.IsNullOrEmpty(result); + } +} diff --git a/Messages/Web/AudioMimeConstants.cs b/Messages/Web/AudioMimeConstants.cs new file mode 100644 index 00000000..a057e14f --- /dev/null +++ b/Messages/Web/AudioMimeConstants.cs @@ -0,0 +1,90 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of audio. + /// + public static class Audio + { + /// + /// The MIME content type of basic audio and sound. + /// + public const string Au = "audio/basic"; + + /// + /// The MIME content type of apt-X (Audio Processing Technology). + /// + public const string Aptx = "audio/aptx"; + + /// + /// The MIME content type of Musical Instrument Digital Interface. + /// + public const string Midi = "audio/midi"; + + /// + /// The MIME content type of MPEG-4. + /// + public const string Mp4 = "audio/mp4"; + + /// + /// The MIME content type of MPEG-1 audio layer 3. + /// + public const string Mp3 = "audio/mpeg"; + + /// + /// The MIME content type of OGG Vobis (by Xiph.Org Foundation). + /// + public const string Ogg = "audio/ogg"; + + /// + /// The MIME content type of opus (by Xiph.Org Foundation). + /// + public const string Opus = "audio/opus"; + + /// + /// The MIME content type of WebA (by Google). + /// + public const string Weba = "audio/webm"; + + /// + /// The MIME content type of Advanced Audio Coding. + /// + public const string Aac = "audio/x-aac"; + + /// + /// The MIME content type of Audio Interchange File Format. + /// + public const string Aif = "audio/x-aiff"; + + /// + /// The MIME content type of Free Lossless Audio Codec. + /// + public const string Flac = "audio/x-flac"; + + /// + /// The MIME content type of ape (Monkey's Audio). + /// + public const string Ape = "audio/x-ape"; + + /// + /// The MIME content type of Matroska. + /// + public const string Matroska = "audio/x-matroska"; + + /// + /// The MIME content type of Windows Media Audio. + /// + public const string Wma = "audio/x-ms-wma"; + + /// + /// The MIME content type of wave audio. + /// + public const string Wav = "audio/wav"; + } +} diff --git a/Messages/Web/DocumentsMimeConstants.cs b/Messages/Web/DocumentsMimeConstants.cs new file mode 100644 index 00000000..f89801ed --- /dev/null +++ b/Messages/Web/DocumentsMimeConstants.cs @@ -0,0 +1,215 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of documents. + /// + public static class Documents + { + /// + /// The MIME content type of Portable Document Format. + /// + public const string Pdf = "application/pdf"; + + /// + /// The MIME content type of ePub. + /// + public const string EPub = "application/epub+zip"; + + /// + /// The MIME content type of lotus 123. + /// + public const string Lotus123 = "vnd.lotus-1-2-3"; + + /// + /// The MIME content type of Microsoft Office Clip. + /// + public const string OfficeClip = "application/x-msclip"; + + /// + /// The MIME content type of Microsoft card file. + /// + public const string Card = "application/x-mscardfile"; + + /// + /// The MIME content type of Microsoft Office Word old binary document. + /// + public const string Doc = "application/msword"; + + /// + /// The MIME content type of Microsoft Office Word document. + /// + public const string Docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + + /// + /// The MIME content type of Microsoft Office Word template. + /// + public const string Dotx = "application/vnd.openxmlformats-officedocument.wordprocessingml.template"; + + /// + /// The MIME content type of Microsoft Office Excel old binary document. + /// + public const string Xls = "application/vnd.ms-excel"; + + /// + /// The MIME content type of Microsoft Office Excel document. + /// + public const string Xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + + /// + /// The MIME content type of Microsoft Office Excel template. + /// + public const string Xltx = "application/vnd.openxmlformats-officedocument.spreadsheetml.template"; + + /// + /// The MIME content type of Microsoft Office PowerPoint old binary document. + /// + public const string Ppt = "application/vnd.ms-powerpoint"; + + /// + /// The MIME content type of Microsoft Office PowerPoint document. + /// + public const string Pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + + /// + /// The MIME content type of Microsoft Office PowerPoint SlideShow. + /// + public const string Ppsx = "application/vnd.openxmlformats-officedocument.presentationml.slideshow"; + + /// + /// The MIME content type of Microsoft Office PowerPoint slide. + /// + public const string Sldx = "application/vnd.openxmlformats-officedocument.presentationml.slide"; + + /// + /// The MIME content type of Microsoft Office PowerPoint template. + /// + public const string Potx = "application/vnd.openxmlformats-officedocument.presentationml.template"; + + /// + /// The MIME content type of Microsoft Office OneNote document. + /// + public const string OneNote = "application/onenote"; + + /// + /// The MIME content type of Microsoft Office Visio document. + /// + public const string Visio = "application/vnd.visio"; + + /// + /// The MIME content type of Microsoft Office Project document. + /// + public const string Project = "application/vnd.ms-project"; + + /// + /// The MIME content type of Microsoft Office Access database. + /// + public const string Access = "application/x-msaccess"; + + /// + /// The MIME content type of Microsoft Office Outlook file. + /// + public const string Outlook = "application/vnd.ms-outlook"; + + /// + /// The MIME content type of XML Paper Specification document. + /// + public const string Xps = "application/vnd.ms-xpsdocument"; + + /// + /// The MIME content type of Open XML Paper Specification document. + /// + public const string Oxps = "application/oxps"; + + /// + /// The MIME content type of Open Document Chart. + /// + public const string Odc = "application/vnd.oasis.opendocument.chart"; + + /// + /// The MIME content type of Open Document Chart Template. + /// + public const string Otc = "application/vnd.oasis.opendocument.chart-template"; + + /// + /// The MIME content type of Open Document Database. + /// + public const string Odb = "application/vnd.oasis.opendocument.database"; + + /// + /// The MIME content type of Open Document Formula. + /// + public const string Odf = "application/vnd.oasis.opendocument.formula"; + + /// + /// The MIME content type of Open Document Formula Template. + /// + public const string Odft = "application/vnd.oasis.opendocument.formula-template"; + + /// + /// The MIME content type of Open Document Graphics. + /// + public const string Odg = "application/vnd.oasis.opendocument.graphics"; + + /// + /// The MIME content type of Open Document Graphics Template. + /// + public const string Otg = "application/vnd.oasis.opendocument.graphics-template"; + + /// + /// The MIME content type of Open Document Image. + /// + public const string Odi = "application/vnd.oasis.opendocument.image"; + + /// + /// The MIME content type of Open Document Image Template. + /// + public const string Oti = "application/vnd.oasis.opendocument.image-template"; + + /// + /// The MIME content type of Open Document Presentation. + /// + public const string Odp = "application/vnd.oasis.opendocument.presentation"; + + /// + /// The MIME content type of Open Document Presentation Template. + /// + public const string Otp = "application/vnd.oasis.opendocument.presentation-template"; + + /// + /// The MIME content type of Open Document Spreadsheet. + /// + public const string Ods = "application/vnd.oasis.opendocument.spreadsheet"; + + /// + /// The MIME content type of Open Document Spreadsheet Template. + /// + public const string Ots = "application/vnd.oasis.opendocument.spreadsheet-template"; + + /// + /// The MIME content type of Open Document Text. + /// + public const string Odt = "application/vnd.oasis.opendocument.text"; + + /// + /// The MIME content type of Open Document Text Master. + /// + public const string Odm = "application/vnd.oasis.opendocument.text-master"; + + /// + /// The MIME content type of Open Document Text Template. + /// + public const string Ott = "application/vnd.oasis.opendocument.text-template"; + + /// + /// The MIME content type of Open Document Text Web. + /// + public const string Oth = "application/vnd.oasis.opendocument.text-web"; + } +} diff --git a/Messages/Web/ImageMimeConstants.cs b/Messages/Web/ImageMimeConstants.cs new file mode 100644 index 00000000..e9164da7 --- /dev/null +++ b/Messages/Web/ImageMimeConstants.cs @@ -0,0 +1,80 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of image. + /// + public static class Images + { + /// + /// The MIME content type of Animated Portable Network Graphics. + /// + public const string Apng = "image/apng"; + + /// + /// The MIME content type of Portable Network Graphics. + /// + public const string Png = "image/png"; + + /// + /// The MIME content type of bitmap (and Device-Independent Bitmap). + /// + public const string Bmp = "image/bmp"; + + /// + /// The MIME content type of AutoCAD drawings. + /// + public const string Dwg = "image/vnd.dwg"; + + /// + /// The MIME content type of Graphics Interchange Format. + /// + public const string Gif = "image/gif"; + + /// + /// The MIME content type of High Efficiency Image Format. + /// + public const string Heif = "image/heif"; + + /// + /// The MIME content type of High Efficiency Image Codec. + /// + public const string Heic = "image/heic"; + + /// + /// The MIME content type of icon and cursor. + /// + public const string Ico = "image/x-ico"; + + /// + /// The MIME content type of Joint Photographic Experts Group. + /// + public const string Jpeg = "image/jpeg"; + + /// + /// The MIME content type of Adobe Photoshop Document. + /// + public const string Psd = "image/vnd.adobe.photoshop"; + + /// + /// The MIME content type of Scalable Vector Graphics. + /// + public const string Svg = "image/svg+xml"; + + /// + /// The MIME content type of WebP (by Google). + /// + public const string Webp = "image/webp"; + + /// + /// The MIME content type of Windows Meta File. + /// + public const string Wmf = "application/x-msmetafile"; + } +} diff --git a/Messages/Web/MimeConstants.cs b/Messages/Web/MimeConstants.cs new file mode 100644 index 00000000..c7bab1c6 --- /dev/null +++ b/Messages/Web/MimeConstants.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.Json; + +using Trivial.Collection; +using Trivial.Text; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + private static MethodInfo method; + private static KeyedDataMapping fem; + + // RFC 6838 + + /// + /// The name of MIME. + /// + public const string Name = "Multipurpose Internet Mail Extensions"; + + /// + /// The MIME content type of octet stream. + /// + public const string StreamMIME = "application/octet-stream"; + + /// + /// The MIME content type of URL encoded form. + /// + public const string FormUrlMIME = "application/x-www-form-urlencoded"; + + /// + /// Gets the MIME content type mapping of file extension. + /// + public static KeyedDataMapping FileExtensionMapping + { + get + { + if (fem != null) return fem; + var prop = typeof(WebFormat).GetProperty("MimeMapping", BindingFlags.Static | BindingFlags.NonPublic); + if (prop == null) prop = typeof(WebFormat).GetProperty("MimeMapping", BindingFlags.Static | BindingFlags.Public); + if (prop?.CanRead == true) fem = prop.GetValue(null) as KeyedDataMapping; + return fem; + } + } + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The MIME content type. + public static string GetByFileExtension(FileInfo file) + => GetByFileExtension(file?.Extension, StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// true if returns null if not supported; otherwise, false. + /// The MIME content type. + public static string GetByFileExtension(FileInfo file, bool returnNullIfUnsupported) + => GetByFileExtension(file?.Extension, returnNullIfUnsupported ? null : StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The default MIME content type. + /// The MIME content type. + public static string GetByFileExtension(FileInfo file, string defaultMime) + => GetByFileExtension(file?.Extension, defaultMime); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension) + => GetByFileExtension(fileExtension, StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// true if returns null if not supported; otherwise, false. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension, bool returnNullIfUnsupported) + => GetByFileExtension(fileExtension, returnNullIfUnsupported ? null : StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// The default MIME content type. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension, string defaultMime) + { + if (string.IsNullOrWhiteSpace(fileExtension)) return null; + if (method == null) + { + method = typeof(WebFormat).GetMethod("GetMime", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null); + if (method == null) + method = typeof(WebFormat).GetMethod("GetMime", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null); + if (method == null) + return defaultMime; + } + + var r = method.Invoke(null, new object[] { fileExtension }); + if (r == null) return defaultMime; + try + { + return (string)r; + } + catch (InvalidCastException) + { + } + + return defaultMime; + } + + /// + /// Registers file extension mapping. + /// + /// The mapping source. + /// true if override the existed one; otherwise, false. + /// The count of item added or changed. + public static int RegisterFileExtensionMapping(JsonObjectNode json, bool overrideIfExist = false) + { + var mapping = FileExtensionMapping; + if (json == null || mapping == null) return 0; + var arr = json.TryGetArrayValue("mime"); + if (arr != null) return RegisterFileExtensionMapping(arr, overrideIfExist); + var body = json.TryGetObjectValue("mime"); + if (body != null) json = body; + var i = 0; + foreach (var item in json) + { + if (item.Value?.ValueKind != JsonValueKind.String) continue; + if (!item.Value.TryGetString(out var s)) continue; + if (mapping.Set(item.Key, s, overrideIfExist)) i++; + } + + return i; + } + + /// + /// Registers file extension mapping. + /// + /// The source. + /// true if override the existed one; otherwise, false. + /// The count of item added or changed. + public static int RegisterFileExtensionMapping(JsonArrayNode json, bool overrideIfExist = false) + { + var mapping = FileExtensionMapping; + if (json == null || mapping == null) return 0; + var i = 0; + foreach (var item in json) + { + if (item is not JsonObjectNode ele) continue; + var ext = ele.TryGetStringValue("extension") ?? ele.TryGetStringValue("ext"); + var mime = ele.TryGetStringValue("mime"); + if (mapping.Set(mime, ext, overrideIfExist)) i++; + } + + return i; + } + + /// + /// Registers file extension mapping. + /// + /// The mapping source. + /// true if override the existed one; otherwise, false. + /// The count of item added or changed. + public static int RegisterFileExtensionMapping(IDictionary source, bool overrideIfExist = false) + { + var mapping = FileExtensionMapping; + if (mapping == null || source == null) return 0; + return mapping.Set(source, overrideIfExist); + } + + /// + /// Registers file extension mapping. + /// + /// The file extension part. + /// The MIME content type. + /// true if override the existed one; otherwise, false. + /// true if registers succeeded; otherwise, false. + public static bool RegisterFileExtensionMapping(string fileExtension, string mime, bool overrideIfExist = false) + { + var mapping = FileExtensionMapping; + if (mapping == null || fileExtension == null) return false; + return mapping.Set(fileExtension, mime, overrideIfExist); + } +} diff --git a/Messages/Web/MultipartConstants.cs b/Messages/Web/MultipartConstants.cs new file mode 100644 index 00000000..9b8530ef --- /dev/null +++ b/Messages/Web/MultipartConstants.cs @@ -0,0 +1,50 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of multipart. + /// + public static class Multipart + { + /// + /// The MIME content type of form data. + /// + public const string FormDataMIME = "multipart/form-data"; + + /// + /// The MIME content type of byte ranges. + /// + public const string ByteRanges = "multipart/byteranges"; + + /// + /// The MIME content type of encrypted. + /// + public const string Encrypted = "multipart/encrypted"; + + /// + /// The MIME content type of multilingual. + /// + public const string Multilingual = "multipart/multilingual"; + + /// + /// The MIME content type of signed. + /// + public const string Signed = "multipart/signed"; + + /// + /// The MIME content type of voice message. + /// + public const string VoiceMessage = "multipart/voice-message"; + + /// + /// The MIME content type of mixed replace. + /// + public const string MixedReplace = "multipart/x-mixed-replace"; + } +} diff --git a/Messages/Web/PackagesMimeConstants.cs b/Messages/Web/PackagesMimeConstants.cs new file mode 100644 index 00000000..2c706369 --- /dev/null +++ b/Messages/Web/PackagesMimeConstants.cs @@ -0,0 +1,115 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of package and compressed file. + /// + public static class Packages + { + /// + /// The MIME content type of Windows application program package. + /// + public const string Application = "application/x-ms-application"; + + /// + /// The MIME content type of ISO 9660 (disc image). + /// + public const string Iso = "application/x-iso9660-image"; + + /// + /// The MIME content type of Microsoft file required downloading. + /// + public const string DownloadToRun = "application/x-msdownload"; + + /// + /// The MIME content type of Windows App package. + /// + public const string Appx = "application/appx"; + + /// + /// The MIME content type of Windows App bundle package. + /// + public const string AppxBundle = "application/appxbundle"; + + /// + /// The MIME content type of Windows App installer. + /// + public const string AppInstaller = "application/appinstaller"; + + /// + /// The MIME content type of Microsoft Installer. + /// + public const string Msix = "application/msix"; + + /// + /// The MIME content type of Microsoft Installer bundler. + /// + public const string MsixBundle = "application/msixbundle"; + + /// + /// The MIME content type of Android App Package. + /// + public const string Apk = "application/vnd.android.package-archive"; + + /// + /// The MIME content type of object. + /// + public const string O = "application/x-object"; + + /// + /// The MIME content type of object. + /// + public const string Obj = "application/x-tgif"; + + /// + /// The MIME content type of Zip. + /// + public const string Zip = "application/zip"; + + /// + /// The MIME content type of 7z. + /// + public const string SevenZip = "application/x-7z-compressed"; + + /// + /// The MIME content type of cab. + /// + public const string Cab = "application/vnd.ms-cab-compressed"; + + /// + /// The MIME content type of WinRAR. + /// + public const string Rar = "application/x-rar-compressed"; + + /// + /// The MIME content type of Tape Archive. + /// + public const string Tar = "application/tar"; + + /// + /// The MIME content type of GNU Zip. + /// + public const string Gz = "application/gzip"; + + /// + /// The MIME content type of brotli. + /// + public const string Brotli = "application/brotli"; + + /// + /// The MIME content type of Tape Archive on GNU Zip. + /// + public const string Tgz = "application/tar+gzip"; + + /// + /// The MIME content type of z compress file. + /// + public const string Z = "application/x-compress"; + } +} diff --git a/Messages/Web/Registry.cs b/Messages/Web/Registry.cs new file mode 100644 index 00000000..90318086 --- /dev/null +++ b/Messages/Web/Registry.cs @@ -0,0 +1,242 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Security; + +using Trivial.Data; +using Trivial.IO; + +using Reg = Microsoft.Win32.Registry; +using RegistryKey = Microsoft.Win32.RegistryKey; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The Windows Registry access. + /// +#if NET6_0_OR_GREATER +[System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif + public static class Registry + { + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The MIME content type. + public static string GetByFileExtension(FileInfo file) + => GetByFileExtension(file?.Extension, StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The default MIME content type. + /// The MIME content type. + public static string GetByFileExtension(FileInfo file, string defaultMime) + => GetByFileExtension(file?.Extension, defaultMime); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The MIME content type. + public static string GetByFileExtension(LocalFileReferenceInfo file) + => GetByFileExtension(file?.Extension, StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file information. + /// The default MIME content type. + /// The MIME content type. + public static string GetByFileExtension(LocalFileReferenceInfo file, string defaultMime) + => GetByFileExtension(file?.Extension, defaultMime); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension) + => GetByFileExtension(fileExtension, StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// true if returns null if not supported; otherwise, false. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension, bool returnNullIfUnsupported) + => GetByFileExtension(fileExtension, returnNullIfUnsupported ? null : StreamMIME); + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension. + /// The default MIME content type. + /// The MIME content type. + public static string GetByFileExtension(string fileExtension, string defaultMime) + { + using var regKey = GetRegistryKeyByFileExtension(fileExtension, true); + return RegistryUtility.TryGetStringValue(regKey, "Content Type", defaultMime); + } + + /// + /// Registers file extension mapping. + /// + /// The file information. + /// true if override the existed one; otherwise, false. + /// true if registers succeeded; otherwise, false. + public static bool RegisterFileExtensionMapping(FileInfo file, bool overrideIfExist = false) + => RegisterFileExtensionMapping(file?.Extension, overrideIfExist); + + /// + /// Registers file extension mapping. + /// + /// The file extension to register. + /// true if override the existed one; otherwise, false. + /// true if registers succeeded; otherwise, false. + public static bool RegisterFileExtensionMapping(string fileExtension, bool overrideIfExist = false) + { + if (!overrideIfExist && FileExtensionMapping.ContainsKey(fileExtension)) return false; + var r = GetRegistryKeyByFileExtension(fileExtension, false); + string v; + if (r != null) + { + v = RegistryUtility.TryGetStringValue(r, "Content Type"); + if (string.IsNullOrWhiteSpace(v)) return false; + return FileExtensionMapping.Set(fileExtension, v, overrideIfExist); + } + + if (fileExtension.IndexOf('/') < 1) return false; + v = fileExtension; + using var mime = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, "MIME\\Database\\Content Type\\" + fileExtension); + fileExtension = RegistryUtility.TryGetStringValue(mime, "Extension"); + return FileExtensionMapping.Set(fileExtension, v, overrideIfExist); + } + + /// + /// Gets the file association information. + /// + /// The file information. + /// The file association information; or null, if not found or failure. + public static FileAssociationInfo GetFileAssociationInfo(FileInfo file) + => GetFileAssociationInfo(file?.Extension); + + /// + /// Gets the file association information. + /// + /// The file information. + /// The file association information; or null, if not found or failure. + public static FileAssociationInfo GetFileAssociationInfo(LocalFileReferenceInfo file) + => GetFileAssociationInfo(file?.Extension); + + /// + /// Gets the file association information. + /// + /// The file extension part. + /// The file association information; or null, if not found or failure. + public static FileAssociationInfo GetFileAssociationInfo(string fileExtension) + { + fileExtension = fileExtension?.Trim()?.ToLowerInvariant(); + if (string.IsNullOrEmpty(fileExtension)) return null; + var info = new FileAssociationInfo + { + FileExtension = fileExtension + }; + using var ext = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, fileExtension); + string h; + if (ext == null) + { + if (fileExtension.IndexOf('/') < 1) return info; + using var mime = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, "MIME\\Database\\Content Type\\" + fileExtension); + if (mime == null) return info; + info.ContentType = fileExtension; + fileExtension = RegistryUtility.TryGetStringValue(mime, "Extension"); + info.FileExtension = fileExtension; + using var ext2 = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, fileExtension); + if (ext2 == null) return info; + h = RegistryUtility.TryGetStringValue(ext2, null); + } + else + { + info.ContentType = RegistryUtility.TryGetStringValue(ext, "Content Type"); + h = RegistryUtility.TryGetStringValue(ext, null); + } + + if (string.IsNullOrEmpty(h)) + { + using var ext2 = RegistryUtility.TryOpenSubKey(ext, "OpenWithProgids"); + if (ext2 == null) return info; + h = RegistryUtility.TryGetValueNames(ext2).FirstOrDefault(ele => !string.IsNullOrWhiteSpace(ele)); + if (string.IsNullOrEmpty(h)) return info; + } + + using var assoc = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, h); + if (assoc == null) return info; + info.Name = RegistryUtility.TryGetStringValue(assoc, null) ?? RegistryUtility.TryGetStringValue(assoc, "FriendlyTypeName"); + using var icon = RegistryUtility.TryOpenSubKey(assoc, "DefaultIcon"); + if (icon != null) info.Icon = RegistryUtility.TryGetStringValue(icon, null); + using var shell = RegistryUtility.TryOpenSubKey(assoc, "shell"); + if (shell == null) return info; + var defaultCommand = RegistryUtility.TryGetStringValue(shell, null); + var commands = RegistryUtility.TryOpenSubKeys(shell)?.ToList(); + if (commands.Count < 1) return info; + foreach (var command in commands) + { + var name = command.Name; + var pos = name?.LastIndexOf('\\') ?? -1; + if (pos >= 0) name = name.Substring(pos + 1); + var cmd = new FileOpenCommandInfo + { + Key = name, + Name = RegistryUtility.TryGetStringValue(command, null) + }; + var exe = RegistryUtility.TryOpenSubKey(command, "command"); + if (exe == null) continue; + var c = RegistryUtility.TryGetStringValue(exe, null); + if (string.IsNullOrWhiteSpace(c)) continue; + cmd.Command = c; + info.Commands.Add(cmd); + } + + if (!string.IsNullOrWhiteSpace(defaultCommand)) + { + info.DefaultCommand = info.Commands.FirstOrDefault(ele => defaultCommand.Equals(ele.Key, StringComparison.OrdinalIgnoreCase)); + } + + if (info.DefaultCommand == null) info.DefaultCommand = info.Commands.FirstOrDefault(); + return info; + } + + /// + /// Gets the MIME content type by file extension part. + /// + /// The file extension part. + /// true if throw an argument exception if the file extension is null or empty; otherwise, false. + /// The registry key. + /// fileExtension was null. + /// fileExtension was empty. + private static RegistryKey GetRegistryKeyByFileExtension(string fileExtension, bool throwExceptionForNullOrEmpty) + { + if (fileExtension == null && throwExceptionForNullOrEmpty) throw new ArgumentNullException(nameof(fileExtension), "fileExtension should not be null."); + fileExtension = fileExtension.Trim().ToLowerInvariant(); + if (fileExtension.Length < 1) + { + if (throwExceptionForNullOrEmpty) + throw new ArgumentException("fileExtension should not be empty.", nameof(fileExtension)); + return null; + } + + var r = RegistryUtility.TryOpenSubKey(Reg.ClassesRoot, fileExtension); + return r; + } + } +} diff --git a/Messages/Web/TextMimeConstants.cs b/Messages/Web/TextMimeConstants.cs new file mode 100644 index 00000000..5bebf194 --- /dev/null +++ b/Messages/Web/TextMimeConstants.cs @@ -0,0 +1,95 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of text and fonts. + /// + public static class Text + { + /// + /// The MIME content type of plain text. + /// + public const string Plain = "text/plain"; + + /// + /// The MIME content type of rich text. + /// + public const string Rtf = "text/richtext"; + + /// + /// The MIME content type of comma-separated values. + /// + public const string Csv = "text/csv"; + + /// + /// The MIME content type of tab-separated values. + /// + public const string Tsv = "text/tsv"; + + /// + /// The MIME content type of vCard (Versitcard). + /// + public const string VCard = "text/x-vcard"; + + /// + /// The MIME content type of diff and patch. + /// + public const string Diff = "text/x-diff"; + + /// + /// The MIME content type of markdown. + /// + public const string Markdown = "text/markdown"; + + /// + /// The MIME content type of math markup. + /// + public const string Math = "text/mathml"; + + /// + /// The MIME content type of Standard Generalized Markup Language. + /// + public const string Sgml = "text/sgml"; + + /// + /// The MIME content type of ink markup. + /// + public const string Ink = "application/inkml+xml"; + + /// + /// The MIME content type of iCalendar. + /// + public const string Calendar = "text/calendar"; + + /// + /// The MIME content type of Microsoft Embedded Open Type. + /// + public const string Eot = "application/vnd.ms-fontobject"; + + /// + /// The MIME content type of TrueType Font. + /// + public const string TrueType = "font/ttf"; + + /// + /// The MIME content type of OpenType Layout Font. + /// + public const string OpenType = "font/otf"; + + /// + /// The MIME content type of Web Open Font Format. + /// + public const string Woff = "font/woff"; + + /// + /// The MIME content type of Web Open Font Format 2. + /// + public const string Woff2 = "font/woff2"; + } +} diff --git a/Messages/Web/VideoMimeConstants.cs b/Messages/Web/VideoMimeConstants.cs new file mode 100644 index 00000000..62bd990c --- /dev/null +++ b/Messages/Web/VideoMimeConstants.cs @@ -0,0 +1,115 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of video. + /// + public static class Videos + { + /// + /// The MIME content type of Audio Video Interleaved. + /// + public const string Avi = "video/x-msvideo"; + + /// + /// The MIME content type of H.264 (Advanced Video Coding). + /// + public const string Avc = "video/h264"; + + /// + /// The MIME content type of H.265 (High Efficiency Video Coding). + /// + public const string Hevc = "video/h265"; + + /// + /// The MIME content type of H.266 (Versatile Video Coding). + /// + public const string Vvc = "video/h266"; + + /// + /// The MIME content type of H.267. + /// + public const string H267 = "video/h267"; + + /// + /// The MIME content type of H.268. + /// + public const string H268 = "video/h268"; + + /// + /// The MIME content type of AV1, a video format by Alliance of Open Media. + /// + public const string Av1 = "video/av1"; + + /// + /// The MIME content type of AV2, a video format by Alliance of Open Media. + /// + public const string Av2 = "video/av2"; + + /// + /// The MIME content type of AV3, a video format by Alliance of Open Media. + /// + public const string Av3 = "video/av3"; + + /// + /// The MIME content type of AVS3. + /// + public const string Avs3 = "video/avs3"; + + /// + /// The MIME content type of AVS4. + /// + public const string Avs4 = "video/avs4"; + + /// + /// The MIME content type of JPEG Video. + /// + public const string Jpgv = "video/jpeg"; + + /// + /// The MIME content type of MPEG-4. + /// + public const string Mp4 = "video/mp4"; + + /// + /// The MIME content type of Moving Picture Experts Group. + /// + public const string Mpeg = "video/mpeg"; + + /// + /// The MIME content type of QuickTime (mov). + /// + public const string QuickTime = "video/quicktime"; + + /// + /// The MIME content type of WebM (by Google). + /// + public const string Webm = "video/webm"; + + /// + /// The MIME content type of Matroska. + /// + public const string Matroska = "video/x-matroska"; + + /// + /// The MIME content type of Windows Media Video. + /// + public const string Wmv = "video/x-ms-wm"; + + /// + /// The MIME content type of Advanced Streaming Format. + /// + public const string Asf = "video/x-ms-asf"; + + /// + /// The MIME content type of Windows Media Video. + /// + public const string Wmx = "video/x-ms-wmx"; + } +} diff --git a/Messages/Web/WebMimeConstants.cs b/Messages/Web/WebMimeConstants.cs new file mode 100644 index 00000000..844e3147 --- /dev/null +++ b/Messages/Web/WebMimeConstants.cs @@ -0,0 +1,95 @@ +using System; + +namespace Trivial.Web; + +/// +/// The MIME constants. +/// +public static partial class MimeConstants +{ + /// + /// The popular MIME constants of web content. + /// + public static class Web + { + /// + /// The MIME content type of Cascading Style Sheets. + /// + public const string Css = "text/css"; + + /// + /// The MIME content type of Syntactically Awesome Style Sheets. + /// + public const string Sass = "text/x-sass"; + + /// + /// The MIME content type of Sassy Cascaded Style Sheets. + /// + public const string Scss = "text/x-scss"; + + /// + /// The MIME content type of Leaner CSS. + /// + public const string Less = "text/x-less"; + + /// + /// The MIME content type of Document Type Definition. + /// + public const string Dtd = "application/xml-dtd"; + + /// + /// The MIME content type of ECMA Script. + /// + public const string Ecma = "application/ecmascript"; + + /// + /// The MIME content type of JavaScript. + /// + public const string Js = "application/javascript"; + + /// + /// The MIME content type of VB Script. + /// + public const string Vbs = "text/vbscript"; + + /// + /// The MIME content type of VB Script. + /// + public const string Dart = "application/vnd.dart"; + + /// + /// The MIME content type of web assembly. + /// + public const string Wasm = "application/wasm"; + + /// + /// The MIME content type of HTML (Hypertext Markup Language). + /// + public const string Html = "text/html"; + + /// + /// The MIME content type of JSON (JavaScript Object Notation). + /// + public const string Json = "application/json"; + + /// + /// The MIME content type of JSON lines. + /// + public const string Jsonl = "application/jsonl"; + + /// + /// The MIME content type of YAML (YAML Ain't Markup Language). + /// + public const string Yaml = "application/x-yaml"; + + /// + /// The MIME content type of Extensible Markup Language. + /// + public const string Xml = "application/xml"; + + /// + /// The MIME content type of Uniform Resource Identifier list. + /// + public const string Uri = "text/uri-list"; + } +} diff --git a/Trivial.sln b/Trivial.sln index 9b281991..555fe877 100644 --- a/Trivial.sln +++ b/Trivial.sln @@ -6,6 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0F8ADD5A-FE92-432F-8387-1D410D61F7FA}" ProjectSection(SolutionItems) = preProject azure-pipelines.yml = azure-pipelines.yml + Basic.props = Basic.props CONTRIBUTING.md = CONTRIBUTING.md LICENSE = LICENSE README.md = README.md @@ -17,17 +18,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{C1155112-852C-414B-A7B2-591C7EEFECE6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Console", "Console\Console.csproj", "{B090E686-8BA7-4F78-BA09-318B1A7F33F6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "Web\Web.csproj", "{08C799A5-47DF-4C53-8C78-E8F7DCF0F53F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chemistry", "Chemistry\Chemistry.csproj", "{CACBF47E-5253-4981-84E4-B38955DEC21B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mime", "Mime\Mime.csproj", "{8C8EAF77-6182-4F04-87AA-1700FC00100D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Maths", "Maths\Maths.csproj", "{E12513EB-B244-46F9-9D52-49EDD297A95A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Messages", "Messages\Messages.csproj", "{424341F2-7CE8-4BF7-B788-0B2C52D31D94}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Messages", "Messages\Messages.csproj", "{424341F2-7CE8-4BF7-B788-0B2C52D31D94}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -43,26 +36,10 @@ Global {C1155112-852C-414B-A7B2-591C7EEFECE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {C1155112-852C-414B-A7B2-591C7EEFECE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {C1155112-852C-414B-A7B2-591C7EEFECE6}.Release|Any CPU.Build.0 = Release|Any CPU - {B090E686-8BA7-4F78-BA09-318B1A7F33F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B090E686-8BA7-4F78-BA09-318B1A7F33F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B090E686-8BA7-4F78-BA09-318B1A7F33F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B090E686-8BA7-4F78-BA09-318B1A7F33F6}.Release|Any CPU.Build.0 = Release|Any CPU - {08C799A5-47DF-4C53-8C78-E8F7DCF0F53F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08C799A5-47DF-4C53-8C78-E8F7DCF0F53F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08C799A5-47DF-4C53-8C78-E8F7DCF0F53F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08C799A5-47DF-4C53-8C78-E8F7DCF0F53F}.Release|Any CPU.Build.0 = Release|Any CPU - {CACBF47E-5253-4981-84E4-B38955DEC21B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CACBF47E-5253-4981-84E4-B38955DEC21B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CACBF47E-5253-4981-84E4-B38955DEC21B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CACBF47E-5253-4981-84E4-B38955DEC21B}.Release|Any CPU.Build.0 = Release|Any CPU {8C8EAF77-6182-4F04-87AA-1700FC00100D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C8EAF77-6182-4F04-87AA-1700FC00100D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C8EAF77-6182-4F04-87AA-1700FC00100D}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C8EAF77-6182-4F04-87AA-1700FC00100D}.Release|Any CPU.Build.0 = Release|Any CPU - {E12513EB-B244-46F9-9D52-49EDD297A95A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E12513EB-B244-46F9-9D52-49EDD297A95A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E12513EB-B244-46F9-9D52-49EDD297A95A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E12513EB-B244-46F9-9D52-49EDD297A95A}.Release|Any CPU.Build.0 = Release|Any CPU {424341F2-7CE8-4BF7-B788-0B2C52D31D94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {424341F2-7CE8-4BF7-B788-0B2C52D31D94}.Debug|Any CPU.Build.0 = Debug|Any CPU {424341F2-7CE8-4BF7-B788-0B2C52D31D94}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/UnitTest/Chemistry/ElementTest.cs b/UnitTest/Chemistry/ElementTest.cs deleted file mode 100644 index 6db933cd..00000000 --- a/UnitTest/Chemistry/ElementTest.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Trivial.Text; - -namespace Trivial.Chemistry -{ - /// - /// Chemical element unit tests. - /// - [TestClass] - public class ElementTest - { - /// - /// Tests the chemical element, isotope and periodic table. - /// - [TestMethod] - public void TestElement() - { - Assert.IsNull(ChemicalElement.Get(0)); - Assert.IsNull(ChemicalElement.Get(-1)); - Assert.IsNull(ChemicalElement.Get("Nothing")); - Assert.IsFalse(new ChemicalElement(-1, null, "Nothing", true).IsValid()); - Assert.IsFalse(ChemicalElement.IsValid("Nothing")); - - var h = ChemicalElement.Get(1); - Assert.IsTrue(h.IsValid()); - Assert.AreEqual(1, h.AtomicNumber); - Assert.AreEqual("H", h.Symbol); - Assert.AreEqual("Hydrogen", h.EnglishName); - Assert.AreEqual(1, h.Period); - Assert.AreEqual(1, h.Group); - Assert.AreEqual(0, h.IndexInPeriod); - Assert.AreEqual("s", h.Block); - Assert.AreEqual(h, ChemicalElement.Get("H")); - Assert.AreEqual(h, ChemicalElement.H); - Assert.AreEqual(h, new ChemicalElement(1, "H", "No.1", true)); - Assert.IsTrue(h.HasAtomicWeight); - Assert.IsTrue(h.AtomicWeight >= 1); - Assert.IsTrue(h.ToString().Contains(h.Symbol)); - Assert.IsTrue(h.IsNonMetallic); - Assert.IsFalse(h.IsAlkaliMetal); - Assert.IsFalse(h.IsAlkalineEarthMetal); - Assert.IsFalse(h.IsChalcogen); - Assert.IsFalse(h.IsHalogen); - Assert.IsFalse(h.IsInBoronGroup); - Assert.IsFalse(h.IsInCarbonGroup); - Assert.IsFalse(h.IsInNitrogenGroup); - Assert.IsFalse(h.IsInVIII); - Assert.IsFalse(h.IsMetal); - Assert.IsFalse(h.IsNoble); - Assert.IsFalse(h.IsTransition); - Assert.IsFalse(h.IsRadioelement()); - Assert.AreEqual("H", ((JsonObjectNode)h).TryGetStringValue("symbol")); - var d = h.Isotope(2); - Assert.AreEqual("D", d.ToString()); - Assert.AreEqual(h, d.Element); - Assert.AreEqual(1, d.AtomicNumber); - Assert.AreEqual(2, d.AtomicMassNumber); - Assert.AreEqual(1, d.Neutrons); - Assert.IsTrue(d.HasAtomicWeight); - Assert.AreEqual(d, new Isotope(h, 2)); - Assert.IsFalse(h.Isotope(10).HasAtomicWeight); - - var c = ChemicalElement.Get(6); - Assert.IsTrue(c.IsValid()); - Assert.IsFalse(c == h); - Assert.IsTrue(c != h); - Assert.IsTrue(c > h); - Assert.IsTrue(c >= h); - Assert.IsFalse(c < h); - Assert.IsFalse(c <= h); - Assert.AreNotEqual(h, c); - Assert.AreEqual(6, c.AtomicNumber); - Assert.AreEqual("C", c.Symbol); - Assert.AreEqual("Carbon", c.EnglishName); - Assert.AreEqual(2, c.Period); - Assert.AreEqual(14, c.Group); - Assert.AreEqual(3, c.IndexInPeriod); - Assert.AreEqual("p", c.Block); - Assert.AreEqual(c, ChemicalElement.Get("C")); - Assert.AreEqual(c, ChemicalElement.C); - Assert.AreEqual(c, new ChemicalElement(6, "C", "No.6", true)); - Assert.IsTrue(c.HasAtomicWeight); - Assert.IsTrue(c.AtomicWeight >= 12); - Assert.IsTrue(c.ToString().Contains(c.Symbol)); - Assert.AreEqual(6, ((JsonObjectNode)c).TryGetInt32Value("number")); - var c12 = c.Isotope(12); - Assert.AreNotEqual(d, c12); - Assert.AreEqual(3, c12.ToString().Length); - Assert.IsTrue(c12.ToString().EndsWith("C")); - Assert.AreEqual(c, c12.Element); - Assert.AreEqual(6, c12.AtomicNumber); - Assert.AreEqual(12, c12.AtomicMassNumber); - Assert.AreEqual(6, c12.Neutrons); - Assert.IsTrue(c12.HasAtomicWeight); - Assert.AreEqual(12, c12.AtomicWeight); - Assert.AreEqual(c12, new Isotope(6, 12)); - - var count = 0; - foreach (var prop in typeof(ChemicalElement).GetProperties(BindingFlags.Static | BindingFlags.Public)) - { - if (!prop.CanRead || prop.PropertyType != typeof(ChemicalElement)) continue; - var ele = (ChemicalElement)prop.GetValue(null); - Assert.IsNotNull(ele); - Assert.AreEqual(prop.Name, ele.Symbol); - Assert.AreEqual(ele, ChemicalElement.Get(ele.AtomicNumber)); - Assert.AreEqual(ele, ChemicalElement.Get(ele.Symbol)); - Assert.IsFalse(string.IsNullOrWhiteSpace(ele.Name)); - count++; - } - - Assert.IsTrue(count >= 118); - var usn = ChemicalElement.Get(170); - Assert.AreNotEqual(h, usn); - Assert.AreNotEqual(c, usn); - Assert.AreEqual("Usn", usn.Symbol); - Assert.AreEqual("Unseptnilium", usn.EnglishName); - Assert.AreEqual(9, usn.Period); - Assert.AreEqual(2, usn.Group); - Assert.AreEqual(1, usn.IndexInPeriod); - Assert.AreEqual("s", usn.Block); - Assert.AreEqual(usn, ChemicalElement.Get("Usn")); - Assert.IsFalse(usn.HasAtomicWeight); - Assert.IsTrue(double.IsNaN(usn.AtomicWeight)); - Assert.IsTrue(usn.ToString().Contains(usn.Symbol)); - - var bbb = ChemicalElement.Get(222); - Assert.AreEqual("Bbb", bbb.Symbol); - Assert.AreEqual("i", bbb.Block); - - var one = new ChemicalElement(17, "Seventeen", "A new sample element", true); - Assert.IsTrue(one.IsValid()); - Assert.AreNotEqual(ChemicalElement.Get(17), one); - } - - /// - /// Tests molecular formula. - /// - [TestMethod] - public void TestMolecularFormula() - { - var s = "NonExist"; - Assert.IsNull(MolecularFormula.TryParse(s)); - - s = "H2CO3"; - var m = MolecularFormula.Parse(s); - Assert.AreEqual(s.Length, m.ToString().Length); - s = m.ToString(); - Assert.IsTrue(s.Contains("CO")); - Assert.AreEqual(6, m.Count); - Assert.AreEqual(0, m.IndexOf("H")); - Assert.AreEqual(-1, m.IndexOf("H", 2)); - Assert.AreEqual(1, m.IndexOf(ChemicalElement.C)); - Assert.AreEqual(1, m.IndexOf(ChemicalElement.C, 1)); - Assert.AreEqual(1, m.GetCount("C")); - Assert.AreEqual(3, m.GetCount(ChemicalElement.O)); - Assert.IsFalse(m.IsIon); - m = MolecularFormula.Parse(s); - Assert.AreEqual(s, m.ToString()); - Assert.AreEqual(6, m.Count); - m = new MolecularFormula(m.Items); - Assert.AreEqual(s, m.ToString()); - - s = "SO₄²ˉ"; - m = MolecularFormula.Parse(s); - Assert.AreEqual(s, m.ToString()); - Assert.IsTrue(m.IsIon); - Assert.AreEqual(-2, m.ChargeNumber); - - m = MolecularFormula.Parse("R-COOH"); - Assert.AreEqual(2, m.GetCount(ChemicalElement.C)); - Assert.AreEqual(2, m.GetCount(ChemicalElement.O)); - Assert.AreEqual(4, m.GetCount(ChemicalElement.H)); - - m = ChemicalElement.Fe * 2 + 3 * ChemicalElement.O; - Assert.AreEqual(2, m.GetCount("Fe")); - Assert.AreEqual(3, m.GetCount(ChemicalElement.O)); - m = ChemicalElement.C + ChemicalElement.O; - Assert.AreEqual(1, m.GetCount("C")); - Assert.AreEqual(1, m.GetCount(ChemicalElement.O)); - m += ChemicalElement.O; - Assert.AreEqual(1, m.GetCount("C")); - Assert.AreEqual(2, m.GetCount(ChemicalElement.O)); - m = ChemicalElement.H + m; - Assert.AreEqual(1, m.GetCount("H")); - Assert.AreEqual(4, m.Count); - - m = ChemicalElement.H * 2 + ChemicalElement.O; - var col = new List - { - { m, 2, ChemicalElement.Na } - }; - Assert.AreEqual(3, col.Count); - Console.WriteLine(MolecularFormula.ToString(col)); - Assert.IsTrue(MolecularFormula.ToString(col).Length > 6); - col.RemoveAt(2); - Assert.IsTrue(MolecularFormula.ConservationOfMass( - new List - { - 4 * ChemicalElement.H, - ChemicalElement.O * 2 - }, - col)); - Assert.IsFalse(MolecularFormula.ConservationOfMass( - new List - { - ChemicalElement.C + ChemicalElement.O * 2 - }, - new List - { - ChemicalElement.Na, - ChemicalElement.Cl - })); - Assert.IsFalse(MolecularFormula.ConservationOfMass( - new List - { - new MolecularFormula(new List - { - new MolecularFormula.Item(ChemicalElement.Cl) - }, -1) - }, - new List - { - new MolecularFormula(ChemicalElement.Cl) - })); - } - - /// - /// Tests molecular formula. - /// - [TestMethod] - public void TestSerialization() - { - var s = "{ \"e\": 6 }"; - var m = JsonSerializer.Deserialize(s).Element; - Assert.AreEqual(ChemicalElement.C, m); - - s = "{ \"e\": \"C\" }"; - m = JsonSerializer.Deserialize(s).Element; - Assert.AreEqual(ChemicalElement.C, m); - - s = "{ \"e\": { \"symbol\": \"C\" } }"; - m = JsonSerializer.Deserialize(s).Element; - Assert.AreEqual(ChemicalElement.C, m); - - s = "{ \"e\": { \"number\": 6 } }"; - m = JsonSerializer.Deserialize(s).Element; - Assert.AreEqual(ChemicalElement.C, m); - - s = "{ \"e\": { \"symbol\": \"C\", \"number\": 6 } }"; - m = JsonSerializer.Deserialize(s).Element; - Assert.AreEqual(ChemicalElement.C, m); - - s = "{ \"e\": { \"symbol\": \"H\", \"number\": 11 } }"; - m = JsonSerializer.Deserialize(s).Element; - Assert.AreNotEqual(ChemicalElement.H, m); - Assert.AreNotEqual(ChemicalElement.Na, m); - Assert.AreEqual("H", m.Symbol); - Assert.AreEqual(11, m.AtomicNumber); - } - } - - class Model - { - [JsonPropertyName("e")] - public ChemicalElement Element { get; set; } - } -} diff --git a/UnitTest/CommandLine/Program.cs b/UnitTest/CommandLine/Program.cs index b0626581..cde5380d 100644 --- a/UnitTest/CommandLine/Program.cs +++ b/UnitTest/CommandLine/Program.cs @@ -23,9 +23,6 @@ static Task Main(string[] args) dispatcher.Register("http"); dispatcher.Register("retry"); dispatcher.Register("csv"); - dispatcher.Register("chemistry"); - dispatcher.Register("select"); - dispatcher.Register("barcode"); return dispatcher.ProcessAsync(); } diff --git a/UnitTest/CommandLine/SelectionVerb.cs b/UnitTest/CommandLine/SelectionVerb.cs deleted file mode 100644 index e5b77389..00000000 --- a/UnitTest/CommandLine/SelectionVerb.cs +++ /dev/null @@ -1,373 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using Trivial.Collection; -using Trivial.Text; - -namespace Trivial.CommandLine; - -class SelectionVerb : BaseCommandVerb -{ - private static List blendColors; - private static List baseColors; - private static List saturateColors; - - public static string Description => "Selection"; - - /// - protected override async Task OnProcessAsync(CancellationToken cancellationToken = default) - { - await RunAsync(null, cancellationToken); - var cli = StyleConsole.Default; - var col = new SelectionData(); - col.Add('a', "Aaa", null); - col.Add('b', "Bbb 二号"); - col.Add('p', "Password"); - col.Add('l', "Progress"); - col.Add('j', "JSON"); - col.Add('e', "Error"); - col.Add('?', "Help", null); - for (var i = 0; i < 16; i++) - { - var mix = (Drawing.ColorMixTypes)i; - col.Add(mix.ToString(), mix); - } - - col.Add("Saturate"); - col.Add("Brightness"); - col.Add("Invert"); - for (var i = 0; i < 120; i++) - { - col.Add(i.ToString()); - } - - var result = cli.Select(col, new SelectionConsoleOptions - { - SelectedBackgroundConsoleColor = ConsoleColor.Cyan, - SelectedForegroundConsoleColor = ConsoleColor.Black, - TipsForegroundConsoleColor = ConsoleColor.Yellow, - SelectedPrefix = "→ ", - Column = 5, - MaxRow = 10, - ManualQuestion = "Type: " - }); - if (result.IsCanceled) - { - cli.WriteLine("The operation is cancelled."); - return; - } - - if (result.IsNotSupported) - { - cli.WriteLine("The selection control is not supported."); - return; - } - - cli.WriteLine("-> {0}\t{1}", result.Value, result.InputType); - switch ((result.Title ?? result.Value)?.ToLowerInvariant()) - { - case "aaa": - case "bbb": - cli.WriteLine(result.Value + '\t' + result.Title + '\t' + result.InputType); - return; - case "password": - cli.Write("Type password: "); - var p = cli.ReadPassword(ConsoleColor.Yellow, '*'); - cli.Write("Your password is "); - cli.Write(ConsoleColor.Magenta, Security.SecureStringExtensions.ToUnsecureString(p)); - cli.WriteLine('.'); - return; - case "progress": - await ShowProgressAsync(); - return; - case "json": - cli.WriteLine(JsonUnitTest.CreateModel(DateTime.Now)); - return; - case "error": - cli.WriteLine(new InvalidOperationException("Test", new NotSupportedException())); - break; - case "saturate": - InitColors(); - for (var i = 0; i < 11; i++) - { - var percent = i * 0.2; - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.Saturate(item, percent), "■"); - } - - cli.WriteLine(percent.ToString("0%")); - } - - for (var i = 0; i < 7; i++) - { - var saturate = (Drawing.RelativeSaturationLevels)i; - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.Saturate(item, saturate), "■"); - } - - cli.WriteLine(saturate.ToString()); - } - - break; - case "brightness": - InitColors(); - for (var i = -4; i < 5; i++) - { - var percent = i * 0.2; - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.Lighten(item, percent), "■"); - } - - cli.WriteLine(percent.ToString("0%")); - } - - for (var i = 0; i < 7; i++) - { - var brightness = (Drawing.RelativeBrightnessLevels)i; - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.ToggleBrightness(item, brightness), "■"); - } - - cli.WriteLine(brightness.ToString()); - } - - break; - case "invert": - InitColors(); - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.Invert(item), "■"); - } - - cli.WriteLine("Invert"); - for (var i = 0; i < 6; i++) - { - var percent = i * 0.2; - foreach (var item in saturateColors) - { - cli.Write(Drawing.ColorCalculator.Invert(item, percent), "■"); - } - - cli.WriteLine(percent.ToString("0%")); - } - - break; - case "help": - case "?": - cli.WriteLine("This is a sample."); - return; - } - - if (result.Data is Drawing.ColorMixTypes mixType) - { - InitColors(); - cli.Write("Blend"); - foreach (var item in blendColors) - { - cli.Write(item, "■"); - } - - cli.WriteLine(); - cli.Write("Base "); - foreach (var item in baseColors) - { - cli.Write(item, "■"); - } - - cli.WriteLine(); - cli.Write("Mixed"); - var colors = Drawing.ColorCalculator.Mix(mixType, blendColors, baseColors); - foreach (var item in colors) - { - cli.Write(item, "■"); - } - } - } - - public static async Task ShowProgressAsync() - { - var cli = StyleConsole.Default; - var progress = cli.WriteLine(new ConsoleProgressStyle - { - Kind = ConsoleProgressStyle.Kinds.AngleBracket, - BarConsoleColor = ConsoleColor.White, - BackgroundConsoleColor = ConsoleColor.DarkBlue - }, "Running 1:"); - cli.WriteLine("And another one..."); - var progress2 = cli.WriteLine(new ConsoleProgressStyle(), "Running 2:"); - for (var i = 0; i <= 50; i++) - { - await Task.Delay(10); - progress.Report(0.02 * i); - progress2.Report(0.03 * i); - if (cli.Mode == StyleConsole.Modes.Text) continue; - cli.BackspaceToBeginning(); - cli.WriteImmediately("Update to {0} (total 50).", i); - } - - cli.WriteLine(" And following is failed."); - progress = cli.WriteLine(new ConsoleProgressStyle(), "Running 3:"); - await progress.IncreaseAsync(null, 0.02, 0.6, 10); - progress.Fail(); - } - - private static void InitColors() - { - if (blendColors == null) - blendColors = new List - { - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x80, 0x80, 0x80), - Color.FromArgb(0xFF, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0), - Color.FromArgb(0x80, 0x80, 0x80), - Color.FromArgb(0xFF, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - }; - if (baseColors == null) - baseColors = new List - { - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0xFF, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0), - Color.FromArgb(0x80, 0x80, 0x80), - Color.FromArgb(0, 0, 0), - Color.FromArgb(0x80, 0x80, 0x80), - Color.FromArgb(0xFF, 0xFF, 0xFF), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - }; - if (saturateColors == null) - saturateColors = new List - { - Color.FromArgb(0xFF, 0, 0), - Color.FromArgb(0xFF, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0), - Color.FromArgb(0, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0xFF), - Color.FromArgb(0xFF, 0, 0xFF), - Color.FromArgb(0x99, 0x66, 0x66), - Color.FromArgb(0x99, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x66), - Color.FromArgb(0x66, 0x99, 0x99), - Color.FromArgb(0x66, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x99), - Color.FromArgb(0x99, 0x66, 0x33), - Color.FromArgb(0x33, 0x99, 0x66), - Color.FromArgb(0x66, 0x33, 0x99), - Color.FromArgb(0x99, 0x33, 0x66), - Color.FromArgb(0x66, 0x99, 0x33), - Color.FromArgb(0x33, 0x66, 0x99), - Color.FromArgb(0xFF, 0x99, 0x99), - Color.FromArgb(0x99, 0xFF, 0x99), - Color.FromArgb(0x99, 0x99, 0xFF), - Color.FromArgb(0x66, 0, 0), - Color.FromArgb(0, 0x66, 0), - Color.FromArgb(0, 0, 0x66), - Color.FromArgb(0x80, 0x80, 0x80), - Color.FromArgb(0xFF, 0xFF, 0xFF), - Color.FromArgb(0, 0, 0) - }; - } -} diff --git a/UnitTest/Data/BarcodeUnitTest.cs b/UnitTest/Data/BarcodeUnitTest.cs deleted file mode 100644 index 8326dd99..00000000 --- a/UnitTest/Data/BarcodeUnitTest.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Trivial.Collection; -using Trivial.CommandLine; - -namespace Trivial.Data -{ - /// - /// The unit test for barcode. - /// - [TestClass] - public class BarcodeUnitTest - { - /// - /// Tests International Article Number parser. - /// - [TestMethod] - public void TestEan() - { - Assert.IsFalse(InternationalArticleNumber.Validate("abcdefg")); - Assert.IsFalse(InternationalArticleNumber.Validate("4003994155480")); - - // EAN-13 - var ean = InternationalArticleNumber.Create("400399415548"); - var bin = ean.ToBarcodeString(); - ean = InternationalArticleNumber.Create(bin); - var s = "4003994155486"; - Assert.AreEqual(s, ean.ToString()); - Assert.AreEqual(13, ean.ToList().Count); - Assert.IsTrue(InternationalArticleNumber.Validate(s)); - - // EAN-8 - ean = InternationalArticleNumber.Create("7351353"); - bin = ean.ToBarcodeString(); - ean = InternationalArticleNumber.Create(bin); - s = "73513537"; - Assert.AreEqual(s, ean.ToString()); - Assert.AreEqual(8, ean.ToList().Count); - Assert.IsTrue(InternationalArticleNumber.Validate(s)); - - // EAN-5 - s = "52495"; - ean = InternationalArticleNumber.Create(s); - bin = ean.ToBarcodeString(); - ean = InternationalArticleNumber.Create(bin); - Assert.AreEqual(s, ean.ToString()); - Assert.AreEqual(5, ean.ToList().Count); - Assert.IsTrue(InternationalArticleNumber.Validate(s)); - - // EAN-2 - s = "53"; - ean = InternationalArticleNumber.Create(s); - bin = ean.ToBarcodeString(); - ean = InternationalArticleNumber.Create(bin); - Assert.AreEqual(s, ean.ToString()); - Assert.AreEqual(2, ean.ToList().Count); - Assert.IsTrue(InternationalArticleNumber.Validate(s)); - - // Code 128 - var code128 = Code128.CreateB(new byte[] { 43, 73, 78, 71, 67, 69, 65, 78 }); - Assert.AreEqual("Kingcean", code128.ToString()); - code128 = Code128.CreateA("Kingcean"); - Assert.AreEqual("Kingcean", code128.ToString()); - - // Code 128 high character - code128 = Code128.CreateB(new byte[] { 52, 100, 52, 52, 100, 100, 52, 52, 100, 52, 52, 100, 100, 52, 100, 100, 101, 52 }); - Assert.AreEqual("TÔTÔÔTÔTÔ", code128.ToString()); - - // GS1-128 - code128 = Code128.CreateC(new byte[] { 102, 42, 18, 40, 20, 50, 101, 16 }); - Assert.AreEqual("[FNC1]42184020500", code128.ToString()); - var ai = code128.GetAiData(); - Assert.AreEqual("42184020500", ai.First()); - code128 = Code128.CreateGs1(421, "84020500"); - Assert.AreEqual("[Start C] [FNC1] 42 18 40 20 50 [Code A] 16 [Check symbol 92] [Stop]", code128.ToString(Code128.Formats.Values)); - Assert.AreEqual((byte)92, code128.Skip(code128.Count - 2).ToList()[0]); - ai = code128.GetAiData(); - Assert.AreEqual("42184020500", ai.First()); - - // Code 128 combination - code128 += Code128.Gs1Generator.BankAccount("100016") + Code128.CreateA(" Something... ") + Code128.Join(new List - { - Code128.CreateA("And "), - Code128.CreateC(123), - Code128.Gs1Generator.Sn("01234567890123456789") - }); - Assert.AreEqual("[FNC1]42184020500[FNC1]8007100016 Something... And 123[FNC1]2101234567890123456789", code128.ToString()); - -//#if NET6_0_OR_GREATER -// if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) -// { -// Assert.IsTrue(RegistryUtility.TryGetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", out string v)); -// Assert.AreEqual("Windows 10 Pro", v); -// Assert.IsTrue(RegistryUtility.TryGetValue(Microsoft.Win32.Registry.LocalMachine, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", out v)); -// Assert.AreEqual("Windows 10 Pro", v); -// } -//#endif - } - } - - class BarcodeVerb : BaseCommandVerb - { - public static string Description => "International Article Number"; - - /// - protected override async Task OnProcessAsync(CancellationToken cancellationToken = default) - { - await RunAsync(null, cancellationToken); - var s = Arguments.Verb.TryGet(0); - if (string.IsNullOrWhiteSpace(s)) - { - DefaultConsole.Write("Please type an EAN-13 code: "); - s = DefaultConsole.ReadLine(); - if (string.IsNullOrWhiteSpace(s)) return; - } - //else if (s == "128A" || s == "128a" || s == "128B" || s == "128b" || s == "128C" || s == "128c") - //{ - // var c = Enum.Parse(s.ToUpperInvariant()[3].ToString()); - // s = Arguments.Verb.TryGet(1); - // if (string.IsNullOrWhiteSpace(s)) - // { - // DefaultConsole.Write("Please type an Code 128: "); - // s = DefaultConsole.ReadLine(); - // if (string.IsNullOrWhiteSpace(s)) return; - // } - - // var code128 = Code128.Create(c, s); - //} - - try - { - var ean = InternationalArticleNumber.Create(s); - ean.ToBarcode(StyleConsole.Default); - } - catch (InvalidOperationException ex) - { - DefaultConsole.WriteLine(ex); - } - catch (ArgumentException ex) - { - DefaultConsole.WriteLine(ex); - } - } - } -} diff --git a/UnitTest/Maths/GeometryTest.cs b/UnitTest/Maths/GeometryTest.cs deleted file mode 100644 index 27326e58..00000000 --- a/UnitTest/Maths/GeometryTest.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Trivial.Maths; - -/// -/// Arithmetic unit test. -/// -[TestClass] -public class GeometryTest -{ - /// - /// Tests arithmetic. - /// - [TestMethod] - public void TestGeometry() - { - // Points - var angle = Geometry.Angle(new DoublePoint2D(0, 0), new DoublePoint2D(1, 0), new DoublePoint2D(0, 1)); - Assert.AreEqual(90, angle.AbsDegree); - - var point = JsonSerializer.Deserialize("{ \"x\": 12.8, \"y\": \"62\" }"); - Assert.AreEqual(13, point.X); - Assert.AreEqual(62, point.Y); - - var point2 = JsonSerializer.Deserialize("{ \"x\": 12.8, \"y\": \"62\" }"); - Assert.AreEqual(12.8, point2.X); - Assert.AreEqual(62, point2.Y); - Assert.AreEqual(0, point2.Z); - } -} diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index 32ab87f0..26ad4151 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -1,37 +1,28 @@  + + Exe net8.0;net6.0;net48 false Trivial.UnitTest Trivial - Trivial - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 The sample of Trivial libraries. - Copyright (c) 2018 Kingcean Tuan. Trivial.CommandLine.Program - MIT - https://github.com/nuscien/trivial/raw/master/Materials/logo.png - https://github.com/nuscien/trivial - 12.0 - True - ..\Trivial.snk - - ..\bin\Debug\netcoreapp3.1\Trivial.UnitTest.xml - ..\bin\Debug\ + + ..\bin\$(Configuration)\ + ..\bin\$(Configuration)\$(TargetFramework)\Trivial.UnitTest.xml - - ..\bin\Release\ - ..\bin\Release\netcoreapp3.1\Trivial.UnitTest.xml - + + + + @@ -41,16 +32,4 @@ - - - - - - - - - - - - diff --git a/UnitTest/Web/MimeUnitTest.cs b/UnitTest/Web/MimeUnitTest.cs deleted file mode 100644 index 712a74dc..00000000 --- a/UnitTest/Web/MimeUnitTest.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.Json; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Trivial.Web -{ - /// - /// MIME unit test. - /// - [TestClass] - public class MimeUnitTest - { - private const string TestMimeValue = "application/x-test"; - - /// - /// Tests MIME mapping. - /// - [TestMethod] - public void TestMime() - { - MimeConstants.FileExtensionMapping[".pdb"] = "application/vnd.palm"; - MimeConstants.FileExtensionMapping.Add(".ts", "application/typescript"); - MimeConstants.FileExtensionMapping.Set(".ts", "application/x-typescript", true); - MimeConstants.RegisterFileExtensionMapping(new Text.JsonObjectNode - { - { "mime", new Text.JsonObjectNode - { - { ".pdb", "application/x-program-database" }, - { ".a", "application/x-test-a" } - } } - }); - MimeConstants.RegisterFileExtensionMapping(new Text.JsonArrayNode()); - MimeConstants.FileExtensionMapping.Remove(new string[] { null, ".a", ".b" }); - MimeConstants.FileExtensionMapping.Remove(".mp4"); - MimeConstants.FileExtensionMapping.BackupGetter = GetMime; - Assert.AreEqual(TestMimeValue, MimeConstants.GetByFileExtension(".test")); - Assert.AreEqual(3, MimeConstants.FileExtensionMapping.Count); - Assert.AreEqual("application/vnd.palm", MimeConstants.GetByFileExtension(".pdb")); - Assert.AreEqual("application/x-typescript", MimeConstants.GetByFileExtension(".ts")); - Assert.AreEqual(MimeConstants.Videos.Mp4, MimeConstants.GetByFileExtension(".mp4")); - Assert.AreEqual(MimeConstants.Documents.Docx, MimeConstants.GetByFileExtension(".docx")); - Assert.AreEqual(MimeConstants.StreamMIME, MimeConstants.GetByFileExtension(".abcdefg")); - Assert.IsNull(MimeConstants.GetByFileExtension(".abcdefg", true)); - MimeConstants.FileExtensionMapping.Clear(); - Assert.AreEqual(0, MimeConstants.FileExtensionMapping.Values.Count); - Assert.AreEqual(MimeConstants.Packages.DownloadToRun, MimeConstants.GetByFileExtension(".pdb")); - Assert.AreEqual(MimeConstants.StreamMIME, MimeConstants.GetByFileExtension(".inf")); - -#if NETFRAMEWORK - if (!MimeConstants.Registry.RegisterFileExtensionMapping(".wma")) return; - MimeConstants.Registry.RegisterFileExtensionMapping(MimeConstants.Images.Jpeg); - Assert.AreEqual(MimeConstants.Audio.Wma, MimeConstants.FileExtensionMapping[".wma"]); - Assert.IsFalse(MimeConstants.Registry.RegisterFileExtensionMapping(".abcdefg")); - Assert.IsFalse(MimeConstants.Registry.RegisterFileExtensionMapping("application/x-test-c")); - var association = MimeConstants.Registry.GetFileAssociationInfo(".cs"); - Assert.AreEqual(".cs", association.FileExtension); - association = MimeConstants.Registry.GetFileAssociationInfo(".wma"); - Assert.AreEqual(MimeConstants.Audio.Wma, association.ContentType); - association = MimeConstants.Registry.GetFileAssociationInfo(MimeConstants.Audio.Wma); - Assert.AreEqual(MimeConstants.Audio.Wma, association.ContentType); -#endif - } - - private static bool GetMime(string key, out string value) - { - if (key == ".test") - { - value = TestMimeValue; - return true; - } - - value = default; - return false; - } - } -} diff --git a/Web/README.md b/Web/README.md deleted file mode 100644 index 1724f4cd..00000000 --- a/Web/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# [Trivial.Web](https://trivial.kingcean.net/web/controller) - -ASP.NET Core extensions. - -## Import - -Add following namespace to your code file to use. - -```csharp -using Trivial.Web; -``` - -## Request - -Some extension methods to get the field from HTTP request. - -## Action result - -Some extension methods to convert some modes to `ActionResult`. diff --git a/Web/Web.csproj b/Web/Web.csproj deleted file mode 100644 index 444afa52..00000000 --- a/Web/Web.csproj +++ /dev/null @@ -1,61 +0,0 @@ - - - - net8.0;net6.0; - Trivial.Web - Trivial - Trivial.Web - Trivial.Web - Kingcean Tuan - Nanchang Jinchen Software Co., Ltd. - 8.0.0 - 8.0.0.0 - 8.0.0.0 - A library for web API. - Copyright (c) 2018 Kingcean Tuan. - MIT - https://github.com/nuscien/trivial/wiki/web - true - true - snupkg - https://github.com/nuscien/trivial - git - true - web.png - https://github.com/nuscien/trivial/raw/master/Materials/logo.png - web mvc - README.md - 12.0 - True - ..\Trivial.snk - - - - ..\bin\Debug\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Web.xml - - - - ..\bin\Release\ - ..\bin\$(Configuration)\$(TargetFramework)\Trivial.Web.xml - - - - - - - - - - - - - - - - - - - - - diff --git a/Web/Web/ControllerExtensions.cs b/Web/Web/ControllerExtensions.cs deleted file mode 100644 index 8f556aa9..00000000 --- a/Web/Web/ControllerExtensions.cs +++ /dev/null @@ -1,913 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security; -using System.Security.Claims; -using System.Text; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; -using Trivial.Collection; -using Trivial.Data; -using Trivial.Net; -using Trivial.Security; -using Trivial.Text; - -namespace Trivial.Web; - -/// -/// The controller extensions. -/// -public static class ControllerExtensions -{ - private const string NullString = "null"; - private static MethodInfo method; - - /// - /// Gets the first string value. - /// - /// The form collection. - /// The key. - /// true if need trim; otherwise, false. - /// The string value; or null, if non-exist. - public static string GetFirstStringValue(this IFormCollection request, string key, bool trim = false) - { - var col = request[key]; - string str = null; - if (trim) - { - foreach (var ele in col) - { - if (ele == null) continue; - var s = ele.Trim(); - if (s.Length == 0) - { - str ??= string.Empty; - continue; - } - - str = s; - } - } - else - { - foreach (var ele in col) - { - if (ele == null) continue; - if (ele.Length == 0) - { - str ??= string.Empty; - continue; - } - - str = ele; - } - } - - return str; - } - - /// - /// Gets the merged string value. - /// - /// The form collection. - /// The key. - /// The splitter charactor. - /// true if need trim; otherwise, false. - /// The string value; or null, if non-exist. - public static string GetMergedStringValue(this IFormCollection request, string key, char split = ',', bool trim = false) - { - IEnumerable col = request[key]; - if (trim) col = col.Select(ele => ele?.Trim()).Where(ele => !string.IsNullOrEmpty(ele)); - return string.Join(split, col); - } - - /// - /// Gets the first string value. - /// - /// The query collection. - /// The key. - /// true if need trim; otherwise, false. - /// The string value; or null, if non-exist. - public static string GetFirstStringValue(this IQueryCollection request, string key, bool trim = false) - { - var col = request[key]; - string str = null; - if (trim) - { - foreach (var ele in col) - { - if (ele == null) continue; - var s = ele.Trim(); - if (s.Length == 0) - { - str ??= string.Empty; - continue; - } - - str = s; - } - } - else - { - foreach (var ele in col) - { - if (ele == null) continue; - if (ele.Length == 0) - { - str ??= string.Empty; - continue; - } - - str = ele; - } - } - - return str; - } - - /// - /// Gets the merged string value. - /// - /// The query collection. - /// The key. - /// The splitter charactor. - /// true if need trim; otherwise, false. - /// The string value; or null, if non-exist. - public static string GetMergedStringValue(this IQueryCollection request, string key, char split = ',', bool trim = false) - { - IEnumerable col = request[key]; - if (trim) col = col.Select(ele => ele?.Trim()).Where(ele => !string.IsNullOrEmpty(ele)); - return string.Join(split, col); - } - - /// - /// Gets the integer value. - /// - /// The query collection. - /// The key. - /// The number value; or null, if non-exist or parse failed. - public static int? TryGetInt32Value(this IQueryCollection request, string key) - { - var s = request[key].Select(ele => ele?.Trim()).FirstOrDefault(ele => !string.IsNullOrEmpty(ele)); - if (Maths.Numbers.TryParseToInt32(s, 10, out var r)) return r; - return null; - } - - /// - /// Gets the integer value. - /// - /// The query collection. - /// The key. - /// The output result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetInt32Value(this IQueryCollection request, string key, out int result) - { - var r = TryGetInt32Value(request, key); - if (r.HasValue) - { - result = r.Value; - return true; - } - - result = default; - return false; - } - - /// - /// Gets the integer value. - /// - /// The query collection. - /// The key. - /// The number value; or null, if non-exist or parse failed. - public static long? TryGetInt64Value(this IQueryCollection request, string key) - { - var s = request[key].Select(ele => ele?.Trim()).FirstOrDefault(ele => !string.IsNullOrEmpty(ele)); - if (Maths.Numbers.TryParseToInt64(s, 10, out var r)) return r; - return null; - } - - /// - /// Gets the integer value. - /// - /// The query collection. - /// The key. - /// The output result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetInt64Value(this IQueryCollection request, string key, out long result) - { - var r = TryGetInt64Value(request, key); - if (r.HasValue) - { - result = r.Value; - return true; - } - - result = default; - return false; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The number value; or null, if non-exist or parse failed. - public static float? TryGetSingleValue(this IQueryCollection request, string key) - { - var s = request[key].Select(ele => ele?.Trim()).FirstOrDefault(ele => !string.IsNullOrEmpty(ele)); - if (float.TryParse(s, out var r)) return r; - return null; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The output result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetSingleValue(this IQueryCollection request, string key, out float result) - { - var r = TryGetSingleValue(request, key); - if (r.HasValue) - { - result = r.Value; - return true; - } - - result = default; - return false; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The number value; or null, if non-exist or parse failed. - public static decimal? TryGetDecimalValue(this IQueryCollection request, string key) - { - var s = request[key].Select(ele => ele?.Trim()).FirstOrDefault(ele => !string.IsNullOrEmpty(ele)); - if (decimal.TryParse(s, out var r)) return r; - return null; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The output result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetDecimalValue(this IQueryCollection request, string key, out decimal result) - { - var r = TryGetDecimalValue(request, key); - if (r.HasValue) - { - result = r.Value; - return true; - } - - result = default; - return false; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The number value; or null, if non-exist or parse failed. - public static double? TryGetDoubleValue(this IQueryCollection request, string key) - { - var s = request[key].Select(ele => ele?.Trim()).FirstOrDefault(ele => !string.IsNullOrEmpty(ele)); - if (double.TryParse(s, out var r)) return r; - return null; - } - - /// - /// Gets the floating value. - /// - /// The query collection. - /// The key. - /// The output result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetDoubleValue(this IQueryCollection request, string key, out double result) - { - var r = TryGetDoubleValue(request, key); - if (r.HasValue) - { - result = r.Value; - return true; - } - - result = default; - return false; - } - - /// - /// Tries to get a property as boolean. - /// - /// The query. - /// The property key. - /// true if it is true; or false, if it is false; or null, if not supported. - public static bool? TryGetBoolean(this IQueryCollection request, string key) - { - var plain = request?.GetFirstStringValue(key, true)?.ToLowerInvariant(); - var isPlain = JsonBooleanNode.TryParse(plain); - return isPlain?.Value; - } - - /// - /// Tries to get a property as boolean. - /// - /// The query. - /// The property key. - /// The result. - /// true if parse succeeded; otherwise, false. - public static bool TryGetBoolean(this IQueryCollection request, string key, out bool result) - { - var plain = request?.GetFirstStringValue(key, true)?.ToLowerInvariant(); - var isPlain = JsonBooleanNode.TryParse(plain); - if (isPlain == null) - { - result = false; - return false; - } - - result = isPlain.Value; - return true; - } - - /// - /// Gets the query data. - /// - /// The HTTP request. - /// The optional encoding. - /// The string value; or null, if non-exist. - public static async Task ReadBodyAsQueryDataAsync(this HttpRequest request, Encoding encoding = null) - { - if (request == null || request.Body == null) return null; - encoding ??= Encoding.UTF8; - using var reader = new StreamReader(request.Body, encoding); - var query = await reader.ReadToEndAsync(); - var q = new QueryData(); - q.ParseSet(query, false, encoding); - return q; - } - - /// - /// Gets the JSON object from body. - /// - /// The HTTP request. - /// The token to monitor for cancellation requests. - /// A JSON object instance; or null, if no body. - /// json does not represent a valid single JSON object. - /// options contains unsupported options. - public static Task ReadBodyAsJsonAsync(this HttpRequest request, CancellationToken cancellationToken) - { - if (request == null || request.Body == null) return null; - return JsonObjectNode.ParseAsync(request.Body, default, cancellationToken); - } - - /// - /// Gets the JSON object from body. - /// - /// The HTTP request. - /// Options to control the reader behavior during parsing. - /// The token to monitor for cancellation requests. - /// A JSON object instance; or null, if no body. - /// json does not represent a valid single JSON object. - /// options contains unsupported options. - public static Task ReadBodyAsJsonAsync(this HttpRequest request, JsonDocumentOptions options, CancellationToken cancellationToken) - { - if (request == null || request.Body == null) return null; - return JsonObjectNode.ParseAsync(request.Body, options, cancellationToken); - } - - /// - /// Gets the JSON array from body. - /// - /// The HTTP request. - /// The token to monitor for cancellation requests. - /// A JSON array instance; or null, if no body. - /// json does not represent a valid single JSON object. - /// options contains unsupported options. - public static Task ReadBodyAsJsonArrayAsync(this HttpRequest request, CancellationToken cancellationToken) - { - if (request == null || request.Body == null) return null; - return JsonArrayNode.ParseAsync(request.Body, default, cancellationToken); - } - - /// - /// Gets the JSON array from body. - /// - /// The HTTP request. - /// Options to control the reader behavior during parsing. - /// The token to monitor for cancellation requests. - /// A JSON array instance; or null, if no body. - /// json does not represent a valid single JSON object. - /// options contains unsupported options. - public static Task ReadBodyAsJsonArrayAsync(this HttpRequest request, JsonDocumentOptions options, CancellationToken cancellationToken) - { - if (request == null || request.Body == null) return null; - return JsonArrayNode.ParseAsync(request.Body, options, cancellationToken); - } - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ActionResult ToActionResult(this ChangingResultInfo value) - { - if (value == null) return new NotFoundResult(); - var ex = value.GetException(); - var status = ex != null ? (GetStatusCode(ex) ?? 500) : 200; - if (status >= 300) - { - status = value.ErrorCode switch - { - ChangeErrorKinds.NotFound => 404, - ChangeErrorKinds.Busy => 503, - ChangeErrorKinds.Unsupported => 501, - ChangeErrorKinds.Conflict => 409, - _ => status - }; - } - - return new JsonResult(value) - { - StatusCode = status - }; - } - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ActionResult ToActionResult(this ChangeMethods value) - => ToActionResult(new ChangingResultInfo(value)); - - /// - /// Convert to an action result. - /// - /// The value. - /// The error message. - /// The action result. - public static ActionResult ToActionResult(this ChangeErrorKinds value, string message) - => ToActionResult(new ChangingResultInfo(value, message)); - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ContentResult ToActionResult(this JsonObjectNode value) - => new() - { - ContentType = WebFormat.JsonMIME, - StatusCode = 200, - Content = value?.ToString() ?? NullString - }; - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ContentResult ToActionResult(this JsonArrayNode value) - => new() - { - ContentType = WebFormat.JsonMIME, - StatusCode = 200, - Content = value?.ToString() ?? NullString - }; - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ContentResult ToActionResult(this IJsonObjectHost value) - => new() - { - ContentType = WebFormat.JsonMIME, - StatusCode = 200, - Content = value?.ToJson()?.ToString() ?? NullString - }; - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ContentResult ToActionResult(System.Text.Json.Nodes.JsonObject value) - => new() - { - ContentType = WebFormat.JsonMIME, - StatusCode = 200, - Content = value?.ToJsonString() ?? NullString - }; - - /// - /// Convert to an action result. - /// - /// The value. - /// The action result. - public static ContentResult ToActionResult(System.Text.Json.Nodes.JsonArray value) - => new() - { - ContentType = WebFormat.JsonMIME, - StatusCode = 200, - Content = value?.ToJsonString() ?? NullString - }; - - /// - /// Converts an exception to action result with exception message. - /// - /// The controller. - /// The exception. - /// true if return null for unknown exception; otherwise, false. - /// The action result. - public static ActionResult ExceptionResult(this ControllerBase controller, Exception ex, bool ignoreUnknownException = false) - { - if (ex == null) return controller.StatusCode(500); - var result = new ErrorMessageResult(ex); - var status = GetStatusCode(ex, ignoreUnknownException); - if (!status.HasValue) return null; - return new JsonResult(result) - { - StatusCode = status.Value - }; - } - - /// - /// Converts an exception to action result with exception message. - /// - /// The controller. - /// The exception. - /// The error code. - /// true if return null for unknown exception; otherwise, false. - /// The action result. - public static ActionResult ExceptionResult(this ControllerBase controller, Exception ex, string errorCode, bool ignoreUnknownException = false) - { - if (ex == null) return controller.StatusCode(500); - var result = new ErrorMessageResult(ex, errorCode); - var status = GetStatusCode(ex, ignoreUnknownException); - if (!status.HasValue) return null; - return new JsonResult(result) - { - StatusCode = status.Value - }; - } - - /// - /// Converts an exception to action result with exception message. - /// - /// The controller. - /// The HTTP status code. - /// The exception. - /// The action result. - public static ActionResult ExceptionResult(this ControllerBase controller, int status, Exception ex) - { - if (ex == null) return controller.StatusCode(status); - var result = new ErrorMessageResult(ex); - return new JsonResult(result) - { - StatusCode = status - }; - } - - /// - /// Converts an exception to action result with exception message. - /// - /// The controller. - /// The HTTP status code. - /// The exception. - /// The error code. - /// The action result. - public static ActionResult ExceptionResult(this ControllerBase controller, int status, Exception ex, string errorCode) - { - if (ex == null) return controller.StatusCode(status); - var result = new ErrorMessageResult(ex, errorCode); - return new JsonResult(result) - { - StatusCode = status - }; - } - - /// - /// Converts an exception to action result with exception message. - /// - /// The controller. - /// The HTTP status code. - /// The exception message. - /// The optional error code. - /// The action result. -#pragma warning disable IDE0060 - public static ActionResult ExceptionResult(this ControllerBase controller, int status, string ex, string errorCode = null) -#pragma warning restore IDE0060 - { - var result = new ErrorMessageResult(ex, errorCode); - return new JsonResult(result) - { - StatusCode = status - }; - } - - /// - /// Gets the query data instance. - /// - /// The request. - /// The query data instance. - public static QueryData GetQueryData(this IQueryCollection request) - { - if (request == null) return null; - var q = new QueryData(); - foreach (var item in request) - { - q.Add(item.Key, item.Value as IEnumerable); - } - - q.Remove("random"); - return q; - } - - /// - /// Signs in. - /// - /// The controller. - /// The token request route. - /// The token maker. - /// The login response. - public static async Task SignInAsync(ControllerBase controller, TokenRequestRoute route, Func tokenMaker) where TToken : TokenInfo - { - TToken result; - try - { - if (controller is null) return default; - var stream = controller.Request.Body; - if (stream is null) - { - result = tokenMaker(); - result.ErrorCode = TokenInfo.ErrorCodeConstants.InvalidRequest; - result.ErrorDescription = "The body was empty."; - return default; - } - - tokenMaker ??= () => Activator.CreateInstance(); - string input; - using (var reader = new StreamReader(controller.Request.Body, Encoding.UTF8)) - { - input = await reader.ReadToEndAsync(); - } - - var r = await route.SignInAsync(input); - result = r?.ItemSelected as TToken; - if (result != null) return result; - result = tokenMaker(); - result.ErrorCode = TokenInfo.ErrorCodeConstants.InvalidRequest; - result.ErrorDescription = "Cannot sign in."; - return result; - } - catch (ArgumentException ex) - { - result = tokenMaker(); - result.ErrorCode = TokenInfo.ErrorCodeConstants.InvalidRequest; - result.ErrorDescription = ex.Message; - return result; - } - catch (IOException ex) - { - result = tokenMaker(); - result.ErrorCode = TokenInfo.ErrorCodeConstants.ServerError; - result.ErrorDescription = ex.Message; - return result; - } - } - - /// - /// Converts a JSON format string to a result. - /// - /// The JSON format string. - /// The content result converted. - public static ContentResult JsonStringResult(string json) - => new() - { - StatusCode = 200, - ContentType = WebFormat.JsonMIME, - Content = json - }; - - /// - /// Creates a file result. - /// - /// The source. - /// The entity tag associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if non-exists. - public static FileStreamResult FileResult(FileInfo source, EntityTagHeaderValue entityTag = null, string mime = null) - { - if (source == null || !source.Exists) return null; - mime ??= GetByFileExtension(source.Extension, WebFormat.StreamMIME); - var result = new FileStreamResult(source.OpenRead(), mime) - { - LastModified = source.LastWriteTime, - FileDownloadName = source.Name, - EntityTag = entityTag - }; - return result; - } - - /// - /// Creates a file result. - /// - /// The source. - /// The entity tag associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if non-exists. - public static FileStreamResult FileResult(IO.BaseFileReferenceInfo source, EntityTagHeaderValue entityTag = null, string mime = null) - => FileResult(source?.Source, entityTag, mime); - - /// - /// Creates a file result. - /// - /// The source. - /// The file name used for downloading. - /// The last modified information associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if non-exists. - public static FileStreamResult FileResult(Stream source, string downloadName, DateTimeOffset? lastModified = null, string mime = null) - => FileResult(source, downloadName, null, lastModified, mime); - - /// - /// Creates a file result. - /// - /// The source. - /// The file name used for downloading. - /// The entity tag associated with the file. - /// The last modified information associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if stream source is null. - public static FileStreamResult FileResult(Stream source, string downloadName, EntityTagHeaderValue entityTag, DateTimeOffset? lastModified = null, string mime = null) - { - if (source == null) return null; - if (string.IsNullOrEmpty(mime) && downloadName?.Contains('.') == true) - { - var ext = downloadName.Trim().Split('.').LastOrDefault(); - if (string.IsNullOrEmpty(ext)) - mime = WebFormat.StreamMIME; - else - mime = GetByFileExtension("." + ext, WebFormat.StreamMIME); - } - - var result = new FileStreamResult(source, mime) - { - LastModified = lastModified, - EntityTag = entityTag - }; - if (!string.IsNullOrWhiteSpace(downloadName)) - result.FileDownloadName = downloadName; - return result; - } - - /// - /// Creates a file result. - /// - /// The source. - /// The file name used for downloading. - /// true if enables range requests processing; otherwise, false. - /// The entity tag associated with the file. - /// The last modified information associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if stream source is null. - public static FileStreamResult FileResult(Stream source, string downloadName, EntityTagHeaderValue entityTag, bool enableRangeProcessing, DateTimeOffset? lastModified = null, string mime = null) - { - var result = FileResult(source, downloadName, entityTag, lastModified, mime); - if (result == null) return null; - result.EnableRangeProcessing = enableRangeProcessing; - return result; - } - - /// - /// Creates a file result. - /// - /// The assembly with the embedded file. - /// The sub path of the embedded file. - /// The file name used for downloading. - /// The entity tag associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if non-exists. - public static FileStreamResult FileResult(Assembly assembly, string subPath, string downloadName, EntityTagHeaderValue entityTag, string mime = null) - { - if (string.IsNullOrWhiteSpace(subPath)) return null; - if (assembly == null) - assembly = Assembly.GetExecutingAssembly(); - var stream = assembly.GetManifestResourceStream(subPath); - if (stream == null) return null; - var file = IO.FileSystemInfoUtility.TryGetFileInfo(assembly.Location); - var lastModified = file?.LastWriteTime; - if (string.IsNullOrWhiteSpace(downloadName)) - downloadName = subPath.Split(new[] { '\\', '/' }).LastOrDefault(); - return FileResult(stream, downloadName, entityTag, lastModified, mime); - } - - /// - /// Creates a file result. - /// - /// The assembly with the embedded file. - /// The sub path of the embedded file. - /// The entity tag associated with the file. - /// The optional MIME content type; or null, if detects automatically. - /// A file result; or null, if non-exists. - public static FileStreamResult FileResult(Assembly assembly, string subPath, EntityTagHeaderValue entityTag, string mime = null) - => FileResult(assembly, subPath, null, entityTag, mime); - - /// - /// Gets the status code. - /// - /// The exception. - /// true if return null for unknown exception; otherwise, false. - /// The action result. - private static int? GetStatusCode(Exception ex, bool ignoreUnknownException = false) - { - if (ex == null) return 500; - if (ex.InnerException != null) - { - if (ex is AggregateException) - { - ex = ex.InnerException; - } - else if (ex is InvalidOperationException) - { - ex = ex.InnerException; - ignoreUnknownException = false; - } - } - - if (ex is SecurityException) return 403; - else if (ex is UnauthorizedAccessException) return 401; - else if (ex is NotSupportedException) return 502; - else if (ex is NotImplementedException) return 502; - else if (ex is TimeoutException) return 408; - else if (ex is OperationCanceledException) return 408; - if (ignoreUnknownException && !( - ex is InvalidOperationException - || ex is ArgumentException - || ex is NullReferenceException - || ex is System.Data.Common.DbException - || ex is JsonException - || ex is System.Runtime.Serialization.SerializationException - || ex is FailedHttpException - || ex is IOException - || ex is ApplicationException - || ex is InvalidCastException - || ex is FormatException - || ex is ArithmeticException - || ex is ExternalException - || ex is InvalidDataException)) return null; - return 500; - } - - /// - /// Gets the MIME content type by file extension part. - /// - /// The file extension. - /// The default MIME content type. - /// The MIME content type. - private static string GetByFileExtension(string fileExtension, string defaultMime) - { - if (string.IsNullOrWhiteSpace(fileExtension)) return null; - if (method == null) - { - method = typeof(WebFormat).GetMethod("GetMime", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null); - if (method == null) - method = typeof(WebFormat).GetMethod("GetMime", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null); - if (method == null) - return defaultMime; - } - - var r = method.Invoke(null, new object[] { fileExtension }); - if (r == null) return defaultMime; - try - { - return (string)r; - } - catch (InvalidCastException) - { - } - - return defaultMime; - } -} diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f340057d..4199a3ca 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,12 +19,6 @@ steps: version: 8.0.x includePreviewVersions: true -- task: UseDotNet@2 - displayName: 'Use .NET SDK 7.0' - inputs: - version: 7.0.x - includePreviewVersions: true - - task: UseDotNet@2 displayName: 'Use .NET SDK 6.0' inputs: diff --git a/docs/assets/badge_ASPNET_5_0.svg b/docs/assets/badge_ASPNET_5_0.svg deleted file mode 100644 index 3103b532..00000000 --- a/docs/assets/badge_ASPNET_5_0.svg +++ /dev/null @@ -1 +0,0 @@ -ASP.NET Core: 5.0ASP.NET Core5.0 \ No newline at end of file diff --git a/docs/assets/badge_ASPNET_6_0.svg b/docs/assets/badge_ASPNET_6_0.svg deleted file mode 100644 index b4f0f48f..00000000 --- a/docs/assets/badge_ASPNET_6_0.svg +++ /dev/null @@ -1 +0,0 @@ -ASP.NET Core: 6.0ASP.NET Core6.0 \ No newline at end of file diff --git a/docs/assets/badge_ASPNET_8_0.svg b/docs/assets/badge_ASPNET_8_0.svg deleted file mode 100644 index 95d324d3..00000000 --- a/docs/assets/badge_ASPNET_8_0.svg +++ /dev/null @@ -1 +0,0 @@ -ASP.NET: 8.0ASP.NET8.0 \ No newline at end of file diff --git a/docs/assets/badge_NET_5.svg b/docs/assets/badge_NET_5.svg deleted file mode 100644 index 40c66bb1..00000000 --- a/docs/assets/badge_NET_5.svg +++ /dev/null @@ -1 +0,0 @@ -.NET: 5.NET5 \ No newline at end of file diff --git a/docs/assets/badge_NET_7.svg b/docs/assets/badge_NET_7.svg deleted file mode 100644 index 0fd25086..00000000 --- a/docs/assets/badge_NET_7.svg +++ /dev/null @@ -1 +0,0 @@ -.NET: 7.NET7 \ No newline at end of file diff --git a/docs/assets/badge_NET_Core_3_1.svg b/docs/assets/badge_NET_Core_3_1.svg deleted file mode 100644 index c96095a3..00000000 --- a/docs/assets/badge_NET_Core_3_1.svg +++ /dev/null @@ -1 +0,0 @@ - .NET Core.NET Core3.13.1 \ No newline at end of file diff --git a/docs/assets/chemistry.png b/docs/assets/chemistry.png deleted file mode 100644 index 866ba0f0..00000000 Binary files a/docs/assets/chemistry.png and /dev/null differ diff --git a/docs/assets/cmd.png b/docs/assets/cmd.png deleted file mode 100644 index 9996d530..00000000 Binary files a/docs/assets/cmd.png and /dev/null differ diff --git a/docs/assets/maths.png b/docs/assets/maths.png deleted file mode 100644 index e735cb0e..00000000 Binary files a/docs/assets/maths.png and /dev/null differ diff --git a/docs/assets/web.png b/docs/assets/web.png deleted file mode 100644 index 05daf89d..00000000 Binary files a/docs/assets/web.png and /dev/null differ