213 lines
4.4 KiB
C#
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);
|
|
}
|
|
}
|