summaryrefslogtreecommitdiff
path: root/test/Checks.hs
blob: 67cc5868f5b710abaf55858c162d5a5cb14ebfa9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
--
-- Graphics.Wavefront.Checks
-- Executable containing checks and tests for the modules in this package
--
-- Jonatan H Sundqvist
-- February 24 2015
--

-- TODO | - Use QuickCheck (?)
--        - Full coverage
--        - Benchmarking

-- SPEC | -
--        -



module Graphics.WaveFront.Checks where



--------------------------------------------------------------------------------------------------------------------------------------------
-- We'll need these
--------------------------------------------------------------------------------------------------------------------------------------------
import Text.Printf (printf)
import Data.Either (lefts)
import Data.Char (toLower)
import System.IO (hFlush, stdout)

import Control.Monad (forM_, when)

import Graphics.WaveFront.Parsers (MTL, OBJ, OBJNoParse(..), MTLNoParse(..), MTLToken(..))
import Graphics.WaveFront.Load    (loadOBJ, loadMTL)



--------------------------------------------------------------------------------------------------------------------------------------------
-- Functions (IO)
--------------------------------------------------------------------------------------------------------------------------------------------

-- IO utilities ----------------------------------------------------------------------------------------------------------------------------

-- | 
promptContinue :: String -> IO ()
promptContinue prompt = do
  putStr prompt
  hFlush stdout
  getChar
  putChar '\n'



-- | 
-- 
-- TODO: Refactor (cf. untilM)
-- TODO: Allow flexible feedback
-- TODO: Default return value for invalid replies (?)
-- TODO: Customisable validation (eg. for other languages than English)
--
askYesNo :: String -> IO Bool
askYesNo q = do
  putStr q
  hFlush stdout
  answer <- getLine
  affirmed $ map toLower answer
  where affirmed answer | answer `elem` ["yes", "y", "yeah"] = return True
                        | answer `elem` ["no", "n", "nah"]   = return False
                        | otherwise                          = askYesNo "I don't understand. Answer 'yes' or 'no': "
  -- return [(`elem` ["yes", "y", "yeah"]), (`elem` "no", "n", "nah")]


-- |
askPerformAction :: String -> IO () -> IO ()
askPerformAction q action = do
  affirmed <- askYesNo q
  when affirmed action


-- |
showTokens :: Show a => [(Int, Either MTLNoParse a, String)] -> IO ()
showTokens materials = mapM_ (uncurry $ printf "[%d] %s\n") [ (n, show token) | (n, Right token, comment) <- materials ] -- TODO: cf. line 65



--------------------------------------------------------------------------------------------------------------------------------------------
-- Entry point
--------------------------------------------------------------------------------------------------------------------------------------------
-- | 
--
-- TODO: Print culprit lines (✓)
--
main :: IO ()
main = do
  putStrLn "This is where the checks should be."

  let path = "C:/Users/Jonatan/Desktop/Python/experiments/WaveFront/"

  forM_ ["queen", "cube"] $ \ fn -> do
    printf "\nParsing OBJ file: %s.obj\n" fn
    model <- loadOBJ $ printf (path ++ "data/%s.obj") fn
    -- TODO: Utility for partioning a list based on several predicates ([a] -> [a -> Bool] -> [[a]])
    -- TODO: Utilities for displaying output and asking for input
    -- TODO: Oh, the efficiency!
    -- TODO: Less ugly naming convention for monadic functions which ignore the output (cf. mapM_, forM_, etc.)
    let unparsed = lefts $ map second model
    let comments = [ c | c@(OBJComment _) <- unparsed ]
    let blanks   = [ c | c@(OBJEmpty)     <- unparsed ]
    let errors   = length unparsed - (length comments + length blanks)
    printf "Found %d invalid rows in OBJ file (%d comments, %d blanks, %d errors).\n" (length unparsed) (length comments) (length blanks) errors
    when (length unparsed > 0) . askPerformAction "Would you like to see view them (yes/no)? " $ putStrLn "Ok, here they are:" >> mapM_ print unparsed

    promptContinue "Press any key to continue..."

    mapM (uncurry $ printf "[%d] %s\n") [ (n, show token) | (n, Right token, comment) <- model ]
    -- TODO: Print culprit lines (✓)

    promptContinue "Press any key to continue..."

    printf "\nParsing MTL file: %s.mtl\n" fn
    materials <- loadMTL $ printf "%sdata/%s.mtl" path fn
    printf "Found %d invalid rows in MTL file (n comments, m blanks, o errors).\n" . length . lefts $ map second materials
    showTokens materials

    promptContinue "Press any key to continue..."
    where second (_, b, _) = b