Last active
March 5, 2017 22:45
-
-
Save Jim-Holmstroem/96df62ad70a9abe121b0590fdd08f8e7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Prelude | |
import Control.Monad.Eff (Eff) | |
import Control.Monad.Eff.Console (CONSOLE, log, logShow) | |
import Control.Monad.Except | |
import Math (sqrt) | |
import Control.Plus (empty) | |
import Control.MonadZero (guard) | |
import Data.Array ((:)) | |
import Data.Traversable (sequence, foldl) | |
import Data.Maybe (Maybe(..), fromMaybe, fromJust) | |
import Data.Int | |
import Data.Int.Bits (xor) | |
import Data.String | |
import Data.Generic | |
import Data.Foreign ( F | |
, ForeignError | |
, unsafeFromForeign | |
, writeObject | |
) | |
import Data.Foreign.Generic | |
import Data.Foreign.Generic.Types | |
import Data.Foreign.Class ( class AsForeign | |
, class IsForeign | |
, readJSON | |
, readProp | |
, (.=) | |
, write | |
) | |
import Control.Monad.Except (runExcept) | |
import Control.Monad.Eff.Class (liftEff) | |
import Control.Monad.Aff (launchAff) | |
import Data.Either (Either(..)) | |
import Data.HTTP.Method (Method(..)) | |
import Network.HTTP.Affjax (get, post, affjax, defaultRequest) | |
import Browser.WebStorage (localStorage, getItem, setItem, removeItem) | |
fromHex :: String -> Maybe Int | |
fromHex = fromStringAs hexadecimal | |
toHex :: Int -> String | |
toHex = toStringAs hexadecimal | |
bytes :: String -> Array (Maybe Int) | |
bytes "" = empty | |
bytes str = fromHex (take 2 str) : bytes (drop 2 str) | |
port :: String | |
port = "5000" | |
solve :: String -> Maybe String | |
solve = map (joinWith "" <<< map (toHex <<< xor 42)) <<< sequence <<< bytes | |
-- TODO(jim) validate with purescript-validate module | |
-- TODO(jim) use generics for decode/encode to remove boilerplate | |
data Challenge = Challenge { challenge :: String | |
} | |
derive instance genericChallenge :: Generic Challenge | |
instance showChallenge :: Show Challenge where | |
show = gShow | |
instance asForeignChallenge :: AsForeign Challenge where | |
write (Challenge challenge) = writeObject [ "challenge" .= challenge.challenge | |
] | |
instance isForeignChallenge :: IsForeign Challenge where | |
read value = do | |
challenge <- readProp "challenge" value | |
pure $ Challenge { challenge: challenge } | |
data Answer = Answer { product :: String | |
, version :: Int | |
, challenge_id :: String | |
, answer :: String | |
} | |
derive instance genericAnswer :: Generic Answer | |
instance showAnswer :: Show Answer where | |
show = gShow | |
instance asForeignAnswer :: AsForeign Answer where | |
write (Answer answer) = writeObject [ "product" .= answer.product | |
, "version" .= answer.version | |
, "challenge_id" .= answer.challenge_id | |
, "answer" .= answer.answer | |
] | |
instance isForeignAnswer :: IsForeign Answer where | |
read value = do | |
product <- readProp "product" value | |
version <- readProp "version" value | |
challenge_id <- readProp "challenge_id" value | |
answer <- readProp "answer" value | |
pure $ Answer { product: product | |
, version: version | |
, challenge_id: challenge_id | |
, answer: answer | |
} | |
data TokenState = TokenState { count :: Int | |
, token :: String | |
} | |
derive instance genericTokenState :: Generic TokenState | |
instance showTokenState :: Show TokenState where | |
show = gShow | |
instance asForeignTokenState :: AsForeign TokenState where | |
write (TokenState tokenState) = writeObject [ "count" .= tokenState.count | |
, "token" .= tokenState.token | |
] | |
instance isForeignTokenState :: IsForeign TokenState where | |
read value = do | |
count <- readProp "count" value | |
token <- readProp "token" value | |
pure $ TokenState { count: count | |
, token: token | |
} | |
defaultTokenState = TokenState { count: 0 | |
, token: "" | |
} | |
storage = localStorage | |
getStorage = getItem localStorage | |
setStorage = setItem localStorage | |
getTokenState = do | |
tokenStateSerialized <- getStorage "tokenState" | |
pure $ case tokenStateSerialized of | |
(Just tokenStateSerialized) -> runExcept $ readJSON tokenStateSerialized :: F TokenState | |
Nothing -> Right defaultTokenState | |
setTokenState tokenState = do | |
tokenStateSerialized <- unsafeFromForeign <<< write $ tokenState | |
setStorage tokenStateSerialized | |
main = do | |
logShow defaultTokenState | |
token <- getTokenState | |
logShow token | |
logShow $ runExcept $ readJSON """{"challenge": "00"}""" :: F Challenge | |
--log $ unsafeFromForeign $ write $ Challenge { challenge: "00" } | |
--main = launchAff $ do | |
-- res <- get $ "http://localhost:" <> port <> "/v1/challenge?p=product&v=1" | |
-- liftEff $ logShow $ runExcept (readJSON res.response :: F Challenge) | |
--main = do | |
-- log <<< show $ solve "deadbeef" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment