(***************************************************************)
(*                        Reactive Asco                        *)
(*             http://reactiveml.org/reactive_asco             *)
(*                                                             *)
(*                                                             *)
(*  Authors: Guillaume Baudart (guillaume.baudart@ens.fr)      *)
(*           Louis Mandel (louis.mandel@lri.fr)                *)
(*                                                             *)
(***************************************************************)

(** Groups traitment. *)

open Types
open Reactive_map


(** Slice the group [g] associated to the event [i] after a delay [delta]. Each action in [g.group_seq] is reassociated to the nearest event. Return a list of score_event. *) let slice instr_score i delta g = let di = instr_score.find i in let rec asso_nearest de l acc = match l with | [] -> acc | (da, ae)::t -> let date = de +. da in let r, d = instr_score.nearest date in begin match acc with | [] -> let dn = date -. d in asso_nearest date t [ (r, [(dn, ae)]) ] | (r', l) :: acc' -> if r = r' then asso_nearest date t ((r, ((da, ae) :: l)) :: acc') else let dn = date -. d in asso_nearest date t ((r, [(dn, ae)]) :: acc) end in let rec build_groups l acc = match l with | [] -> acc | (r, l1)::l2 -> let br = List.rev l1 in let g = { group_synchro = Loose; group_error = g.group_error; group_seq = br; } in let se = { event = r; seq = [(0.0, Group(g))]; } in build_groups l2 (se::acc) in let nl = asso_nearest (di +. delta) g.group_seq [] in build_groups nl []

(** Split the group [g] associated to the event [i] after a delay [delta] in two. Actions that should happen before event [j] and action that should happen after [j]. Return two sequences of actions. *) let split instr_score i j delta g = let di = instr_score.find i in let dj = instr_score.find j in let rec aux de ael p f df = match ael with | [] -> p, f, df | (da, ae)::t -> if (de +. da) < dj then aux (de +. da) t ((da, ae)::p) f (de +. da) else aux (de +. da) t p ((da, ae)::f) df in let p, f, df = aux (di +. delta) g.group_seq [] [] (di +. delta) in let past, future = List.rev p, List.rev f in let future = match future with | [] -> [] | (dae, ae)::t -> ((df +. dae -. dj), ae)::t in past, future

(** Extract groups from a list of electronic actions. *) let rec extract_group l = let rec aux d l = match l with | [] -> [] | (da, ae)::t -> begin match ae with | Group(g) -> (da +. d, ae)::(aux 0.0 t) | _ -> aux (da +. d) t end in aux 0.0 l