module DND.Sheet.Parser ( parseSheet , createExample , getName , getStat , getSkill , getSkillNames , getStatNames , getSkillScore , getProficiency ) where import Control.Monad import Data.Aeson import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.UTF8 as BSU import Data.Maybe (fromJust) import DND.Bob (bob) import DND.Sheet.Content import qualified Data.Map as Map parseSheet :: FilePath -> IO Character parseSheet x = unwrap . decode =<< B.readFile x where unwrap (Just y) = return y unwrap Nothing = error $ "Failed to parse character sheet: " ++ x createExample :: FilePath -> IO () createExample = flip encodeFile bob getName :: Character -> String getName = charName . preamble getStat :: Character -> String -> Stat getStat char s = head . filter (\a -> statName a == s) . stats $ char getSkill :: Character -> String -> Skill getSkill char s = head . filter (\a -> skillName a == s) . skills $ char getSkillNames :: Character -> [String] getSkillNames = map skillStat . skills getStatNames :: Character -> [String] getStatNames = map statName . stats getProficiency :: Character -> Int getProficiency = fromJust . flip Map.lookup profTable . charLevel . preamble -- https://www.nerdsandscoundrels.com/how-to-calculate-proficiency-bonus-5e/ -- for some fucking reason there appears to be no simple mathematical way to get a character's proficiency bonus where profTable = Map.fromList [ (1,2), (2,2), (3,2), (4,2) , (5,3), (6,3), (7,3), (8,3) , (9,4), (10,4), (11,4), (12,4) , (13,5), (14,5), (15,5), (16,5) , (17,6), (18,6), (19,6), (20,6) ] -- https://worldbuildersjunction.com/dungeon-and-dragons-ability-scores-explained-for-beginners/ -- from the Go implementation -- return (stat.Score - 10) / 2 getSkillScore :: Character -> String -> Int getSkillScore char skillString = let skill = getSkill char skillString stat = getStat char $ skillStat skill prof = getProficiency char modifier = case skillMod skill of Proficient -> prof Expertise -> prof * 2 Half -> div prof 2 None -> 0 in (modifier +) . (`div` 2) $ statScore stat - 10