import System (getArgs) import System.Console.GetOpt import IO import Tuning import Tuning.Standard import Guitar import Exercises import System.Random import Data.Array.IO import Control.Monad -- | Randomly shuffle a list -- /O(N)/ shuffle :: [a] -> IO [a] shuffle xs = do ar <- newArray n xs forM [1..n] $ \i -> do j <- randomRIO (i,n) vi <- readArray ar i vj <- readArray ar j writeArray ar j vi return vj where n = length xs newArray :: Int -> [a] -> IO (IOArray Int a) newArray n xs = newListArray (1,n) xs main = do args <- getArgs hSetBuffering stdout NoBuffering let guitar = Guitar standardTuning 22 let barreForms = [formA, formA7, formAm, formAm7, formE, formE7, formEm, formEm7] let openForms = [formC, formC7, formG, formG7, formD, formD7, formDm, formDm7] ++ barreForms let barreChords = [ applyForm (tuning guitar) cf f | f <- [1..12], cf <- barreForms] let openChords = openB7 : [ applyForm (tuning guitar) cf 0 | cf <- openForms ] chrds <- shuffle $ openChords sqs <- shuffle $ [ (s,f) | s <- [1..6], f <- [0 .. len guitar]] menu [ ("Ask me to play chords", mapM_ (playChord guitar) $ chrds), ("Ask me to identify chords", mapM_ (nameChord guitar) $ chrds), ("Ask me to identify notes", mapM_ (nameNote guitar) $ sqs) ] menu :: [(String, IO ())] -> IO () menu exs = do let lu = zip (map (head . show) [1..]) exs let is = map fst lu putStrLn "\nSelect an exercise:\n" mapM_ (\(i, (n,a)) -> putStrLn $ i : ") " ++ n ) lu putStr $ "\nChoice (1-" ++ (show . length $ exs) ++ "): " (c:_) <- getLine when (not $ c `elem` is) $ menu exs case lookup c lu of Just (n, a) -> a