---------------------------------------------------------------------------- -- | -- Module : HCube.Cube -- Copyright : (c) Todd Wegner 2012 -- License : BSD-style (see the LICENSE file) -- -- Maintainer : echbar137@yahoo.co.in -- Stability : provisional -- Portability : portable -- -- Executable of hcube. ----------------------------------------------------------------------------- {-# LANGUAGE Trustworthy #-} module Main where import System.Environment (getArgs) import Control.Monad (foldM, (>=>)) import Data.Maybe (fromMaybe) import System.Directory (createDirectoryIfMissing) import HCube.Data import HCube.Lib import HCube.Utility import HCube.Cons import HCube.Test (runTests) import HCube.Theory import HCube.Template (render) import HCube.OrientGroup import HCube.Permutation {- ghci Cube.hs :set args 2 :set args "physicalCubeExample" -} path = "store/" main :: IO () main = getArgs >>= f where f args = createDirectoryIfMissing True path >> putStrLn "enter 'help' for menu" >> getCube args >>= render >>= console >>= saveCube2 >> return () where console :: Rubik -> IO Rubik console = doM loop f where f = (getLine >>= parseCmd ~> processCmd) >=> render processCmd :: Command -> Rubik -> IO Rubik processCmd cm rk = f cm where f (Projection pj) = return $ rk { view = pj } f Quit = return $ rk { loop = False } f (Operation ops) = appendHis ops rk >>= return . doCubeOps ops f Undo = undo rk f Help = putStrLn help >> return rk f NoCommand = return rk appendHis :: [Rotation] -> Rubik -> IO Rubik appendHis ops rk = return $ rk { his = ops ++ (his rk) } removeLastHis :: Rubik -> IO Rubik removeLastHis rk = return $ rk { his = tail (his rk) } undo :: Rubik -> IO Rubik undo rk = f (his rk) where f [] = return rk f hs = return ( doCubeOps [invOpp $ head hs] rk ) >>= removeLastHis help = unlines ["l1+ rotate layer 1 clockwise", "l2- rotate layer 2 counter", "h3+ rotate horizontal slab 3 clockwise", "h1- rotate horizontal slab 1 counter", "v2+ rotate vertical slab 2 clockwise", "v3- rotate vertical slab 3 counter", "l left side view", "r right side view", "r+ rotate whole cube clockwise 90 degrees (z axis)", "r- rotate whole cube counter clockwise 90 degrees (z axis)", "r2 rotate whole cube 180 degrees", "fh flip whole cube over along horizontal axis", "fv flip whole cube over along vertical axis", "u undo last cube operation", "q quit"] parseCmd :: String -> IO Command parseCmd = return . f where f "l" = Projection LeftV f "r" = Projection RightV f "q" = Quit f "r+" = Operation [RotateCube Layer Clockwise] f "r-" = Operation [RotateCube Layer Counter] f "r2" = Operation [RotateCube Layer Twice] f "fh" = Operation [RotateCube HSlice Twice] f "fv" = Operation [RotateCube VSlice Twice] f "help" = Help f (a:b:c:[]) = verifyOp (g a) (h c) (i b) f "u" = Undo f _ = NoCommand g 'l' = Layer g 'h' = HSlice g 'v' = VSlice g _ = NoSlab h '+' = Clockwise h '-' = Counter h '2' = Twice h _ = NoDir i ch = fromMaybe 0 $ maybeRead [ch] verifyOp :: Slab -> Direction -> Numb -> Command verifyOp = f where f NoSlab _ _ = NoCommand f _ NoDir _ = NoCommand f _ _ 0 = NoCommand f sl dr nm = Operation [Rotation sl dr nm] getCube :: [String] -> IO Rubik getCube = f where f [] = loadCube2 3 f args = maybe g loadCube2 (maybeRead h) where g = fromPhysical $ concat [path, h] h = head args loadCube2 :: Size -> IO Rubik loadCube2 sz = loadCube sz f where f = concat [path, g, "x", g, "x", g] g = show sz saveCube2 :: Rubik -> IO () saveCube2 rk = saveCube f rk where f = concat [path, g, "x", g, "x", g] g = show $ n rk