Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 346 lines (310 sloc) 14.525 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
;; Author(s):
;; unknown -- originators of code from Andes team
;; Linwood H. Taylor (lht) <lht@lzri.com>
;; Collin Lynch (CL) <Collinl@pitt.edu>
;; Modified:
;; 12 March 2001 - (lht) -- this file created for Andes 2
;;; Modifications by Anders Weinstein 2001-2008
;;; Modifications by Brett van de Sande, 2005-2008
;;; Copyright 2009 by Kurt Vanlehn and Brett van de Sande
;;; This file is part of the Andes Intelligent Tutor Stystem.
;;;
;;; The Andes Intelligent Tutor System is free software: you can redistribute
;;; it and/or modify it under the terms of the GNU Lesser General Public
;;; License as published by the Free Software Foundation, either version 3
;;; of the License, or (at your option) any later version.
;;;
;;; The Andes Solver is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public License
;;; along with the Andes Intelligent Tutor System. If not, see
;;; <http:;;;www.gnu.org/licenses/>.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(in-package :cl-user)
(eval-when (:load-toplevel :compile-toplevel)
  (use-package :symbols))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; commands.lsp/cl -- Lisp functions handling API commands sent by the Andes
;; Workbench to the Help System.
;;
;; This corresponds to the "Manager" in the spec. It has one handler function
;; for each API command. These handler functions implement the commands mainly
;; by delegating to worker functions in the relevant modules. This module
;; also maintains the record of the current dialog state if any for use in
;; responding to subsequent student input.
;; 20 May 2002 - (CL) -- Added in entry-auto-logging and other macros to
;; permit the creation of the *Studentactions* Stack in future these may
;; be made a stock part of the system but, for now, it is a compiler setting.
;; The additions have been made to:
;; Check-noneq-entries: Added log-studententry-act
;; Handle-student-response: Added log-turn-response-act
;; 3/12/2003 -- (Cl) -- Added declaration to lookup-andes-command-type to
;; suppress special warning.
;; 7/10/2003 -- (CL) --
;; 1. Moved the execute-andes-command function to Dispatcher.cl
;; 2. Modified the State apis to return empty green-turns as opposed to the
;; T value that they were returning previously.
;; 3. Moved return-turn to Dispatcher.cl
;;
;; Lastly I completed reorganizing the commands to clean up the code and
;; to facilitate the execution process.
;;
;; 7/30/2003 -- (CL) -- Removing calls to return-turn from funcs.
;;
;; This file contains the API calls that are called by the Andes workbench.
;; as such it represents the language that the workbench uses to communicate
;; with the help system. Additional meta-information about the API is located
;; in the file API.cl which is present in the Help module and in the
;; LogProcessing/CmdReader/ module. Between these two files we have the
;; complete communication language for the Andes2 system from help system
;; to workbench and back.
;;
;; When the student initiates a command on the workbench it will produce an
;; appropriate api call and then send it through the TCP/IP stream. Initially
;; these calls were read directly off from the stream by the server code in
;; Andes2-Main.cl. Now the calls are passed on
;; to the execute-andes-command which generates a cmd struct for them and then
;; calls them.
;;
;; It might be feasible to move some of the processing that is done in interface.cl
;; into the functions here but I have chosen to locate it there for semantic
;; purposes.

;; Initially those calls were read directlyu off of the TCP/IP stream by the
;; server code in Andes2-Main and called. Now the calls
;; are passed to the execute-andes-command function located in interface.cl
;; before being called.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(in-package :cl-user)


;;; ==========================================================================
;;; Eqn-entry
;;; Equation entry commands.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; solve-for-var -- solve for the given var using the equations the student has
;; entered so far. Only uses correct equations, so the result must also be
;; correct
;; argument(s):
;; var: the variable to solve for a string
;; new-id: the id number of the equation window in which to put the new sim-
;; plified equation.
;; returns:
;; a string representing the equation to be put into the new id-slot and op-
;; tionally a message to be displayed in the hint window. the equation gives
;; the value of the var if possible, otherwise it gives an equation with all
;; other known values substituded in.
;; note(s):
;; adds the new equation to the list of entered equations, and the value of
;; the variable, if found, to the value of the corresponding scalar/magnitude.
;;
;; It is also designed to log the result of the call for future use.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun solve-for-var (entry)
  (let* ((new-id (StudentEntry-id entry))
(var (StudentEntry-symbol entry))
(tmp (student-to-canonical var))
(result (when tmp (solver-power-solve 31 tmp new-id))))
    
    (cond ((and (null tmp) (has-algebraic-operators var))
(make-eqn-failure-turn
entry
"Sorry, Andes can only solve for a single variable."
:mode 'complicated-lhs))
((null tmp)
(make-eqn-failure-turn
entry
(format nil "The variable <var>~A</var> is undefined." var)
:mode 'undefined-var))
((and result (listp result))
(solve-for-var-success entry result))
((stringp result)
(make-eqn-failure-turn
entry
(format NIL "Unable to solve for ~A: ~A" var result)
:mode result))
(t (make-eqn-failure-turn
entry
;; implemented in next-step-help.cl
(get-failure-to-solve-hint var))))))

;; see function make-red-turn
(defun make-eqn-failure-turn (entry Msg &key mode)
  "Generate an eqn entry turn."
  (make-tutor-response
   entry
   (list msg)
   :state +incorrect+
   :spontaneous t
   :diagnosis (list 'solve-for-var mode)))


(defparameter *algebraic-operators* '(#\+ #\- #\/ #\^ #\*))

(defun has-algebraic-operators (var)
  "Determine if string has algebraic operators."
  (loop for x across var
       thereis (member x *algebraic-operators*)))

(defun solve-for-var-success (entry result)
  (let* ((studText (algebra result)))
    
    ;; Update the studententry
    (setf (StudentEntry-verbatim entry) studText)
    (setf (StudentEntry-prop entry)
`(solve-for-var ,(symbols-referent (StudentEntry-symbol entry))))
    (setf (StudentEntry-parsedEqn entry) result)
    (setf (StudentEntry-state entry) +correct+)
    
    ;; save final result as if it were a new student entry. We need to
    ;; remember slot is occupied for add-entry to trigger automatic
    ;; cleanup of equation in algebra on new entry.
    (add-entry entry)
    ;; finally return student equation turn
    (make-eqn-turn studText :id (StudentEntry-id entry))))


;;; =========================================================================
;;; Answer API Calls

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; lookup-mc-answer
;;
;; Handle entries associated with buttons.
;;
;; Currently, we have multiple choice and a single "done" button. This is
;; used for both the n-way multiple choice questions of the type in vec9
;; where the student is selecting from among a set of choices.
;; It is also used in the fbd-only
;; problems and other problems as an "I am done" button.
;;;
;; The code below identifies the case that we are in and then calls the
;; appropriate handler code in entry-api.
(defun lookup-mc-answer (entry)
  ;; Use the purpose field to determine type.
  (cond
    ;; Case of an "I am done button"
    ((equal (car (StudentEntry-prop entry)) 'done)
     (check-mc-no-quant-done-answer-sought entry))
    
    ;; Handle the multiple choice case by generating the entry prop
    ;; and then handling it like any other.
    ((and (eql (car (StudentEntry-prop entry)) 'choose-answer)
(StudentEntry-checked entry))
     ;; update with the box that has been clicked
     (let ((ch (mapcar #'read-from-string (StudentEntry-checked entry))))
       ;; Construct new list since old prop still used in grading
       (setf (StudentEntry-prop entry)
(list (car (StudentEntry-prop entry))
(cadr (StudentEntry-prop entry))
(if (cdr (StudentEntry-checked entry))
(cons 'orderless ch) ;checkboxes
(car ch))))) ;radio buttons
     (check-noneq-entry entry))
    
    ;; In the event that an unrecognized type is supplied handle it like so.
    (t (warn "Unrecognized button entry: ~a, checked: ~A"
(StudentEntry-prop entry)
(StudentEntry-checked entry)))))

  
;;; ==========================================================================
;;; Help API Types.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; handle-student-response -- dispatch student dialog response to responder
;; set in most recent tutor turn.
;; Returns: result string to be sent to workbench
;; Side-effect: updates last turn via return-turn.
;;
;; A responder function should take a single response code argument and return
;; the next tutor turn. Reponse codes are not examined here but just passed
;; through as a magic cookie. The response codes must be defined by the
;; protocol with the workbench so that it identifies the response chosen by
;; the student for the purposes of the responder functions.
(defun handle-student-response (response-code)
  ;; Response code is either a symbol or a string.
  ;; A symbol indicates a link has been clicked while a
  ;; string indicates text that has been entered.
  (cond
    ;; We have a responder function from a previous tutor turn.
    (*last-turn-response*
     ;; dispatch the response to the responder function.
     ;; Since handle-student-response is wrapped by return-turn, the
     ;; result will be logged, and *last-turn-response* will be updated.
     (let ((response (apply *last-turn-response*
(list response-code))))
       ;; Retire this response.
       ;; This prevents the student from getting the same hint repeatedly
       ;; by clicking on "explain-more."
       ;; If there are multiple-choice responses, it may no longer
       ;; make sense to retire old ones.
       (setf *last-turn-response* nil)

       ;; Result may be a tutor turn or a function that
       ;; evaluates to one.
       (when (functionp response) (setf response (funcall response)))
       (if (or (null response) (turn-p response))
response
(warn 'log-condition:log-warn
:tag (list 'invalid-last-turn-response response)
:text "*last-turn-response* invalid form"))))
    
    ;; Student types text, but there is no responder
    ;; from last term.
    ((and (stringp response-code)
(string-responder response-code)))

    ;; link clicked, but responder gone!
    (T (make-end-dialog-turn
(strcat "Sorry, but you have already seen this hint.&nbsp; You can "
*help-button-action* " for more help.")
:Assoc '((handle-link . stale))))))

(defun string-responder (str &key explain-more)
  (cond
    ((is-a-question str)
     (make-end-dialog-turn
      (strcat "Sorry, I don't know how to answer your question.&nbsp; "
(if explain-more
(strcat "Either click on \"" *explain-more-text*
"\" or "
*help-button* " below.")
(strcat "Please " *help-button-action* " for help.")))
      :Assoc '((handle-text . question))))
    
    ((bad-language str)
     (make-end-dialog-turn
      (strcat "Please watch your language.&nbsp; "
(random-elt
'("I am just a machine and don't always understand people."
"Sorry you find me to be so frustrating."
"However, constructive comments are always welcome.")))
      :Assoc '((handle-text . bad-language))))
    
    ((maybe-a-question str)
     (make-end-dialog-turn
      (strcat "Your comment has been recorded.&nbsp; "
(if explain-more
(strcat "If you need help, either click on \""
*explain-more-text*
"\" or "
*help-button* " below.")
(strcat "If you need help, " *help-button-action* ".")))
      :Assoc '((handle-text . possible-question))))
    
    ;; Assume everything else is a genuine comment.
    (t
     (make-end-dialog-turn
      (random-elt '("Your comment has been recorded."
"Thanks for the comment."
"I am just a machine.&nbsp; Comments will be read later by a human."))
:Assoc '((handle-text . comment))))))

(defun is-a-question (str)
  "Determine if student phrase is a question."
    ;; Test text for presence of a question.
    ;; Based on an analysis of the WHRHS logs on Oct. 1, 2010
    ;; 88 comments, of which 43 are questions or general requests for help
    ;; 35 questions begin with "how" "is" "should" "what" "where" "why"
    ;; 8 other questions or requests. 2 start with "help".
    ;; 2/3 of questions end in ?
    ;; However, a significant number of regular comments end in "?"
  (< (match:best-value
      (match:match-model (list (car (match:word-parse str)))
'(or "how" "is" "should" "what" "where" "why"))) 1))

(defun maybe-a-question (str)
  "Determine if student phrase may be a question."
    ;; Ending with a "?" is a less reliable indicator of a question,
    ;; Likewise, comments starting with "help" or "hint" are often not
    ;; intended as questions.
  (or (string-ends-with '(#\?) str)
(< (match:best-value
(match:match-model
(list (car (match:word-parse str)))
'(or "help" "hint"))) 1)))

(defun string-ends-with (endings x)
  "Test if string ends with a given character, trimming whitespace."
  (let ((y (string-right-trim match:*whitespace* x)))
    (member (char y (- (length y) 1)) endings)))

(defparameter *foul-language* '("shit" "fuck" "asshole"))

(defun bad-language (str)
  (loop for word in *foul-language*
thereis (search word str :test #'char-equal)))
Something went wrong with that request. Please try again.