| 2 | 2 |  | 
| 3 | 3 | module Types where | 
| 4 | 4 |  | 
|  | 5 | import qualified Control.Exception as Exn | 
| 5 | 6 | import qualified Data.Map.Strict as Map | 
| 6 | 7 | import qualified Data.Text as Text | 
| 7 |  | import qualified Data.Text.IO as Text | 
| 8 | 8 | import qualified System.Random as Rand | 
| 9 | 9 |  | 
| 10 |  | data Range = Range { rFrom :: Int, rTo :: Int } | 
|  | 10 | type TableName = Text.Text | 
|  | 11 | type Roll = Int | 
|  | 12 |  | 
|  | 13 | data Range = Range { rFrom :: Roll, rTo :: Roll } | 
| 11 | 14 | deriving (Eq, Show) | 
| 12 | 15 |  | 
| 13 |  | type TableMap = Map.Map T ext.TextTable | 
|  | 16 | type TableMap = Map.Map TableName Table | 
| 14 | 17 |  | 
| 15 | 18 | data Table = Table | 
| 16 | 19 | { tableName :: Text.Text | 
            
              
                |  | 
            
          | 25 | 28 | data Result = Result { fromResult ::  [Fragment] } | 
| 26 | 29 | deriving (Eq, Show) | 
| 27 | 30 |  | 
|  | 31 | -- * Values | 
|  | 32 |  | 
| 28 | 33 | data Value = Value | 
| 29 |  | { valueMsg :: Text.Text | 
|  | 34 | { valueMsg     :: Text.Text | 
|  | 35 | , valueFrom    :: TableName | 
|  | 36 | , valueResult  :: Roll | 
|  | 37 | , valueSources :: [Value] | 
| 30 | 38 | } deriving (Eq, Show) | 
| 31 | 39 |  | 
|  | 40 | concatValues :: Context -> [Value] -> Value | 
|  | 41 | concatValues _ [v] = v | 
|  | 42 | concatValues Context { ctxSelf = table, ctxRoll = roll } vs = Value | 
|  | 43 | { valueMsg     = foldMap valueMsg vs | 
|  | 44 | , valueFrom    = table | 
|  | 45 | , valueResult  = roll | 
|  | 46 | , valueSources = vs | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | bareValue :: Context -> Text.Text -> Value | 
|  | 50 | bareValue Context { ctxSelf = table, ctxRoll = roll } text = Value | 
|  | 51 | { valueMsg     = text | 
|  | 52 | , valueFrom    = table | 
|  | 53 | , valueResult  = roll | 
|  | 54 | , valueSources = [] | 
|  | 55 | } | 
|  | 56 |  | 
| 32 | 57 | stripValue :: Value -> Value | 
| 33 |  | stripValue = Value . Text.strip . valueMsg | 
|  | 58 | stripValue value = value { valueMsg = Text.strip (valueMsg value) } | 
|  | 59 |  | 
|  | 60 | -- * Exceptions | 
|  | 61 |  | 
|  | 62 | data NoSuchTable = NoSuchTable Text.Text | 
|  | 63 | deriving (Eq, Show) | 
|  | 64 |  | 
|  | 65 | instance Exn.Exception NoSuchTable where | 
|  | 66 |  | 
|  | 67 | -- * Context | 
| 34 | 68 |  | 
| 35 | 69 | data Context = Context | 
| 36 | 70 | { ctxMap  :: TableMap | 
            
              
                |  | 
            
          | 38 | 72 | , ctxSelf :: Text.Text | 
| 39 | 73 | } | 
| 40 | 74 |  | 
|  | 75 | -- * Evaluating Tables | 
|  | 76 |  | 
| 41 | 77 | findTable :: Text.Text -> Context -> Maybe Table | 
| 42 | 78 | findTable name ctx = Map.lookup name (ctxMap ctx) | 
| 43 | 79 |  | 
| 44 | 80 | computeFragments :: Context -> Fragment -> IO Value | 
| 45 |  | computeFragments _ (FragText msg) = pure (Valuemsg) | 
|  | 81 | computeFragments ctx (FragText msg) = pure (bareValue ctx msg) | 
| 46 | 82 | computeFragments ctx (FragRoll name) = | 
| 47 | 83 | let absolute = case Text.stripPrefix "self" name of | 
| 48 | 84 | Just rest -> ctxSelf ctx <> rest | 
| 49 | 85 | Nothing   -> name | 
| 50 | 86 | in case findTable absolute ctx of | 
| 51 | 87 | Just t -> rollTable (ctxMap ctx) t | 
| 52 |  | Nothing -> error ("no such table: " ++ showabsolute) | 
|  | 88 | Nothing -> Exn.throwIO (NoSuchTable absolute) | 
| 53 | 89 |  | 
| 54 | 90 | computeResult :: Context -> Result -> IO Value | 
| 55 | 91 | computeResult ctx (Result msgs) = do | 
| 56 | 92 | vs <- mapM (computeFragments ctx) msgs | 
| 57 |  | pure ( Value (foldMap valueMsg vs)) | 
|  | 93 | pure (concatValues ctx vs) | 
| 58 | 94 |  | 
| 59 | 95 | tableDie :: Table -> Int | 
| 60 | 96 | tableDie t = maximum [ x | (Range _ x, _) <- tableChoices t ] |