module Text.Numeral.BigNum ( cardinal , rule , cardinalRepr , symMap , forms , PostfixRepr , scaleRepr , pelletierRepr , quantityName , ordQuantityName ) where ------------------------------------------------------------------------------- -- Imports ------------------------------------------------------------------------------- import "base" Data.Function ( fix ) import "base" Data.Monoid ( (<>) ) import qualified "containers" Data.Map as M import "this" Text.Numeral import "this" Text.Numeral.Misc ( dec ) import "text" Data.Text ( Text ) -------------------------------------------------------------------------------- -- Language of Big Numbers -------------------------------------------------------------------------------- cardinal :: (Integral a) => Inflection -> a -> Maybe Text cardinal inf = render cardinalRepr inf . (pos $ fix rule) rule :: (Integral a) => Rule a rule = findRule ( 1, lit ) [ ( 11, add 10 L ) , ( 20, mul 10 L L) , ( 100, lit ) , ( 101, add 100 L ) , ( 200, mul 100 R L) , (1000, lit ) , (1001, add 1000 L ) , (2000, mul 1000 R L) ] (dec 4 - 1) cardinalRepr :: Repr cardinalRepr = defaultRepr { reprValue = \_ n -> M.lookup n symMap , reprAdd = Just $ \_ _ _ -> "" , reprMul = Just $ \_ _ _ -> "" } symMap :: (Integral a) => M.Map a (Ctx Exp -> Text) symMap = M.fromList [ (1, forms "m" "un" "un" "" "") , (2, forms "b" "duo" "duo" "vi" "du") , (3, forms "tr" "tre" "tres" "tri" "tre") , (4, forms "quadr" "quattuor" "quattuor" "quadra" "quadri") , (5, forms "quint" "quin" "quinqua" "quinqua" "quin") , (6, forms "sext" "sex" "ses" "sexa" "ses") , (7, forms "sept" "septen" "septem" "septua" "septin") , (8, forms "oct" "octo" "octo" "octo" "octin") , (9, forms "non" "novem" "novem" "nona" "non") , (10, \c -> case c of CtxAdd _ (Lit 100) _ -> "deci" CtxMul _ _ (CtxAdd L (Lit 100) _) -> "ginta" CtxMul {} -> "gint" _ -> "dec" ) , (100, \c -> case c of CtxMul _ (Lit n) _ | n `elem` [2,3,6] -> "cent" | otherwise -> "gent" _ -> "cent" ) , (1000, const "millin") ] forms :: Text -> Text -> Text -> Text -> Text -> Ctx Exp -> Text forms t a1 a2 m1 m2 ctx = case ctx of CtxAdd _ (Lit 10) _ -> a1 CtxAdd {} -> a2 CtxMul _ (Lit 10) _ -> m1 CtxMul {} -> m2 _ -> t -------------------------------------------------------------------------------- -- Representations of scales -------------------------------------------------------------------------------- -- | Function that renders the postfix part of a large number name. Or -- more simply put, this calculates the \"illion\" part of -- \"million\", \"billion\", etc. type PostfixRepr = Inflection -- ^ Current inflection. -> Ctx Exp -- ^ Context. -> Text -- ^ Postfix representation. scaleRepr :: PostfixRepr -> [(Integer, Ctx Exp -> Text)] -- ^ Additional symbol map entries. -> ScaleRepr scaleRepr pf syms inf _ _ e ctx = (<> pf inf ctx) <$> render repr inf e where repr = cardinalRepr { reprValue = \_ n -> M.lookup n syms' } syms' = M.fromList syms `M.union` symMap pelletierRepr :: PostfixRepr -- ^Postfix for offset 0 names. -> PostfixRepr -- ^Postfix for offset 3 names. -> [(Integer, Ctx Exp -> Text)] -- ^ Additional symbol map entries. -> ScaleRepr pelletierRepr pf0 pf3 syms inf b o e ctx | o == 0 = scaleRepr pf0 syms inf b o e ctx | o == 3 = scaleRepr pf3 syms inf b o e ctx | otherwise = Nothing quantityName :: Text -> Text -> PostfixRepr quantityName s p _ ctx = case ctx of CtxMul _ (Lit 1) _ -> s CtxMul {} -> p _ -> s ordQuantityName :: Text -> Text -> Text -> Text -> PostfixRepr ordQuantityName sc so pc po _ ctx = case ctx of CtxMul _ (Lit 1) _ | outside -> so | otherwise -> sc CtxMul {} | outside -> po | otherwise -> pc _ | outside -> so | otherwise -> sc where outside = isOutside R ctx