""" Ported from units.py - Sopel Unit Conversion Plugin Copyright © 2013, Elad Alfassa, Copyright © 2013, Dimitri Molenaars, Licensed under the Eiffel Forum License 2. https://sopel.chat Eiffel Forum License, version 2 1. Permission is hereby granted to use, copy, modify and/or distribute this package, provided that: * copyright notices are retained unchanged, * any distribution of this package, whether modified or not, includes this license text. 2. Permission is hereby also granted to distribute binary programs which depend on this package. If the binary program depends on a modified version of this package, you are encouraged to publicly release the modified version of this package. *********************** THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THIS PACKAGE. *********************** """ import re find_temp = re.compile(r'(-?[0-9]*\.?[0-9]*)[ °]*(K|C|F)', re.IGNORECASE) find_length = re.compile(r'([0-9]*\.?[0-9]*)[ ]*(mile[s]?|mi|inch|in|foot|feet|ft|yard[s]?|yd|(?:milli|centi|kilo|)meter[s]?|[mkc]?m|ly|light-year[s]?|au|astronomical unit[s]?|parsec[s]?|pc)', re.IGNORECASE) find_mass = re.compile(r'([0-9]*\.?[0-9]*)[ ]*(lb|lbm|pound[s]?|ounce|oz|(?:kilo|)gram(?:me|)[s]?|[k]?g)', re.IGNORECASE) def f_to_c(temp): return (float(temp) - 32) * 5 / 9 def c_to_k(temp): return temp + 273.15 def c_to_f(temp): return (9.0 / 5.0 * temp + 32) def k_to_c(temp): return temp - 273.15 # A quick "reply" function def _reply(irc, hostmask, args, msg): mention = hostmask[0] if not hostmask[0].endswith('>'): mention += ':' irc.msg(args[0], mention, msg) @register_command('temp') def temperature(irc, hostmask, is_admin, args): """Convert temperatures""" reply = lambda msg : _reply(irc, hostmask, args, msg) try: source = find_temp.match(args[-1]).groups() except (AttributeError, TypeError): reply("That's not a valid temperature.") return unit = source[1].upper() numeric = float(source[0]) celsius = 0 if unit == 'C': celsius = numeric elif unit == 'F': celsius = f_to_c(numeric) elif unit == 'K': celsius = k_to_c(numeric) kelvin = c_to_k(celsius) fahrenheit = c_to_f(celsius) if kelvin >= 0: reply("{:.2f}°C = {:.2f}°F = {:.2f}K".format(celsius, fahrenheit, kelvin)) else: reply("Physically impossible temperature.") @register_command('length', 'distance') def distance(irc, hostmask, is_admin, args): """Convert distances""" reply = lambda msg : _reply(irc, hostmask, args, msg) try: source = find_length.match(args[-1]).groups() except (AttributeError, TypeError): reply("That's not a valid length unit.") return unit = source[1].lower() numeric = float(source[0]) meter = 0 if unit in ("meters", "meter", "m"): meter = numeric elif unit in ("millimeters", "millimeter", "mm"): meter = numeric / 1000 elif unit in ("kilometers", "kilometer", "km"): meter = numeric * 1000 elif unit in ("miles", "mile", "mi"): meter = numeric / 0.00062137 elif unit in ("inch", "in"): meter = numeric / 39.370 elif unit in ("centimeters", "centimeter", "cm"): meter = numeric / 100 elif unit in ("feet", "foot", "ft"): meter = numeric / 3.2808 elif unit in ("yards", "yard", "yd"): meter = numeric / (3.2808 / 3) elif unit in ("light-year", "light-years", "ly"): meter = numeric * 9460730472580800 elif unit in ("astronomical unit", "astronomical units", "au"): meter = numeric * 149597870700 elif unit in ("parsec", "parsecs", "pc"): meter = numeric * 30856776376340068 if meter >= 1000: metric_part = '{:.2f}km'.format(meter / 1000) elif meter < 0.01: metric_part = '{:.2f}mm'.format(meter * 1000) elif meter < 1: metric_part = '{:.2f}cm'.format(meter * 100) else: metric_part = '{:.2f}m'.format(meter) inch = meter * 39.37 foot = int(inch) // 12 inch = inch - (foot * 12) yard = foot // 3 mile = meter * 0.000621371192 if yard > 500: imperial_part = '{:.2f} miles'.format(mile) else: parts = [] if yard >= 100: parts.append('{} yards'.format(yard)) foot -= (yard * 3) if foot == 1: parts.append('1 foot') elif foot != 0: parts.append('{:.0f} feet'.format(foot)) parts.append('{:.2f} inches'.format(inch)) imperial_part = ', '.join(parts) reply('{} = {}'.format(metric_part, imperial_part)) @register_command('weight', 'mass') def mass(irc, hostmask, is_admin, args): """Convert mass""" reply = lambda msg : _reply(irc, hostmask, args, msg) try: source = find_mass.match(args[-1]).groups() except (AttributeError, TypeError): reply("That's not a valid mass unit.") return unit = source[1].lower() numeric = float(source[0]) metric = 0 if unit in ("gram", "grams", "gramme", "grammes", "g"): metric = numeric elif unit in ("kilogram", "kilograms", "kilogramme", "kilogrammes", "kg"): metric = numeric * 1000 elif unit in ("lb", "lbm", "pound", "pounds"): metric = numeric * 453.59237 elif unit in ("oz", "ounce"): metric = numeric * 28.35 if metric >= 1000: metric_part = '{:.2f}kg'.format(metric / 1000) else: metric_part = '{:.2f}g'.format(metric) ounce = metric * .035274 pound = int(ounce) // 16 ounce = ounce - (pound * 16) if pound >= 1: imperial_part = f'{pound} pound{"" if pound == 1 else "s"}' if ounce > 0.01: imperial_part += ' {:.2f} ounces'.format(ounce) else: imperial_part = '{:.2f} oz'.format(ounce) reply('{} = {}'.format(metric_part, imperial_part))