Package edu.neu.ccs.task.agent

Source Code of edu.neu.ccs.task.agent.AgentSession

package edu.neu.ccs.task.agent;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.QName;

import edu.neu.ccs.task.Plan;
import edu.neu.ccs.task.Slot;
import edu.neu.ccs.task.Task;
import edu.neu.ccs.task.TaskEngine;
import edu.neu.ccs.task.TaskModelSet;
import edu.neu.ccs.task.TaskPlan;
import edu.neu.ccs.task.flash.FlashTranslator;
import edu.neu.ccs.task.flash.SpeechServerConfig;
import edu.neu.ccs.task.util.Bool;
import edu.neu.ccs.task.util.Decorator;
import edu.neu.ccs.task.util.Pair;

public class AgentSession {
  private final Agent agent;
  private final String top;
  private final Map<String, String> topInputs;
  private final SpeechServerConfig speechConfig;
  private final List<OutputFilter> outputFilters;
  protected final PrintStream out;
  protected final BufferedReader in;
  private boolean nullTermOutput = false;
 
  public AgentSession(Agent agent,
      String top,
      Map<String, String> topInputs,
      SpeechServerConfig speechConfig,
      List<OutputFilter> outputFilters,
      Socket socket) throws IOException {
    this.agent = agent;
    this.top = top;
    this.topInputs = topInputs;
    this.speechConfig = speechConfig;
    this.outputFilters = new ArrayList<OutputFilter>(outputFilters);
    this.out = new PrintStream(socket.getOutputStream());
    this.in = new BufferedReader(
      new InputStreamReader(socket.getInputStream()));
  }
 
  public void run() throws IOException {
    String login = receive("<USER_LOGIN", "<CLIENT_LOGIN");
    String user = parseAttrib("ID", login, null);
   
    // autodetect flash-based clients, which use a speech server.
    // If we've got one, we'll need to do 2 things different:
    // 1) Use null-terminated output
    // 2) Use a TTS server for all agent speech
    if (login.startsWith("<CLIENT_LOGIN")) {
      nullTermOutput = true;
      outputFilters.add(new FlashTranslator(speechConfig));
    }
   
    initPlan(user);
   
    send("<SESSION OK=\"true\"/>");
    send("<PERFORM><PAGE URL=\"NONE\"/><PERFORM/>");
    receive("<PERFORM_COMPLETE");
   
    while (agent.isLive()) {
      if (agent.nextTurn())
        performTurn();
    }
   
    send("<PERFORM><DISPLAY CMD=\"HIDE\"/></PERFORM>");
    receive("<PERFORM_COMPLETE");
    send("<SESSION EXIT=\"SOMETHING\"/>");
  }
 
  private void initPlan(String user) {
    TaskEngine engine = agent.getEngine();
    TaskModelSet modelSet = engine.getModelSet();
    QName topName = new QName(modelSet.getDefaultModel().getURI(), top);
    TaskPlan topPlan = engine.newTaskPlan(topName);
    Task topTask = topPlan.getTask();
   
    for (Map.Entry<String, String> e : topInputs.entrySet())
      topTask.setSlotValueScript(e.getKey(), e.getValue(), "init agent");
   
    if (user != null) {
      Slot userSlot = topTask.getType().getSlotIfExists("user");
      if ((userSlot != null) &&
        userSlot.isInput() &&
        userSlot.getType().equals("string") &&
        !topInputs.containsKey("user"))
        topTask.setSlotValue("user", user);
    }
   
    if (Bool.isFalse(topTask.isApplicable()))
      throw new IllegalArgumentException("task not applicable: " + topTask);
   
    List<String> undefs = topTask.getUndefinedInputs();
    if ( ! undefs.isEmpty())
      throw new IllegalArgumentException("undefined inputs: " + undefs);
   
    agent.setFocus(topPlan);
  }
 
  private void performTurn() throws IOException {
    String output = agent.getCurrentAnnotatedOutput();
    if (output != null)
      speech(output);
   
    List<Pair<String, Integer>> inputs = agent.getCurrentInputs();
    if (inputs != null) {
      while (true) {
        int choice = menu(inputs);
        if (choice < 0)
          speech(agent.getCurrentAnnotatedAltOutput());
        else {
          agent.applyCurrentTurn(choice);
          break;
        }
      }
    } else
      agent.applyCurrentTurn();
  }
 
  protected void speech(String msg) throws IOException {
    for (OutputFilter of : outputFilters)
      msg = of.process(msg);
    send("<PERFORM>" + msg + "</PERFORM>");
    receive("<PERFORM_COMPLETE");
  }
 
  protected int menu(List<Pair<String, Integer>> prompts) throws IOException {
    StringBuilder sb = new StringBuilder();
    sb.append("<PERFORM><MENU>");
    for (Pair<String, Integer> p : prompts)
      sb.append("<ITEM>" + p.first.trim() + "</ITEM>");
    sb.append("</MENU></PERFORM>");
   
    send(sb.toString());
    String response = receive("<USER_INPUT MENU");
    return prompts.get(parseInt("MENU", response)).second;
  }
 
  public String parseAttrib(String attrib, String input, String defaultVal) {
    Matcher m = Pattern.compile(attrib + "=\"([^\"]+)\"").matcher(input);
    if (m.find())
      return m.group(1);
    else
      return defaultVal;
  }
 
  public String parseAttrib(String attrib, String input) {
    String value = parseAttrib(attrib, input, null);
    if (value == null)
      throw new IllegalArgumentException("bad input: " + input);
    return value;
  }
 
  public int parseInt(String attrib, String input) {
    return Integer.parseInt(parseAttrib(attrib, input));
  }
 
  protected void send(String msg) {
    out.println(msg);
    if (nullTermOutput)
      out.print((char) 0); // Flash requires null-terminated output
    out.flush();
    System.out.println("Sent: " + msg);
  }
 
  protected String receive(String... types) throws IOException {
    while (true) {
      String line = receive();
      for (String type : types)
        if (line.startsWith(type))
          return line;
      receiveUnexpected(line);
    }
  }
 
  protected String receive() throws IOException {
    String line = in.readLine();
    if (line == null)
      throw new RuntimeException("user disconnected");
   
    // Flash sends null-byte terminated strings
    // Because of this, we may see a null byte at the beginning of the
    // next input.  Strip it off...
    if (line.charAt(0) == 0)
      line = line.substring(1);
   
    System.out.println("Received: " + line);
    return line;
  }
 
  protected void receiveUnexpected(String msg) {
    if (msg.startsWith("<DUMP_REQUEST TYPE=\"USER"))
      dumpUserModel();
    else if (msg.startsWith("<DUMP_REQUEST TYPE=\"PLAN"))
      dumpPlan();
    else if (msg.startsWith("<USER_EXIT"))
      throw new RuntimeException("user quit");
  }
 
  private void dumpUserModel() {
    dump("USER", agent.getEngine().dumpUserModel());
  }
 
  private void dumpPlan() {
    StringWriter sw = new StringWriter();
    Plan plan = agent.getTop();
    if (plan != null)
      plan.printTree(new PrintWriter(sw), true, new Decorator() {
        public String decorate(Object o) {
          return (o == agent.getFocus()) ? " <-focus" : "";
        }
      });
   
    dump("PLAN", sw.toString());
  }
 
  private void dump(String type, String msg) {
    send("<DUMP TYPE=\"" + type + "\">" +
       msg.replaceAll("\\r(\\n?)", "\\\\n") +
       "</DUMP>");
  }
}
TOP

Related Classes of edu.neu.ccs.task.agent.AgentSession

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.