Package ch.tatool.core.executable

Source Code of ch.tatool.core.executable.QuestionnaireExecutable

/*******************************************************************************
* Copyright (c) 2011 Michael Ruflin, Andr� Locher, Claudia von Bastian.
*
* This file is part of Tatool.
*
* Tatool 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.
*
* Tatool 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 Tatool. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package ch.tatool.core.executable;

import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.bytecode.opencsv.CSVReader;
import ch.tatool.core.data.DataUtils;
import ch.tatool.core.data.Level;
import ch.tatool.core.data.Misc;
import ch.tatool.core.data.Points;
import ch.tatool.core.data.Question;
import ch.tatool.core.data.Result;
import ch.tatool.core.data.Timing;
import ch.tatool.core.display.swing.ExecutionDisplayUtils;
import ch.tatool.core.display.swing.SwingExecutionDisplay;
import ch.tatool.core.display.swing.action.ActionPanel;
import ch.tatool.core.display.swing.action.ActionPanelListener;
import ch.tatool.core.display.swing.action.InputActionPanel;
import ch.tatool.core.display.swing.action.KeyActionPanel;
import ch.tatool.core.display.swing.container.ContainerUtils;
import ch.tatool.core.display.swing.container.RegionsContainer;
import ch.tatool.core.display.swing.container.RegionsContainer.Region;
import ch.tatool.core.display.swing.panel.CenteredTextPanel;
import ch.tatool.core.element.handler.timeout.DefaultTimeoutHandler;
import ch.tatool.data.DescriptivePropertyHolder;
import ch.tatool.data.Property;
import ch.tatool.data.Trial;
import ch.tatool.exec.ExecutionContext;
import ch.tatool.exec.ExecutionOutcome;
import ch.tatool.exec.ExecutionPhaseListener;

/**
* Questionnaire
*
* Displays questions and allows the user to answer.
*
* @author Andre Locher
*/
public class QuestionnaireExecutable extends BlockingAWTExecutable implements
    ActionPanelListener, ExecutionPhaseListener, DescriptivePropertyHolder{

  Logger logger = LoggerFactory.getLogger(QuestionnaireExecutable.class);

  private DefaultTimeoutHandler timeoutHandler;

  private RegionsContainer regionsContainer;
  private SwingExecutionDisplay display;

  public String stimuliFile = "questionnaire_stimuli.csv";
  public String stimuliPath = "/ch/tatool/data/questionnaire/";

  private List<String[]> stimuliData = new ArrayList<String[]>();

  /** Question panel. */
  private CenteredTextPanel imgPanel;
  private KeyActionPanel keyActionPanel;
  private InputActionPanel inputActionPanel;

  /** Stimuli. */
  private String[] stimulusInfo;
  private String item;
  private String correctResponse;
  private String givenResponse;
  private Trial currentTrial;
  private Map<Integer,String> trialResponses;

  /** Default Constructor. */
  public QuestionnaireExecutable() {
    super("questionnaire-task");
    trialResponses = new HashMap<Integer,String>();
    initComponents();
  }

  private void initComponents() {
    // question panel
    imgPanel = new CenteredTextPanel();
  }

  /**
   * Setup the action panel according to the type needed
   *
   * @param format
   *            dichot: dichotomous yes/no format
   *            open: open format
   *            proportional: scale format
   */
  private void setupActionPanel(String format, int scale) {

    if (format.equals("dichot")) {
      initBinaryScale();
      regionsContainer.setRegionContent(Region.SOUTH, keyActionPanel);
    } else if (format.equals("open")) {
      initOpenFormat();
      regionsContainer.setRegionContent(Region.SOUTH, inputActionPanel);
    } else if (format.equals("scale")) {
      initRatingScale(scale);
      regionsContainer.setRegionContent(Region.SOUTH, keyActionPanel);
    } else if (format.equals("none")) {
      initNone();
      regionsContainer.setRegionContent(Region.SOUTH, keyActionPanel);
    }
  }

  private void initOpenFormat() {
    inputActionPanel = new InputActionPanel();
    inputActionPanel.setTextDocument(250, InputActionPanel.FORMAT_ALL);
    inputActionPanel.addActionPanelListener(this);
  }

  private void initBinaryScale() {
    keyActionPanel = new KeyActionPanel();
    keyActionPanel.addKey(KeyEvent.VK_A, stimulusInfo[7], stimulusInfo[8]);
    keyActionPanel.addKey(KeyEvent.VK_L, stimulusInfo[9], stimulusInfo[10]);
    keyActionPanel.addActionPanelListener(this);
  }

  private void initNone() {
    keyActionPanel = new KeyActionPanel();
    keyActionPanel.addKey(KeyEvent.VK_RIGHT, "Weiter", "");
    keyActionPanel.addActionPanelListener(this);
  }

  private void initRatingScale(int scale) {
    keyActionPanel = new KeyActionPanel();

    for (int i = 0; i < (scale * 2); i = i + 2) {
      int j = 7 + i;
      keyActionPanel.addKey(translateToKeyEvent(Integer
          .parseInt(stimulusInfo[j])), "", stimulusInfo[j + 1]);
    }

    keyActionPanel.addActionPanelListener(this);
  }

  private int translateToKeyEvent(int key) {
    switch (key) {
    case 0:
      return KeyEvent.VK_0;
    case 1:
      return KeyEvent.VK_1;
    case 2:
      return KeyEvent.VK_2;
    case 3:
      return KeyEvent.VK_3;
    case 4:
      return KeyEvent.VK_4;
    case 5:
      return KeyEvent.VK_5;
    case 6:
      return KeyEvent.VK_6;
    case 7:
      return KeyEvent.VK_7;
    case 8:
      return KeyEvent.VK_8;
    case 9:
      return KeyEvent.VK_9;
    default:
      return KeyEvent.VK_0;
    }
  }

  public void startExecutionAWT() {
    regionsContainer = ContainerUtils.getRegionsContainer();
    display = ExecutionDisplayUtils.getDisplay(getExecutionContext());
    ContainerUtils.showRegionsContainer(display);
    ExecutionContext context = getExecutionContext();
   
    // get current stimulus
    getCurrentStimulus();
   
    // check for question dependency
    if (!stimulusInfo[1].equals("")) {
      int questionID = Integer.parseInt(stimulusInfo[1]);
      String oldResponse = trialResponses.get(questionID);
      if (!oldResponse.equals(stimulusInfo[2])) {
        // skip this question
        if (getFinishExecutionLock()) {
          cancelExecutionAWT();
          finishExecution();
          return;
        }
      }
    }

    // create trial
    currentTrial = context.getExecutionData().getCreateLastTrial();
    currentTrial.setParentId(getId());
    Timing.getStartTimeProperty().setValue(this, new Date());


    item = stimulusInfo[3];
    URL iconURL = getClass()
        .getResource(stimuliPath + item);
    ImageIcon icon = new ImageIcon(iconURL);
    correctResponse = "";
    givenResponse = null;

    // set some properties
    Question.setQuestionAnswer(this, stimulusInfo[4], correctResponse);
    Points.setZeroOneMinMaxPoints(this);

    // setup the views
    regionsContainer.removeRegionContent(Region.CENTER);
    regionsContainer.removeRegionContent(Region.SOUTH);
    imgPanel.setIcon(icon);
    regionsContainer.setRegionContent(Region.CENTER, imgPanel);
    setupActionPanel(stimulusInfo[5], Integer.parseInt(stimulusInfo[6]));
    regionsContainer.setRegionContentVisibility(Region.CENTER, true);

    // enable the actions
    if (stimulusInfo[5].equals("open")) {
      inputActionPanel.enableActionPanel();
    } else {
      keyActionPanel.enableActionPanel();
    }

    // start timer
    if (timeoutHandler != null) {
      timeoutHandler.startTimeout(context);
    }
  }

  private void getCurrentStimulus() {
    // read stimuli list if none available in the list
    if (stimuliData.size() > 0) {
      stimulusInfo = stimuliData.get(0);
      stimuliData.remove(0);
    } else {
      readStimuli();
      stimulusInfo = stimuliData.get(0);
      stimuliData.remove(0);
    }
  }

  public void readStimuli() {
      // read stimuli info
    stimuliData.clear();

    CSVReader reader = null;
    try {
      reader = new CSVReader(new InputStreamReader(this.getClass()
          .getResourceAsStream(stimuliPath + stimuliFile),
          "ISO-8859-1"), ';','"',1);
    } catch (UnsupportedEncodingException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }
    try {
      stimuliData = reader.readAll();
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
    } finally {
      try {
        reader.close();
      } catch (IOException e) {
        logger.error(e.getMessage(), e);
      }
    }
  }
 
  /**
   * Cleanup after element execution
   */
  @Override
  protected void cancelExecutionAWT() {
    // disable actions
    RegionsContainer regionsContainer = ContainerUtils.getRegionsContainer();
    regionsContainer.removeRegionContent(Region.CENTER);
    regionsContainer.removeRegionContent(Region.SOUTH);
    if (timeoutHandler != null) {
      timeoutHandler.cancelTimeout();
    }
    if (inputActionPanel != null) {
      inputActionPanel.disableActionPanel();
    }
    if (keyActionPanel != null) {
      keyActionPanel.disableActionPanel();
    }
  }

  /** Called when either of the two action panel choices have been selected. */
  public void actionTriggered(ActionPanel source, Object actionValue) {
    givenResponse = (String) actionValue;

    // allow only 255 characters
    if (givenResponse.length() > 255) {
      givenResponse = givenResponse.substring(0, 255);
    }
   
    if (inputActionPanel != null) {
      inputActionPanel.disableActionPanel();
    }
    if (keyActionPanel != null) {
      keyActionPanel.disableActionPanel();
    }
   
    Question.getResponseProperty().setValue(this, givenResponse);
    trialResponses.put(Integer.parseInt(stimulusInfo[0]),givenResponse);
   
    // set the final properties
    if (Integer.parseInt(stimulusInfo[6]) > 0) {
      Points.getPointsProperty().setValue(this,
          Integer.parseInt(givenResponse));
    } else {
      Points.getPointsProperty().setValue(this, 0);
    }

    Result.getResultProperty().setValue(this, true);

    Timing.getEndTimeProperty().setValue(this, new Date());
    long duration = 0;
        if (Timing.getStartTimeProperty().getValue(this) != null && Timing.getEndTimeProperty().getValue(this) != null) {
          duration = Timing.getEndTimeProperty().getValue(this).getTime() - Timing.getStartTimeProperty().getValue(this).getTime();
        }
        Timing.getDurationTimeProperty().setValue(this, duration);
        Misc.getOutcomeProperty().setValue(this, ExecutionOutcome.FINISHED);
        Misc.getOutcomeProperty().setValue(getExecutionContext(), ExecutionOutcome.FINISHED);
        DataUtils.storeProperties(currentTrial, this);

    if (getFinishExecutionLock()) {
      cancelExecutionAWT();
      finishExecution();
    }
  }
 
  public Property<?>[] getPropertyObjects() {
    return new Property[] { Level.getLevelProperty(),
        Points.getMinPointsProperty(),
        Points.getPointsProperty(),
        Points.getMaxPointsProperty(),
        Question.getQuestionProperty(),
        Question.getAnswerProperty(),
        Question.getResponseProperty(),
        Misc.getOutcomeProperty(),
        Result.getResultProperty(),
        Timing.getStartTimeProperty(),
        Timing.getEndTimeProperty(),
        Timing.getDurationTimeProperty()};
  }

  public void processExecutionPhase(ExecutionContext context) {
    switch (context.getPhase()) {
    case SESSION_START:
      trialResponses.clear();
      break;
    }
  }

  public DefaultTimeoutHandler getTimeoutAspect() {
    return timeoutHandler;
  }

  public void setTimeoutAspect(DefaultTimeoutHandler timer) {
    this.timeoutHandler = timer;
    this.timeoutHandler.setParent(this);
    this.timeoutHandler.setId("timer");
  }

  public String getStimuliFile() {
    return stimuliFile;
  }

  public void setStimuliFile(String stimuliFile) {
    this.stimuliFile = stimuliFile;
  }

  public String getStimuliPath() {
    return stimuliPath;
  }

  public void setStimuliPath(String stimuliPath) {
    this.stimuliPath = stimuliPath;
  }

}
TOP

Related Classes of ch.tatool.core.executable.QuestionnaireExecutable

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.