#lang racket/gui

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require "Receptor.rkt")
(require "Efectores.rkt")
(require "Cerebro1.rkt")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define animat%
  (class object%
    (init-field
     (Sensores 'receptor_sensorial)
     (Efectores 'efectores)
     (control_central 'cerebro)
     )
    (field
     (tipo 3)
     (energia 0)
     (historia-energia '())
     (puntos-latex '())
     )
    ;;historia-energia y puntos-latex
    ;;sobran. Son para hacer estadísticas.
    ;;los métodos: get-puntos-latex y get-pares-latex
    ;;get-historia-energia y
    ;;puntos-energia y latex-par, también sobran por la misma razón.
    (define/public get-puntos-latex
      (lambda ()
        puntos-latex ))
    (define/public get-pares-latex
      (lambda ()
        (define pares-latex
          (lambda (primer resto)
            (if (null? resto)
                '()
                (cons
                 (list primer (car resto))
                 (pares-latex (car resto) (cdr resto))
                 )
            )
            ))
        (pares-latex '(0.5 6) (take (reverse puntos-latex) 20))
        ))
    (define/public get-historia-energia
      (lambda ()
        historia-energia ))
    (define puntos-energia
      (lambda (energia-valor)
        (let* ((decimas
                (lambda (valor cociente)
                  (* (remainder valor cociente) 0.025)
                  ))
               (decima
                (lambda (valor cociente)
                  (let ((resto (abs (remainder valor cociente))))
                    (case resto
                      ((0) 0)
                      ((1) 0.225)
                      ((2) 0.20)
                      ((3) 0.175)
                      ((4) 0.15)
                      ((5) 0.125)
                      ((6) 0.100)
                      ((7) 0.075)
                  ((8) 0.05)
                      ((9) 0.025)
                      )
                    )
                  ))
               (tabla_pos
                (lambda (v)
                  (cond
                    ((> v -10) (+ 5.5 (decima v 10)))
                    ((> v -20) (+ 5 (decima v 10)))
                    ((> v -30) (+ 4.5 (decima v 10)))
                    ((> v -40) (+ 4 (decima v 10)))
                    ((> v -50) (+ 3.5 (decima v 10)))
                    ((> v -60) (+ 3 (decima v 10)))
                    ((> v -70) (+ 2.5 (decima v 10)))
                    ((> v -80) (+ 2 (decima v 10)))
                    ((> v -90) (+ 1.5 (decima v 10)))
                    ((> v -100) (+ 1 (decima v 10)))
                    
                    ((< v 10) (+ 6 (decimas v 10)))
                    ((< v 20) (+ 6.5 (decimas v 20)))
                    ((< v 30) (+ 7 (decimas v 30)))
                    ((< v 40) (+ 7.5 (decimas v 40)))
                    ((< v 50) (+ 8 (decimas v 50)))
                    ((< v 60) (+ 8.5 (decimas v 60)))
                    ((< v 70) (+ 9 (decimas v 70)))
                    ((< v 80) (+ 9.5 (decimas v 80)))
                    ((< v 90) (+ 10 (decimas v 90)))
                    ((< v 100) (+ 10.5 (decimas v 100)))
                    (else (+ 11 (decimas v)))
                    )
                  ))
               )
          (tabla_pos energia-valor)
          )
        ))    
    (define/public latex-par
      (lambda (energia iter)
        (list
         (cond
           ((= iter 0) 0.5)
           ((= iter 20) 1)
           ((= iter 40) 1.5)
           ((= iter 60) 2)
           ((= iter 80) 2.5)
           ((= iter 100) 3)
           ((= iter 120) 3.5)
           ((= iter 140) 4)
           ((= iter 160) 4.5)
           ((= iter 180) 5)
           ((= iter 200) 5.5)
           ((= iter 220) 6)
           ((= iter 240) 6.5)
           ((= iter 260) 7)
           ((= iter 280) 7.5)
           ((= iter 300) 8)
           ((= iter 320) 8.5)
           ((= iter 340) 9)
           ((= iter 360) 9.5)
           ((= iter 380) 10)
           ((= iter 400) 10.5)
           (else iter)
           )
         (puntos-energia energia))
        ))
    ;;;;;;;;;;;;;;;;;;;;
    (define/public set-energia
      (lambda (valor)
        (set! energia valor)
        ))
    (define/public get-energia
      (lambda ()
        energia))
    (define/public get-BC
      (lambda ()
        (send control_central get-bc)
        ))
    (define/public get-bc
      (lambda ()
        (send control_central get_bc)
        ))
    (define/public get-tipo
      (lambda ()
        tipo ))
    (define/public set-exito
      (lambda (valor num_iter)
        (send control_central set-exito valor num_iter)
        ))    
    ;;;;;;;;;;;;;;;;;;;;
    (define/public procesar!
      (lambda (lista-8vec-coord lista-8vec-obj iter)
        (let*-values
            ([(output_receptor) (send Sensores proceso! lista-8vec-obj)]
             [(ordinal_vec) (send control_central proceso! output_receptor iter)]
             [(clave_acto vec_coord)
              (send Efectores proceso! ordinal_vec output_receptor lista-8vec-coord)]
             )
          (printf "Acción deseada: ~a a ~a~n" clave_acto vec_coord)
          (cond
            ((eq? clave_acto 'avanzar)
             (set! energia (sub1 energia))
             (printf "Energía ~a " -1)
             )
            (else
             (set! energia (+ 3 energia))
             (printf "Energía ~a " +3)
             )
            )
          (printf "= ~a~n" energia)
          (set! historia-energia (cons energia historia-energia))
          (if (= (remainder iter 20) 0) 
              (set! puntos-latex (cons (latex-par energia iter) puntos-latex))
              #t)
          (values clave_acto vec_coord)
          )
        ))     
    (super-new)
    ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define A1 (make-object animat% receptor_sensorial efectores cerebro))

(provide animat% A1)