1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#!/usr/bin/perl
# Unit conversions (weight/measure/etc) for an irssi bot.
use warnings;
no strict;
use POSIX 'round';
use Irssi qw/signal_add/;
$helpmsg = "Usage: !units <number> <unit> [[to] <to-unit>]. Examples: !units 50 miles km; !units 20C to F. With no <to-unit>, tries to guess based on <unit> (e.g. C will convert to F)";
# default output unit based on input unit
%default_unit = (
F => 'C',
C => 'F',
f => 'c',
c => 'f',
mi => 'km',
mile => 'km',
km => 'mile',
ft => 'meter',
foot => 'm',
feet => 'm',
yd => 'm',
yard => 'm',
in => 'cm',
inch => 'cm',
inches => 'cm',
lb => 'kg',
pound => 'kg',
lbs => 'kg',
gal => 'l',
gallon => 'l',
cc => 'floz',
floz => 'cc',
);
# round to nearest 1/100, e.g. 1.004 is 1, 1.005 is 1.01.
sub round_result {
return round($_[0] * 100) / 100;
}
sub convert {
for($_[0]) {
s/°([cfk])\b/$1/i;
if(/[^\s0-9a-zA-Z\/\^]/) {
return "malformed request";
}
s/\s+to\b//;
s/fl\w*\.?\s?o[uz]\w*/floz/;
my ($num, $from, $to) = (/(\d+|\.\d+|\d+\.\d+)\s*([\w\^\/]+)(?:\s+([\w+\^\/]+))?$/);
return "malformed request" unless defined $num && defined $from;
$to = $default_unit{$from} unless defined $to;
unless(defined $to) {
my $f = $from;
$f =~ s/s$//;
$to = $default_unit{$f};
}
return "no default conversion for $from" unless defined $to;
#warn "was: num $num, from $from, to $to\n";
my $realfrom = $from;
my $realto = $to;
my $realnum = $num;
my $space = " ";
if($from =~ /^([cfk])$/i) {
$realfrom = uc $1;
$from = "temp" . uc($1) . "($num)";
$num = "";
$space = "";
}
if($to =~ /^([cfk])$/i) {
$realto = uc $1;
$to = "temp" . uc($1);
$space = "";
}
#warn "now: num $num, from $from, to $to\n";
# was using: -o'%.1f', but it doesn't do rounding, plus it
# prints 1 as 1.0.
chomp($result = `units -1t '$num$from' '$to' 2>&1`);
if($?) {
if($result =~ /conformability error/) {
return "Can't convert $realfrom to $realto";
} else {
return $result;
}
} else {
$result = round_result($result);
return "$realnum$space$realfrom is $result$space$realto";
}
}
}
sub on_public_msg {
my ($server, $msg, $nick, $address, $target) = @_;
my $mynick = $server->{nick};
unless(length $target) {
$target = $nick;
$nick = $mynick;
}
if($target eq $mynick) {
# private message... send response to sender
$target = $nick;
}
if($msg !~ /^!units\s+(.+)/) {
return;
}
my $input = $1;
my $result = convert($input);
$server->command("msg $target $result");
}
signal_add("message public", "on_public_msg");
|