-- | Defines units for use in Drasil. Often used in a unital-related chunk that has an associated symbol.
module Data.Drasil.SI_Units where

import Language.Drasil
import Language.Drasil.Display
import Language.Drasil.ShortHands (cOmega)

-- * Lists of Units

fundamentals :: [UnitDefn]
fundamentals :: [UnitDefn]
fundamentals = [UnitDefn
metre, UnitDefn
kilogram, UnitDefn
second, UnitDefn
kelvin, UnitDefn
mole, UnitDefn
ampere, UnitDefn
candela]

derived :: [UnitDefn]
derived :: [UnitDefn]
derived = [UnitDefn
becquerel, UnitDefn
calorie, UnitDefn
centigrade, UnitDefn
coulomb, UnitDefn
farad, UnitDefn
gray, UnitDefn
henry, UnitDefn
hertz, UnitDefn
joule,
  UnitDefn
katal, UnitDefn
kilopascal, UnitDefn
kilowatt, UnitDefn
litre, UnitDefn
lumen, UnitDefn
lux,  UnitDefn
millimetre, UnitDefn
newton, UnitDefn
ohm,
  UnitDefn
pascal, UnitDefn
radian, UnitDefn
siemens, UnitDefn
sievert, UnitDefn
steradian, UnitDefn
tesla, UnitDefn
volt, UnitDefn
watt, UnitDefn
weber]

siUnits :: [UnitDefn]
siUnits :: [UnitDefn]
siUnits = (UnitDefn -> UnitDefn) -> [UnitDefn] -> [UnitDefn]
forall a b. (a -> b) -> [a] -> [b]
map UnitDefn -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper [UnitDefn]
fundamentals [UnitDefn] -> [UnitDefn] -> [UnitDefn]
forall a. [a] -> [a] -> [a]
++ (UnitDefn -> UnitDefn) -> [UnitDefn] -> [UnitDefn]
forall a b. (a -> b) -> [a] -> [b]
map UnitDefn -> UnitDefn
forall u. IsUnit u => u -> UnitDefn
unitWrapper [UnitDefn]
derived

-- * Fundamental SI Units

metre, kilogram, second, kelvin, mole, ampere, candela :: UnitDefn
metre :: UnitDefn
metre    = String -> String -> String -> UnitDefn
fund "metre"    "length"               "m"
kilogram :: UnitDefn
kilogram = String -> String -> String -> UnitDefn
fund "kilogram" "mass"                 "kg"
second :: UnitDefn
second   = String -> String -> String -> UnitDefn
fund "second"   "time"                 "s"
kelvin :: UnitDefn
kelvin   = String -> String -> String -> UnitDefn
fund "kelvin"   "temperature"          "K"
mole :: UnitDefn
mole     = String -> String -> String -> UnitDefn
fund "mole"     "amount of substance"  "mol"
ampere :: UnitDefn
ampere   = String -> String -> String -> UnitDefn
fund "ampere"   "electric current"     "A"
candela :: UnitDefn
candela  = String -> String -> String -> UnitDefn
fund "candela"  "luminous intensity"   "cd"

-- * Commonly Defined Units

degree :: UnitDefn --FIXME: define degree in terms of radians and pi
-- degree = UD (dcc "degree" (cn' "degree") "angle") (BaseSI (US [(Special Circle,1)])) ["degree"]
degree :: UnitDefn
degree = String -> String -> Symbol -> UnitDefn
fund' "degree" "angle" (Special -> Symbol
Special Special
Circle)

-- Some of these units are easiest to define via others less common names, 
-- which we define first.
s_2 :: UnitDefn
s_2 :: UnitDefn
s_2 = String -> UnitEquation -> UnitDefn
newUnit "seconds squared" (UnitEquation -> UnitDefn) -> UnitEquation -> UnitDefn
forall a b. (a -> b) -> a -> b
$ UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: 2

m_2, m_3 :: UnitDefn
m_2 :: UnitDefn
m_2 = String -> UnitEquation -> UnitDefn
newUnit "square metres"   (UnitEquation -> UnitDefn) -> UnitEquation -> UnitDefn
forall a b. (a -> b) -> a -> b
$ UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: 2
m_3 :: UnitDefn
m_3 = String -> UnitEquation -> UnitDefn
newUnit "cubic metres"    (UnitEquation -> UnitDefn) -> UnitEquation -> UnitDefn
forall a b. (a -> b) -> a -> b
$ UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: 3

-- And now for the ones with 'common' names

becquerel, calorie, centigrade, coulomb, farad, gray, henry, hertz, joule,
  katal, kilopascal, kilowatt, litre, lumen, lux,  millimetre, newton, ohm,
  pascal, radian, siemens, sievert, steradian, tesla, volt, watt, weber :: UnitDefn

becquerel :: UnitDefn
becquerel = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "becquerel" 
  "becquerel" "activity" (String -> Symbol
label "Bq") --of a Radionuclide
  (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-1))
  
calorie :: UnitDefn
calorie = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC "calorie" 
  "calorie" "energy" (String -> Symbol
label "cal") (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
scale 4.184 UnitDefn
joule)

centigrade :: UnitDefn
centigrade = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC "centigrade" 
  "centigrade" "temperature" ([Symbol] -> Symbol
Concat [Special -> Symbol
Special Special
Circle, String -> Symbol
label "C"])
  (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
shift 273.15 UnitDefn
kelvin)

coulomb :: UnitDefn
coulomb = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "coulomb" 
  "coulomb" "electric charge" (String -> Symbol
label "C") (UnitDefn
ampere UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
second)

farad :: UnitDefn
farad = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "farad" 
  "farad" "capacitance" (String -> Symbol
label "F") (UnitDefn
coulomb UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
volt)

gray :: UnitDefn
gray = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "gray" 
  "gray" "absorbed dose" (String -> Symbol
label "Gy") (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)
  
henry :: UnitDefn
henry = String -> NP -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC'' "henry" 
  (String -> NP
cnIES "henry") "inductance" (String -> Symbol
label "H") (UnitDefn
weber UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)
  
hertz :: UnitDefn
hertz = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC "hertz" 
  "hertz" "frequency" (String -> Symbol
label "Hz") (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-1))

joule :: UnitDefn
joule = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "joule" 
  "joule" "energy" (String -> Symbol
label "J") 
 (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
m_2 UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-2))))

katal :: UnitDefn
katal = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "katal" 
  "katal" "catalytic activity" (String -> Symbol
label "kat") (UnitDefn
mole UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
second)

kilopascal :: UnitDefn
kilopascal = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' "kilopascal" 
  "kilopascal" "pressure"
  ([Symbol] -> Symbol
Concat [String -> Symbol
label "k", String -> Symbol
label "Pa"]) (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
scale 1000 UnitDefn
pascal)

kilowatt :: UnitDefn
kilowatt = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' "kilowatt" 
  "kilowatt" "power" ([Symbol] -> Symbol
Concat [String -> Symbol
label "k", String -> Symbol
label "W"]) (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
scale 1000 UnitDefn
watt)
  
litre :: UnitDefn
litre = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' "litre"
  "litre" "volume" (String -> Symbol
label "L") (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
scale (1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/1000) UnitDefn
m_3)

lumen :: UnitDefn
lumen = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "lumen" 
  "lumen" "luminous flux" (String -> Symbol
label "lm") (UnitDefn
candela UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
steradian)

lux :: UnitDefn
lux = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC "lux" 
  "lux" "illuminance" (String -> Symbol
label "lx") (UnitDefn
lumen UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2)

millimetre :: UnitDefn
millimetre = String -> String -> String -> Symbol -> UDefn -> UnitDefn
derUC' "millimetre"
  "millimetre" "length" (String -> Symbol
label "mm") (Double -> UnitDefn -> UDefn
forall s. IsUnit s => Double -> s -> UDefn
scale 0.0001 UnitDefn
metre)

newton :: UnitDefn
newton = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "newton"
  "newton" "force" (String -> Symbol
label "N") (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-2)))
  
ohm :: UnitDefn
ohm = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "ohm"
  "ohm" "resistance" Symbol
cOmega (UnitDefn
volt UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)
  
pascal :: UnitDefn
pascal = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "pascal" 
  "pascal" "pressure" (String -> Symbol
label "Pa")
  (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
/$ (UnitDefn
metre UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: 2)))
  
radian :: UnitDefn
radian = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "radian" 
  "radian" "angle" (String -> Symbol
label "rad") (UnitDefn
metre UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
metre)
            
siemens :: UnitDefn
siemens = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC "siemens" 
  "siemens" "conductance" (String -> Symbol
label "S") (UnitDefn
ohm UnitDefn -> Integer -> UnitEquation
^: (-1))
  
sievert :: UnitDefn
sievert = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "sievert" 
  "sievert" "dose equivalent" (String -> Symbol
label "Sv")
  (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)
            
steradian :: UnitDefn
steradian = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "steradian" 
  "steradian" "solid angle" (String -> Symbol
label "sr") (UnitDefn
m_2 UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2 )
  
tesla :: UnitDefn
tesla = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC "tesla"
  "tesla" "magnetic flux density" (String -> Symbol
label "T") (UnitDefn
weber UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
m_2)

volt :: UnitDefn
volt = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "volt" 
  "volt" "voltage" (String -> Symbol
label "V") (UnitDefn
watt UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
ampere)

watt :: UnitDefn
watt = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "watt" "watt" "power" (String -> Symbol
label "W")
  (UnitDefn
kilogram UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
m_2 UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
second UnitDefn -> Integer -> UnitEquation
^: (-3))))
          
weber :: UnitDefn
weber = String -> String -> String -> Symbol -> UnitEquation -> UnitDefn
derCUC' "weber"
  "weber" "magnetic flux" (String -> Symbol
label "Wb") (UnitDefn
volt UnitDefn -> UnitDefn -> UnitEquation
*: UnitDefn
second)
  
specificE :: UnitDefn
specificE :: UnitDefn
specificE = ConceptChunk -> UnitEquation -> UnitDefn
makeDerU (String -> NP -> String -> ConceptChunk
dcc "specificE" (String -> NP
cnIES "specific energy") 
  "energy per unit mass") (UnitDefn
joule UnitDefn -> UnitDefn -> UnitEquation
/: UnitDefn
kilogram)

specificWeight :: UnitDefn
specificWeight :: UnitDefn
specificWeight = ConceptChunk -> UnitEquation -> UnitDefn
makeDerU (String -> NP -> String -> ConceptChunk
dcc "specificWeight" (String -> NP
cn' "specific weight")
  "weight per unit volume") (UnitDefn
newton UnitDefn -> UnitEquation -> UnitEquation
*$ (UnitDefn
metre UnitDefn -> Integer -> UnitEquation
^: (-3)))
  
-- FIXME: Need to add pi 
--degrees = DUC
  --  (UD (dcc "Degrees" "angle") (UName (Special Circle)))
  --  Equiv to pi/180 rad.