aboutsummaryrefslogblamecommitdiff
path: root/judge/main.ml
blob: 38de6159a26fde235a27ef68b62cd7731b039add (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13












                          
                                  





                            
             



                          



                                                                    








                                   

                             


                                                
                              
                           
                      



                                                          




                                                                   

                                                                           

                                      

                              
                                                                   




                              
                                                                   


                         







                                                                             

                                                         
                                                                            









                                                

            


                   
                               

                                      

                                         
                                                         

                  




                                

                                




                                        
                                  
                          


                                                     

                                         




                                        


















                                                                              

                                     

                       

                                  











                                                       

                 










                                       




                                
                                                              
                    


                                                  





















                                                                                            















                            
              

                           
                           





                                                                  






                    
open Core
open Graphics

(* ****************** *)
(* The user interface *)
(* ****************** *)

exception Exit_judge

module UI (C : CORE) : sig

  val init : unit -> unit
  val close : unit -> unit
  val handle_events : unit -> bool
  val display : unit -> unit

end = struct

  module G = C.G

  open G_util

  (* Init/Close *)
  let init () =
    open_graph " 800x600";
    set_font "-misc-fixed-bold-r-normal--15-120-90--c-90-iso8859-1";
    auto_synchronize false;
    display_mode false;
    remember_mode true;
    fullscreen_msg "Starting up..."

  let close () =
    close_graph ()

  (* View types *)
  type view =
    | ScoreBoard
    | MatchList of bool
    | ViewLastGame
    | NavGame of C.game * int
    | Question of string * (unit -> unit) * view

  let rec handle_events () =
    let usefull = ref false in
    while key_pressed () do
      usefull := true;
      match !curr_view, read_key() with
      | ScoreBoard, '\t' -> curr_view := MatchList false
      | MatchList _, '\t' -> curr_view := ScoreBoard
      | MatchList e, 'f' -> curr_view := MatchList (not e)
      | MatchList _, 'r' -> curr_view := Question(
          "Launch new round?",
          (fun () -> C.add_rounds(); curr_view := MatchList false),
          !curr_view
        )
      | MatchList _, 'v' when C.games () <> [] -> curr_view := ViewLastGame
      | MatchList _, 'n' when C.games () <> [] ->
        let g = List.hd (C.games()) in
        curr_view := NavGame (g, -1)
      | NavGame (g, _), 'n' ->
        let rec dx = function
          | gg::pg::_ when pg == g -> curr_view := NavGame (gg, -1)
          | _::l -> dx l
          | [] -> ()
        in dx (C.games())
      | NavGame (g, _), 'p' ->
        let rec dx = function
          | pg::gg::_ when pg == g -> curr_view := NavGame (gg, -1)
          | _::l -> dx l
          | [] -> ()
        in dx (C.games())
      | NavGame (g, n), 'b' when n > 0 ->
        curr_view := NavGame (g, n-1)
      | NavGame (g, n), 'b' when n = -1 ->
        curr_view := NavGame (g, List.length (C.hist g) - 1)
      | NavGame (g, n), 'f' when n < List.length (C.hist g) - 1 && n <> -1 ->
        curr_view := NavGame (g, n+1)
      | NavGame (g, n), 'f' when n = List.length (C.hist g) - 1 ->
        curr_view := NavGame (g, -1)
      | NavGame(g, _), 'a' -> curr_view := NavGame(g, 0)
      | NavGame(g, _), 'z' -> curr_view := NavGame(g, -1)
      | ViewLastGame, '\t' | NavGame _, '\t' -> curr_view := MatchList false
      | Question(_, y, n), 'y' -> y()
      | Question(_, y, n), 'n' -> curr_view := n
      | v, 'q' ->
        curr_view := Question(
          "Really quit?",
          (fun () ->
            fullscreen_msg "Exiting...";
            raise Exit_judge),
          v)
      | _ -> ()
    done;
    !usefull

  and display () =
    clear_graph ();
    begin match !curr_view with
    | ScoreBoard -> scoreboard_disp ()
    | MatchList f -> matchlist_disp f
    | ViewLastGame -> last_game_disp ()
    | NavGame (g, n) -> nav_game_disp g n
    | Question (q, _, _) -> fullscreen_msg (q ^ " (y/n)")
    end;
    synchronize ()

  and curr_view = ref ScoreBoard

  (* Scoreboard view *)
  and scoreboard_disp () =
    text1 1 black "score board";
    text4 1 grey "match list >";
    hl();
    let scores = List.sort
      (fun (_, sc) (_, sc') -> sc' - sc)
      (C.scores())
    in
    let p_sc = ref (-199028109) in
    let show_sc i (n, s) =
      if s <> !p_sc then
        text2 (i+4) black (string_of_int (i+1)^". ");
      p_sc := s;
      text3 (i+4) black n;
      text4 (i+4) black (string_of_int s)
    in
    List.iteri show_sc scores

  (* Match list view *)
  and matchlist_disp show_only_running =
    text1 1 black "match list";
    text2 1 black "queued matches:";
    text3 1 black (string_of_int (C.ql ()));
    text4 1 grey "score board >";
    hl();
    let games =
      if show_only_running then
        List.filter
          (fun g -> match C.p1 g, C.p2 g with Dead, Dead -> false | _ -> true)
          (C.games())
      else C.games()
    in
    let time = Unix.gettimeofday() in
    let print_g i g =
      let cp1, cp2 = match C.s g with
      | TurnOf _ -> black, black
      | Won P1 -> green, red
      | Won P2 -> red, green
      | Tie -> grey, grey
      | Eliminated P1 -> orange, grey
      | Eliminated P2 -> grey, orange
      in
      let mp = function
        | Loading -> grey, "-> []"
        | Saving -> grey, "[] ->"
        | Dead -> black, ""
        | StandBy t -> grey, Format.sprintf "%.2f" t
        | Thinking (t, tb) -> black,
          Format.sprintf "[ %.2f ]" (t -. (time -. tb))
      in
      let p1n, p2n = C.pn g in
      let c, m = mp (C.p1 g) in text1 (i+4) c m;
      text2 (i+4) cp1 p1n;
      text3 (i+4) cp2 p2n;
      let c, m = mp (C.p2 g) in text4 (i+4) c m
    in
    List.iteri print_g games

  (* Game view *)
  and last_game_disp () =
    match C.games () with
    | g::_ ->
      let p1n, p2n = C.pn g in
      text1 1 p1c p1n;
      text2 1 p2c p2n;
      text4 1 grey "match list >";
      hl();
      G.display_game (C.g g) (p1n, p2n)
    | _ -> ()
  and nav_game_disp g n =
    let p1n, p2n = C.pn g in
    text1 1 p1c p1n;
    text2 1 p2c p2n;
    text4 1 grey "match list >";
    hl();
    let n = if n = -1 then List.length (C.hist g) -1 else n in
    let put_st i g =
      let ni = (size_x() - 60) / 12 + 1 in
      let cx = 12 * (i mod ni) + 30 in
      let cy = size_y () - 60 - (20 * (i / ni)) in
      begin match G.s g with
        | TurnOf p ->
          set_color (pc p);
          draw_circle cx cy 2
        | Won p -> 
          set_color (pc p);
          draw_circle cx cy 2;
          draw_circle cx cy 4
        | Tie ->
          set_color black;
          draw_circle cx cy 4
        | Eliminated p ->
          set_color (pc p);
          draw_segments [| cx - 3, cy - 3, cx + 4, cy + 4; cx - 3, cy + 3, cx + 4, cy - 4 |]
      end;
      if i = n then begin
        set_color black;
        fill_circle cx (cy-10) 2;
        G.display_game g (p1n, p2n)
      end
    in
    List.iteri put_st (List.rev (C.hist g))

end

(* ************* *)
(* The main loop *)
(* ************* *)

module Juge (C : CORE) : sig

  val run : unit -> unit

end = struct

  module UI = UI(C)

  let run () =
    UI.init();
    C.init();
    let last_r = ref 0.0 in
    begin try while true do
      let a = C.handle_events () in
      let b = UI.handle_events () in
      if a || b || Unix.gettimeofday() -. !last_r > 0.1 then begin
        UI.display ();
        last_r := Unix.gettimeofday()
      end
    done with
      Exit_judge ->
        C.finish ();
        UI.close ()
    end

end