Skip to content

Instantly share code, notes, and snippets.

@Jim-Holmstroem
Created March 7, 2017 22:30
Show Gist options
  • Save Jim-Holmstroem/abfa6783ab3e2b05423c84438d15f6dd to your computer and use it in GitHub Desktop.
Save Jim-Holmstroem/abfa6783ab3e2b05423c84438d15f6dd to your computer and use it in GitHub Desktop.
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.List.Types (NonEmptyList)
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 ( EffWebStorage
, 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
defaultTokenState = TokenState { count: 0
, token: ""
}
storage = localStorage
getTokenState :: forall eff. EffWebStorage eff (Either (NonEmptyList ForeignError) TokenState)
getTokenState = do
tokenStateSerialized <- getItem storage "tokenState"
pure $ case tokenStateSerialized of
(Just tokenStateSerialized) -> runExcept $ readJSON tokenStateSerialized :: F TokenState
Nothing -> Right defaultTokenState
setTokenState :: forall eff. TokenState -> EffWebStorage eff Unit
setTokenState tokenState = do
tokenStateSerialized <- unsafeFromForeign <<< write $ tokenState
setItem storage "tokenState" tokenStateSerialized
incrementCount :: TokenState -> TokenState
incrementCount (TokenState tokenState@{count: count}) = TokenState $ tokenState {count = count + 1}
main = do
Right tokenState <- getTokenState
logShow tokenState
setTokenState $ defaultTokenState
--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