|
1
|
|
|
# coding=utf-8 |
|
2
|
|
|
""" |
|
3
|
|
|
units.py - Unit conversion module for Sopel |
|
4
|
|
|
Copyright © 2013, Elad Alfassa, <[email protected]> |
|
5
|
|
|
Copyright © 2013, Dimitri Molenaars, <[email protected]> |
|
6
|
|
|
Licensed under the Eiffel Forum License 2. |
|
7
|
|
|
|
|
8
|
|
|
https://sopel.chat |
|
9
|
|
|
""" |
|
10
|
|
|
from __future__ import unicode_literals, absolute_import, print_function, division |
|
11
|
|
|
|
|
12
|
|
|
import re |
|
13
|
|
|
|
|
14
|
|
|
from sopel.module import commands, example, NOLIMIT |
|
15
|
|
|
|
|
16
|
|
|
|
|
17
|
|
|
find_temp = re.compile(r'(-?[0-9]*\.?[0-9]*)[ °]*(K|C|F)', re.IGNORECASE) |
|
18
|
|
|
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) |
|
19
|
|
|
find_mass = re.compile(r'([0-9]*\.?[0-9]*)[ ]*(lb|lbm|pound[s]?|ounce|oz|(?:kilo|)gram(?:me|)[s]?|[k]?g)', re.IGNORECASE) |
|
20
|
|
|
|
|
21
|
|
|
|
|
22
|
|
|
def f_to_c(temp): |
|
23
|
|
|
return (float(temp) - 32) * 5 / 9 |
|
24
|
|
|
|
|
25
|
|
|
|
|
26
|
|
|
def c_to_k(temp): |
|
27
|
|
|
return temp + 273.15 |
|
28
|
|
|
|
|
29
|
|
|
|
|
30
|
|
|
def c_to_f(temp): |
|
31
|
|
|
return (9.0 / 5.0 * temp + 32) |
|
32
|
|
|
|
|
33
|
|
|
|
|
34
|
|
|
def k_to_c(temp): |
|
35
|
|
|
return temp - 273.15 |
|
36
|
|
|
|
|
37
|
|
|
|
|
38
|
|
|
@commands('temp') |
|
39
|
|
|
@example('.temp 100F', '37.78°C = 100.00°F = 310.93K') |
|
40
|
|
|
@example('.temp 100C', '100.00°C = 212.00°F = 373.15K') |
|
41
|
|
|
@example('.temp 100K', '-173.15°C = -279.67°F = 100.00K') |
|
42
|
|
|
def temperature(bot, trigger): |
|
43
|
|
|
"""Convert temperatures""" |
|
44
|
|
|
try: |
|
45
|
|
|
source = find_temp.match(trigger.group(2)).groups() |
|
46
|
|
|
except (AttributeError, TypeError): |
|
47
|
|
|
bot.reply("That's not a valid temperature.") |
|
48
|
|
|
return NOLIMIT |
|
49
|
|
|
unit = source[1].upper() |
|
50
|
|
|
numeric = float(source[0]) |
|
51
|
|
|
celsius = 0 |
|
52
|
|
|
if unit == 'C': |
|
53
|
|
|
celsius = numeric |
|
54
|
|
|
elif unit == 'F': |
|
55
|
|
|
celsius = f_to_c(numeric) |
|
56
|
|
|
elif unit == 'K': |
|
57
|
|
|
celsius = k_to_c(numeric) |
|
58
|
|
|
|
|
59
|
|
|
kelvin = c_to_k(celsius) |
|
60
|
|
|
fahrenheit = c_to_f(celsius) |
|
61
|
|
|
|
|
62
|
|
|
if kelvin >= 0: |
|
63
|
|
|
bot.reply("{:.2f}°C = {:.2f}°F = {:.2f}K".format(celsius, fahrenheit, kelvin)) |
|
64
|
|
|
else: |
|
65
|
|
|
bot.reply("Physically impossible temperature.") |
|
66
|
|
|
|
|
67
|
|
|
|
|
68
|
|
|
@commands('length', 'distance') |
|
69
|
|
|
@example('.distance 3m', '3.00m = 9 feet, 10.11 inches') |
|
70
|
|
|
@example('.distance 3km', '3.00km = 1.86 miles') |
|
71
|
|
|
@example('.distance 3 miles', '4.83km = 3.00 miles') |
|
72
|
|
|
@example('.distance 3 inch', '7.62cm = 3.00 inches') |
|
73
|
|
|
@example('.distance 3 feet', '91.44cm = 3 feet, 0.00 inches') |
|
74
|
|
|
@example('.distance 3 yards', '2.74m = 9 feet, 0.00 inches') |
|
75
|
|
|
@example('.distance 155cm', '1.55m = 5 feet, 1.02 inches') |
|
76
|
|
|
@example('.length 3 ly', '28382191417742.40km = 17635876112814.77 miles') |
|
77
|
|
|
@example('.length 3 au', '448793612.10km = 278867421.71 miles') |
|
78
|
|
|
@example('.length 3 parsec', '92570329129020.20km = 57520535754731.61 miles') |
|
79
|
|
|
def distance(bot, trigger): |
|
80
|
|
|
"""Convert distances""" |
|
81
|
|
|
try: |
|
82
|
|
|
source = find_length.match(trigger.group(2)).groups() |
|
83
|
|
|
except (AttributeError, TypeError): |
|
84
|
|
|
bot.reply("That's not a valid length unit.") |
|
85
|
|
|
return NOLIMIT |
|
86
|
|
|
unit = source[1].lower() |
|
87
|
|
|
numeric = float(source[0]) |
|
88
|
|
|
meter = 0 |
|
89
|
|
|
if unit in ("meters", "meter", "m"): |
|
90
|
|
|
meter = numeric |
|
91
|
|
|
elif unit in ("millimeters", "millimeter", "mm"): |
|
92
|
|
|
meter = numeric / 1000 |
|
93
|
|
|
elif unit in ("kilometers", "kilometer", "km"): |
|
94
|
|
|
meter = numeric * 1000 |
|
95
|
|
|
elif unit in ("miles", "mile", "mi"): |
|
96
|
|
|
meter = numeric / 0.00062137 |
|
97
|
|
|
elif unit in ("inch", "in"): |
|
98
|
|
|
meter = numeric / 39.370 |
|
99
|
|
|
elif unit in ("centimeters", "centimeter", "cm"): |
|
100
|
|
|
meter = numeric / 100 |
|
101
|
|
|
elif unit in ("feet", "foot", "ft"): |
|
102
|
|
|
meter = numeric / 3.2808 |
|
103
|
|
|
elif unit in ("yards", "yard", "yd"): |
|
104
|
|
|
meter = numeric / (3.2808 / 3) |
|
105
|
|
|
elif unit in ("light-year", "light-years", "ly"): |
|
106
|
|
|
meter = numeric * 9460730472580800 |
|
107
|
|
|
elif unit in ("astronomical unit", "astronomical units", "au"): |
|
108
|
|
|
meter = numeric * 149597870700 |
|
109
|
|
|
elif unit in ("parsec", "parsecs", "pc"): |
|
110
|
|
|
meter = numeric * 30856776376340068 |
|
111
|
|
|
|
|
112
|
|
|
if meter >= 1000: |
|
113
|
|
|
metric_part = '{:.2f}km'.format(meter / 1000) |
|
114
|
|
|
elif meter < 0.01: |
|
115
|
|
|
metric_part = '{:.2f}mm'.format(meter * 1000) |
|
116
|
|
|
elif meter < 1: |
|
117
|
|
|
metric_part = '{:.2f}cm'.format(meter * 100) |
|
118
|
|
|
else: |
|
119
|
|
|
metric_part = '{:.2f}m'.format(meter) |
|
120
|
|
|
|
|
121
|
|
|
# Shit like this makes me hate being an American. |
|
122
|
|
|
inch = meter * 39.37 |
|
123
|
|
|
foot = int(inch) // 12 |
|
124
|
|
|
inch = inch - (foot * 12) |
|
125
|
|
|
yard = foot // 3 |
|
126
|
|
|
mile = meter * 0.000621371192 |
|
127
|
|
|
|
|
128
|
|
|
if yard > 500: |
|
129
|
|
|
stupid_part = '{:.2f} miles'.format(mile) |
|
130
|
|
|
else: |
|
131
|
|
|
parts = [] |
|
132
|
|
|
if yard >= 100: |
|
133
|
|
|
parts.append('{} yards'.format(yard)) |
|
134
|
|
|
foot -= (yard * 3) |
|
135
|
|
|
|
|
136
|
|
|
if foot == 1: |
|
137
|
|
|
parts.append('1 foot') |
|
138
|
|
|
elif foot != 0: |
|
139
|
|
|
parts.append('{:.0f} feet'.format(foot)) |
|
140
|
|
|
|
|
141
|
|
|
parts.append('{:.2f} inches'.format(inch)) |
|
142
|
|
|
|
|
143
|
|
|
stupid_part = ', '.join(parts) |
|
144
|
|
|
|
|
145
|
|
|
bot.reply('{} = {}'.format(metric_part, stupid_part)) |
|
146
|
|
|
|
|
147
|
|
|
|
|
148
|
|
|
@commands('weight', 'mass') |
|
149
|
|
|
def mass(bot, trigger): |
|
150
|
|
|
"""Convert mass""" |
|
151
|
|
|
try: |
|
152
|
|
|
source = find_mass.match(trigger.group(2)).groups() |
|
153
|
|
|
except (AttributeError, TypeError): |
|
154
|
|
|
bot.reply("That's not a valid mass unit.") |
|
155
|
|
|
return NOLIMIT |
|
156
|
|
|
unit = source[1].lower() |
|
157
|
|
|
numeric = float(source[0]) |
|
158
|
|
|
metric = 0 |
|
159
|
|
|
if unit in ("gram", "grams", "gramme", "grammes", "g"): |
|
160
|
|
|
metric = numeric |
|
161
|
|
|
elif unit in ("kilogram", "kilograms", "kilogramme", "kilogrammes", "kg"): |
|
162
|
|
|
metric = numeric * 1000 |
|
163
|
|
|
elif unit in ("lb", "lbm", "pound", "pounds"): |
|
164
|
|
|
metric = numeric * 453.59237 |
|
165
|
|
|
elif unit in ("oz", "ounce"): |
|
166
|
|
|
metric = numeric * 28.35 |
|
167
|
|
|
|
|
168
|
|
|
if metric >= 1000: |
|
169
|
|
|
metric_part = '{:.2f}kg'.format(metric / 1000) |
|
170
|
|
|
else: |
|
171
|
|
|
metric_part = '{:.2f}g'.format(metric) |
|
172
|
|
|
|
|
173
|
|
|
ounce = metric * .035274 |
|
174
|
|
|
pound = int(ounce) // 16 |
|
175
|
|
|
ounce = ounce - (pound * 16) |
|
176
|
|
|
|
|
177
|
|
|
if pound > 1: |
|
178
|
|
|
stupid_part = '{} pounds'.format(pound) |
|
179
|
|
|
if ounce > 0.01: |
|
180
|
|
|
stupid_part += ' {:.2f} ounces'.format(ounce) |
|
181
|
|
|
else: |
|
182
|
|
|
stupid_part = '{:.2f} oz'.format(ounce) |
|
183
|
|
|
|
|
184
|
|
|
bot.reply('{} = {}'.format(metric_part, stupid_part)) |
|
185
|
|
|
|
|
186
|
|
|
|
|
187
|
|
|
if __name__ == "__main__": |
|
188
|
|
|
from sopel.test_tools import run_example_tests |
|
189
|
|
|
run_example_tests(__file__) |
|
190
|
|
|
|