{-| Module: Sudoku.Loader Description : Provides functions to load a sudoku from the internet. Copyright: (c) Marcel Moosbrugger, 2017 License : MIT This module contains functions to load sudokus from the internet. -} module Sudoku.Loader(loadSudoku) where import Data.ByteString.Lazy.Char8 (unpack) import Data.List (elemIndex, transpose) import Data.Maybe (fromMaybe) import Network.HTTP.Client import Network.HTTP.Client.TLS import Sudoku.Type import Text.HandsomeSoup import Text.Printf (printf) import Text.XML.HXT.Core import Util -- | Converts a difficulty to number which can be plugged into the url. toNumber :: Difficulty -> Int toNumber Easy = 40 toNumber Medium = 33 toNumber Hard = 26 toNumber Evil = 17 -- | Creates the url for a given difficullty level from which the sudokus get -- loaded. url :: Difficulty -> String url d = "https://kjell.haxx.se/sudoku/?visade=" ++ (show $ toNumber d) ++ "&seed=%28random+seed%29&action=Create+a+field&hardchange=0" -- | Loads a sudoku with a given difficulty level from the internet. loadSudoku :: Difficulty -> IO (Maybe Sudoku) loadSudoku d = do manager <- newManager tlsManagerSettings request <- parseRequest (url d) response <- httpLbs request manager let doc = parseHtml $ unpack $ responseBody response values <- runX $ doc >>> css "input.sgrid" ! "value" -- in the html the values are aranged block wise and not row wise let transposedValues = ungroup . ungroup . transpose . groupBy 3 . groupBy 9 . ungroup . ungroup . transpose . groupBy 3 . groupBy 3 $ values let sudokuString = concat $ map (\v -> if v == "" then blankval:"" else v) transposedValues pure (fromString sudokuString)