/**
   * Check for accident in laboratory.
   *
   * @param time the amount of time researching (in millisols)
   */
  private void checkForAccident(double time) {

    double chance = .001D;

    // Science skill modification.
    SkillType scienceSkill = science.getSkill();
    int skill = person.getMind().getSkillManager().getEffectiveSkillLevel(scienceSkill);
    if (skill <= 3) {
      chance *= (4 - skill);
    } else {
      chance /= (skill - 2);
    }

    Malfunctionable entity = null;
    if (lab instanceof Research) {
      entity = ((Research) lab).getBuilding();
    } else {
      entity = person.getVehicle();
    }

    if (entity != null) {

      // Modify based on the entity's wear condition.
      chance *= entity.getMalfunctionManager().getWearConditionAccidentModifier();

      if (RandomUtil.lessThanRandPercent(chance * time)) {
        logger.info(person.getName() + " has a lab accident while doing " + science + " research.");
        entity.getMalfunctionManager().accident();
      }
    }
  }
  /**
   * Gets the effective research time based on the person's science skill.
   *
   * @param time the real amount of time (millisol) for research.
   * @return the effective amount of time (millisol) for research.
   */
  private double getEffectiveResearchTime(double time) {
    // Determine effective research time based on the science skill.
    double researchTime = time;
    int scienceSkill = getEffectiveSkillLevel();
    if (scienceSkill == 0) {
      researchTime /= 2D;
    } else if (scienceSkill > 1) {
      researchTime += researchTime * (.2D * scienceSkill);
    }

    // Modify by tech level of laboratory.
    int techLevel = lab.getTechnologyLevel();
    if (techLevel > 0) {
      researchTime *= techLevel;
    }

    // If research assistant, modify by assistant's effective skill.
    if (hasResearchAssistant()) {
      SkillManager manager = researchAssistant.getMind().getSkillManager();
      int assistantSkill = manager.getEffectiveSkillLevel(science.getSkill());
      if (scienceSkill > 0) {
        researchTime *= 1D + ((double) assistantSkill / (double) scienceSkill);
      }
    }

    return researchTime;
  }
 @Override
 protected void addExperience(double time) {
   // Add experience to relevant science skill
   // (1 base experience point per 25 millisols of research time)
   // Experience points adjusted by person's "Academic Aptitude" attribute.
   double newPoints = time / 25D;
   int academicAptitude =
       person.getNaturalAttributeManager().getAttribute(NaturalAttribute.ACADEMIC_APTITUDE);
   newPoints += newPoints * ((double) academicAptitude - 50D) / 100D;
   newPoints *= getTeachingExperienceModifier();
   SkillType scienceSkill = science.getSkill();
   person.getMind().getSkillManager().addExperience(scienceSkill, newPoints);
 }
  /**
   * Constructor.
   *
   * @param person the person performing the task.
   */
  public PerformLaboratoryResearch(Person person) {
    // Use task constructor.
    super(NAME, person, true, false, STRESS_MODIFIER, true, 10D + RandomUtil.getRandomDouble(50D));

    researchAssistant = null;

    // Determine study.
    study = determineStudy();
    if (study != null) {
      science = getScience(person, study);
      if (science != null) {
        setDescription(
            Msg.getString(
                "Task.description.performLaboratoryResearch.detail",
                science.getName())); // $NON-NLS-1$
        lab = getLocalLab(person, science);
        if (lab != null) {
          addPersonToLab();
        } else {
          logger.info("lab could not be determined.");
          endTask();
        }
      } else {
        logger.info("science could not be determined");
        endTask();
      }
    } else {
      logger.info("study could not be determined");
      endTask();
    }

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

    // Initialize phase
    addPhase(RESEARCHING);
    setPhase(RESEARCHING);
  }
 @Override
 public int getEffectiveSkillLevel() {
   SkillManager manager = person.getMind().getSkillManager();
   return manager.getEffectiveSkillLevel(science.getSkill());
 }
 @Override
 public List<SkillType> getAssociatedSkills() {
   List<SkillType> results = new ArrayList<SkillType>(1);
   results.add(science.getSkill());
   return results;
 }