{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE ExistentialQuantification #-} {-# OPTIONS -Wall #-} module Main where import Control.DeepSeq (deepseq, NFData(..)) import Data.Int import qualified Data.ByteString.Lazy.Char8 as BS import System.Environment import System.Random import System.Clock import GHC.Generics import Data.Aeson import Data.Maybe import StrategyManager import Strategy0 import Datatypes.Game(Game,Command) import VM import Opt import JSONDeser(readInput) import PowerPhrases strategyTag :: String strategyTag = "lilik0" logFileName :: String logFileName = "scores" timeLimitRatio :: Double timeLimitRatio = 0.96 memLimitRatio :: Double memLimitRatio = 1.0 computationsPerStep :: Int computationsPerStep = 10 data JSONSer = JSONSer { problemId :: Int, problemSeed :: Int, problemTag :: String, problemSolution :: String } deriving (Show, Generic) instance FromJSON JSONSer instance ToJSON JSONSer type Id = Int type Seed = Int strategies :: Game -> StdGen -> Maybe [Command] -> GameComputation strategies g sgen cmd = [MkStrategyWrapper (initst g sgen cmd :: Strategy0)] -- = [MkStrategyWrapper (initst g sgen cmd :: NullStrategy1), -- MkStrategyWrapper (initst g sgen cmd :: NullStrategy2)] -- example :: -- = [MkStrategyWrapper (init g sgen cmd :: Strat0), -- MkStrategyWrapper (init g sgen cmd :: Strat1), -- MkStrategyWrapper (init g sgen cmd :: Strat2)] main :: IO () main = do initTime <- secTime args <- getArgs opt <- parseArgs args let files = optFile opt let maxTime = optTime opt let maxMem = optMem opt let powerPhrase = optPowerPhrase opt let logFile = optLog opt rng <- getStdGen initialData <- createComputationsFromFiles files rng powerPhrase let (_, _,gameComputations) = unzip3 initialData commandResults <- iterateGame gameComputations (timeStruct maxTime initTime) maxMem let stringResults = map (\(cmds,score,algoIdx) -> (cmdToString cmds,score,algoIdx)) commandResults let outJSONstructs = zipWith jsonBuilder initialData stringResults BS.putStrLn $ encode outJSONstructs writeLogFile logFile (zipWith logFileBuilder initialData stringResults) where timeStruct Nothing _ = Nothing timeStruct (Just stopTime) initialTime = Just (fromIntegral stopTime,fromIntegral initialTime) jsonBuilder (idx, seed, _) (strCmds, _, _) = (JSONSer idx seed strategyTag strCmds) logFileBuilder (idx, seed, _) (_ ,score , algoIdx) = (idx, seed, score, algoIdx) createComputationsFromFiles :: [String] -> StdGen -> Maybe String -> IO [(Id,Seed,GameComputation)] createComputationsFromFiles fileNames randomGen powerPhrase = do inputs <- readFiles fileNames let igames = map readInput inputs let cstruct = compstruct igames return (gcstruct cstruct) where compstruct ig = concat (map genf ig) genf (i,g) = zipWith (\x (y,z) -> (x,y,z)) (replicate (length g) i) g gcstruct cst = map (\(x,y,z) -> (x,y,j z)) cst where j game = strategies game randomGen (powerCommands powerPhrase) powerCommands Nothing = Nothing powerCommands (Just a) = Just (mapMaybe charToCommand a) readFiles :: [String] -> IO [BS.ByteString] readFiles [] = return [] readFiles (x:xs) = do f <- BS.readFile x fs <- readFiles xs return (f:fs) instance NFData Command where rnf x = seq x () iterateGame :: [GameComputation] -> Maybe (Double,Double) -> Maybe Int -> IO [FinishedGame] iterateGame gameComputations timeLimitData memLimitData = do alive <- checkComputationAlive if alive then nextPass else return bestGames where nextPass = (bestGames `deepseq` (iterateGame nextGameComputations timeLimitData memLimitData)) nextGameComputations = (applyNtimes computationsPerStep advanceGameComputations gameComputations) checkComputationAlive = do timeLimitFlag <- timeLimit timeLimitData memLimitFlag <- memLimit memLimitData let finishedComputation = (and $ map finishedGameComputation gameComputations) return $ not (timeLimitFlag || memLimitFlag || finishedComputation) advanceGameComputations computations = map advanceGameComputation computations bestGames = map getBestGameComputation gameComputations timeLimit :: Maybe (Double, Double) -> IO Bool timeLimit Nothing = return False timeLimit (Just (initialTime,stopTime)) = do actualTime <- secTime let actualTimeD = fromIntegral actualTime let timeDifference = (actualTimeD - initialTime) return (stopTime <= timeDifference) memLimit :: Maybe Int -> IO Bool memLimit _ = return False secTime :: IO Int64 secTime = do (TimeSpec s _) <- getTime Monotonic return s writeLogFile :: Bool -> [(Int,Int,Int,Int)] -> IO () writeLogFile False _ = return () writeLogFile _ els = writeFile logFileName scoredata where scoredata = foldl strlog "\n" els strlog x (a,b,c,d) = sa ++ sb ++ sc ++ sd ++ x ++ "\n\n" where sa = (show a) ++ " " sb = (show b) ++ " " sc = (show c) ++ " " sd = (show d) ++ " " applyNtimes :: Int -> (a -> a) -> a -> a applyNtimes 0 _ accum = accum applyNtimes n f accum = applyNtimes (n - 1) f (f accum)