/**
   * Gets the field of science that the researcher is involved with in a study.
   *
   * @param researcher the researcher.
   * @param study the scientific study.
   * @return the field of science or null if researcher is not involved with study.
   */
  private static ScienceType getScience(Person researcher, ScientificStudy study) {
    ScienceType result = null;

    if (study.getPrimaryResearcher().equals(researcher)) {
      result = study.getScience();
    } else if (study.getCollaborativeResearchers().containsKey(researcher)) {
      result = study.getCollaborativeResearchers().get(researcher);
    }

    return result;
  }
  /**
   * Performs the researching phase.
   *
   * @param time the amount of time (millisols) to perform the phase.
   * @return the amount of time (millisols) left over after performing the phase.
   */
  protected double researchingPhase(double time) {

    // If person is incapacitated, end task.
    if (person.getPerformanceRating() == 0D) {
      endTask();
    }

    // Check for laboratory malfunction.
    if (malfunctions.hasMalfunction()) endTask();

    // Check if research in study is completed.
    boolean isPrimary = study.getPrimaryResearcher().equals(person);
    if (isPrimary) {
      if (study.isPrimaryResearchCompleted()) {
        endTask();
      }
    } else {
      if (study.isCollaborativeResearchCompleted(person)) {
        endTask();
      }
    }

    // Check if person is in a moving rover.
    if (inMovingRover(person)) {
      endTask();
    }

    if (isDone()) {
      return time;
    }

    // Add research work time to study.
    double researchTime = getEffectiveResearchTime(time);
    if (isPrimary) {
      study.addPrimaryResearchWorkTime(researchTime);
    } else {
      study.addCollaborativeResearchWorkTime(person, researchTime);
    }

    // Add experience
    addExperience(time);

    // Check for lab accident.
    checkForAccident(time);

    return 0D;
  }
  /**
   * Determines the scientific study that will be researched.
   *
   * @return study or null if none available.
   */
  private ScientificStudy determineStudy() {
    ScientificStudy result = null;

    List<ScientificStudy> possibleStudies = new ArrayList<ScientificStudy>();

    // Add primary study if in research phase.
    ScientificStudyManager manager = Simulation.instance().getScientificStudyManager();
    ScientificStudy primaryStudy = manager.getOngoingPrimaryStudy(person);
    if (primaryStudy != null) {
      if (ScientificStudy.RESEARCH_PHASE.equals(primaryStudy.getPhase())
          && !primaryStudy.isPrimaryResearchCompleted()) {

        // Check that a lab is available for primary study science.
        Lab lab = getLocalLab(person, primaryStudy.getScience());
        if (lab != null) {

          // Primary study added twice to double chance of random selection.
          possibleStudies.add(primaryStudy);
          possibleStudies.add(primaryStudy);
        }
      }
    }

    // Add all collaborative studies in research phase.
    Iterator<ScientificStudy> i = manager.getOngoingCollaborativeStudies(person).iterator();
    while (i.hasNext()) {
      ScientificStudy collabStudy = i.next();
      if (ScientificStudy.RESEARCH_PHASE.equals(collabStudy.getPhase())
          && !collabStudy.isCollaborativeResearchCompleted(person)) {

        // Check that a lab is available for collaborative study science.
        ScienceType collabScience = collabStudy.getCollaborativeResearchers().get(person);

        Lab lab = getLocalLab(person, collabScience);
        if (lab != null) {

          possibleStudies.add(collabStudy);
        }
      }
    }

    // Randomly select study.
    if (possibleStudies.size() > 0) {
      int selected = RandomUtil.getRandomInt(possibleStudies.size() - 1);
      result = possibleStudies.get(selected);
    }

    return result;
  }