sig
  type contest = Entry.slot Contest.t
  module type GROUP =
    sig
      type t
      val make : unit -> Group.GROUP.t
      val make_one : Group.contest -> Group.GROUP.t
      val iteri : (int -> Group.contest -> unit) -> Group.GROUP.t -> unit
      val length : Group.GROUP.t -> int
      val contains : (Group.contest -> bool) -> Group.GROUP.t -> bool
      val first : Group.GROUP.t -> Group.contest option
      val add : Group.contest -> Group.GROUP.t -> unit
      val compare_length_then_first : Group.GROUP.t -> Group.GROUP.t -> int
      val match_first :
        Group.contest -> Group.GROUP.t -> (Entry.slot -> 'a) -> bool
      val extract_first_first : Group.GROUP.t -> (Entry.slot -> 'a) -> 'a
      val sort :
        (Group.contest -> Group.contest -> int) -> Group.GROUP.t -> unit
    end
  module Group : GROUP
  type group_result = { quit : bool; this_group : bool; }
  class type grouping_spec =
    object
      method column_extractor :
        num_contests:int -> index:int -> Group.contest -> Columns.column list
      method compare_contest : Group.contest -> Group.contest -> int
      method compare_group : Group.t -> Group.t -> int
      method header_spec :
        num_rounds:int ->
        num_groups:int -> pos:int -> Group.t -> Columns.header_spec
      method in_group : Group.contest -> Group.t -> Group.group_result
      method name : string
    end
  module type GROUP_LIST =
    sig
      type t
      val make : Group.grouping_spec -> Group.GROUP_LIST.t
      val add_contest : Group.contest -> Group.GROUP_LIST.t -> unit
      val sort : Group.GROUP_LIST.t -> unit
      val iteri : (int -> Group.t -> unit) -> Group.GROUP_LIST.t -> unit
      val length : Group.GROUP_LIST.t -> int
    end
  module GroupList : GROUP_LIST
end