using System; using System.Diagnostics.Contracts; using System.Globalization; using System.Text; using System.Text.RegularExpressions; namespace DominionBase { [Serializable] public class Currency : IDisposable { private static readonly Regex RegexParser = new Regex("((?\\d+))?((?\\d+))?((?\\d+))?"); public Currency() { } public Currency(Currency currency) : this(currency?.Coin, currency.Potion, currency.Debt) { } public Currency(Cards.Cost cost) : this(cost?.Coin, cost.Potion, cost.Debt) { } public Currency(Currencies.Coin coin, Currencies.Potion potion = null, Currencies.Debt debt = null) { Contract.Requires(coin != default(Currencies.Coin), "coin cannot be null"); Coin.Value = coin.Value; Coin.IsVariable = coin.IsVariable; if (potion != null) { Potion.Value = potion.Value; Potion.IsVariable = Potion.IsVariable; } if (debt != null) { Debt.Value = debt.Value; Debt.IsVariable = Debt.IsVariable; } } public Currency(int coin = 0, int potion = 0, int debt = 0) { Coin.Value = coin; Potion.Value = potion; Debt.Value = debt; } public Currency(string currency) { var matched = RegexParser.Match(currency); if (!matched.Success) throw new ArgumentException("Could not parse currency!"); if (matched.Groups["coinValue"].Success) Coin.Value = int.Parse(matched.Groups["coinValue"].Value, CultureInfo.InvariantCulture); if (matched.Groups["potionValue"].Success) Potion.Value = int.Parse(matched.Groups["potionValue"].Value, CultureInfo.InvariantCulture); if (matched.Groups["debtValue"].Success) Debt.Value = int.Parse(matched.Groups["debtValue"].Value, CultureInfo.InvariantCulture); } #region IDisposable variables, properties, & methods // Track whether Dispose has been called. private bool _disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!_disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. Coin = null; Potion = null; Debt = null; } // Call the appropriate methods to clean up // unmanaged resources here. // If disposing is false, // only the following code is executed. // Note disposing has been done. _disposed = true; } } ~Currency() { Dispose(false); } #endregion public Currencies.Coin Coin { get; set; } = new Currencies.Coin(); public Currencies.Potion Potion { get; set; } = new Currencies.Potion(); public Currencies.Debt Debt { get; set; } = new Currencies.Debt(); public bool IsVariable => Coin.IsVariable || Potion.IsVariable || Debt.IsVariable; public bool IsBlank => Coin.Value == 0 && Potion.Value == 0 && Debt.Value == 0; public Currency Clone() { return new Currency(this); } internal void Add(Currency currency) { Coin += currency.Coin; Potion += currency.Potion; Debt += currency.Debt; } public static Currency operator +(Currency x, Currency y) { Contract.Requires(y != default(Currency), "y cannot be null"); var newCurrency = new Currency(x); newCurrency.Coin += y.Coin; newCurrency.Potion += y.Potion; newCurrency.Debt += y.Debt; return newCurrency; } public static Currency operator +(Currency x, Cards.Cost y) { Contract.Requires(y != default(Cards.Cost), "y cannot be null"); var newCurrency = new Currency(x); newCurrency.Coin += y.Coin; newCurrency.Potion += y.Potion; newCurrency.Debt += y.Debt; return newCurrency; } public static Currency operator +(Currency x, Currencies.Coin y) { var newCurrency = new Currency(x); newCurrency.Coin += y; return newCurrency; } public static Currency operator +(Currency x, Currencies.Potion y) { var newCurrency = new Currency(x); newCurrency.Potion += y; return newCurrency; } public static Currency operator +(Currency x, Currencies.Debt y) { var newCurrency = new Currency(x); newCurrency.Debt += y; return newCurrency; } public static Currency operator -(Currency x, Currency y) { Contract.Requires(y != default(Currency), "y cannot be null"); var newCurrency = new Currency(x); newCurrency.Coin -= y.Coin; newCurrency.Potion -= y.Potion; newCurrency.Debt -= y.Debt; return newCurrency; } public static Currency Subtract(Currency left, Currency right) { return left - right; } public static Currency operator -(Currency x, Cards.Cost y) { Contract.Requires(y != default(Cards.Cost), "y cannot be null"); var newCurrency = new Currency(x); newCurrency.Coin -= y.Coin; newCurrency.Potion -= y.Potion; newCurrency.Debt -= y.Debt; return newCurrency; } public static Currency operator -(Currency x, Currencies.Coin y) { var newCurrency = new Currency(x); newCurrency.Coin -= y; return newCurrency; } public static Currency operator -(Currency x, Currencies.Potion y) { var newCurrency = new Currency(x); newCurrency.Potion -= y; return newCurrency; } public static Currency operator -(Currency x, Currencies.Debt y) { var newCurrency = new Currency(x); newCurrency.Debt -= y; return newCurrency; } public static Currency operator -(Currency c) { Contract.Requires(c != default(Currency), "c cannot be null"); return new Currency(-c.Coin, -c.Potion, -c.Debt); } public static Currency Negate(Currency item) { return -item; } public override int GetHashCode() { return Coin.GetHashCode() + 19 * Potion.GetHashCode() + 23 * Debt.GetHashCode(); } public static bool operator ==(Currency x, Currency y) { if (ReferenceEquals(x, y)) return true; // If one is null, but not both, return false. if (x is null || y is null) return false; return x.Equals(y); } public static bool operator !=(Currency x, Currency y) { return !(x == y); } public static bool operator ==(Currency x, Cards.Cost y) { // If one is null, but not both, return false. if (x is null || y is null) return false; return x.Equals(y); } public static bool operator !=(Currency x, Cards.Cost y) { return !(x == y); } public static bool operator <(Currency x, Currency y) { Contract.Requires(x != default(Currency), "x cannot be null"); Contract.Requires(y != default(Currency), "y cannot be null"); return (x.Coin < y.Coin && x.Potion == y.Potion && x.Debt == y.Debt) || (x.Coin == y.Coin && x.Potion < y.Potion && x.Debt == y.Debt) || (x.Coin == y.Coin && x.Potion == y.Potion && x.Debt < y.Debt) || (x.Coin < y.Coin && x.Potion < y.Potion && x.Debt == y.Debt) || (x.Coin < y.Coin && x.Potion == y.Potion && x.Debt < y.Debt) || (x.Coin == y.Coin && x.Potion < y.Potion && x.Debt < y.Debt) || (x.Coin < y.Coin && x.Potion < y.Potion && x.Debt < y.Debt); } public static bool operator >(Currency x, Currency y) { return (y < x); } public static bool operator <=(Currency x, Currency y) { return (x == y || x < y); } public static bool operator >=(Currency x, Currency y) { return (x == y || x > y); } public static bool operator <(Currency x, Cards.Cost y) { Contract.Requires(x != default(Currency), "x cannot be null"); Contract.Requires(y != default(Cards.Cost), "y cannot be null"); return (x.Coin < y.Coin && x.Potion == y.Potion && x.Debt == y.Debt) || (x.Coin == y.Coin && x.Potion < y.Potion && x.Debt == y.Debt) || (x.Coin == y.Coin && x.Potion == y.Potion && x.Debt < y.Debt) || (x.Coin < y.Coin && x.Potion < y.Potion && x.Debt == y.Debt) || (x.Coin < y.Coin && x.Potion == y.Potion && x.Debt < y.Debt) || (x.Coin == y.Coin && x.Potion < y.Potion && x.Debt < y.Debt) || (x.Coin < y.Coin && x.Potion < y.Potion && x.Debt < y.Debt); } public static bool operator >(Currency x, Cards.Cost y) { return (y < x); } public static bool operator <=(Currency x, Cards.Cost y) { return (x == y || x < y); } public static bool operator >=(Currency x, Cards.Cost y) { return (x == y || x > y); } public override bool Equals(object obj) { if (obj is Cards.Cost oCost) return Coin.Equals(oCost.Coin) && Potion.Equals(oCost.Potion) && Debt.Equals(oCost.Debt); if (obj is Currency oCurr) return Coin.Equals(oCurr.Coin) && Potion.Equals(oCurr.Potion) && Debt.Equals(oCurr.Debt); return false; } public int CompareTo(object o) { return CompareTo(o as Currency); } public int CompareTo(Currency other) { // Check for null if (other is null) return -1; // Check for same reference if (ReferenceEquals(this, other)) return 0; if (this < other) return -1; if (this > other) return 1; if (this == other) return 0; // I... don't know if this is true??? Currency is weird return 0; } public override string ToString() { var sb = new StringBuilder(); sb.AppendFormat("{0}", Coin.Value); if (Potion.Value > 0) sb.AppendFormat(", {0}", Potion.Value); if (Debt.Value > 0) sb.AppendFormat(", {0}", Debt.Value); return sb.ToString(); } public string ToStringInline() { var s = Coin.ToString(); if (Potion.Value > 0) { if (Coin.Value == 0) s = string.Empty; s += Potion.ToString(); } if (Debt.Value > 0) { if (Coin.Value == 0) s = string.Empty; s += Debt.ToString(); } return s; } } }