ATrade console quote display
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
3.6 KiB

6 years ago
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Brick.AttrMap
import Brick.BChan
import Brick.Main
import Brick.Types
import Brick.Widgets.Border
import Brick.Widgets.Core
import Control.Concurrent
import qualified Control.Concurrent.BoundedChan as BC
import Control.Exception
import Control.Monad
import Data.Aeson
import qualified Data.ByteString.Lazy as B
import Data.IORef
6 years ago
import qualified Data.List as L
6 years ago
import qualified Data.Map.Strict as M
import qualified Graphics.Vty as Vty
import Lens.Micro.Platform
import Lens.Micro.TH
import System.ZMQ4
import ATrade.QuoteSource.Client
import ATrade.Types
import Config
import QuoteTable
data Name = Viewport1
deriving (Show, Eq, Ord)
data AppEvent = QuoteTableUpdate QuoteTable
6 years ago
data AppState = AppState {
_quotes :: QuoteTable
}
6 years ago
makeLenses ''AppState
qsThread :: IORef QuoteTable -> AppConfig -> IO ()
qsThread quotetable config = withContext $ \ctx -> do
6 years ago
qschan <- BC.newBoundedChan 1000
bracket (startQuoteSourceClient qschan (config ^. tickers) ctx (config ^. quoteSourceEndpoint) defaultClientSecurityParams) stopQuoteSourceClient $ \_ -> forever $ do
qsdata <- BC.readChan qschan
case qsdata of
QDTick tick -> handleNewTick quotetable tick
6 years ago
_ -> return ()
where
handleNewTick s t = atomicModifyIORef s $ \table -> (updateTable table t, ())
quoteTableWriterThread :: IORef QuoteTable -> BChan AppEvent -> IO ()
quoteTableWriterThread qtRef chan = forever $ do
threadDelay 1000000
qt <- readIORef qtRef
writeBChan chan $ QuoteTableUpdate qt
6 years ago
main :: IO ()
main = do
maybeConfig <- decode' <$> B.readFile "atrade-brick.config"
case maybeConfig of
Nothing -> error "Can't parse config"
Just config -> do
let app = App {
appDraw = draw,
appChooseCursor = chooseCursor,
appHandleEvent = handleEvent,
appStartEvent = startEvent,
appAttrMap = attrMap'
}
quoteTableRef <- newIORef M.empty
6 years ago
eventChan <- Brick.BChan.newBChan 10
let buildVty = Vty.mkVty Vty.defaultConfig
initialVty <- buildVty
qsThreadId <- forkIO $ qsThread quoteTableRef config
qtwThreadId <- forkIO $ quoteTableWriterThread quoteTableRef eventChan
void $ customMain buildVty (Just eventChan) app (initialState M.empty)
6 years ago
where
initialState ref = AppState ref
6 years ago
draw :: AppState -> [Widget Name]
draw s = [hBox . L.intersperse vBorder $ hLimit 30 . padLeftRight 3 <$> [vBox ([str "Ticker", hBorder] ++ (txt <$> tickers s)),
6 years ago
vBox ([str "Last", hBorder] ++ (str <$> fmap (printEntry s qteLastPrice) (tickers s))),
vBox ([str "Bid", hBorder] ++ (str <$> fmap (printEntry s qteBid) (tickers s))),
vBox ([str "Ask", hBorder] ++ (str <$> fmap (printEntry s qteAsk) (tickers s)))] ]
6 years ago
printEntry s l tickerId = case s ^. quotes . at tickerId of
Just qte -> show $ qte ^. l
Nothing -> "-"
tickers s = M.keys (s ^. quotes)
chooseCursor s loc = Nothing
handleEvent s event = case event of
VtyEvent e -> case e of
Vty.EvKey (Vty.KChar 'q') [] -> halt s
_ -> continue s
AppEvent e -> case e of
QuoteTableUpdate t -> continue $ AppState t
6 years ago
_ -> continue s
startEvent = return
attrMap' s = attrMap Vty.defAttr []