diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Selection.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange/Selection.hs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/Network/BitTorrent/Exchange/Selection.hs b/src/Network/BitTorrent/Exchange/Selection.hs new file mode 100644 index 00000000..2724fabc --- /dev/null +++ b/src/Network/BitTorrent/Exchange/Selection.hs | |||
@@ -0,0 +1,85 @@ | |||
1 | -- | | ||
2 | -- Copyright : (c) Sam Truzjan 2013 | ||
3 | -- License : BSD3 | ||
4 | -- Maintainer : pxqr.sta@gmail.com | ||
5 | -- Stability : experimental | ||
6 | -- Portability : portable | ||
7 | -- | ||
8 | -- Piece selection algorithms. | ||
9 | -- | ||
10 | module Network.BitTorrent.Exchange.Selection | ||
11 | ( -- * Selection | ||
12 | Selector | ||
13 | , selector | ||
14 | , strategyClass | ||
15 | |||
16 | , strictFirst | ||
17 | , strictLast | ||
18 | , rarestFirst | ||
19 | , randomFirst | ||
20 | , endGame | ||
21 | ) where | ||
22 | |||
23 | import Data.Ratio | ||
24 | |||
25 | import Data.Torrent.Bitfield | ||
26 | |||
27 | |||
28 | type Selector = Bitfield -- ^ Indices of client /have/ pieces. | ||
29 | -> Bitfield -- ^ Indices of peer /have/ pieces. | ||
30 | -> [Bitfield] -- ^ Indices of other peers /have/ pieces. | ||
31 | -> Maybe PieceIx -- ^ Zero-based index of piece to request | ||
32 | -- to, if any. | ||
33 | |||
34 | selector :: Selector -- ^ Selector to use at the start. | ||
35 | -> Ratio PieceCount | ||
36 | -> Selector -- ^ Selector to use after the client have | ||
37 | -- the C pieces. | ||
38 | -> Selector -- ^ Selector that changes behaviour based | ||
39 | -- on completeness. | ||
40 | selector start pt ready h a xs = | ||
41 | case strategyClass pt h of | ||
42 | SCBeginning -> start h a xs | ||
43 | SCReady -> ready h a xs | ||
44 | SCEnd -> endGame h a xs | ||
45 | |||
46 | data StartegyClass | ||
47 | = SCBeginning | ||
48 | | SCReady | ||
49 | | SCEnd | ||
50 | deriving (Show, Eq, Ord, Enum, Bounded) | ||
51 | |||
52 | |||
53 | strategyClass :: Ratio PieceCount -> Bitfield -> StartegyClass | ||
54 | strategyClass threshold = classify . completeness | ||
55 | where | ||
56 | classify c | ||
57 | | c < threshold = SCBeginning | ||
58 | | c + 1 % numerator c < 1 = SCReady | ||
59 | -- FIXME numerator have is not total count | ||
60 | | otherwise = SCEnd | ||
61 | |||
62 | |||
63 | -- | Select the first available piece. | ||
64 | strictFirst :: Selector | ||
65 | strictFirst h a _ = Just $ findMin (difference a h) | ||
66 | |||
67 | -- | Select the last available piece. | ||
68 | strictLast :: Selector | ||
69 | strictLast h a _ = Just $ findMax (difference a h) | ||
70 | |||
71 | -- | | ||
72 | rarestFirst :: Selector | ||
73 | rarestFirst h a xs = rarest (map (intersection want) xs) | ||
74 | where | ||
75 | want = difference h a | ||
76 | |||
77 | -- | In average random first is faster than rarest first strategy but | ||
78 | -- only if all pieces are available. | ||
79 | randomFirst :: Selector | ||
80 | randomFirst = do | ||
81 | -- randomIO | ||
82 | error "randomFirst" | ||
83 | |||
84 | endGame :: Selector | ||
85 | endGame = strictLast | ||