From 50ac34fb28a9a655c3cba7639966de3f85210075 Mon Sep 17 00:00:00 2001 From: MathiasL Date: Fri, 20 May 2022 22:20:45 +0200 Subject: [PATCH] Add hacky damage displayer (Will get refactored) * Change Shared namespace to SteamShared * Add damage displayer which also calculates, gets local weather and fuel prices * API Key for tankerkoenig has to be supplied because I didn't push it --- DamagePrinter/DamagePrinter.sln | 65 +++ .../DamagePrinter/DamagePrinter.csproj | 20 + DamagePrinter/DamagePrinter/Program.cs | 363 ++++++++++++++ .../ConvertExpression.cs | 225 +++++++++ .../ExpressionBase.cs | 35 ++ .../FunctionExpression.cs | 113 +++++ .../GlobalSuppressions.cs | 2 + .../LoreSoft.MathExpressions/IExpression.cs | 15 + .../LoreSoft.MathExpressions.csproj | 185 +++++++ .../LoreSoft.MathExpressions/MathEvaluate.cs | 7 + .../LoreSoft.MathExpressions/MathEvaluator.cs | 458 ++++++++++++++++++ .../MathExpressions.snk | Bin 0 -> 596 bytes .../LoreSoft.MathExpressions/MathOperators.cs | 19 + .../Metadata/AbbreviationAttribute.cs | 45 ++ .../Metadata/AttributeReader.cs | 108 +++++ .../NumberExpression.cs | 68 +++ .../OperatorExpression.cs | 203 ++++++++ .../ParseException.cs | 40 ++ .../Properties/AssemblyInfo.cs | 50 ++ .../Properties/Resources.Designer.cs | 198 ++++++++ .../Properties/Resources.resx | 165 +++++++ .../UnitConversion/LengthConverter.cs | 75 +++ .../UnitConversion/MassConverter.cs | 65 +++ .../UnitConversion/SpeedConverter.cs | 71 +++ .../UnitConversion/TemperatureConverter.cs | 67 +++ .../UnitConversion/TimeConverter.cs | 94 ++++ .../UnitConversion/UnitType.cs | 19 + .../UnitConversion/VolumeConverter.cs | 74 +++ .../VariableDictionary.cs | 82 ++++ .../SteamHelpers/SteamHelpers/CsgoHelper.cs | 6 +- .../SteamHelpers/DDSImageParser.cs | 2 +- Shared/SteamHelpers/SteamHelpers/Globals.cs | 2 +- .../SteamHelpers/Models/BSPHeader.cs | 2 +- .../SteamHelpers/Models/BSPLump.cs | 2 +- .../SteamHelpers/Models/CsgoMap.cs | 2 +- .../SteamHelpers/Models/CsgoWeapon.cs | 2 +- .../Models/MapCustomOverwriteMapping.cs | 2 +- .../SteamHelpers/Models/MapPoint.cs | 2 +- .../SteamHelpers/Models/NavApproachSpot.cs | 2 +- .../SteamHelpers/Models/NavArea.cs | 2 +- .../SteamHelpers/Models/NavAreaBind.cs | 2 +- .../SteamHelpers/Models/NavConnectionData.cs | 2 +- .../SteamHelpers/Models/NavEncounterPath.cs | 2 +- .../SteamHelpers/Models/NavEncounterSpot.cs | 2 +- .../SteamHelpers/Models/NavHeader.cs | 2 +- .../SteamHelpers/Models/NavHidingSpot.cs | 2 +- .../SteamHelpers/Models/NavLadder.cs | 2 +- .../Models/NavLadderIDSequence.cs | 2 +- .../SteamHelpers/Models/NavMesh.cs | 2 +- .../SteamHelpers/Models/PlayerSpawn.cs | 2 +- .../SteamHelpers/Models/Settings.cs | 2 +- .../SteamHelpers/Models/SteamGame.cs | 2 +- .../SteamHelpers/Models/SteamLibrary.cs | 2 +- .../SteamHelpers/Models/Vector3.cs | 2 +- Shared/SteamHelpers/SteamHelpers/NavFile.cs | 4 +- .../SteamHelpers/SourceCFG/SourceCFG.cs | 12 + .../SteamHelpers/SteamHelpers/SteamHelper.cs | 8 +- ...SteamHelpers.csproj => SteamShared.csproj} | 3 +- .../ZatVdfParser/BackupVdfReader.cs | 2 +- .../SteamHelpers/ZatVdfParser/Element.cs | 2 +- .../SteamHelpers/ZatVdfParser/VdfFile.cs | 4 +- 61 files changed, 2982 insertions(+), 38 deletions(-) create mode 100644 DamagePrinter/DamagePrinter.sln create mode 100644 DamagePrinter/DamagePrinter/DamagePrinter.csproj create mode 100644 DamagePrinter/DamagePrinter/Program.cs create mode 100644 Shared/LoreSoft.MathExpressions/ConvertExpression.cs create mode 100644 Shared/LoreSoft.MathExpressions/ExpressionBase.cs create mode 100644 Shared/LoreSoft.MathExpressions/FunctionExpression.cs create mode 100644 Shared/LoreSoft.MathExpressions/GlobalSuppressions.cs create mode 100644 Shared/LoreSoft.MathExpressions/IExpression.cs create mode 100644 Shared/LoreSoft.MathExpressions/LoreSoft.MathExpressions.csproj create mode 100644 Shared/LoreSoft.MathExpressions/MathEvaluate.cs create mode 100644 Shared/LoreSoft.MathExpressions/MathEvaluator.cs create mode 100644 Shared/LoreSoft.MathExpressions/MathExpressions.snk create mode 100644 Shared/LoreSoft.MathExpressions/MathOperators.cs create mode 100644 Shared/LoreSoft.MathExpressions/Metadata/AbbreviationAttribute.cs create mode 100644 Shared/LoreSoft.MathExpressions/Metadata/AttributeReader.cs create mode 100644 Shared/LoreSoft.MathExpressions/NumberExpression.cs create mode 100644 Shared/LoreSoft.MathExpressions/OperatorExpression.cs create mode 100644 Shared/LoreSoft.MathExpressions/ParseException.cs create mode 100644 Shared/LoreSoft.MathExpressions/Properties/AssemblyInfo.cs create mode 100644 Shared/LoreSoft.MathExpressions/Properties/Resources.Designer.cs create mode 100644 Shared/LoreSoft.MathExpressions/Properties/Resources.resx create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/LengthConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/MassConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/SpeedConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/TemperatureConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/TimeConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/UnitType.cs create mode 100644 Shared/LoreSoft.MathExpressions/UnitConversion/VolumeConverter.cs create mode 100644 Shared/LoreSoft.MathExpressions/VariableDictionary.cs create mode 100644 Shared/SteamHelpers/SteamHelpers/SourceCFG/SourceCFG.cs rename Shared/SteamHelpers/SteamHelpers/{SteamHelpers.csproj => SteamShared.csproj} (85%) 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 0000000000000000000000000000000000000000..7788283f6fba900ffae398c004025024b2de0271 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098M?u?~)IDd?UW9IpEykRf(7U1c4b}y5n zL#-#+?@8gG1$z!1qV3oJQWko25yu42h6EW4jm3oX!ipuN#jh3vrUK!D15}92C^T>z z>*K^DLw5MO-n#uBtYGGOV4SRHU)9Nc4oLrG3i7n_R%br~L7i!{Uc>*wguEam4gt6k zb~lr`_Hq7AneLk@sq6*RYW&3=QEnxNqIf$C!PMath 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();