open Graphics ;; Random.self_init () ;; type operation = Val of int | Sum of operation * operation | Diff of operation * operation | Prod of operation * operation | Exp of operation * int ;; let rec calculate = function | Val k -> k | Exp (op, k) -> Math.pw (calculate op) k | Sum (f, g) -> (calculate f) + (calculate g) | Diff (f, g) -> (calculate f) - (calculate g) | Prod (f, g) -> (calculate f) * (calculate g) ;; let generate_random_calc ?plus_w:(pw=10) ?minus_w:(mw=8) ?prod_w:(uw=2) ?exp_w:(ew=0) (length : int) (inf : int) (sup : int) = let sum = pw + mw + uw + ew in let rec aux = function | 0 | 1 -> Val (inf + Random.int (sup - inf)) | k -> let r = Random.int sum in if r < pw then begin if Random.int 2 = 0 then Sum(aux 0, aux (k-1)) else Sum(aux (k-1), aux 0) end else if r < pw+mw then begin if Random.int 2 = 0 then Diff(aux 0, aux (k-1)) else Diff(aux (k-1), aux 0) end else if r < pw+mw+uw then begin if Random.int 2 = 0 then Prod(aux 0, aux (k-1)) else Prod(aux (k-1), aux 0) end else begin Exp(aux (k-1), 2 + Random.int 2) end in aux length ;; let draw_bracket_open ?retval:(rv=Drawing.fodder) (x : int) (y : int) (size : int) = moveto (x + size/4) (y+5*size/4) ; lineto (x) (y+size/2) ; lineto (x) (y-size/2) ; lineto (x + size/4) (y-5*size/4) ; rv := x + size/4 +6 ;; let draw_bracket_close ?retval:(rv=Drawing.fodder) (x : int) (y : int) (size : int) = moveto (x) (y+5*size/4) ; lineto (x + size/4) (y+size/2) ; lineto (x + size/4) (y-size/2) ; lineto (x) (y-5*size/4) ; rv := x + size/4 +6 ;; let draw_sign ?retval:(rv=Drawing.fodder) (x : int) (y : int) (len : int) = function | '+' -> draw_poly_line [|(x, y); (x + len, y)|] ; draw_poly_line [|(x+len/2, y + len/2); (x+len/2, y - len/2)|] ; | '-' -> draw_poly_line [|(x, y); (x + len, y)|] ; | 'x' -> Drawing.draw_letter x y 'x' len ; | _ -> failwith "incorrect\n" ;; let require_bracket = function | Val _ -> false | _ -> true ;; let print_calc (f : operation) (x0 : int) (y0 : int) (size : int) = set_line_width 3 ; set_color black ; let x = ref x0 in let rec aux = function | Val k -> Drawing.draw_integer_alignedleft !x y0 k size ~retval:x ; (*Printf.printf "%d --> \n" !x ;*) | Exp (f, k) -> () | Sum (f, g) -> if require_bracket f then draw_bracket_open !x y0 size ~retval:x ; aux f ; if require_bracket f then draw_bracket_close !x y0 size ~retval:x ; draw_sign !x y0 size '+' ~retval:x ; x := !x + size*10/7 ; if require_bracket g then draw_bracket_open !x y0 size ~retval:x ; aux g ; if require_bracket g then draw_bracket_close !x y0 size ~retval:x ; | Diff (f, g) -> if require_bracket f then draw_bracket_open !x y0 size ~retval:x ; aux f ; if require_bracket f then draw_bracket_close !x y0 size ~retval:x ; draw_sign !x y0 size '-' ~retval:x ; x := !x + size*10/7 ; if require_bracket g then draw_bracket_open !x y0 size ~retval:x ; aux g ; if require_bracket g then draw_bracket_close !x y0 size ~retval:x ; | Prod (f, g) -> if require_bracket f then draw_bracket_open !x y0 size ~retval:x ; aux f ; if require_bracket f then draw_bracket_close !x y0 size ~retval:x ; draw_sign !x y0 (size/2) 'x' ~retval:x ; x := !x + size*10/7 ; if require_bracket g then draw_bracket_open !x y0 size ~retval:x ; aux g ; if require_bracket g then draw_bracket_close !x y0 size ~retval:x ; in aux f ;; let init_odds () = match !(Csts.difficulty) with | 1 -> Csts.plus_ch := 10 ; Csts.minus_ch := 0 ; Csts.prod_ch := 0 ; | 2 -> Csts.plus_ch := 0 ; Csts.minus_ch := 1 ; Csts.prod_ch := 0 ; | 3 -> Csts.plus_ch := 7 ; Csts.minus_ch := 5 ; Csts.prod_ch := 0 ; | 4 -> Csts.plus_ch := 5 ; Csts.minus_ch := 5 ; Csts.prod_ch := 0 ; | 5 -> Csts.plus_ch := 5 ; Csts.minus_ch := 5 ; Csts.prod_ch := 1 ; | 6 -> Csts.plus_ch := 6 ; Csts.minus_ch := 4 ; Csts.prod_ch := 1 ; | 7 -> Csts.plus_ch := 7 ; Csts.minus_ch := 2 ; Csts.prod_ch := 2 ; | 8 -> Csts.plus_ch := 7 ; Csts.minus_ch := 2 ; Csts.prod_ch := 3 ; | 9 -> Csts.plus_ch := 6 ; Csts.minus_ch := 1 ; Csts.prod_ch := 4 ; | 10 -> Csts.plus_ch := 5 ; Csts.minus_ch := 0 ; Csts.prod_ch := 5 ; | _ -> failwith "unsupported\n" ;; let sign = function | k when k < 0 -> -1 | _ -> 1 ;; let update_ans () = if key_pressed () then begin match Char.code (read_key ()) with | 45 (* minus *) -> Csts.ans := !Csts.ans * (-1) | 32 (* space *) | 8 (* del *) -> let s = sign !Csts.ans in Csts.ans := !Csts.ans * s ; Csts.ans := !Csts.ans / 10 ; Csts.ans := !Csts.ans * s ; | k when k >= 48 && k <= 57 (* digit *) -> let s = sign !Csts.ans in Csts.ans := !Csts.ans * s ; Csts.ans := 10 * !Csts.ans + k - 48 ; Csts.ans := !Csts.ans * s ; | x -> ()(*Printf.printf "%d -> %c\n" x (Char.chr x)*) end ;; let grad_color (remt : float) (initt : float) = set_color (rgb (int_of_float (255. *. remt /. initt)) (int_of_float (255. *. (1. -. (remt /. initt)))) 0) ;; let maeth_main () = let start = Unix.gettimeofday () in let cur = ref (Unix.gettimeofday ()) in let found = ref false in let equ = generate_random_calc ~plus_w:(!Csts.plus_ch) ~minus_w:(!Csts.minus_ch) ~prod_w:(!Csts.prod_ch) !Csts.calc_length !Csts.n_inf !Csts.n_sup in let resu = calculate equ in while not !found && (!cur -. start <= !Csts.time_to_ans_f) do auto_synchronize false ; clear_graph () ; set_color black ; print_calc equ 10 (Csts.__height__/2) 15 ; Drawing.draw_string_centered (Csts.__width__/2) (Csts.__height__/3) "Answer" 50 ; Drawing.draw_integer (Csts.__width__/2) (Csts.__height__/3 - 100) !Csts.ans 75 ; fill_rect (Csts.__width__ - 70) (Csts.__height__/4) 70 (Csts.__height__/2) ; set_color (rgb 129 255 0) ; fill_rect (Csts.__width__ - 60) (Csts.__height__/4 + 10) 50 (max 0 (Csts.__height__/2 - 20 - int_of_float (float_of_int (Csts.__height__/2 - 20) *. (!cur -. !Csts.start_0) /. !Csts.total_time_f))) ; grad_color (!cur -. start) (!Csts.time_to_ans_f) ; fill_rect 0 (7*Csts.__height__/8) (int_of_float ((float_of_int Csts.__width__) *. (!cur -. start) /. !Csts.time_to_ans_f)) (Csts.__height__/8+1) ; set_color (rgb 192 192 0) ; Drawing.draw_string 10 (Csts.__height__ - 40) "Score" 35 ; set_color (rgb 128 128 0) ; Drawing.draw_integer_alignedleft (10+(5+1)*35*10/7) (Csts.__height__ - 40) !Csts.score 35 ; set_color (rgb 0 128 128) ; Drawing.draw_integer_alignedright (Csts.__width__ - 20) (10+35) !Csts.combo 35 ; set_color (rgb 0 192 192) ; Drawing.draw_string (Csts.__width__ - 20 - 35*(5+1 + Math.ln_b 10 !Csts.combo)*11/7) (10+35) "Combo" 35 ; auto_synchronize true ; update_ans () ; if !Csts.ans = resu then found := true ; Unix.sleepf Csts.sleep_d ; cur := Unix.gettimeofday () ; done ; Csts.ans := 0 ; if !found then begin incr Csts.combo ; Csts.max_combo := max (!Csts.max_combo) !Csts.combo ; Csts.score := !Csts.score + int_of_float ((float_of_int !Csts.max_score) *. (!Csts.time_to_ans_f -. (!cur -. start)) /. !Csts.time_to_ans_f) ; true end else begin Csts.combo := 0 ; false end ;;