TLQ72DSJD7GGPWN6HGBHAVPBRQFKEQ6KSK43U7JWWID4ZWAF47JAC MXLZBRQNXRIJ4BTAEDSLA4N5PABEG7GMWSM7GS4ACJQ6BE4PVAKQC LUM4VQJIHJKQWWD5NVWTVSNPKQTMGQQICTFOTM6W4BMME2G3G5RQC LAROLAYUGJ4Q5AEFV5EJMIA2ZKBNCBWHHHPCJ3CKCNIUIYUKRFVQC MWUPXTBF2LATVOJLJTXSDFB3OMFGMXDNETWJA3JHUOUBTUJ7WJAAC 75N3UJ4JK56KXF56GASGPAWLFYGJDETVJNYTF4KXFCQM767JUU5AC WO2MINIF4TXOHWSE7JWXRZYN64XRVLYIRFMF4SMPSOXKA2V77KMQC EMVTF2IWNQGRL44FC4JNG5FYYQTZSFPNM6SOM7IAEH6T7PPK2NVAC 64VI73NPSFNWTL6UXM6YHRFLNJZ3NUJ2R3CL53MO2HSZWFGBIRTQC 64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC WFZDMVUXZ2KPTMRAZGEYHKEJTKOKWVYCXKKAKQ7K6I5TMSLBUJ4QC TZQJVHBAMDNWDBYCDE3SDVGBG2T5FOE3J5JAD6NENRW36XBHUUFQC FRPWIKCNGK6PM6VCKEHEUG5A2LWL7WFN66L4CPQ7DLN4WAS3TIZQC NVOCQVASZWTKQJG7GPH7KHKZZR7NUG4WLV5YY4KAIRPCJRWCZPIAC Y35QCWYW2OTZ27ZVTH2BA3XJTUCJ2WMLKU32ZCOCDY3AW7TIZXRAC P6NR2CGXCWAW6GXXSIXCGOBIRAS2BM4LEM6D5ADPN4IL7TMW6UVAC GKGVYBZGPJXO7N7GLHLRNYQPXFHBQSNQN53OKRFCXLQEYDTC5I4QC 2OIPAQCBDIUJBXB4K2QVP3IEBIUOCQHSWSWFVMVSVZC7GHX2VK7AC RSEB2NFGUBTFESE5BJKDUVQL5Y5ZVGY5O4CJX2LNP63MS3NRHHZQC NTPC7KJEAPA34SBIA74FVQSJXYNW32RIUQTHUSUTKMEUCPLUIBJAC N4NDAZYTLSI2W22KT3SYXL257DBMSH3UT2BXOYM7LH7FSZAY4RLAC 7DBNV3GV773FH5ZLQWFX4RBOS4Q3CIK2RYZNNABY3ZOETYZCXRNQC 4QX5E5ACVN57KJLCWOM4JEI6JSV4XZNCWVYPOTKSOMUW3SOMCNJAC bidSeconds bid = toRational $ bid ^. secondsbidAmount bid = toRational $ bid ^. (btcAmount . btc)costRatio bid = bidSeconds bid / bidAmount bid
secs bid = toRational $ bid ^. bidSecondsbtc bid = toRational $ bid ^. (bidAmount . satoshis)costRatio bid = secs bid / btc bid
winFraction = (toRational $ remainder ^. btc) / (toRational $ x ^. (btcAmount . btc))remainderSeconds = Seconds . round $ winFraction * (toRational $ x ^. seconds)
winFraction = (toRational $ remainder ^. satoshis) / (toRational $ x ^. (bidAmount . satoshis))remainderSeconds = Seconds . round $ winFraction * (toRational $ x ^. bidSeconds)
sqliteQDB :: SQLiteHandle -> IO (QDB (EitherT Text IO) SQLiteHandle)sqliteQDB db = do_ <- defineTableOpt db True eventTable_ <- defineTableOpt db True auctionTablereturn $ QDB{ recordEvent = recordEvent', readWorkIndex = readWorkIndex', newAuction = newAuction', readAuction = readAuction', recordBid = recordBid', readBids = readBids', createUser = createUser'}recordEvent' :: LogEntry -> ReaderT SQLiteHandle (EitherT Text IO) ()recordEvent' (LogEntry ba ev) = dodb <- asklift . lift . void $ insertRow db "workEvents"[ ("btcAddr", ba ^. address ^. from packed), ("event", unpack (eventName ev)), ("eventTime", formatSqlTime (logTime ev))]readWorkIndex' :: ReaderT SQLiteHandle (EitherT Text IO) WorkIndexreadWorkIndex' = dodb <- asklet selection = execStatement db "SELECT btcAddr, event, eventTime from workEvents"rows <- lift . EitherT $ fmap (over _Left pack) selectionreturn . intervals . catMaybes $ fmap parseLogEntry (join rows)newAuction' :: Auction -> ReaderT SQLiteHandle (EitherT Text IO) AuctionIdnewAuction' a = dodb <- ask_ <- lift . lift $ insertRow db "auctions"[ ("raiseAmount", show $ a ^. (raiseAmount . btc)), ("eventTime", formatSqlTime $ a ^. endsAt)]lift . lift . fmap (AuctionId . fromInteger) $ getLastRowID db
readAuction' :: AuctionId -> ReaderT a (EitherT Text IO) AuctionreadAuction' (AuctionId aid) = dodb <- asklet selection = execParamStatement db"SELECT raiseAmount, endsAt FROM auctions WHERE ROWID = :aid"[("aid", Int aid)]rows <- lift . EitherT $ fmap (over _Left pack) selection
newtype PLogEntry = PLogEntry LogEntrymakePrisms ''PLogEntry
recordBid' :: UTCTime -> Bid -> ReaderT a (EitherT Text IO) ()recordBid' = undefinedreadBids' :: AuctionId -> ReaderT a (EitherT Text IO) [(UTCTime, Bid)]readBids' = undefined
instance FromRow PLogEntry wherefromRow =let workEventParser = WorkEvent <$> (field >>= nameEvent) <*> fieldlogEntryParser = LogEntry <$> (fmap BtcAddr field) <*> workEventParserin fmap PLogEntry logEntryParser
parseLogEntry :: Row Value -> Maybe LogEntryparseLogEntry row = doa <- lookup "btcAddr" row >>= valueAddrt <- lookup "eventTime" row >>= valueTimeev <- lookup "event" row >>= (valueEvent t)return $ LogEntry a evparseAuction :: Row Value -> Maybe AuctionparseAuction row =Auction <$> (lookup "raiseAmount" row >>= valueBTC)<*> (lookup "endsAt" row >>= valueTime)
instance FromRow PAuction wherefromRow =let auctionParser = Auction <$> (fmap BTC field) <*> fieldin fmap PAuction auctionParser
valueBTC :: Value -> Maybe BTCvalueBTC (Int i) _ = Just $ BTC ivalueBTC _ = Nothing
recordEvent' :: LogEntry -> ReaderT Connection IO ()recordEvent' logEntry = doconn <- asklift $ execute conn"INSERT INTO work_events (btc_addr, event_type, event_time) VALUES (?, ?, ?)"(logEntry ^. (from _PLogEntry))
valueAddr :: Value -> Maybe BtcAddrvalueAddr (Text t) = parseBtcAddr $ pack tvalueAddr _ = Nothing
readWorkIndex' :: ReaderT Connection IO WorkIndexreadWorkIndex' = doconn <- askrows <- lift $ query_ conn"SELECT btc_addr, event_type, event_time from workEvents"lift . return . workIndex $ fmap (^. _PLogEntry) rows
valueTime :: Value -> Maybe UTCTimevalueTime (Text t) = parseTime defaultTimeLocale "%c" tvalueTime _ = Nothing
newAuction' :: Auction -> ReaderT Connection IO AuctionIdnewAuction' auc = doconn <- asklift $ execute conn"INSERT INTO auctions (raise_amount, end_time) VALUES (?, ?)"(auc ^. (raiseAmount . satoshis), auc ^. auctionEnd)lift . fmap AuctionId $ lastInsertRowId conn
valueEvent :: UTCTime -> Value -> Maybe WorkEventvalueEvent t (Text "start") = Just (StartWork t)valueEvent t (Text "stop") = Just (StopWork t)valueEvent _ _ = Nothing
readAuction' :: AuctionId -> ReaderT Connection IO (Maybe Auction)readAuction' (AuctionId aid) = doconn <- askrows <- lift $ query conn"SELECT raise_amount, end_time FROM auctions WHERE ROWID = ?"(Only aid)lift . return . headMay $ fmap (^. _PAuction) rows
formatSqlTime :: UTCTime -> StringformatSqlTime t = formatTime defaultTimeLocale "%c" t
recordBid' :: AuctionId -> Bid -> ReaderT Connection IO ()recordBid' (AuctionId aid) bid = doconn <- asklift $ execute conn"INSERT INTO bids (auction_id, user_id, bid_seconds, bid_amount, bid_time) values (?, ?, ?, ?, ?)"(aid, bid ^. bidUser, bid ^. bidSeconds, bid ^. bidAmount, bid ^. bidTime)
eventTable :: SQLTableeventTable = Table "workEvents"[ Column "btcAddr" (SQLVarChar 256) [], Column "event" (SQLVarChar 64) [], Column "eventTime" (SQLDateTime DATETIME) []] []
readBids' :: AuctionId -> ReaderT Connection IO [(UTCTime, Bid)]readBids' = undefined
auctionTable :: SQLTableauctionTable = Table "auctions"[ Column "raiseAmouont" (SQLInt BIG False False) [], Column "endsAt" (SQLDateTime DATETIME) []] []
createUser' :: User -> ReaderT Connection IO UserIdcreateUser' = undefined
sqliteQDB :: QDB IO ConnectionsqliteQDB = QDB{ recordEvent = recordEvent', readWorkIndex = readWorkIndex', newAuction = newAuction', readAuction = readAuction', recordBid = recordBid', readBids = readBids', createUser = createUser'}
eventName :: WorkEvent -> TexteventName (StartWork _) = "start"eventName (StopWork _) = "stop"
eventName :: EventType -> TexteventName StartWork = "start"eventName StopWork = "stop"nameEvent :: MonadPlus m => Text -> m EventTypenameEvent "start" = return StartWorknameEvent "stop" = return StopWorknameEvent _ = mzero
parseJSON (Object jv) = dot <- jv .: "type" :: A.Parser Textcase t of"start" -> StartWork <$> jv .: "timestamp""stop" -> StopWork <$> jv .: "timestamp"_ -> mzero
parseJSON (Object jv) =WorkEvent <$> (jv .: "type" >>= nameEvent) <*> jv .: "timestamp"
intervals :: Foldable f => f LogEntry -> WorkIndexintervals logEntries =let logSum = F.foldl' appendLogEntry MS.empty logEntriesin MS.map (bimap (fmap event) (fmap workInterval)) $ logSum
workIndex :: Foldable f => f LogEntry -> WorkIndexworkIndex logEntries =let logSum :: RawIndexlogSum = F.foldl' appendLogEntry MS.empty logEntriesin MS.map (bimap (fmap (^. event)) (fmap workInterval)) $ logSum
appendLogEntry workIndex entry =let acc = reduceToIntervals $ pushEntry entry workIndexin insert (btcAddr entry) acc workIndex
appendLogEntry idx entry =let acc = reduceToIntervals $ pushEntry entry idxin insert (entry ^. btcAddr) acc idx