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 Text.Text Table
|
| 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 (Value msg)
|
| 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: " ++ show absolute)
|
| 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 ]
|