# unit convertor for DCT, by Shiar

# 1.11.0 200410291000 - use redraw()
# 1.10.5 200410151900 - data storage units (8 total, including LOC)
# 1.10.4 200410132300 - hp49 units for mass
# 1.10.3 200410130000 - fix error when run without menu module
# 1.10.2 200410122200 - adds submenus with all units
# 1.10.1 200410122030 - hp49 units for area, volume, time, speed, force, energy, power
# 1.09.2 200410112205 - all code moved here as well
# 1.09.1 200410022305 - moved %unit specs from 1.9 main

use strict;
use warnings;
use utf8;

my $menugroup = addmenu(["main", 0], "unit") if defined &addmenu;

my %unit;  # unit table (build below)
my $i = 0;  # unit group counter (temporary)
do {
	$i++;  # next group
	my $title = shift @$_;  # first element is group title, no unit
	addmenu(["unit", $menugroup], $title, map "_$_->[0]", @$_) if defined &addmenu;
	$unit{$_->[0]} = {
		type=>$i, name=>$_->[0], val=>$_->[1], desc=>$_->[2], diff=>$_->[3]
	} for @$_;
} for (
	[
		"length",
		['m', 1, "metre"],
		['cm', .01, "centimeter"],
		['mm', .001, "millimeter"],
		['yd', .0254*36, "yard"],
		['ft', .0254*12, "feet"],
		['in', .0254, "inch"],
		['Mpc', 3.085_677_581_3*10**22, "Mega parsec"],
		['pc', 3.085_677_581_3*10**16, "parsec"], # 180*60*60/pi au
		['lyr', 299_792_458*86_400*365.25, "light-year"], # c0*(seconds/year) - 9.46052840488e+15
		['au', 149_597_870.691*30, "astronomical unit"],
		['km', 1000, "kilometer"],
		['mi', .0254*12*5280, "international mile"],
		['nmi', 1852, "nautical mile"],
		['miUS', 1200/3937*5280, "US statute mile"],
		['chain', .0254*12*66, "Gunter's chain"],
		['rd', .0254*198, "rod/pole/perch"],
		['fath', .0254*72, "fathom"],
		['ftUS', 1200/3937, "survey foot"],
		['Mil', 2.54e-5, "Mil/thou"],
		['μ', 1e-6, "micron"], # μm
		['Å', 1e-10, "ångström"], # .1nm
		['fermi', 1e-15, "fermi"], # 1fm
#		['a0', .291_772_083*10**-11*19e-20, "atomic unit of length"],
#		['ell', .0254*45, "ell"],
#		['rope', .0254*12*20, "rope"],
#		TI86 order: mm cm m in ft  yd km mile mmile lt-yr  mil Ang fermi rod fath
	], # lengths
	[
		"area",
		['m²', 1, "square metre"],
		['cm²', .01**2, "square centimetre"],
		['b', 1e-28, "barn"],
		['yd²', (.0254*36)**2, "square yard"],
		['ft²', (.0254*12)**2, "square feet"],
		['in²', (.0254)**2, "square inch"],
		['km²', 1_000_000, "square kilometre"],
		['ha', 10_000, "hectare"],
		['a', 100, "are"],
		['mi²', (.0254*12*5280)**2, "square mile"],
		['miUS²', (1200/3937*5280)**2, "square statute mile"],
		['acre', (.0254*12*66)**2*10, "acre"],
#		['chain²', (.0254*12*66)**2, "square Gunter's chain"],
#		['ba', .0254**2*12, "board"],
	], # area
	[
		"volume", #todo
		['m³', 1, "cubic metre"],
#		['st', 0, "stere"],
		['cm³', 1e-6, "cubic centimetre"],
		['yd³', (.0254*36)**3, "cubic yard"],
		['ft³', (.0254*12)**3, "cubic feet"],
		['in³', (.0254)**3, "cubic inch"],
		['l', 100, "litre"],
		['galUK', .045_460_9, "Imperial gallon"],
		['galC', 0, "Canadian gallon"],
		['gal', 0, "US gallon"],
		['qt', 0, "quart"],
		['pt', 0, "pint"],
		['ml', 100e6, "mililitre"],
		['cu', 0, "US cup"],
		['ozfl', 0, "US fluid ounce"],
		['ozUK', 0, "UK fluid ounce"],
		['tbsp', 0, "tablespoon"],
		['tsp', 0, "teaspoon"],
		['bbl', 0, "barrel"],
		['bu', 0, "bushel"],
		['pk', 0, "peck"],
		['fbm', 0, "board foot"],
	], # volume
	[
		"time",
		['yr', 365.2425*86_400, "year (Gregorian)"],
		['d', 86_400, "day"],
		['h', 3_600, "hour"],
		['min', 60, "minute"],
		['s', 1, "second"],
#		['Hz', 1, "hertz"],
		['week', 604_800, "week"], # new
#		['au', 2.418_884_254e-17, "atomic unit of time"], # a[0]/(α*c)
	], # time
	[
		"speed",
		['m/s', 1, "meter per second"],
		['cm/s', 100, "centimeter per second"],
		['ft/s', 8.466_667e-5, "feet per second"],
		['kph', 2.777_778e-1, "kilometer per hour"],
		['mph', .447_04, "mile per hour"],
#		['mph', .447_041, "statute mile per hour"],
		['knot', .514_444, "nautical miles per hour"],
		['c', 2.997_924_58e8, "speed of light in vacuum"],
#		['ga', 0, "acceleration of gravity"],
	], # speed
	[
		"mass",
		['kg', 1, "kilogram"],
		['g', 1e-3, "gram"],
		['Lb', .453_592_37, "avoirdupois pound"],
		['oz', 28.349_523_125, "ounce"],
		['slug', 14.593_903, "slug"],
		['lbt', .373_241_721_6, "Troy pound"],
		['ton', 907.184_74, "short ton"],
		['tonUK', 1016.046_908_8, "long ton"],
		['t', 1000, "tonne (metric ton)"],
		['ozt', .031_103_476_8, "Troy ounce"],
		['ct', 64.798_91e-6*19/6, "carat"], # 3+1/6 gr
#		['kt', 200e-6, "metric carat"], # new
		['grain', 64.798_91e-6, "grain"],
		['u', 1.660_538_73e-27 * 13e-35, "unified atomic mass"],
#		['mol', 0, "mole"], # mole = g/u
	], # mass
	[
		"force",
		['N', 1, "newton"], # kg*m/s²
		['dyn', 1e-5, "dyne"],
		['gf', 9_806.65, "gram-force"],
		['kip', 4.448_221_615_260_500_0, "kilopound-force"],
		['lbf', 4.448_221_615_260_5, "pound-force"],
		['pdl', .138_254_954_376, "poundal"], # lb*ft/s²
		['kgf', 9.806_65, "kilogram-force/grave"],
	], # force
	[
		"energy",
		['J', 1, "joule"], # N*m
		['erg', 1e-7, "erg"], # g*cm²/s²
		['Kcal', 4_186.8, "kilocalorie"],
		['Cal', 4.186_8, "calorie"],
		['Btu', 1_055.055_852_62, "International table btu"],
		['ft*lbf', 1.355_817_948_331_400_4, "foot-pound"],
		['therm', 105_505_585.262, "EEC therm"],
		['MeV', 1/6.241_509_629_152_65e12, "mega electron-volt"],
		['eV', 1/6.241_509_629_152_65e18, "electron-volt"],
	], # energy
	[
		"power",
		['W', 1, "watt"],
		['hp', 735.498_75, "horse power"],
	], # power
#	[
#		"pressure",
#	], # pressure
	[
		"temperature", #todo
		['°C', 1, "degree Celsius", 273.15],
		['°F', 5/9, "degree Fahrenheit", 459.67],
		['K', 1, "Kelvin"],
		['°R', 5/9, "degree Rankine"],
	], # temperature
#	[], # electric current
#	[], # angle
#	[], # light
#	[], # radiation
#	[], # viscosity

	[
		"data storage", # memory
		['B', 1, "byte"],
		['kB', 1024, "kilobyte"],
		['MB', 1024**2, "megabyte"],
		['GB', 1024**3, "gigabyte"],
		['TB', 1024**4, "terabyte"],
		['bit', 1/8, "bit/octet"],
		['Mbit', 1024**2/8, "megabit"],
		['LOC', 19e12, 'Library of Congress'], # est. 17-20TB
	],
); # units table

push @{$hook{precmd}}, sub {
	if ($_ =~ /^_/) {{
		$_ = $unit{substr $_, 1} or next;
		if (exists $val{unit} and $val{unit}{type}==$_->{type}) {
			unshift @stack, $val{i} if defined $val{i};
#			$stack[0] -= $_->{diff} if $_->{diff};
#			$stack[0] += $val{unit}{diff}*$val{unit}{val}/$_->{val} if $val{unit}{diff};
			$stack[0] *= delete($val{unit})->{val} / $_->{val};
			redraw(1);
			undef %val;
		} # convert
		else {
			$val{unit} = $_;
		} # set source unit
		return 1;
	}} # conversion
}; # precmd

push @{$hook{postentry}}, sub {
	exists $val{unit} && '_'.$val{unit}{name};
}; # showentry

return {
	author  => "Shiar",
	title   => "unit convertor",
	version => "1.11",
};

