Implement a simple priority queue mechanism
- pseudo-random index generator to that favours priority indices
This commit is contained in:
parent
8fcea9c84b
commit
04abd71582
|
@ -136,6 +136,7 @@ executable chan-delorean-consoomer
|
||||||
Network.DataClientTypes
|
Network.DataClientTypes
|
||||||
Common.Server.ConsumerSettings
|
Common.Server.ConsumerSettings
|
||||||
Common.Server.JSONSettings
|
Common.Server.JSONSettings
|
||||||
|
PriorityQueue
|
||||||
|
|
||||||
-- LANGUAGE extensions used by modules in this package.
|
-- LANGUAGE extensions used by modules in this package.
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
|
@ -159,7 +160,9 @@ executable chan-delorean-consoomer
|
||||||
mime-types,
|
mime-types,
|
||||||
perceptual-hash,
|
perceptual-hash,
|
||||||
async,
|
async,
|
||||||
temporary
|
temporary,
|
||||||
|
stm,
|
||||||
|
random
|
||||||
|
|
||||||
-- Directories containing source files.
|
-- Directories containing source files.
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
|
@ -8,17 +8,6 @@ import System.Console.CmdArgs
|
||||||
import Common.Server.JSONSettings
|
import Common.Server.JSONSettings
|
||||||
import Lib
|
import Lib
|
||||||
|
|
||||||
-- TODO: detect saged threads by reading the bump time from the thread and comparing
|
|
||||||
-- that time to the timestamp of the most recent post. If the post is newer
|
|
||||||
-- - then the thread is being saged. Reasons it can be saged:
|
|
||||||
-- - it's saged by a mod
|
|
||||||
-- - the post has sage in the email field
|
|
||||||
-- - the thread is full.
|
|
||||||
--
|
|
||||||
-- Better to support all those flags via the api: saged, locked, cyclical?, sticky
|
|
||||||
-- - deleted could be there too
|
|
||||||
-- - edited could be there too
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
settingsValue <- cmdArgs $ SettingsCLI "backfill_settings.json"
|
settingsValue <- cmdArgs $ SettingsCLI "backfill_settings.json"
|
||||||
|
|
|
@ -83,6 +83,7 @@ httpFileGetters settings = FileGetters
|
||||||
putStrLn $ "Copy Or Move (Move) src: " ++ src ++ " dest: " ++ dest
|
putStrLn $ "Copy Or Move (Move) src: " ++ src ++ " dest: " ++ dest
|
||||||
createDirectoryIfMissing True common_dest
|
createDirectoryIfMissing True common_dest
|
||||||
moveFile src dest
|
moveFile src dest
|
||||||
|
|
||||||
case m_thumb_src of
|
case m_thumb_src of
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
Just thumb_src -> moveFile thumb_src thumb_dest
|
Just thumb_src -> moveFile thumb_src thumb_dest
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
{-
|
||||||
|
The purpose of this module is to provide a way to store things
|
||||||
|
in order (for example as most recent), take the nth item in
|
||||||
|
the order out, and put a new item in. In O(log n) time.
|
||||||
|
|
||||||
|
There is also a function to choose a random integer, but favours lower ones.
|
||||||
|
Together, this lets us process data in a safe way asynchronously,
|
||||||
|
where if we keep choosing a skewed random item to process all of the items
|
||||||
|
eventually get processed. No two threads will process the same thing at the
|
||||||
|
same time, and more popular things get processed more often.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module PriorityQueue
|
||||||
|
( Elem (..)
|
||||||
|
, Queue
|
||||||
|
, take
|
||||||
|
, put
|
||||||
|
, selectSkewedIndex
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Prelude hiding (splitAt, take)
|
||||||
|
import Data.Set hiding (take, foldr, map)
|
||||||
|
import Data.Ord (comparing)
|
||||||
|
import System.Random (StdGen, getStdGen, randomR)
|
||||||
|
import Data.List (sort, group)
|
||||||
|
|
||||||
|
|
||||||
|
data Elem a = Elem
|
||||||
|
{ priority :: Int
|
||||||
|
, element :: a
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Ord (Elem a) where
|
||||||
|
compare = comparing priority
|
||||||
|
|
||||||
|
|
||||||
|
instance Eq (Elem a) where
|
||||||
|
(==) x y = priority x == priority y
|
||||||
|
|
||||||
|
|
||||||
|
type Queue a = Set (Elem a)
|
||||||
|
|
||||||
|
|
||||||
|
take :: Int -> Queue a -> (Elem a, Queue a)
|
||||||
|
take n set =
|
||||||
|
let (_, greater) = splitAt (size set - n - 1) set
|
||||||
|
elem = findMin greater
|
||||||
|
in (elem, delete elem set)
|
||||||
|
|
||||||
|
|
||||||
|
put :: Elem a -> Queue a -> Queue a
|
||||||
|
put = insert
|
||||||
|
|
||||||
|
|
||||||
|
-- Simplified function to generate a number linearly skewed towards the start of the range
|
||||||
|
linearSkewRandom :: Double -> Double -> StdGen -> (Double, StdGen)
|
||||||
|
linearSkewRandom min max rng =
|
||||||
|
let (u, rng') = randomR (0.0, 1.0) rng
|
||||||
|
-- skewedValue = min + (u ** 2) * (max - min)
|
||||||
|
skewedValue = (min - 0.5) + (u ** 2) * (max - min + 0.5)
|
||||||
|
-- skewedValue = (min - 0.5) + (1 - sqrt u) * (max - min + 0.5)
|
||||||
|
-- skewedValue = min + (1 - sqrt u) * (max - min)
|
||||||
|
in (skewedValue, rng')
|
||||||
|
|
||||||
|
|
||||||
|
-- Function to select an index from 0 to n-1 with a linear skew towards lower numbers
|
||||||
|
selectSkewedIndex :: Int -> StdGen -> (Int, StdGen)
|
||||||
|
selectSkewedIndex n rng =
|
||||||
|
let max = fromIntegral (n - 1)
|
||||||
|
(randValue, newRng) = linearSkewRandom 0 max rng
|
||||||
|
in (ceiling randValue, newRng)
|
||||||
|
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
stdGen <- getStdGen
|
||||||
|
--putStrLn "Hello World"
|
||||||
|
|
||||||
|
-- let i = fst $ selectSkewedIndex (size q) stdGen
|
||||||
|
-- let x = fst $ take i q
|
||||||
|
-- print (i, priority x)
|
||||||
|
|
||||||
|
let rs = foldr f ([], stdGen) [1..100000]
|
||||||
|
mapM_ pf $ countOccurrences $ fst rs
|
||||||
|
|
||||||
|
where
|
||||||
|
pf :: (Show a, Show b) => (a, b) -> IO ()
|
||||||
|
pf (a, b) = putStrLn $ (show a) ++ "," ++ (show b)
|
||||||
|
|
||||||
|
f _ (xs, gen) =
|
||||||
|
let (x, newgen) = selectSkewedIndex (size q) gen
|
||||||
|
in (x:xs, newgen)
|
||||||
|
|
||||||
|
q :: Queue Int
|
||||||
|
q = fromList [ Elem i undefined | i <- [1..100] ]
|
||||||
|
|
||||||
|
countOccurrences :: (Eq a, Ord a) => [a] -> [(a, Int)]
|
||||||
|
countOccurrences rolls = map (\x -> (head x, length x)) . group . sort $ rolls
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue