#! /bin/sh
#|
exec racket -tm "$0" ${1+"$@"}
|#

#lang racket

;; read XML element from STDIN, interpret and send response as XML to STDOUT 
;; raises error if request is invalid 

(provide main)

;; ---------------------------------------------------------------------------------------------------
;; IMPLEMENTATION

(require (except-in "../game.rkt" main)
         "../player.rkt" 
         "../strategy.rkt"
         (only-in "../internal-state.rkt" state->xexpr)
         (only-in "../board.rkt" IMPOSSIBLE)
         "../basics.rkt" 
         "../xharness.rkt" 
         "../Lib/xml.rkt")

(module+ test
  (require (rename-in "../Lib/io.rkt" (tester tt)) rackunit))

;; Xexpr -> Xexpr 
(define interpret 
  (xml-parser (run ((rounds string->cash)) (p named-player-p) ... #:action (my-run rounds p))))

;; Xexpr -> String 
(define named-player-p (xml-parser (player ((name name-p)) #:action name)))

;; String -> [Maybe String]
(define (name-p x) (and (<= (string-length x) 20) x))

;; Nat [Listof String] -> Xexpr 
(define (my-run rounds p)
  (define players (for/list ((name p)) (create name largest-alpha)))
  (define-values (status los) (run players rounds))
  (define states (map state->xexpr los))
  (cond
    [(eq? DONE status)       `(done () ,@states)]
    [(eq? EXHAUSTED status)  `(exhausted () ,@states)]
    [(eq? IMPOSSIBLE status) `(impossible () ,@states)]
    [(eq? SCORE status)      `(score () ,@states)]))

(define main (make-main interpret))
(define pr (make-process-request interpret))

;; ---------------------------------------------------------------------------------------------------
(module+ test
  ;; uncomment to create test cases 
  ;; (create-tests #t)
  (define BF "largest-alpha")
  
  ;; String *-> [Listof Xexpr]
  (define (players . lop)
    (for/list ((p lop)) `(player ((name ,p)))))
  
  ;; Nat Nat [Listof String] Symbol Nat -> Void 
  (define (run-test file rounds player-names expected-status expected-length-of-sequence)
    (define result
      (tt BF file pr `(run ((rounds ,(number->string rounds))) ,@(apply players player-names))))
    (check-equal? (first result) expected-status)
    (check-equal? (length (cddr result)) expected-length-of-sequence))

  (run-test 0 4 '("a" "b" "c" "d")          'done   5)
  (run-test 1 17 '("a" "b" "c")             'score 16)
  (run-test 2 23 '("a" "b" "c" "d" "e" "f") 'done  24))
