diff --git a/DamagePrinter/DamagePrinter.sln b/DamagePrinter/DamagePrinter.sln
new file mode 100644
index 0000000..7e7a7b2
--- /dev/null
+++ b/DamagePrinter/DamagePrinter.sln
@@ -0,0 +1,65 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32407.343
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamagePrinter", "DamagePrinter\DamagePrinter.csproj", "{AF6F5837-94D3-4D44-9D1C-6B5CD600C698}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamShared", "..\Shared\SteamHelpers\SteamHelpers\SteamShared.csproj", "{4DB55154-E33B-49D8-BE05-DC11CA5B32A4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoreSoft.MathExpressions", "..\Shared\LoreSoft.MathExpressions\LoreSoft.MathExpressions.csproj", "{B6813448-FCE2-429C-81B5-9722FEA839B8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|x64.ActiveCfg = Debug|x64
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|x64.Build.0 = Debug|x64
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Debug|x86.Build.0 = Debug|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|x64.ActiveCfg = Release|x64
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|x64.Build.0 = Release|x64
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|x86.ActiveCfg = Release|Any CPU
+ {AF6F5837-94D3-4D44-9D1C-6B5CD600C698}.Release|x86.Build.0 = Release|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|x64.ActiveCfg = Debug|x64
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|x64.Build.0 = Debug|x64
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Debug|x86.Build.0 = Debug|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|x64.ActiveCfg = Release|x64
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|x64.Build.0 = Release|x64
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|x86.ActiveCfg = Release|Any CPU
+ {4DB55154-E33B-49D8-BE05-DC11CA5B32A4}.Release|x86.Build.0 = Release|Any CPU
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|x64.ActiveCfg = Debug|x64
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|x64.Build.0 = Debug|x64
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|x86.ActiveCfg = Debug|x86
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Debug|x86.Build.0 = Debug|x86
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|x64.ActiveCfg = Release|x64
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|x64.Build.0 = Release|x64
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|x86.ActiveCfg = Release|x86
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B75CC20D-F989-4D9F-86F7-9610737FCBE9}
+ EndGlobalSection
+EndGlobal
diff --git a/DamagePrinter/DamagePrinter/DamagePrinter.csproj b/DamagePrinter/DamagePrinter/DamagePrinter.csproj
new file mode 100644
index 0000000..c5d95e5
--- /dev/null
+++ b/DamagePrinter/DamagePrinter/DamagePrinter.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net6.0-windows
+ disable
+ enable
+ AnyCPU;x64
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DamagePrinter/DamagePrinter/Program.cs b/DamagePrinter/DamagePrinter/Program.cs
new file mode 100644
index 0000000..0421284
--- /dev/null
+++ b/DamagePrinter/DamagePrinter/Program.cs
@@ -0,0 +1,363 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
+using System.Threading;
+using SteamShared;
+using LoreSoft.MathExpressions;
+using System.Net.Http;
+using System.Text.Json.Nodes;
+using Newtonsoft.Json;
+
+static class Program
+{
+ static readonly uint WM_COPYDATA = 0x004A;
+ static SteamHelper steamHelper = new SteamHelper();
+ static MathEvaluator mathEval = new MathEvaluator();
+ static HttpClient httpClient = new HttpClient();
+
+ [DllImport("user32.dll")]
+ static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ static extern int SendMessage(IntPtr windowHandle, uint message, IntPtr wParam, IntPtr lParam);
+
+ [STAThread]
+ static void Main(string[] args)
+ {
+ string? gamePath = steamHelper.GetGamePathFromExactName("Counter-Strike: Global Offensive");
+
+ if (gamePath == null)
+ return;
+
+ string consoleLogPath = Path.Combine(gamePath, "csgo", "console.log");
+ bool consoleLogExists = false;
+
+ long oldFileSize = 0;
+ try
+ {
+ oldFileSize = new FileInfo(consoleLogPath).Length;
+ } catch { }
+
+ long nextLineOffset = oldFileSize; // bytes from the start of the file, by default not to read anything
+ int minDamageToCount = 20;
+ bool initialScan = true;
+ var prevTaggedPlayers = new List>();
+ DateTime lastFuelRequestTime = DateTime.MinValue;
+
+ if (FindWindow("Valve001", null) == IntPtr.Zero)
+ File.Delete(consoleLogPath);
+
+ // here we start fresh at line 0 cause it got deleted
+ while (true)
+ {
+ if (File.Exists(consoleLogPath))
+ {
+ bool update = false;
+
+ if (!consoleLogExists && initialScan) {
+ consoleLogExists = true;
+ initialScan = false;
+ }
+
+ long curFileSize = new FileInfo(consoleLogPath).Length;
+ if (curFileSize != oldFileSize)
+ {
+ update = true;
+ oldFileSize = curFileSize;
+ }
+
+ if (update)
+ {
+ int damageTakenTotal = 0;
+
+ List lines = new List();
+ using (var fs = File.Open(consoleLogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ fs.Position = nextLineOffset;
+ bool endOfFile = false;
+
+ while (!endOfFile)
+ {
+ string line = "";
+ bool endOfLine = false;
+ while (!endOfLine)
+ {
+ int nextByte = fs.ReadByte();
+
+ if (nextByte == -1 && line != "")
+ {
+ lines.Add(line);
+ endOfFile = true;
+ break;
+ }
+
+ char nextChar = (char)nextByte;
+
+ if (nextChar == '\n' && line != "")
+ {
+ lines.Add(line);
+ endOfLine = true;
+ }
+ else
+ if(nextChar != '\r')
+ line += nextChar;
+ }
+ }
+
+ nextLineOffset = fs.Position;
+ }
+
+ var taggedPlayers = new List>();
+ string calcKeyWord = "!calc";
+ string fuelPriceKeyWord = "!fuel";
+ string weatherKeyWord = "!weather";
+
+ foreach (string line in lines)
+ {
+ /* -------------------------
+ Damage Given to "BOT Eugene" - 65 in 2 hits
+ -------------------------
+ Damage Taken from "BOT Eugene" - 117 in 4 hits*/
+ if (line.StartsWith("Damage Taken"))
+ {
+ Regex regexTaken = new Regex("Damage Taken from \"(.+?)\" - (\\d+) in \\d+ hits?");
+ Match takenMatch = regexTaken.Match(line);
+
+ if (takenMatch.Success)
+ {
+ damageTakenTotal += int.Parse(takenMatch.Groups[2].Value);
+ }
+ }
+ else if (line.StartsWith("Damage Given"))
+ {
+ Regex regexTaken = new Regex("Damage Given to \"(.+?)\" - (\\d+) in (\\d+) hits?");
+ Match givenMatch = regexTaken.Match(line);
+
+ if (givenMatch.Success)
+ {
+ string name = givenMatch.Groups[1].Value;
+ int damage = int.Parse(givenMatch.Groups[2].Value);
+ int hits = int.Parse(givenMatch.Groups[3].Value);
+
+ if(damage < 100 && damage > minDamageToCount && taggedPlayers.FirstOrDefault(player => player.Item1 == name) == null)
+ // not in list yet so add
+ taggedPlayers.Add(new Tuple(name, damage, hits));
+ }
+ }
+ else if (line.ToLower().Contains(calcKeyWord + ' '))
+ {
+ // Calculate
+ string expression = line.Substring(line.IndexOf(calcKeyWord + ' ') + calcKeyWord.Length);
+ if (String.IsNullOrWhiteSpace(expression))
+ continue;
+
+ try
+ {
+ double res = mathEval.Evaluate(expression);
+ Thread.Sleep(700); // so the chat message is shown if we requested it ourselves
+ ExecuteCommands(true, $"say \"Answer: {res}\"");
+ }
+ catch { }
+ }
+ else if (line.ToLower().Contains(fuelPriceKeyWord))
+ {
+ if (DateTime.Now - lastFuelRequestTime < TimeSpan.FromMinutes(1))
+ continue;
+
+ string apiKey = "";
+ string nordOelID = "69ad1928-e972-421b-a33c-4319da73deaa";
+ string shellID = "a507dd35-4a7f-46d1-86b6-accc4769a47b";
+ string request = $"https://creativecommons.tankerkoenig.de/json/prices.php?ids={nordOelID},{shellID}&apikey={apiKey}";
+
+ HttpResponseMessage response;
+ try
+ {
+ response = httpClient.GetAsync(request).Result;
+
+ lastFuelRequestTime = DateTime.Now;
+ }
+ catch { continue; }
+
+ var responseString = response.Content.ReadAsStringAsync().Result;
+
+ dynamic? jsonResponse = JsonConvert.DeserializeObject(responseString);
+
+ if (jsonResponse == null || (bool)jsonResponse!.ok == false)
+ continue;
+
+ var cmds = new List();
+
+ if((string)jsonResponse!.prices[nordOelID].status == "open")
+ {
+ cmds.Add($"say \"NORDOEL: Super: {(string)jsonResponse!.prices[nordOelID].e5} Euro, Diesel: {(string)jsonResponse!.prices[nordOelID].diesel} Euro\"");
+ }
+ else
+ {
+ cmds.Add("say \"NORDOEL: Geschlossen\"");
+ }
+
+ if ((string)jsonResponse.prices[shellID].status == "open")
+ {
+ cmds.Add($"say \"Shell: Super: {(string)jsonResponse!.prices[shellID].e5} Euro, Diesel: {(string)jsonResponse!.prices[shellID].diesel} Euro\"");
+ }
+ else
+ {
+ cmds.Add("say \"Shell: Geschlossen\"");
+ }
+
+ ExecuteCommands(true, cmds.ToArray());
+ }
+ else if (line.ToLower().Contains(weatherKeyWord))
+ {
+ string request = $"https://api.open-meteo.com/v1/forecast?latitude=54.2335&longitude=10.3397&hourly=temperature_2m,cloudcover&daily=precipitation_hours&timezone=Europe%2FBerlin";
+
+ HttpResponseMessage response;
+ try
+ {
+ response = httpClient.GetAsync(request).Result;
+ }
+ catch { continue; }
+
+ var responseString = response.Content.ReadAsStringAsync().Result;
+
+ dynamic? jsonResponse = JsonConvert.DeserializeObject(responseString);
+
+ if (jsonResponse == null)
+ continue;
+
+ string cmd = $"say \"{((double)jsonResponse!.hourly.temperature_2m[0]).ToString(System.Globalization.CultureInfo.InvariantCulture)} C, Wolkendecke {(double)jsonResponse!.hourly.cloudcover[0]} %, Stunden Regen: {Math.Round((double)jsonResponse!.daily.precipitation_hours[0] * 100 / 24)} %\"";
+
+ ExecuteCommands(true, cmd);
+ }
+ }
+
+ bool didPlayerDie = damageTakenTotal >= 100;
+
+ if (!didPlayerDie)
+ {
+ continue;
+ }
+
+ if (areListsEqual(taggedPlayers, prevTaggedPlayers))
+ {
+ // Last is the same as previous, likely dealt damage, died and now the round ended and it was printed again
+ Console.WriteLine("Double console output.");
+ continue;
+ }
+
+ prevTaggedPlayers = taggedPlayers;
+
+ if (taggedPlayers.Count < 1)
+ continue;
+
+ string[] commands = new string[taggedPlayers.Count];
+
+ // We didn't have a round end, but got killed
+ for (int i = 0; i < commands.Length; i++)
+ {
+ commands[i] += "say_team \"";
+ if (taggedPlayers[i].Item2 > 90)
+ {
+ // One-shot
+ commands[i] += $"{taggedPlayers[i].Item1} is one-shot {taggedPlayers[i].Item2}";
+ }
+ else if (taggedPlayers[i].Item2 >= 70)
+ {
+ // Lit
+ commands[i] += $"{taggedPlayers[i].Item1} is lit for {taggedPlayers[i].Item2}";
+ }
+ else
+ {
+ // Tagged
+ commands[i] += $"{taggedPlayers[i].Item1} is tagged for {taggedPlayers[i].Item2}";
+ }
+
+ commands[i] += "\"";
+ }
+
+ // Notify players
+ ExecuteCommands(false, commands);
+ }
+ }
+ Thread.Sleep(50);
+ }
+ }
+
+ static bool areListsEqual(List> list1, List> list2)
+ {
+ if (list1.Count != list2.Count)
+ return false;
+
+ // still same length
+ for (int i = 0; i < list1.Count; i++)
+ {
+ if (list1[i].Item1 != list2[i].Item1)
+ return false;
+ if (list1[i].Item2 != list2[i].Item2)
+ return false;
+ if (list1[i].Item3 != list2[i].Item3)
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool ExecuteCommands(bool triggeredByCommand, params string[] cmds)
+ {
+ if (cmds == null)
+ return false;
+
+ IntPtr hWnd = FindWindow("Valve001", null!);
+
+ if (hWnd == IntPtr.Zero)
+ return false;
+
+ int chatTimeoutMs = 700;
+ int commandsHandled = 0;
+
+ for (int i = 0; i < cmds.Length; i++)
+ {
+ if (cmds[i] == null)
+ continue;
+
+ cmds[i] = cmds[i].Trim();
+
+ COPYDATASTRUCT data;
+ data.dwData = 0;
+ data.cbData = (uint)cmds[i].Length + 1;
+ data.lpData = cmds[i];
+
+ if (triggeredByCommand)
+ Thread.Sleep(chatTimeoutMs);
+
+ // Allocate for data
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(data));
+ Marshal.StructureToPtr(data, ptr, false);
+
+ int ret = SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ptr);
+
+ Console.WriteLine(cmds[i]);
+
+ // Free data
+ Marshal.FreeHGlobal(ptr);
+
+ if (ret == 0)
+ commandsHandled++;
+
+ if (cmds[i].StartsWith("say") || cmds[i].StartsWith("say_team"))
+ Thread.Sleep(chatTimeoutMs);
+ }
+
+ return cmds.Length > 0 && commandsHandled == cmds.Length;
+ }
+}
+
+struct COPYDATASTRUCT
+{
+ public ulong dwData;
+ public uint cbData;
+ public string lpData;
+}
diff --git a/Shared/LoreSoft.MathExpressions/ConvertExpression.cs b/Shared/LoreSoft.MathExpressions/ConvertExpression.cs
new file mode 100644
index 0000000..04527b0
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/ConvertExpression.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Collections.Generic;
+using LoreSoft.MathExpressions.Properties;
+using LoreSoft.MathExpressions.UnitConversion;
+using System.Globalization;
+using LoreSoft.MathExpressions.Metadata;
+using System.Reflection;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// A class representing unit convertion expressions.
+ ///
+ public class ConvertExpression : ExpressionBase
+ {
+ private static Dictionary convertionCache;
+ private static object cacheLock = new object();
+
+ private ConvertionMap current;
+ private string expression;
+
+ /// The format of a convertion expression.
+ public const string ExpressionFormat = "[{0}->{1}]";
+
+ /// Initializes a new instance of the class.
+ /// The convertion expression for this instance.
+ public ConvertExpression(string expression)
+ {
+ VerifyCache();
+ if (!convertionCache.ContainsKey(expression))
+ throw new ArgumentException(Resources.InvalidConvertionExpression + expression, "expression");
+
+ this.expression = expression;
+ current = convertionCache[expression];
+ base.Evaluate = new MathEvaluate(Convert);
+ }
+
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ public override int ArgumentCount
+ {
+ get { return 1; }
+ }
+
+ /// Convert the numbers to the new unit.
+ /// The numbers used in the convertion.
+ /// The result of the convertion execution.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Convert(double[] numbers)
+ {
+ base.Validate(numbers);
+ double fromValue = numbers[0];
+
+ switch (current.UnitType)
+ {
+ case UnitType.Length:
+ return LengthConverter.Convert(
+ (LengthUnit) current.FromUnit,
+ (LengthUnit) current.ToUnit,
+ fromValue);
+ case UnitType.Mass:
+ return MassConverter.Convert(
+ (MassUnit) current.FromUnit,
+ (MassUnit) current.ToUnit,
+ fromValue);
+ case UnitType.Speed:
+ return SpeedConverter.Convert(
+ (SpeedUnit) current.FromUnit,
+ (SpeedUnit) current.ToUnit,
+ fromValue);
+ case UnitType.Temperature:
+ return TemperatureConverter.Convert(
+ (TemperatureUnit) current.FromUnit,
+ (TemperatureUnit) current.ToUnit,
+ fromValue);
+ case UnitType.Time:
+ return TimeConverter.Convert(
+ (TimeUnit) current.FromUnit,
+ (TimeUnit) current.ToUnit,
+ fromValue);
+ case UnitType.Volume:
+ return VolumeConverter.Convert(
+ (VolumeUnit) current.FromUnit,
+ (VolumeUnit) current.ToUnit,
+ fromValue);
+ default:
+ throw new ArgumentOutOfRangeException("numbers");
+ }
+ }
+
+
+ ///
+ /// Determines whether the specified expression name is for unit convertion.
+ ///
+ ///The expression to check.
+ ///true if the specified expression is a unit convertion; otherwise, false.
+ public static bool IsConvertExpression(string expression)
+ {
+ //do basic checks before creating cache
+ if (string.IsNullOrEmpty(expression))
+ return false;
+
+ if (expression[0] != '[')
+ return false;
+
+ VerifyCache();
+ return convertionCache.ContainsKey(expression);
+ }
+
+
+ private static void VerifyCache()
+ {
+ if (convertionCache != null)
+ return;
+
+ lock (cacheLock)
+ {
+ if (convertionCache != null)
+ return;
+
+ convertionCache = new Dictionary(
+ StringComparer.OrdinalIgnoreCase);
+
+ AddToCache(UnitType.Length);
+ AddToCache(UnitType.Mass);
+ AddToCache(UnitType.Speed);
+ AddToCache(UnitType.Temperature);
+ AddToCache(UnitType.Time);
+ AddToCache(UnitType.Volume);
+ }
+ }
+
+ private static void AddToCache(UnitType unitType)
+ where T : struct, IComparable, IFormattable, IConvertible
+ {
+ Type enumType = typeof(T);
+ int[] a = (int[])Enum.GetValues(enumType);
+
+ for (int x = 0; x < a.Length; x++)
+ {
+ MemberInfo parentInfo = GetMemberInfo(enumType, Enum.GetName(enumType, x));
+ string parrentKey = AttributeReader.GetAbbreviation(parentInfo);
+
+ for (int i = 0; i < a.Length; i++)
+ {
+ if (x == i)
+ continue;
+
+ MemberInfo info = GetMemberInfo(enumType, Enum.GetName(enumType, i));
+
+ string key = string.Format(
+ CultureInfo.InvariantCulture,
+ ExpressionFormat,
+ parrentKey,
+ AttributeReader.GetAbbreviation(info));
+
+ convertionCache.Add(
+ key, new ConvertionMap(unitType, x, i));
+ }
+ }
+ }
+
+ private static MemberInfo GetMemberInfo(Type type, string name)
+ {
+ MemberInfo[] info = type.GetMember(name);
+ if (info == null || info.Length == 0)
+ return null;
+
+ return info[0];
+ }
+ ///
+ /// Returns a that represents the current .
+ ///
+ ///
+ /// A that represents the current .
+ ///
+ /// 2
+ public override string ToString()
+ {
+ return expression;
+ }
+
+ private class ConvertionMap
+ {
+ public ConvertionMap(UnitType unitType, int fromUnit, int toUnit)
+ {
+ _unitType = unitType;
+ _fromUnit = fromUnit;
+ _toUnit = toUnit;
+ }
+
+ private UnitType _unitType;
+
+ public UnitType UnitType
+ {
+ get { return _unitType; }
+ }
+
+ private int _fromUnit;
+
+ public int FromUnit
+ {
+ get { return _fromUnit; }
+ }
+
+ private int _toUnit;
+
+ public int ToUnit
+ {
+ get { return _toUnit; }
+ }
+
+ public override string ToString()
+ {
+ return string.Format(
+ CultureInfo.CurrentCulture,
+ "{0}, [{1}->{2}]",
+ _unitType,
+ _fromUnit,
+ _toUnit);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/ExpressionBase.cs b/Shared/LoreSoft.MathExpressions/ExpressionBase.cs
new file mode 100644
index 0000000..b571d40
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/ExpressionBase.cs
@@ -0,0 +1,35 @@
+using System;
+using LoreSoft.MathExpressions.Properties;
+
+namespace LoreSoft.MathExpressions
+{
+ /// The base class for expressions
+ public abstract class ExpressionBase : IExpression
+ {
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ public abstract int ArgumentCount { get; }
+
+ private MathEvaluate _evaluateDelegate;
+
+ /// Gets or sets the evaluate delegate.
+ /// The evaluate delegate.
+ public virtual MathEvaluate Evaluate
+ {
+ get { return _evaluateDelegate; }
+ set { _evaluateDelegate = value; }
+ }
+
+ /// Validates the specified numbers for the expression.
+ /// The numbers to validate.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ protected void Validate(double[] numbers)
+ {
+ if (numbers == null)
+ throw new ArgumentNullException("numbers");
+ if (numbers.Length != ArgumentCount)
+ throw new ArgumentException(Resources.InvalidLengthOfArray, "numbers");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/FunctionExpression.cs b/Shared/LoreSoft.MathExpressions/FunctionExpression.cs
new file mode 100644
index 0000000..30c574f
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/FunctionExpression.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Reflection;
+using LoreSoft.MathExpressions.Properties;
+using System.Globalization;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// A class representing the System.Math function expressions
+ ///
+ public class FunctionExpression : ExpressionBase
+ {
+ // must be sorted
+ /// The supported math functions by this class.
+ private static readonly string[] mathFunctions = new string[]
+ {
+ "abs", "acos", "asin", "atan", "ceiling", "cos", "cosh", "exp",
+ "floor", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh"
+ };
+
+ /// Initializes a new instance of the class.
+ /// The function name for this instance.
+ public FunctionExpression(string function) : this(function, true)
+ {
+ }
+
+ /// Initializes a new instance of the class.
+ /// The function.
+ /// if set to true to validate the function name.
+ internal FunctionExpression(string function, bool validate)
+ {
+ function = function.ToLowerInvariant();
+
+ if (validate && !IsFunction(function))
+ throw new ArgumentException(
+ string.Format(CultureInfo.CurrentCulture, Resources.InvalidFunctionName, _function),
+ "function");
+
+ _function = function;
+ base.Evaluate = new MathEvaluate(Execute);
+ }
+
+ private string _function;
+
+ /// Gets the name function for this instance.
+ /// The function name.
+ public string Function
+ {
+ get { return _function; }
+ }
+
+ /// Executes the function on specified numbers.
+ /// The numbers used in the function.
+ /// The result of the function execution.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Execute(double[] numbers)
+ {
+ base.Validate(numbers);
+
+ string function = char.ToUpperInvariant(_function[0]) + _function.Substring(1);
+ MethodInfo method = typeof (Math).GetMethod(
+ function,
+ BindingFlags.Static | BindingFlags.Public,
+ null,
+ new Type[] { typeof(double) },
+ null);
+
+ if (method == null)
+ throw new InvalidOperationException(
+ string.Format(CultureInfo.CurrentCulture,
+ Resources.InvalidFunctionName, _function));
+
+ object[] parameters = new object[numbers.Length];
+ Array.Copy(numbers, parameters, numbers.Length);
+ return (double) method.Invoke(null, parameters);
+ }
+
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ public override int ArgumentCount
+ {
+ get { return 1; }
+ }
+
+ /// Determines whether the specified function name is a function.
+ /// The function name.
+ /// true if the specified name is a function; otherwise, false.
+ public static bool IsFunction(string function)
+ {
+ return (Array.BinarySearch(
+ mathFunctions, function,
+ StringComparer.OrdinalIgnoreCase) >= 0);
+ }
+
+ /// Returns a that represents the current .
+ /// A that represents the current .
+ /// 2
+ public override string ToString()
+ {
+ return _function;
+ }
+
+ ///
+ /// Gets the function names.
+ ///
+ /// An array of function names.
+ public static string[] GetFunctionNames()
+ {
+ return (string[])mathFunctions.Clone();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/GlobalSuppressions.cs b/Shared/LoreSoft.MathExpressions/GlobalSuppressions.cs
new file mode 100644
index 0000000..af500e5
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/GlobalSuppressions.cs
@@ -0,0 +1,2 @@
+using System.Diagnostics.CodeAnalysis;
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "LoreSoft.MathExpressions.Metadata")]
diff --git a/Shared/LoreSoft.MathExpressions/IExpression.cs b/Shared/LoreSoft.MathExpressions/IExpression.cs
new file mode 100644
index 0000000..f75e849
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/IExpression.cs
@@ -0,0 +1,15 @@
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// The interface used when running expressions
+ ///
+ public interface IExpression
+ {
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ int ArgumentCount { get; }
+ /// Gets or sets the evaluate delegate.
+ /// The evaluate delegate.
+ MathEvaluate Evaluate { get; set; }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/LoreSoft.MathExpressions.csproj b/Shared/LoreSoft.MathExpressions/LoreSoft.MathExpressions.csproj
new file mode 100644
index 0000000..59dfa89
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/LoreSoft.MathExpressions.csproj
@@ -0,0 +1,185 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {B6813448-FCE2-429C-81B5-9722FEA839B8}
+ Library
+ Properties
+ LoreSoft.MathExpressions
+ LoreSoft.MathExpressions
+ true
+ MathExpressions.snk
+
+
+ 3.5
+
+
+ v4.8
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+
+ true
+ full
+ false
+ ..\..\Build\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\..\Build\Debug\LoreSoft.MathExpressions.XML
+ true
+ AllRules.ruleset
+ false
+
+
+ pdbonly
+ true
+ ..\..\Build\Release\
+ TRACE
+ prompt
+ 4
+ ..\..\Build\Release\LoreSoft.MathExpressions.XML
+ AllRules.ruleset
+ false
+
+
+ true
+ ..\..\Build\x86\Debug\
+ CODE_ANALYSIS;DEBUG;TRACE
+ ..\..\Build\Debug\LoreSoft.MathExpressions.XML
+ full
+ x86
+ true
+ true
+ GlobalSuppressions.cs
+ prompt
+ AllRules.ruleset
+ false
+
+
+ ..\..\Build\x86\Release\
+ TRACE
+ ..\..\Build\Release\LoreSoft.MathExpressions.XML
+ true
+ pdbonly
+ x86
+ true
+ GlobalSuppressions.cs
+ prompt
+ AllRules.ruleset
+ false
+
+
+ true
+ ..\..\Build\x64\Debug\
+ CODE_ANALYSIS;DEBUG;TRACE
+ ..\..\Build\Debug\LoreSoft.MathExpressions.XML
+ full
+ x64
+ true
+ true
+ GlobalSuppressions.cs
+ prompt
+ AllRules.ruleset
+ false
+
+
+ ..\..\Build\x64\Release\
+ TRACE
+ ..\..\Build\Release\LoreSoft.MathExpressions.XML
+ true
+ pdbonly
+ x64
+ true
+ GlobalSuppressions.cs
+ prompt
+ AllRules.ruleset
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/MathEvaluate.cs b/Shared/LoreSoft.MathExpressions/MathEvaluate.cs
new file mode 100644
index 0000000..44e3ca5
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/MathEvaluate.cs
@@ -0,0 +1,7 @@
+namespace LoreSoft.MathExpressions
+{
+ /// Delegate used by an expression to do the math evaluation.
+ /// The numbers to evaluate.
+ /// The result of the evaluated numbers.
+ public delegate double MathEvaluate(double[] numbers);
+}
diff --git a/Shared/LoreSoft.MathExpressions/MathEvaluator.cs b/Shared/LoreSoft.MathExpressions/MathEvaluator.cs
new file mode 100644
index 0000000..c84234e
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/MathEvaluator.cs
@@ -0,0 +1,458 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Text;
+using LoreSoft.MathExpressions.Properties;
+using System.Globalization;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// Evaluate math expressions
+ ///
+ /// Using the MathEvaluator to calculate a math expression.
+ ///
+ /// MathEvaluator eval = new MathEvaluator();
+ /// //basic math
+ /// double result = eval.Evaluate("(2 + 1) * (1 + 2)");
+ /// //calling a function
+ /// result = eval.Evaluate("sqrt(4)");
+ /// //evaluate trigonometric
+ /// result = eval.Evaluate("cos(pi * 45 / 180.0)");
+ /// //convert inches to feet
+ /// result = eval.Evaluate("12 [in->ft]");
+ /// //use variable
+ /// result = eval.Evaluate("answer * 10");
+ ///
+ ///
+ public class MathEvaluator : IDisposable
+ {
+ /// The name of the answer variable.
+ ///
+ public const string AnswerVariable = "answer";
+
+ //instance scope to optimize reuse
+ private Stack _symbolStack;
+ private Queue _expressionQueue;
+ private Dictionary _expressionCache;
+ private StringBuilder _buffer;
+ private Stack _calculationStack;
+ private Stack _parameters;
+ private List _innerFunctions;
+
+ private StringReader _expressionReader;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MathEvaluator()
+ {
+ _variables = new VariableDictionary(this);
+ _innerFunctions = new List(FunctionExpression.GetFunctionNames());
+ _functions = new ReadOnlyCollection(_innerFunctions);
+ _expressionCache = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ _symbolStack = new Stack();
+ _expressionQueue = new Queue();
+ _buffer = new StringBuilder();
+ _calculationStack = new Stack();
+ _parameters = new Stack(2);
+ }
+
+ private VariableDictionary _variables;
+
+ ///
+ /// Gets the variables collections.
+ ///
+ /// The variables for .
+ public VariableDictionary Variables
+ {
+ get { return _variables; }
+ }
+
+ private ReadOnlyCollection _functions;
+
+ /// Gets the functions available to .
+ /// The functions for .
+ ///
+ public ReadOnlyCollection Functions
+ {
+ get { return _functions; }
+ }
+
+ /// Gets the answer from the last evaluation.
+ /// The answer variable value.
+ ///
+ public double Answer
+ {
+ get { return _variables[AnswerVariable]; }
+ }
+
+ /// Evaluates the specified expression.
+ /// The expression to evaluate.
+ /// The result of the evaluated expression.
+ /// When expression is null or empty.
+ /// When there is an error parsing the expression.
+ public double Evaluate(string expression)
+ {
+ if (string.IsNullOrEmpty(expression))
+ throw new ArgumentNullException("expression");
+
+ _expressionReader = new StringReader(expression);
+ _symbolStack.Clear();
+ _expressionQueue.Clear();
+
+ ParseExpressionToQueue();
+
+ double result = CalculateFromQueue();
+
+ _variables[AnswerVariable] = result;
+ return result;
+ }
+
+ /// Registers a function for the .
+ /// Name of the function.
+ /// An instance of for the function.
+ /// When functionName or expression are null.
+ /// When IExpression.Evaluate property is null or the functionName is already registered.
+ ///
+ ///
+ public void RegisterFunction(string functionName, IExpression expression)
+ {
+ if (string.IsNullOrEmpty(functionName))
+ throw new ArgumentNullException("functionName");
+ if (expression == null)
+ throw new ArgumentNullException("expression");
+ if (expression.Evaluate == null)
+ throw new ArgumentException(Resources.EvaluatePropertyCanNotBeNull, "expression");
+ if (_innerFunctions.BinarySearch(functionName) >= 0)
+ throw new ArgumentException(
+ string.Format(CultureInfo.CurrentCulture,
+ Resources.FunctionNameRegistered, functionName), "functionName");
+
+ _innerFunctions.Add(functionName);
+ _innerFunctions.Sort();
+ _expressionCache.Add(functionName, expression);
+ }
+
+ /// Determines whether the specified name is a function.
+ /// The name of the function.
+ /// true if the specified name is function; otherwise, false.
+ internal bool IsFunction(string name)
+ {
+ return (_innerFunctions.BinarySearch(name, StringComparer.OrdinalIgnoreCase) >= 0);
+ }
+
+ private void ParseExpressionToQueue()
+ {
+ char l = '\0';
+ char c = '\0';
+
+ do
+ {
+ // last non white space char
+ if (!char.IsWhiteSpace(c))
+ l = c;
+
+ c = (char)_expressionReader.Read();
+
+ if (char.IsWhiteSpace(c))
+ continue;
+
+ if (TryNumber(c, l))
+ continue;
+
+ if (TryString(c))
+ continue;
+
+ if (TryStartGroup(c))
+ continue;
+
+ if (TryOperator(c))
+ continue;
+
+ if (TryEndGroup(c))
+ continue;
+
+ if (TryConvert(c))
+ continue;
+
+ throw new ParseException(Resources.InvalidCharacterEncountered + c);
+ } while (_expressionReader.Peek() != -1);
+
+ ProcessSymbolStack();
+ }
+
+ private bool TryConvert(char c)
+ {
+ if (c != '[')
+ return false;
+
+ _buffer.Length = 0;
+ _buffer.Append(c);
+
+ char p = (char)_expressionReader.Peek();
+ while (char.IsLetter(p) || char.IsWhiteSpace(p) || p == '-' || p == '>' || p == ']')
+ {
+ if (!char.IsWhiteSpace(p))
+ _buffer.Append((char)_expressionReader.Read());
+ else
+ _expressionReader.Read();
+
+ if (p == ']')
+ break;
+
+ p = (char)_expressionReader.Peek();
+ }
+
+ if (ConvertExpression.IsConvertExpression(_buffer.ToString()))
+ {
+ IExpression e = GetExpressionFromSymbol(_buffer.ToString());
+ _expressionQueue.Enqueue(e);
+ return true;
+ }
+
+ throw new ParseException(Resources.InvalidConvertionExpression + _buffer);
+ }
+
+ private bool TryString(char c)
+ {
+ if (!char.IsLetter(c))
+ return false;
+
+ _buffer.Length = 0;
+ _buffer.Append(c);
+
+ char p = (char)_expressionReader.Peek();
+ while (char.IsLetter(p))
+ {
+ _buffer.Append((char)_expressionReader.Read());
+ p = (char)_expressionReader.Peek();
+ }
+
+ if (_variables.ContainsKey(_buffer.ToString()))
+ {
+ double value = _variables[_buffer.ToString()];
+ NumberExpression expression = new NumberExpression(value);
+ _expressionQueue.Enqueue(expression);
+
+ return true;
+ }
+
+ if (IsFunction(_buffer.ToString()))
+ {
+ _symbolStack.Push(_buffer.ToString());
+ return true;
+ }
+
+ throw new ParseException(Resources.InvalidVariableEncountered + _buffer);
+ }
+
+ private bool TryStartGroup(char c)
+ {
+ if (c != '(')
+ return false;
+
+ _symbolStack.Push(c.ToString());
+ return true;
+ }
+
+ private bool TryEndGroup(char c)
+ {
+ if (c != ')')
+ return false;
+
+ bool hasStart = false;
+
+ while (_symbolStack.Count > 0)
+ {
+ string p = _symbolStack.Pop();
+ if (p == "(")
+ {
+ hasStart = true;
+
+ if (_symbolStack.Count == 0)
+ break;
+
+ string n = _symbolStack.Peek();
+ if (FunctionExpression.IsFunction(n))
+ {
+ p = _symbolStack.Pop();
+ IExpression f = GetExpressionFromSymbol(p);
+ _expressionQueue.Enqueue(f);
+ }
+
+ break;
+ }
+
+ IExpression e = GetExpressionFromSymbol(p);
+ _expressionQueue.Enqueue(e);
+ }
+
+ if (!hasStart)
+ throw new ParseException(Resources.UnbalancedParentheses);
+
+ return true;
+ }
+
+ private bool TryOperator(char c)
+ {
+ if (!OperatorExpression.IsSymbol(c))
+ return false;
+
+ bool repeat;
+ string s = c.ToString();
+
+ do
+ {
+ string p = _symbolStack.Count == 0 ? string.Empty : _symbolStack.Peek();
+ repeat = false;
+ if (_symbolStack.Count == 0)
+ _symbolStack.Push(s);
+ else if (p == "(")
+ _symbolStack.Push(s);
+ else if (Precedence(s) > Precedence(p))
+ _symbolStack.Push(s);
+ else
+ {
+ IExpression e = GetExpressionFromSymbol(_symbolStack.Pop());
+ _expressionQueue.Enqueue(e);
+ repeat = true;
+ }
+ } while (repeat);
+
+ return true;
+ }
+
+ private bool TryNumber(char c, char l)
+ {
+ bool isNumber = NumberExpression.IsNumber(c);
+ // only negative when last char is group start or symbol
+ bool isNegative = NumberExpression.IsNegativeSign(c) &&
+ (l == '\0' || l == '(' || OperatorExpression.IsSymbol(l));
+
+ if (!isNumber && !isNegative)
+ return false;
+
+ _buffer.Length = 0;
+ _buffer.Append(c);
+
+ char p = (char)_expressionReader.Peek();
+ while (NumberExpression.IsNumber(p))
+ {
+ _buffer.Append((char)_expressionReader.Read());
+ p = (char)_expressionReader.Peek();
+ }
+
+ double value;
+ if (!(double.TryParse(_buffer.ToString(), out value)))
+ throw new ParseException(Resources.InvalidNumberFormat + _buffer);
+
+ NumberExpression expression = new NumberExpression(value);
+ _expressionQueue.Enqueue(expression);
+
+ return true;
+ }
+
+ private void ProcessSymbolStack()
+ {
+ while (_symbolStack.Count > 0)
+ {
+ string p = _symbolStack.Pop();
+ if (p.Length == 1 && p == "(")
+ throw new ParseException(Resources.UnbalancedParentheses);
+
+ IExpression e = GetExpressionFromSymbol(p);
+ _expressionQueue.Enqueue(e);
+ }
+ }
+
+ private IExpression GetExpressionFromSymbol(string p)
+ {
+ IExpression e;
+
+ if (_expressionCache.ContainsKey(p))
+ e = _expressionCache[p];
+ else if (OperatorExpression.IsSymbol(p))
+ {
+ e = new OperatorExpression(p);
+ _expressionCache.Add(p, e);
+ }
+ else if (FunctionExpression.IsFunction(p))
+ {
+ e = new FunctionExpression(p, false);
+ _expressionCache.Add(p, e);
+ }
+ else if (ConvertExpression.IsConvertExpression(p))
+ {
+ e = new ConvertExpression(p);
+ _expressionCache.Add(p, e);
+ }
+ else
+ throw new ParseException(Resources.InvalidSymbolOnStack + p);
+
+ return e;
+ }
+
+ private static int Precedence(string c)
+ {
+ if (c.Length == 1 && (c[0] == '*' || c[0] == '/' || c[0] == '%'))
+ return 2;
+
+ return 1;
+ }
+
+ private double CalculateFromQueue()
+ {
+ double result;
+ _calculationStack.Clear();
+
+ foreach (IExpression expression in _expressionQueue)
+ {
+ if (_calculationStack.Count < expression.ArgumentCount)
+ throw new ParseException(Resources.NotEnoughNumbers + expression);
+
+ _parameters.Clear();
+ for (int i = 0; i < expression.ArgumentCount; i++)
+ _parameters.Push(_calculationStack.Pop());
+
+ _calculationStack.Push(expression.Evaluate.Invoke(_parameters.ToArray()));
+ }
+
+ result = _calculationStack.Pop();
+ return result;
+ }
+
+ #region IDisposable Members
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and managed resources
+ ///
+ ///
+ /// true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_expressionReader != null)
+ {
+ _expressionReader.Dispose();
+ _expressionReader = null;
+ }
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/MathExpressions.snk b/Shared/LoreSoft.MathExpressions/MathExpressions.snk
new file mode 100644
index 0000000..7788283
Binary files /dev/null and b/Shared/LoreSoft.MathExpressions/MathExpressions.snk differ
diff --git a/Shared/LoreSoft.MathExpressions/MathOperators.cs b/Shared/LoreSoft.MathExpressions/MathOperators.cs
new file mode 100644
index 0000000..ba7fa85
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/MathOperators.cs
@@ -0,0 +1,19 @@
+namespace LoreSoft.MathExpressions
+{
+ /// Math Operators
+ public enum MathOperators
+ {
+ /// Add Operator
+ Add,
+ /// Subtract Operator
+ Subtract,
+ /// Multiple Operator
+ Multiple,
+ /// Divide Operator
+ Divide,
+ /// Modulo Operator
+ Modulo,
+ /// Power Operator
+ Power
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/Metadata/AbbreviationAttribute.cs b/Shared/LoreSoft.MathExpressions/Metadata/AbbreviationAttribute.cs
new file mode 100644
index 0000000..b2365fb
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/Metadata/AbbreviationAttribute.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace LoreSoft.MathExpressions.Metadata
+{
+ ///
+ /// Specifies an abbreviation for a instance.
+ ///
+ [AttributeUsageAttribute(AttributeTargets.All)]
+ public sealed class AbbreviationAttribute : Attribute
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The abbreviation text.
+ public AbbreviationAttribute(string text)
+ {
+ _text = text;
+ }
+
+ private string _text;
+
+ ///
+ /// Gets the abbreviation text.
+ ///
+ /// The abbreviation text.
+ public string Text
+ {
+ get { return _text; }
+ }
+
+ ///
+ /// Returns a that represents the current .
+ ///
+ ///
+ /// A that represents the current .
+ ///
+ /// 2
+ public override string ToString()
+ {
+ return _text;
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/Metadata/AttributeReader.cs b/Shared/LoreSoft.MathExpressions/Metadata/AttributeReader.cs
new file mode 100644
index 0000000..f468e5c
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/Metadata/AttributeReader.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+using System.ComponentModel;
+
+namespace LoreSoft.MathExpressions.Metadata
+{
+ ///
+ /// A class to read attributes from type members.
+ ///
+ public static class AttributeReader
+ {
+ ///
+ /// Gets the description from the on an enum.
+ ///
+ /// An enum type.
+ /// The value to get the description from.
+ /// The or the name of the instance.
+ ///
+ public static string GetDescription(T instance)
+ {
+ if (instance == null)
+ throw new ArgumentNullException("instance");
+
+ string result = instance.ToString();
+
+ Type type = instance.GetType();
+ MemberInfo[] members = type.GetMember(result);
+
+ if (members == null || members.Length == 0)
+ return result;
+
+ return GetDescription(members[0]);
+ }
+
+ ///
+ /// Gets the description from the on a MemberInfo.
+ ///
+ /// The member info to look for the description.
+ /// The or the name of the member.
+ ///
+ public static string GetDescription(MemberInfo info)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+
+ string result = info.Name;
+
+ object[] attributes = info.GetCustomAttributes(typeof(DescriptionAttribute), false);
+ if (attributes == null || attributes.Length == 0)
+ return result;
+
+ DescriptionAttribute description = attributes[0] as DescriptionAttribute;
+ if (description == null || string.IsNullOrEmpty(description.Description))
+ return result;
+
+ return description.Description;
+ }
+
+ ///
+ /// Gets the abbreviation from the on an enum.
+ ///
+ /// An enum type.
+ /// The enum to get the abbreviation from.
+ /// The or the name of the memeber.
+ ///
+ public static string GetAbbreviation(T instance)
+ {
+ if (instance == null)
+ throw new ArgumentNullException("instance");
+
+ string result = instance.ToString();
+
+ Type type = instance.GetType();
+ MemberInfo[] members = type.GetMember(result);
+
+ if (members == null || members.Length == 0)
+ return result;
+
+ return GetAbbreviation(members[0]);
+ }
+
+ ///
+ /// Gets the abbreviation from the on a instance.
+ ///
+ /// The instance info look for the abbreviation.
+ /// The or the name of the instance.
+ ///
+ public static string GetAbbreviation(MemberInfo info)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+
+ string result = info.Name;
+
+ object[] attributes = info.GetCustomAttributes(typeof(AbbreviationAttribute), false);
+ if (attributes == null || attributes.Length == 0)
+ return result;
+
+ AbbreviationAttribute abbreviation = attributes[0] as AbbreviationAttribute;
+ if (abbreviation == null || string.IsNullOrEmpty(abbreviation.Text))
+ return result;
+
+ return abbreviation.Text;
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/NumberExpression.cs b/Shared/LoreSoft.MathExpressions/NumberExpression.cs
new file mode 100644
index 0000000..335dab1
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/NumberExpression.cs
@@ -0,0 +1,68 @@
+using System.Globalization;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// Class representing a constant number expression.
+ ///
+ public class NumberExpression : ExpressionBase
+ {
+ /// Initializes a new instance of the class.
+ /// The number value for this expression.
+ public NumberExpression(double value)
+ {
+ _value = value;
+ base.Evaluate = delegate
+ {
+ return Value;
+ };
+ }
+
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ public override int ArgumentCount
+ {
+ get { return 0; }
+ }
+
+ private double _value;
+
+ /// Gets the number value for this expression.
+ /// The number value.
+ public double Value
+ {
+ get { return _value; }
+ }
+
+ /// Determines whether the specified char is a number.
+ /// The char to test.
+ /// true if the specified char is a number; otherwise, false.
+ /// This method checks if the char is a digit or a decimal separator.
+ public static bool IsNumber(char c)
+ {
+ NumberFormatInfo f = CultureInfo.CurrentUICulture.NumberFormat;
+ return char.IsDigit(c) || f.NumberDecimalSeparator.IndexOf(c) >= 0;
+ }
+
+ /// Determines whether the specified char is negative sign.
+ /// The char to check.
+ /// true if the specified char is negative sign; otherwise, false.
+ public static bool IsNegativeSign(char c)
+ {
+ NumberFormatInfo f = CultureInfo.CurrentUICulture.NumberFormat;
+ return f.NegativeSign.IndexOf(c) >= 0;
+ }
+
+ ///
+ /// Returns a that represents the current .
+ ///
+ ///
+ /// A that represents the current .
+ ///
+ /// 2
+ public override string ToString()
+ {
+ return _value.ToString(CultureInfo.CurrentCulture);
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/OperatorExpression.cs b/Shared/LoreSoft.MathExpressions/OperatorExpression.cs
new file mode 100644
index 0000000..cc8de70
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/OperatorExpression.cs
@@ -0,0 +1,203 @@
+using System;
+using LoreSoft.MathExpressions.Properties;
+using System.Diagnostics.CodeAnalysis;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// Class representing a math operator expression.
+ ///
+ public class OperatorExpression : ExpressionBase
+ {
+ /// The supported math operators by this class.
+ private static readonly char[] operatorSymbols = new char[] {'+', '-', '*', '/', '%', '^'};
+
+ /// Initializes a new instance of the class.
+ /// The operator to use for this class.
+ /// When the operator is null or empty.
+ /// When the operator is invalid.
+ public OperatorExpression(string @operator)
+ {
+ if (string.IsNullOrEmpty(@operator))
+ throw new ArgumentNullException("operator");
+
+ switch (@operator)
+ {
+ case "+":
+ base.Evaluate = new MathEvaluate(Add);
+ _mathOperator = MathOperators.Add;
+ break;
+ case "-":
+ base.Evaluate = new MathEvaluate(Subtract);
+ _mathOperator = MathOperators.Subtract;
+ break;
+ case "*":
+ base.Evaluate = new MathEvaluate(Multiple);
+ _mathOperator = MathOperators.Multiple;
+ break;
+ case "/":
+ base.Evaluate = new MathEvaluate(Divide);
+ _mathOperator = MathOperators.Divide;
+ break;
+ case "%":
+ base.Evaluate = new MathEvaluate(Modulo);
+ _mathOperator = MathOperators.Modulo;
+ break;
+ case "^":
+ base.Evaluate = new MathEvaluate(Power);
+ _mathOperator = MathOperators.Power;
+ break;
+
+ default:
+ throw new ArgumentException(Resources.InvalidOperator + @operator, "operator");
+ }
+ }
+
+ private MathOperators _mathOperator;
+
+ /// Gets the math operator.
+ /// The math operator.
+ public MathOperators MathOperator
+ {
+ get { return _mathOperator; }
+ }
+
+ /// Gets the number of arguments this expression uses.
+ /// The argument count.
+ public override int ArgumentCount
+ {
+ get { return 2; }
+ }
+
+ /// Adds the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Add(double[] numbers)
+ {
+ base.Validate(numbers);
+ double result = 0;
+ foreach (double n in numbers)
+ result += n;
+
+ return result;
+ }
+
+ /// Subtracts the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Subtract(double[] numbers)
+ {
+ base.Validate(numbers);
+ double? result = null;
+ foreach (double n in numbers)
+ if (result.HasValue)
+ result -= n;
+ else
+ result = n;
+
+ return result ?? 0;
+ }
+
+ /// Multiples the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Multiple(double[] numbers)
+ {
+ base.Validate(numbers);
+ double? result = null;
+ foreach (double n in numbers)
+ if (result.HasValue)
+ result *= n;
+ else
+ result = n;
+
+ return result ?? 0;
+ }
+
+ /// Divides the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Divide(double[] numbers)
+ {
+ base.Validate(numbers);
+ double? result = null;
+ foreach (double n in numbers)
+ if (result.HasValue)
+ result /= n;
+ else
+ result = n;
+
+ return result ?? 0;
+ }
+
+ /// Modulo the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Modulo(double[] numbers)
+ {
+ base.Validate(numbers);
+ double? result = null;
+ foreach (double n in numbers)
+ if (result.HasValue)
+ result %= n;
+ else
+ result = n;
+
+ return result ?? 0;
+ }
+
+ /// Power for the specified numbers.
+ /// The numbers.
+ /// The result of the operation.
+ /// When numbers is null.
+ /// When the length of numbers do not equal .
+ public double Power(double[] numbers)
+ {
+ base.Validate(numbers);
+ return Math.Pow(numbers[0], numbers[1]);
+ }
+
+ /// Determines whether the specified string is a math symbol.
+ /// The string to check.
+ /// true if the specified string is a math symbol; otherwise, false.
+ [SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
+ public static bool IsSymbol(string s)
+ {
+ if (s == null || s.Length != 1)
+ return false;
+
+ char c = s[0];
+ return IsSymbol(c);
+ }
+
+ /// Determines whether the specified char is a math symbol.
+ /// The char to check.
+ /// true if the specified char is a math symbol; otherwise, false.
+ public static bool IsSymbol(char c)
+ {
+ return Array.Exists(operatorSymbols, delegate(char s) { return s == c; });
+ }
+
+ ///
+ /// Returns a that represents the current .
+ ///
+ ///
+ /// A that represents the current .
+ ///
+ /// 2
+ public override string ToString()
+ {
+ return _mathOperator.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/ParseException.cs b/Shared/LoreSoft.MathExpressions/ParseException.cs
new file mode 100644
index 0000000..6788843
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/ParseException.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// The exception that is thrown when there is an error parsing a math expression.
+ ///
+ [Serializable]
+ public class ParseException : Exception
+ {
+ /// Initializes a new instance of the class.
+ public ParseException()
+ : base()
+ { }
+
+ /// Initializes a new instance of the class.
+ /// The message.
+ public ParseException(string message)
+ : base(message)
+ { }
+
+ /// Initializes a new instance of the class.
+ /// The message.
+ /// The inner exception.
+ public ParseException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ ///
+ /// Initializes a new instance of the class with serialized data.
+ ///
+ /// The SerializationInfo that holds the serialized object data about the exception being thrown.
+ /// The StreamingContext that contains contextual information about the source or destination.
+ protected ParseException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/Properties/AssemblyInfo.cs b/Shared/LoreSoft.MathExpressions/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b797d4e
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34209
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+[assembly: System.Reflection.AssemblyTitle("LoreSoft.MathExpressions")]
+[assembly: System.Reflection.AssemblyProduct("LoreSoft.MathExpressions")]
+[assembly: System.Reflection.AssemblyDescription("Math Expression Parser.")]
+[assembly: System.Reflection.AssemblyCompany("LoreSoft")]
+[assembly: System.Reflection.AssemblyCopyright("Copyright © 2015 Paul Welter")]
+[assembly: System.Runtime.InteropServices.Guid("348985f4-3fcf-4ec3-b207-6f09e918b297")]
+[assembly: System.Runtime.InteropServices.ComVisible(false)]
+[assembly: System.CLSCompliant(true)]
+[assembly: System.Reflection.AssemblyConfiguration("Release")]
+[assembly: System.Reflection.AssemblyVersion("1.2.0.0")]
+[assembly: System.Reflection.AssemblyFileVersion("1.2.0.36")]
+[assembly: System.Reflection.AssemblyInformationalVersion("1.2.0.36")]
+
+
+
+internal sealed partial class ThisAssembly {
+
+ internal const string AssemblyTitle = "LoreSoft.MathExpressions";
+
+ internal const string AssemblyProduct = "LoreSoft.MathExpressions";
+
+ internal const string AssemblyDescription = "Math Expression Parser.";
+
+ internal const string AssemblyCompany = "LoreSoft";
+
+ internal const string AssemblyCopyright = "Copyright © 2015 Paul Welter";
+
+ internal const string Guid = "348985f4-3fcf-4ec3-b207-6f09e918b297";
+
+ internal const string AssemblyConfiguration = "Release";
+
+ internal const string AssemblyVersion = "1.2.0.0";
+
+ internal const string AssemblyFileVersion = "1.2.0.36";
+
+ internal const string AssemblyInformationalVersion = "1.2.0.36";
+
+ private ThisAssembly() {
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/Properties/Resources.Designer.cs b/Shared/LoreSoft.MathExpressions/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..b2b9020
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/Properties/Resources.Designer.cs
@@ -0,0 +1,198 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace LoreSoft.MathExpressions.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [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("LoreSoft.MathExpressions.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The IExpression.Evaluate property can not be null..
+ ///
+ internal static string EvaluatePropertyCanNotBeNull {
+ get {
+ return ResourceManager.GetString("EvaluatePropertyCanNotBeNull", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The function name '{0}' is already registered..
+ ///
+ internal static string FunctionNameRegistered {
+ get {
+ return ResourceManager.GetString("FunctionNameRegistered", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid character: .
+ ///
+ internal static string InvalidCharacterEncountered {
+ get {
+ return ResourceManager.GetString("InvalidCharacterEncountered", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid convertion expression: .
+ ///
+ internal static string InvalidConvertionExpression {
+ get {
+ return ResourceManager.GetString("InvalidConvertionExpression", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid function name '{0}'..
+ ///
+ internal static string InvalidFunctionName {
+ get {
+ return ResourceManager.GetString("InvalidFunctionName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid length of array..
+ ///
+ internal static string InvalidLengthOfArray {
+ get {
+ return ResourceManager.GetString("InvalidLengthOfArray", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid math expression..
+ ///
+ internal static string InvalidMathExpression {
+ get {
+ return ResourceManager.GetString("InvalidMathExpression", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid number format: .
+ ///
+ internal static string InvalidNumberFormat {
+ get {
+ return ResourceManager.GetString("InvalidNumberFormat", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid operator: .
+ ///
+ internal static string InvalidOperator {
+ get {
+ return ResourceManager.GetString("InvalidOperator", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid symbol on stack: .
+ ///
+ internal static string InvalidSymbolOnStack {
+ get {
+ return ResourceManager.GetString("InvalidSymbolOnStack", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid function or variable: .
+ ///
+ internal static string InvalidVariableEncountered {
+ get {
+ return ResourceManager.GetString("InvalidVariableEncountered", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid number for expression: .
+ ///
+ internal static string NotEnoughNumbers {
+ get {
+ return ResourceManager.GetString("NotEnoughNumbers", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Unbalanced parentheses..
+ ///
+ internal static string UnbalancedParentheses {
+ get {
+ return ResourceManager.GetString("UnbalancedParentheses", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The variable name conflicts with function '{0}'..
+ ///
+ internal static string VariableNameConflict {
+ get {
+ return ResourceManager.GetString("VariableNameConflict", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The variable name can only contain letters..
+ ///
+ internal static string VariableNameContainsLetters {
+ get {
+ return ResourceManager.GetString("VariableNameContainsLetters", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/Properties/Resources.resx b/Shared/LoreSoft.MathExpressions/Properties/Resources.resx
new file mode 100644
index 0000000..cca9f22
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/Properties/Resources.resx
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Invalid length of array.
+
+
+ Invalid function name '{0}'.
+
+
+ The IExpression.Evaluate property can not be null.
+
+
+ The function name '{0}' is already registered.
+
+
+ Invalid character:
+
+
+ Invalid function or variable:
+
+
+ Unbalanced parentheses.
+
+
+ Invalid number format:
+
+
+ Invalid symbol on stack:
+
+
+ Invalid operator:
+
+
+ The variable name conflicts with function '{0}'.
+
+
+ The variable name can only contain letters.
+
+
+ Invalid math expression.
+
+
+ Invalid convertion expression:
+
+
+ Invalid number for expression:
+
+
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/LengthConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/LengthConverter.cs
new file mode 100644
index 0000000..5b0829a
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/LengthConverter.cs
@@ -0,0 +1,75 @@
+using LoreSoft.MathExpressions.Metadata;
+
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Length
+ public enum LengthUnit
+ {
+ /// Millimeter unit (mm)
+ [Abbreviation("mm")]
+ Millimeter = 0,
+ /// Centimeter unit (cm)
+ [Abbreviation("cm")]
+ Centimeter = 1,
+ /// Meter unit (m)
+ [Abbreviation("m")]
+ Meter = 2,
+ /// Kilometer unit (km)
+ [Abbreviation("km")]
+ Kilometer = 3,
+ /// Inch unit (in)
+ [Abbreviation("in")]
+ Inch = 4,
+ /// Feet unit (ft)
+ [Abbreviation("ft")]
+ Feet = 5,
+ /// Yard unit (yd)
+ [Abbreviation("yd")]
+ Yard = 6,
+ /// Mile unit (mile)
+ [Abbreviation("mile")]
+ Mile = 7
+ }
+
+ ///
+ /// Class representing length convertion.
+ ///
+ public static class LengthConverter
+ {
+ // In enum order
+ private static readonly double[] factors = new double[]
+ {
+ 0.001d, //millimeter
+ 0.01d, //centimeter
+ 1d, //meter
+ 1000d, //kilometer
+ 0.3048d/12d, //inch
+ 0.3048d, //feet
+ 0.9144d, //yard
+ 0.3048d*5280d, //mile
+ };
+
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ LengthUnit fromUnit,
+ LengthUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ double fromFactor = factors[(int)fromUnit];
+ double toFactor = factors[(int) toUnit];
+ double result = fromFactor * fromValue / toFactor;
+ return result;
+ }
+
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/MassConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/MassConverter.cs
new file mode 100644
index 0000000..9baca5d
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/MassConverter.cs
@@ -0,0 +1,65 @@
+using LoreSoft.MathExpressions.Metadata;
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Mass
+ public enum MassUnit
+ {
+ /// Milligram unit (mg)
+ [Abbreviation("mg")]
+ Milligram = 0,
+ /// Gram unit (g)
+ [Abbreviation("g")]
+ Gram = 1,
+ /// Kilogram unit (kg)
+ [Abbreviation("kg")]
+ Kilogram = 2,
+ /// Ounce unit (oz)
+ [Abbreviation("oz")]
+ Ounce = 3,
+ /// Pound unit (lb)
+ [Abbreviation("lb")]
+ Pound = 4,
+ /// Ton unit (ton)
+ [Abbreviation("ton")]
+ Ton = 5,
+ }
+
+ ///
+ /// Class representing mass convertion.
+ ///
+ public static class MassConverter
+ {
+ // In enum order
+ private static readonly double[] factors = new double[]
+ {
+ 0.000001d, //milligram
+ 0.001d, //gram
+ 1d, //kilogram
+ 0.45359237d/16d, //ounce
+ 0.45359237d, //pound
+ 0.45359237d*2000d, //ton [short, US]
+ };
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ MassUnit fromUnit,
+ MassUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ double fromFactor = factors[(int)fromUnit];
+ double toFactor = factors[(int)toUnit];
+ double result = fromFactor * fromValue / toFactor;
+ return result;
+ }
+
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/SpeedConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/SpeedConverter.cs
new file mode 100644
index 0000000..82b4c50
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/SpeedConverter.cs
@@ -0,0 +1,71 @@
+using LoreSoft.MathExpressions.Metadata;
+using System.ComponentModel;
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Speed
+ public enum SpeedUnit
+ {
+ /// Meter/Second unit (m/s)
+ [Abbreviation("m/s")]
+ [Description("Meter/Second")]
+ MeterPerSecond = 0,
+ /// Kilometer/Hour unit (kph)
+ [Abbreviation("kph")]
+ [Description("Kilometer/Hour")]
+ KilometerPerHour = 1,
+ /// Foot/Second unit (ft/s)
+ [Abbreviation("ft/s")]
+ [Description("Foot/Second")]
+ FootPerSecond = 2,
+ /// Mile/Hour unit (mph)
+ [Abbreviation("mph")]
+ [Description("Mile/Hour")]
+ MilePerHour = 3,
+ /// Knot unit (knot)
+ [Abbreviation("knot")]
+ Knot = 4,
+ /// Mach unit (mach)
+ [Abbreviation("mach")]
+ Mach = 5,
+ }
+
+ ///
+ /// Class representing speed convertion.
+ ///
+ public static class SpeedConverter
+ {
+ // In enum order
+ private static readonly double[] factors = new double[]
+ {
+ 1d, //meter/second
+ 1000d/3600d, //kilometer/hour
+ 0.3048d, //foot/second
+ (0.3048d*5280d)/3600d, //mile/hour (mph)
+ 1852d/3600d, //knot
+ 340.29d, //mach
+ };
+
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ SpeedUnit fromUnit,
+ SpeedUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ double fromFactor = factors[(int)fromUnit];
+ double toFactor = factors[(int)toUnit];
+ double result = fromFactor * fromValue / toFactor;
+ return result;
+ }
+
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/TemperatureConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/TemperatureConverter.cs
new file mode 100644
index 0000000..5589398
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/TemperatureConverter.cs
@@ -0,0 +1,67 @@
+using LoreSoft.MathExpressions.Metadata;
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Temperature
+ public enum TemperatureUnit
+ {
+ /// Degrees Celsius unit (c)
+ [Abbreviation("c")]
+ Celsius = 0,
+ /// Degrees Fahrenheit unit (f)
+ [Abbreviation("f")]
+ Fahrenheit = 1,
+ /// Degrees Kelvin unit (k)
+ [Abbreviation("k")]
+ Kelvin = 2
+ }
+
+ ///
+ /// Class representing temperature convertion.
+ ///
+ public static class TemperatureConverter
+ {
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ TemperatureUnit fromUnit,
+ TemperatureUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ double result = 0;
+
+ if (fromUnit == TemperatureUnit.Celsius)
+ {
+ if (toUnit == TemperatureUnit.Kelvin)
+ result = fromValue + 273.15d;
+ else if (toUnit == TemperatureUnit.Fahrenheit)
+ //(9/5 * C) + 32 = F
+ result = (9.0d/5.0d*fromValue) + 32d;
+ }
+ else if (fromUnit == TemperatureUnit.Kelvin)
+ {
+ if (toUnit == TemperatureUnit.Celsius)
+ result = fromValue - 273.15d;
+ else if (toUnit == TemperatureUnit.Fahrenheit)
+ result = 5.0d/9.0d*((fromValue - 273.15d) + 32d);
+ }
+ else if (fromUnit == TemperatureUnit.Fahrenheit)
+ {
+ if (toUnit == TemperatureUnit.Celsius)
+ //(F - 32) * 5/9 = C
+ result = 5.0d/9.0d*(fromValue - 32d);
+ else if (toUnit == TemperatureUnit.Kelvin)
+ result = (5.0d/9.0d*(fromValue - 32d)) + 273.15;
+ }
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/TimeConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/TimeConverter.cs
new file mode 100644
index 0000000..a786e69
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/TimeConverter.cs
@@ -0,0 +1,94 @@
+using System;
+using LoreSoft.MathExpressions.Metadata;
+
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Time
+ public enum TimeUnit
+ {
+ /// Millisecond unit (ms)
+ [Abbreviation("ms")]
+ Millisecond = 0,
+ /// Second unit (sec)
+ [Abbreviation("sec")]
+ Second = 1,
+ /// Minute unit (min)
+ [Abbreviation("min")]
+ Minute = 2,
+ /// Hour unit (hr)
+ [Abbreviation("hr")]
+ Hour = 3,
+ /// Day unit (d)
+ [Abbreviation("d")]
+ Day = 4,
+ /// Week unit (wk)
+ [Abbreviation("wk")]
+ Week = 5
+ }
+
+ ///
+ /// Class representing time convertion.
+ ///
+ public static class TimeConverter
+ {
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ TimeUnit fromUnit,
+ TimeUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ TimeSpan span;
+ switch (fromUnit)
+ {
+ case TimeUnit.Millisecond:
+ span = TimeSpan.FromMilliseconds(fromValue);
+ break;
+ case TimeUnit.Second:
+ span = TimeSpan.FromSeconds(fromValue);
+ break;
+ case TimeUnit.Minute:
+ span = TimeSpan.FromMinutes(fromValue);
+ break;
+ case TimeUnit.Hour:
+ span = TimeSpan.FromHours(fromValue);
+ break;
+ case TimeUnit.Day:
+ span = TimeSpan.FromDays(fromValue);
+ break;
+ case TimeUnit.Week:
+ span = TimeSpan.FromDays(fromValue * 7d);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("fromUnit");
+ }
+
+ switch (toUnit)
+ {
+ case TimeUnit.Millisecond:
+ return span.TotalMilliseconds;
+ case TimeUnit.Second:
+ return span.TotalSeconds;
+ case TimeUnit.Minute:
+ return span.TotalMinutes;
+ case TimeUnit.Hour:
+ return span.TotalHours;
+ case TimeUnit.Day:
+ return span.TotalDays;
+ case TimeUnit.Week:
+ return span.TotalDays / 7d;
+ default:
+ throw new ArgumentOutOfRangeException("toUnit");
+ }
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/UnitType.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/UnitType.cs
new file mode 100644
index 0000000..17457dd
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/UnitType.cs
@@ -0,0 +1,19 @@
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ ///The unit types available for conversion.
+ public enum UnitType
+ {
+ ///Length unit types.
+ Length,
+ ///Mass unit types.
+ Mass,
+ ///Speed unit types.
+ Speed,
+ ///Temperature unit types.
+ Temperature,
+ ///Time unit types.
+ Time,
+ ///Volume unit types.
+ Volume
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/UnitConversion/VolumeConverter.cs b/Shared/LoreSoft.MathExpressions/UnitConversion/VolumeConverter.cs
new file mode 100644
index 0000000..5661b3a
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/UnitConversion/VolumeConverter.cs
@@ -0,0 +1,74 @@
+using LoreSoft.MathExpressions.Metadata;
+using System.ComponentModel;
+namespace LoreSoft.MathExpressions.UnitConversion
+{
+ /// Units for Liquid Volume
+ public enum VolumeUnit
+ {
+ /// Milliliter unit (ml)
+ [Abbreviation("ml")]
+ Milliliter = 0,
+ /// Liter unit (l)
+ [Abbreviation("l")]
+ Liter = 1,
+ /// Kiloliter unit (kl)
+ [Abbreviation("kl")]
+ Kiloliter = 2,
+ /// Fluid ounce unit (oz)
+ [Abbreviation("oz")]
+ [Description("Fluid Ounce")]
+ FluidOunce = 3,
+ /// Cup unit (cup)
+ [Abbreviation("cup")]
+ Cup = 4,
+ /// Pint unit (pt)
+ [Abbreviation("pt")]
+ Pint = 5,
+ /// Quart unit (qt)
+ [Abbreviation("qt")]
+ Quart = 6,
+ /// Gallon unit (gal)
+ [Abbreviation("gal")]
+ Gallon = 7
+ }
+
+ ///
+ /// Class representing liquid volume convertion.
+ ///
+ public static class VolumeConverter
+ {
+ // In enum order
+ private static readonly double[] factors = new double[]
+ {
+ 0.000001d, //milliliter
+ 0.001d, //liter
+ 1d, //kiloliter
+ 0.0037854118d/128d, //ounce [US, liquid]
+ 0.0037854118d/16d, //cup [US]
+ 0.0037854118d/8d, //pint [US, liquid]
+ 0.0037854118d/4d, //quart [US, liquid]
+ 0.0037854118d, //gallon [US, liquid]
+ };
+
+ ///
+ /// Converts the specified from unit to the specified unit.
+ ///
+ /// Covert from unit.
+ /// Covert to unit.
+ /// Covert from value.
+ /// The converted value.
+ public static double Convert(
+ VolumeUnit fromUnit,
+ VolumeUnit toUnit,
+ double fromValue)
+ {
+ if (fromUnit == toUnit)
+ return fromValue;
+
+ double fromFactor = factors[(int)fromUnit];
+ double toFactor = factors[(int)toUnit];
+ double result = fromFactor * fromValue / toFactor;
+ return result;
+ }
+ }
+}
diff --git a/Shared/LoreSoft.MathExpressions/VariableDictionary.cs b/Shared/LoreSoft.MathExpressions/VariableDictionary.cs
new file mode 100644
index 0000000..30ed676
--- /dev/null
+++ b/Shared/LoreSoft.MathExpressions/VariableDictionary.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using LoreSoft.MathExpressions.Properties;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace LoreSoft.MathExpressions
+{
+ ///
+ /// Class representing a collection of variable names and values.
+ ///
+ ///
+ /// Variable names can only contain letters, numbers and symbols are not allowed.
+ ///
+ [Serializable]
+ public class VariableDictionary : Dictionary
+ {
+ private MathEvaluator _evaluator;
+
+ /// Initializes a new instance of the class.
+ /// The evaluator.
+ internal VariableDictionary(MathEvaluator evaluator)
+ : base(StringComparer.OrdinalIgnoreCase)
+ {
+ _evaluator = evaluator;
+ base.Add(MathEvaluator.AnswerVariable, 0);
+ base.Add("pi", Math.PI);
+ base.Add("e", Math.E);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A object containing the information required to serialize the .
+ /// A structure containing the source and destination of the serialized stream associated with the .
+ protected VariableDictionary(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+
+ /// Adds the specified variable and value to the dictionary.
+ /// The name of the variable to add.
+ /// The value of the variable.
+ /// When variable name is null.
+ /// When variable name contains non-letters or the name exists in the list.
+ ///
+ ///
+ ///
+ public new void Add(string name, double value)
+ {
+ Validate(name);
+ base.Add(name, value);
+ }
+
+ private void Validate(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ throw new ArgumentNullException("name");
+
+ if (_evaluator.IsFunction(name))
+ throw new ArgumentException(
+ string.Format(CultureInfo.CurrentCulture,
+ Resources.VariableNameConflict, name), "name");
+
+ for (int i = 0; i < name.Length; i++)
+ if (!char.IsLetter(name[i]))
+ throw new ArgumentException(Resources.VariableNameContainsLetters, "name");
+ }
+
+ ///
+ /// Implements the interface and returns the data needed to serialize the instance.
+ ///
+ /// A object that contains the information required to serialize the instance.
+ /// A structure that contains the source and destination of the serialized stream associated with the instance.
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ }
+
+ }
+}
diff --git a/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs b/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs
index 2345a0f..36775e2 100644
--- a/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs
+++ b/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs
@@ -1,5 +1,5 @@
-using Shared.Models;
-using Shared.ZatVdfParser;
+using SteamShared.Models;
+using SteamShared.ZatVdfParser;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -9,7 +9,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared
+namespace SteamShared
{
public class CsgoHelper
{
diff --git a/Shared/SteamHelpers/SteamHelpers/DDSImageParser.cs b/Shared/SteamHelpers/SteamHelpers/DDSImageParser.cs
index 3e10087..08f987c 100644
--- a/Shared/SteamHelpers/SteamHelpers/DDSImageParser.cs
+++ b/Shared/SteamHelpers/SteamHelpers/DDSImageParser.cs
@@ -5,7 +5,7 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
-namespace Shared
+namespace SteamShared
{
#region DDSImage Class
public class DDSImage : IDisposable
diff --git a/Shared/SteamHelpers/SteamHelpers/Globals.cs b/Shared/SteamHelpers/SteamHelpers/Globals.cs
index 2c2f54c..7063ba2 100644
--- a/Shared/SteamHelpers/SteamHelpers/Globals.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Globals.cs
@@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
-namespace Shared
+namespace SteamShared
{
public static class Globals
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/BSPHeader.cs b/Shared/SteamHelpers/SteamHelpers/Models/BSPHeader.cs
index 86a7d93..3d4bf37 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/BSPHeader.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/BSPHeader.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
internal class BSPHeader
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/BSPLump.cs b/Shared/SteamHelpers/SteamHelpers/Models/BSPLump.cs
index 40fc2db..e0e0e06 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/BSPLump.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/BSPLump.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
internal class BSPLump
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/CsgoMap.cs b/Shared/SteamHelpers/SteamHelpers/Models/CsgoMap.cs
index 596da28..fa42b63 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/CsgoMap.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/CsgoMap.cs
@@ -6,7 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class CsgoMap
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs b/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs
index c80edaf..bddd24e 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs
@@ -6,7 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class CsgoWeapon
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/MapCustomOverwriteMapping.cs b/Shared/SteamHelpers/SteamHelpers/Models/MapCustomOverwriteMapping.cs
index 3b7f033..65b2398 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/MapCustomOverwriteMapping.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/MapCustomOverwriteMapping.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class MapCustomOverwriteMapping
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/MapPoint.cs b/Shared/SteamHelpers/SteamHelpers/Models/MapPoint.cs
index ee6e05e..1ccb0d6 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/MapPoint.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/MapPoint.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class MapPoint
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavApproachSpot.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavApproachSpot.cs
index 56a2627..a591afd 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavApproachSpot.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavApproachSpot.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavApproachSpot
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavArea.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavArea.cs
index 032f7cf..c0bab9b 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavArea.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavArea.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavArea
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavAreaBind.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavAreaBind.cs
index 008184a..fd92f48 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavAreaBind.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavAreaBind.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavAreaBind
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavConnectionData.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavConnectionData.cs
index 1ac6cb2..63afe14 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavConnectionData.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavConnectionData.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavConnectionData
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterPath.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterPath.cs
index 126bb58..8555141 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterPath.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterPath.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavEncounterPath
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterSpot.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterSpot.cs
index e300093..f52606b 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterSpot.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavEncounterSpot.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavEncounterSpot
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavHeader.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavHeader.cs
index c6cbc5b..ba6b65e 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavHeader.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavHeader.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavHeader
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavHidingSpot.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavHidingSpot.cs
index 72d4af4..07b72d8 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavHidingSpot.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavHidingSpot.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
[Flags]
public enum HidingSpotAttribute
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavLadder.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavLadder.cs
index 4c4d95e..5f36b8f 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavLadder.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavLadder.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavLadder
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavLadderIDSequence.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavLadderIDSequence.cs
index 8691de0..8114d6a 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavLadderIDSequence.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavLadderIDSequence.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavLadderIDSequence
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/NavMesh.cs b/Shared/SteamHelpers/SteamHelpers/Models/NavMesh.cs
index 2ce0357..411f7aa 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/NavMesh.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/NavMesh.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class NavMesh
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/PlayerSpawn.cs b/Shared/SteamHelpers/SteamHelpers/Models/PlayerSpawn.cs
index 2604696..e30f5cb 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/PlayerSpawn.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/PlayerSpawn.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class PlayerSpawn
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/Settings.cs b/Shared/SteamHelpers/SteamHelpers/Models/Settings.cs
index 518d32f..d185fa0 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/Settings.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/Settings.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class Settings
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/SteamGame.cs b/Shared/SteamHelpers/SteamHelpers/Models/SteamGame.cs
index 3e59471..771ace9 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/SteamGame.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/SteamGame.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class SteamGame
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/SteamLibrary.cs b/Shared/SteamHelpers/SteamHelpers/Models/SteamLibrary.cs
index fc69adb..d7b0273 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/SteamLibrary.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/SteamLibrary.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class SteamLibrary
{
diff --git a/Shared/SteamHelpers/SteamHelpers/Models/Vector3.cs b/Shared/SteamHelpers/SteamHelpers/Models/Vector3.cs
index fd8a084..95ca3c6 100644
--- a/Shared/SteamHelpers/SteamHelpers/Models/Vector3.cs
+++ b/Shared/SteamHelpers/SteamHelpers/Models/Vector3.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace Shared.Models
+namespace SteamShared.Models
{
public class Vector3
{
diff --git a/Shared/SteamHelpers/SteamHelpers/NavFile.cs b/Shared/SteamHelpers/SteamHelpers/NavFile.cs
index 79f683d..20e8601 100644
--- a/Shared/SteamHelpers/SteamHelpers/NavFile.cs
+++ b/Shared/SteamHelpers/SteamHelpers/NavFile.cs
@@ -4,9 +4,9 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Shared.Models;
+using SteamShared.Models;
-namespace Shared
+namespace SteamShared
{
public enum NavDisplayModes { None, Wireframe, Filled }
diff --git a/Shared/SteamHelpers/SteamHelpers/SourceCFG/SourceCFG.cs b/Shared/SteamHelpers/SteamHelpers/SourceCFG/SourceCFG.cs
new file mode 100644
index 0000000..1d2bbb9
--- /dev/null
+++ b/Shared/SteamHelpers/SteamHelpers/SourceCFG/SourceCFG.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SteamShared
+{
+ public class SourceCFG
+ {
+ }
+}
diff --git a/Shared/SteamHelpers/SteamHelpers/SteamHelper.cs b/Shared/SteamHelpers/SteamHelpers/SteamHelper.cs
index 52a608f..ace081b 100644
--- a/Shared/SteamHelpers/SteamHelpers/SteamHelper.cs
+++ b/Shared/SteamHelpers/SteamHelpers/SteamHelper.cs
@@ -4,11 +4,11 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Shared.ZatVdfParser;
+using SteamShared.ZatVdfParser;
using Microsoft.Win32;
-using Shared.Models;
+using SteamShared.Models;
-namespace Shared
+namespace SteamShared
{
public class SteamHelper
{
@@ -75,7 +75,7 @@ namespace Shared
}
///
- /// Forcefully tries to update the property with the current Steam path, even if it should be already set.
+ /// Forcefully tries to update the property with the current Steam libraries, even if they should be already set.
///
public void UpdateSteamLibraries()
{
diff --git a/Shared/SteamHelpers/SteamHelpers/SteamHelpers.csproj b/Shared/SteamHelpers/SteamHelpers/SteamShared.csproj
similarity index 85%
rename from Shared/SteamHelpers/SteamHelpers/SteamHelpers.csproj
rename to Shared/SteamHelpers/SteamHelpers/SteamShared.csproj
index 3419fff..5624e47 100644
--- a/Shared/SteamHelpers/SteamHelpers/SteamHelpers.csproj
+++ b/Shared/SteamHelpers/SteamHelpers/SteamShared.csproj
@@ -1,10 +1,11 @@
-
+
net6.0-windows
enable
true
True
+ AnyCPU;x64
diff --git a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/BackupVdfReader.cs b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/BackupVdfReader.cs
index 5ce8e8e..c7edb66 100644
--- a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/BackupVdfReader.cs
+++ b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/BackupVdfReader.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.IO;
-namespace Shared.ZatVdfParser
+namespace SteamShared.ZatVdfParser
{
///
/// This class was copied from here as a backup, in case didn't work well enough.
diff --git a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/Element.cs b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/Element.cs
index cf179cb..20e33b2 100644
--- a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/Element.cs
+++ b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/Element.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
-namespace Shared.ZatVdfParser
+namespace SteamShared.ZatVdfParser
{
public class Element
{
diff --git a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/VdfFile.cs b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/VdfFile.cs
index 87e567b..0c570e5 100644
--- a/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/VdfFile.cs
+++ b/Shared/SteamHelpers/SteamHelpers/ZatVdfParser/VdfFile.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
-namespace Shared.ZatVdfParser
+namespace SteamShared.ZatVdfParser
{
public class VDFFile
{
@@ -55,7 +55,7 @@ namespace Shared.ZatVdfParser
string? line = null;
while ((line = reader.ReadLine()) != null)
{
- if (line.StartsWith("\0"))
+ if (line.StartsWith("\0", StringComparison.Ordinal))
return;
line = line.Trim();