Skip to content

Instantly share code, notes, and snippets.

@eentzel
Forked from rapha/simulation.ml
Created July 20, 2010 02:39

Revisions

  1. @rapha rapha revised this gist Mar 17, 2010. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion simulation.ml
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    #!/usr/bin/env ocamlfind batteries/ocaml
    open List

    let num_devs = 20
  2. @rapha rapha created this gist Mar 17, 2010.
    88 changes: 88 additions & 0 deletions simulation.ml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    #!/usr/bin/env ocamlfind batteries/ocaml
    open List

    let num_devs = 20
    let failure_rate = 0.20
    let build_time = (15. (* mins *) /. 60.) (* hours *)
    let commit_wait_timeslots = 4. /. build_time (* on average *)
    let working_hours = 8.
    let num_timeslots = working_hours /. build_time |> int_of_float

    type build_status = Idle | Building | Pass | Retry | Fail

    let random_choice = function
    | [] -> None
    | xs -> Some (xs |> length |> Random.int |> at xs)

    let possibly probability value default =
    if (Random.float 1.0) <= probability then value else default

    let statuses =
    () |> Unix.time |> int_of_float |> Random.init;
    Enum.unfold
    (make num_devs Idle)
    (fun prev_timeslot ->
    let passed_index = prev_timeslot
    |> mapi (fun i s -> (i,s))
    |> filter (snd |- (=) Building)
    |> map fst
    |> random_choice in
    let current_timeslot = prev_timeslot
    |> mapi (fun i s -> if (Some i) = passed_index then Pass else s)
    |> map (function Building -> possibly failure_rate Fail Retry | s -> s) in
    let next_timeslot = current_timeslot
    |> map (function
    | Retry -> Building
    | Fail | Pass | Idle -> possibly (1. /. commit_wait_timeslots) Building Idle
    | status -> status
    )
    in
    Some (current_timeslot, next_timeslot)
    )
    |> Enum.take num_timeslots |> of_enum

    let to_html =
    let name = function
    | Idle -> "idle"
    | Building -> "building"
    | Pass -> "pass"
    | Retry -> "retry"
    | Fail -> "fail"
    in
    mapi (fun col ->
    mapi (fun row status ->
    let title = Printf.sprintf "build %s for dev %d" (name status) row in
    Printf.sprintf "<span class='status %s row_%d col_%d' title='%s'>&nbsp;</span>" (name status) row col title
    ) |- reduce (^)
    ) |- reduce (^)

    let styles =
    let box_size = 20 in
    ((0 -- num_devs) |> Enum.map (fun row -> Printf.sprintf
    ".row_%d { position:absolute; height:%dpx; top:%dpx }\n" row box_size (row * box_size)
    ) |> Enum.reduce (^))
    ^
    ((0 -- num_timeslots) |> Enum.map (fun col -> Printf.sprintf
    ".col_%d { position:absolute; width:%dpx; left:%dpx }\n" col box_size (col * box_size)
    ) |> Enum.reduce (^))

    let _ =
    Printf.printf "
    <html>
    <head>
    <style type='text/css'>
    .status { border: 1px solid gray; padding:0; margin:0; }
    .idle { background-color:white }
    .building { background-color:blue }
    .pass { background-color:green }
    .retry { background-color:orange }
    .fail { background-color:red }
    %s
    </style>
    </head>
    <body>%s</body>
    </html>
    "
    styles
    (statuses |> to_html)
    ;;