-
Notifications
You must be signed in to change notification settings - Fork 0
/
cranks.ml
104 lines (89 loc) · 3.22 KB
/
cranks.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
open Common
(* we need to serialize float to Cstr ourselves so
that R will be able to read it back
Otoky stores all kinds of OCaml's own type info,
which R won't undertand. We should either use
raw Tokyo_cabinet, or understand R's STRING_ELT
serialization to string, or, even better, write
.rda directly instead of .mlb
module TC=Tokyo_cabinet
let matureCapsTC ?(days=5) dcaps toName =
let count = ref 0 in
let tc = HDB.new_ () in
TC.open_ tc ~omode:[Owriter] toName;
H.enum dcaps |>
E.filter (fun (user,caps) -> (L.length caps) > days) |>
E.map (fun (k,v::vs) -> (k,v)) |>
E.iter begin fun (k,v) ->
TC.put tc k v;
incr count
end;
TC.close tc;
leprintfln "wrote %d pairs to %s" !count toName
*)
(* ensure we only work with the mature values, replace immature ones,
younger than maturity days, by minimum *)
let matureDayUserReals: int -> float -> user_day_reals -> day_user_reals =
fun maturity minimum dcaps ->
let res = Array.init Const.daysTotal (fun _ -> H.create Const.usersDaily) in
H.iter begin fun user days ->
let ordered = L.rev days in
let day0 = ordered |> L.hd |> fst in
L.iter begin fun (day,x) ->
let c = if (day - day0) >= maturity then x else minimum in
H.add res.(day) user c
end ordered
end dcaps;
res
let rankHash: user_reals -> ranked_users =
fun hl ->
let r = H.create (H.length hl) in
H.iter begin fun k v ->
let ks = H.find_default r v [] in
H.replace r v (k::ks)
end hl;
let a = H.enum r |> A.of_enum in
(* sort descending
NB for floats, we may choose equality within an epsilon,
and handle NaNs a lá Soc_run *)
A.sort compPairDesc1 a;
A.enum a |> E.map (fun (_,users) -> users)
let rankList x = rankHash x |> L.of_enum
(* first, we can save the array of daily rankings as is,
converting daily enums to lists for ease of inspection *)
let aranks: int -> float -> user_day_reals -> day_rank_users =
fun maturity minimum dcaps ->
let byday = matureDayUserReals maturity minimum dcaps in
A.map rankList byday
(* then, we rewrite dcaps as dranks,
replacing capitals with ranks, processing enums directly *)
let dranks: int -> float -> user_day_reals -> user_day_ranks =
fun maturity minimum dcaps ->
let byday = matureDayUserReals maturity minimum dcaps in
let ranked = A.map rankHash byday in
let res = H.create (H.length dcaps) in
A.iteri begin fun day eusers ->
E.iteri begin fun i users ->
L.iter begin fun user ->
let days = H.find_default res user [] in
H.replace res user ((day,i)::days)
end users
end eusers
end ranked;
res
(* here. we return both aranks and dranks, so we convert enums to lists
right away *)
let daranks: int -> float -> user_day_reals -> user_day_ranks * day_rank_users =
fun maturity minimum dcaps ->
let byday = matureDayUserReals maturity minimum dcaps in
let ranked = A.map (rankHash |- L.of_enum) byday in
let res = H.create (H.length dcaps) in
A.iteri begin fun day eusers ->
L.iteri begin fun i users ->
L.iter begin fun user ->
let days = H.find_default res user [] in
H.replace res user ((day,i)::days)
end users
end eusers
end ranked;
(res, ranked)