Files

213 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
namespace AxCopilot.Handlers;
internal static class UnitConverter
{
private static readonly Regex Pattern = new Regex("^(-?\\d+(?:\\.\\d+)?)\\s*([a-z°/²³µ]+)\\s+(?:in|to)\\s+([a-z°/²³µ]+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Dictionary<string, double> _length = new Dictionary<string, double>
{
["km"] = 1000.0,
["m"] = 1.0,
["cm"] = 0.01,
["mm"] = 0.001,
["mi"] = 1609.344,
["mile"] = 1609.344,
["miles"] = 1609.344,
["ft"] = 0.3048,
["feet"] = 0.3048,
["foot"] = 0.3048,
["in"] = 0.0254,
["inch"] = 0.0254,
["inches"] = 0.0254,
["yd"] = 0.9144,
["yard"] = 0.9144,
["yards"] = 0.9144,
["nm"] = 1E-09
};
private static readonly Dictionary<string, double> _weight = new Dictionary<string, double>
{
["t"] = 1000.0,
["ton"] = 1000.0,
["tonnes"] = 1000.0,
["kg"] = 1.0,
["g"] = 0.001,
["mg"] = 1E-06,
["lb"] = 0.453592,
["lbs"] = 0.453592,
["pound"] = 0.453592,
["pounds"] = 0.453592,
["oz"] = 0.0283495,
["ounce"] = 0.0283495,
["ounces"] = 0.0283495
};
private static readonly Dictionary<string, double> _speed = new Dictionary<string, double>
{
["m/s"] = 1.0,
["mps"] = 1.0,
["km/h"] = 5.0 / 18.0,
["kmh"] = 5.0 / 18.0,
["kph"] = 5.0 / 18.0,
["mph"] = 0.44704,
["kn"] = 0.514444,
["knot"] = 0.514444,
["knots"] = 0.514444
};
private static readonly Dictionary<string, double> _data = new Dictionary<string, double>
{
["b"] = 1.0,
["byte"] = 1.0,
["bytes"] = 1.0,
["kb"] = 1024.0,
["kib"] = 1024.0,
["mb"] = 1048576.0,
["mib"] = 1048576.0,
["gb"] = 1073741824.0,
["gib"] = 1073741824.0,
["tb"] = 1099511627776.0,
["tib"] = 1099511627776.0,
["pb"] = 1125899906842624.0
};
private static readonly Dictionary<string, double> _area = new Dictionary<string, double>
{
["m²"] = 1.0,
["m2"] = 1.0,
["km²"] = 1000000.0,
["km2"] = 1000000.0,
["cm²"] = 0.0001,
["cm2"] = 0.0001,
["ha"] = 10000.0,
["acre"] = 4046.86,
["acres"] = 4046.86,
["ft²"] = 0.092903,
["ft2"] = 0.092903
};
private static readonly List<Dictionary<string, double>> _tables = new List<Dictionary<string, double>> { _length, _weight, _speed, _data, _area };
public static bool TryConvert(string input, out string? result)
{
result = null;
Match match = Pattern.Match(input.Trim());
if (!match.Success)
{
return false;
}
if (!double.TryParse(match.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
{
return false;
}
string text = match.Groups[2].Value.ToLowerInvariant();
string text2 = match.Groups[3].Value.ToLowerInvariant();
if (TryConvertTemperature(result2, text, text2, out var r))
{
result = FormatNum(r) + " " + TemperatureLabel(text2);
return true;
}
foreach (Dictionary<string, double> table in _tables)
{
if (table.TryGetValue(text, out var value) && table.TryGetValue(text2, out var value2))
{
double v = result2 * value / value2;
result = FormatNum(v) + " " + text2;
return true;
}
}
return false;
}
private static bool TryConvertTemperature(double v, string from, string to, out double r)
{
r = 0.0;
double num;
switch (from)
{
case "c":
case "°c":
case "celsius":
num = v;
break;
case "f":
case "°f":
case "fahrenheit":
num = (v - 32.0) * 5.0 / 9.0;
break;
case "k":
case "kelvin":
num = v - 273.15;
break;
default:
return false;
}
switch (to)
{
case "c":
case "°c":
case "celsius":
r = num;
break;
case "f":
case "°f":
case "fahrenheit":
r = num * 9.0 / 5.0 + 32.0;
break;
case "k":
case "kelvin":
r = num + 273.15;
break;
default:
return false;
}
return true;
}
private static string TemperatureLabel(string unit)
{
if (1 == 0)
{
}
string result;
switch (unit)
{
case "c":
case "°c":
case "celsius":
result = "°C";
break;
case "f":
case "°f":
case "fahrenheit":
result = "°F";
break;
case "k":
case "kelvin":
result = "K";
break;
default:
result = unit;
break;
}
if (1 == 0)
{
}
return result;
}
private static string FormatNum(double v)
{
if (v == Math.Floor(v) && Math.Abs(v) < 1000000000000.0)
{
return ((long)v).ToString("N0", CultureInfo.CurrentCulture);
}
return v.ToString("G6", CultureInfo.InvariantCulture);
}
}