silvi-0.0.3: src/Silvi/Random.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Silvi.Random
( rand
, randLogExplicit
, randLog
) where
import Chronos (now, timeToDatetime)
import Chronos.Types
import Data.Exists (Exists (..), Reify (..),
SingList (..))
import Data.Text (Text)
import Data.Word (Word8)
import Net.IPv4 (ipv4)
import Net.Types (IPv4 (..))
import qualified Network.HTTP.Types.Method as HttpM
import qualified Network.HTTP.Types.Status as HttpS
import Network.HTTP.Types.Version (http09, http10, http11, http20)
import qualified Network.HTTP.Types.Version as HttpV
import Savage
import Savage.Randy (element, enum, enumBounded, int,
int8, print, word16, word8)
import Savage.Range (constantBounded)
import Silvi.Record (Field (..), SingField (..),
Value (..), rmap, rtraverse)
import Silvi.Types
import System.IO.Unsafe (unsafePerformIO)
import Topaz.Rec (Rec (..), fromSingList)
rand :: SingField a -> Gen (Value a)
rand = \case
SingBracketNum -> ValueBracketNum <$> randomBracketNum
SingHttpMethod -> ValueHttpMethod <$> randomHttpMethod
SingHttpStatus -> ValueHttpStatus <$> randomHttpStatus
SingHttpVersion -> ValueHttpVersion <$> randomHttpVersion
SingUrl -> ValueUrl <$> randomUrl
SingUserId -> ValueUserId <$> randomUserident
SingObjSize -> ValueObjSize <$> randomObjSize
SingIp -> ValueIp <$> randomIPv4
SingTimestamp -> ValueTimestamp <$> randomOffsetDatetime
randLog :: forall as. (Reify as) => Gen (Rec Value as)
randLog = randLogExplicit (fromSingList (reify :: SingList as))
randLogExplicit :: Rec SingField rs -> Gen (Rec Value rs)
randLogExplicit = rtraverse rand
randomIPv4 :: Gen IPv4
randomIPv4 = ipv4
<$> word8 constantBounded
<*> word8 constantBounded
<*> word8 constantBounded
<*> word8 constantBounded
randomBracketNum :: Gen BracketNum
randomBracketNum = BracketNum <$> word8 constantBounded
randomHttpMethod :: Gen HttpM.StdMethod
randomHttpMethod = enumBounded
randomHttpStatus :: Gen HttpS.Status
randomHttpStatus = enumBounded
randomHttpVersion :: Gen HttpV.HttpVersion
randomHttpVersion = element [http09, http10, http11, http20]
randomUserident :: Gen UserId
randomUserident = element userIdents
randomObjSize :: Gen ObjSize
randomObjSize = ObjSize <$> word16 constantBounded
randomUrl :: Gen Url
randomUrl = element urls
randomDatetime :: Gen Datetime
randomDatetime = Datetime
<$> randomDate
<*> randomTimeOfDay
randomTimeOfDay :: Gen TimeOfDay
randomTimeOfDay = TimeOfDay
<$> enum 0 24
<*> enum 0 59
<*> enum 0 59999
randomDate :: Gen Date
randomDate = Date
<$> (Year <$> enum 1995 2100)
<*> (Month <$> enum 0 11)
<*> (DayOfMonth <$> enum 1 31)
randomYear' :: Int -- ^ Origin year
-> Int -- ^ End year, Usually current year
-> Gen Year
randomYear' a b = Year <$> enum (min a b) (max a b)
-- | Random year, generated from a given year to the current one.
--
randomYear :: Int -- ^ Origin year
-> Gen Year
randomYear a = randomYear' a b
where b = (getYear . dateYear . datetimeDate) $ (timeToDatetime (unsafePerformIO now))
randomMonth' :: Int -- ^ Origin month
-> Int -- ^ End month, usually current
-> Gen Month
randomMonth' a b = Month <$> enum (min a b) (max a b)
randomMonth :: Int -- ^ Origin month
-> Gen Month
randomMonth a = randomMonth' a b
where b = (getMonth . dateMonth . datetimeDate) $ (timeToDatetime (unsafePerformIO now))
randomDay' :: Int -- ^ Origin Day
-> Int -- ^ End day, usually the current day
-> Gen DayOfMonth
randomDay' a b = DayOfMonth <$> enum (min a b) (max a b)
randomDay :: Int -- ^ Origin Day
-> Gen DayOfMonth
randomDay a = randomDay' a b
where b = (getDayOfMonth . dateDay . datetimeDate) $ (timeToDatetime (unsafePerformIO now))
randomOffsetDatetime :: Gen OffsetDatetime
randomOffsetDatetime = OffsetDatetime
<$> randomDatetime
<*> randomOffset
randomOffset :: Gen Offset
randomOffset = element offsets
-- | List of sample Useridents.
userIdents :: [UserId]
userIdents = map UserId ["-","andrewthad","cement","chessai"]
-- | List of sample URLs.
urls :: [Url]
urls = map Url ["https://github.com","https://youtube.com","layer3com.com"]
-- | List of sample
-- | List of Time Zone Offsets. See:
-- https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
offsets :: [Offset]
offsets = map Offset [100,200,300,330,400,430,500,530,545,600,630,700,800,845,900,930,1000,1030,1100,1200,1245,1300,1345,1400,0,-100,-200,-230,-300,-330,-400,-500,-600,-700,-800,-900,-930,-1000,-1100,-1200]