gt: 		if (vehicle instanceof Rover) {
context: /*
   * Mars Simulation Project
   * StudyFieldSamples.java
   * @date 2021-10-21
   * @author Scott Davis
   */
  package org.mars_sim.msp.core.person.ai.task;
  
  import java.io.Serializable;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.logging.Level;
  
  import org.mars_sim.msp.core.Msg;
  import org.mars_sim.msp.core.Unit;
  import org.mars_sim.msp.core.UnitType;
  import org.mars_sim.msp.core.environment.ExploredLocation;
  import org.mars_sim.msp.core.equipment.ResourceHolder;
  import org.mars_sim.msp.core.logging.SimLogger;
  import org.mars_sim.msp.core.malfunction.Malfunctionable;
  import org.mars_sim.msp.core.person.Person;
  import org.mars_sim.msp.core.person.ai.NaturalAttributeType;
  import org.mars_sim.msp.core.person.ai.SkillManager;
  import org.mars_sim.msp.core.person.ai.mission.Exploration;
  import org.mars_sim.msp.core.person.ai.mission.Mission;
  import org.mars_sim.msp.core.person.ai.task.utils.Task;
  import org.mars_sim.msp.core.person.ai.task.utils.TaskPhase;
  import org.mars_sim.msp.core.resource.ResourceUtil;
  import org.mars_sim.msp.core.science.ScienceType;
  import org.mars_sim.msp.core.science.ScientificStudy;
  import org.mars_sim.msp.core.structure.Lab;
  import org.mars_sim.msp.core.structure.Settlement;
  import org.mars_sim.msp.core.structure.building.Building;
  import org.mars_sim.msp.core.structure.building.BuildingManager;
  import org.mars_sim.msp.core.structure.building.function.FunctionType;
  import org.mars_sim.msp.core.structure.building.function.Research;
  import org.mars_sim.msp.core.tool.RandomUtil;
  import org.mars_sim.msp.core.vehicle.Rover;
  import org.mars_sim.msp.core.vehicle.Vehicle;
  
  /**
   * A task for studying collected field samples (rocks, etc).
   */
  public class StudyFieldSamples extends Task implements ResearchScientificStudy, Serializable {
  
  	/** default serial id. */
  	private static final long serialVersionUID = 1L;
  
  	/** default logger. */
  	private static SimLogger logger = SimLogger.getLogger(StudyFieldSamples.class.getName());
  
  	/** Task name */
  	private static final String NAME = Msg.getString("Task.description.studyFieldSamples"); //$NON-NLS-1$
  
  	/** The stress modified per millisol. */
  	private static final double STRESS_MODIFIER = -.1D;
  
  	/** Task phases. */
  	private static final TaskPhase STUDYING_SAMPLES = new TaskPhase(Msg.getString("Task.phase.studyingSamples")); //$NON-NLS-1$
  
  	/** Mass (kg) of field sample to study. */
  	public static final double SAMPLE_MASS = 1D;
  
  	private static final double ESTIMATE_IMPROVEMENT_FACTOR = 5D;
  
  	// Data members.
  	/** The scientific study the person is researching for. */
  	private ScientificStudy study;
  	/** The laboratory the person is working in. */
  	private Lab lab;
  	/** The science that is being researched. */
  	private ScienceType science;
  	/** The lab's associated malfunction manager. */
  	private Malfunctionable malfunctions;
  	/** The research assistant. */
  	private Person researchAssistant;
  
  	/**
  	 * Constructor.
  	 * 
  	 * @param person {@link Person} the person performing the task.
  	 */
  	public StudyFieldSamples(Person person) {
  		// Use Task constructor. Skill determined on the science
  		super(NAME, person, true, false, STRESS_MODIFIER, null, 10D, 10D + RandomUtil.getRandomDouble(40D));
  		setExperienceAttribute(NaturalAttributeType.ACADEMIC_APTITUDE);
  		
  		// Determine study.
  		study = determineStudy();
  		if (study != null) {
  			science = study.getContribution(person);
  			if (science != null) {
  				addAdditionSkill(science.getSkill());
  				
  				lab = getLocalLab(person, science);
  				if (lab != null) {
  					addPersonToLab();
  				} else {
  					logger.log(person, Level.WARNING, 0, "lab could not be determined.");
  					endTask();
  				}
  			} else {
  				logger.log(person, Level.WARNING, 0, "science could not be determined");
  				endTask();
  			}
  		} else {
  			logger.log(person, Level.WARNING, 0, "study could not be determined");
  			endTask();
  		}
  
  		// Check if person is in a moving rover.
  		if (Vehicle.inMovingRover(person)) {
  			endTask();
  		}
  
  		// Take field samples from inventory.
  		if (!isDone()) {
  			Unit container = person.getContainerUnit();
  			if (container.getUnitType() != UnitType.PLANET) {
  				double totalRockSampleMass = ((ResourceHolder)container).getAmountResourceStored(ResourceUtil.rockSamplesID);
  				if (totalRockSampleMass >= SAMPLE_MASS) {
  					double fieldSampleMass = RandomUtil.getRandomDouble(SAMPLE_MASS * 2D);
  					if (fieldSampleMass > totalRockSampleMass) {
  						fieldSampleMass = totalRockSampleMass;
  					}
  					((ResourceHolder)container).retrieveAmountResource(ResourceUtil.rockSamplesID, fieldSampleMass);
  					// Record the amount of rock samples being studied
  					person.getAssociatedSettlement().addResourceCollected(ResourceUtil.rockSamplesID, fieldSampleMass);
  				}
  			}
  		}
  
  		// Initialize phase
  		addPhase(STUDYING_SAMPLES);
  		setPhase(STUDYING_SAMPLES);
  	}
  
  	/**
  	 * Gets all the sciences related to studying field samples.
  	 * 
  	 * @return list of sciences.
  	 */
  	public static List<ScienceType> getFieldSciences() {
  
  		// Create list of possible sciences for studying field samples.
  		List<ScienceType> fieldSciences = new ArrayList<ScienceType>(3);
  		fieldSciences.add(ScienceType.AREOLOGY);
  		fieldSciences.add(ScienceType.ASTRONOMY);
  		fieldSciences.add(ScienceType.BIOLOGY);
  		fieldSciences.add(ScienceType.CHEMISTRY);
  		fieldSciences.add(ScienceType.ENGINEERING);
  		fieldSciences.add(ScienceType.METEOROLOGY);
  		fieldSciences.add(ScienceType.PHYSICS);
  		
  		return fieldSciences;
  	}
  
  	/**
  	 * Gets the crowding modifier for a researcher to use a given laboratory
  	 * building.
  	 * 
  	 * @param researcher the researcher.
  	 * @param lab        the laboratory.
  	 * @return crowding modifier.
  	 */
  	public static double getLabCrowdingModifier(Person researcher, Lab lab) {
  		double result = 1D;
  		if (researcher.isInSettlement()) {
  			Building labBuilding = ((Research) lab).getBuilding();
  			if (labBuilding != null) {
  				result *= Task.getCrowdingProbabilityModifier(researcher, labBuilding);
  				result *= Task.getRelationshipModifier(researcher, labBuilding);
  			}
  		}
  		return result;
  	}
  
  	/**
  	 * 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>();
  
  		// Create list of possible sciences for studying field samples.
  		List<ScienceType> fieldSciences = getFieldSciences();
  
  		// Add primary study if appropriate science and in research phase.
  		ScientificStudy primaryStudy = person.getStudy();
  		if (primaryStudy != null) {
  			if (ScientificStudy.RESEARCH_PHASE.equals(primaryStudy.getPhase())
  					&& !primaryStudy.isPrimaryResearchCompleted()) {
  				if (fieldSciences.contains(primaryStudy.getScience())) {
  					// Primary study added twice to double chance of random selection.
  					possibleStudies.add(primaryStudy);
  					possibleStudies.add(primaryStudy);
  				}
  			}
  		}
  
  		// Add all collaborative studies with appropriate sciences and in research
  		// phase.
  		Iterator<ScientificStudy> i = person.getCollabStudies().iterator();
  		while (i.hasNext()) {
  			ScientificStudy collabStudy = i.next();
  			if (ScientificStudy.RESEARCH_PHASE.equals(collabStudy.getPhase())
  					&& !collabStudy.isCollaborativeResearchCompleted(person)) {
  				ScienceType collabScience = collabStudy.getContribution(person);
  				if (fieldSciences.contains(collabScience)) {
  					possibleStudies.add(collabStudy);
  				}
  			}
  		}
  
  		// Randomly select study.
  		if (possibleStudies.size() > 0) {
  			int selected = RandomUtil.getRandomInt(possibleStudies.size() - 1);
  			result = possibleStudies.get(selected);
  		}
  
  		return result;
  	}
  
  	/**
  	 * Gets a local lab for studying field samples.
  	 * 
  	 * @param person  the person checking for the lab.
  	 * @param science the science to research.
  	 * @return laboratory found or null if none.
  	 */
  	public static Lab getLocalLab(Person person, ScienceType science) {
  		Lab result = null;
  
  		if (person.isInSettlement()) {
  			result = getSettlementLab(person, science);
  		} else if (person.isInVehicle()) {
  			result = getVehicleLab(person.getVehicle(), science);
  		}
  
  		return result;
  	}
  
  	/**
  	 * Gets a settlement lab for studying field samples.
  	 * 
  	 * @param person  the person looking for a lab.
  	 * @param science the science to research.
  	 * @return a valid research lab.
  	 */
  	private static Lab getSettlementLab(Person person, ScienceType science) {
  		Lab result = null;
  
  		BuildingManager manager = person.getSettlement().getBuildingManager();
  		List<Building> labBuildings = manager.getBuildings(FunctionType.RESEARCH);
  		labBuildings = getSettlementLabsWithSpecialty(science, labBuildings);
  		labBuildings = BuildingManager.getNonMalfunctioningBuildings(labBuildings);
  		labBuildings = getSettlementLabsWithAvailableSpace(labBuildings);
  		labBuildings = BuildingManager.getLeastCrowdedBuildings(labBuildings);
  
  		if (labBuildings.size() > 0) {
  			Map<Building, Double> labBuildingProbs = BuildingManager.getBestRelationshipBuildings(person, labBuildings);
  			result = RandomUtil.getWeightedRandomObject(labBuildingProbs).getResearch();
  		}
  
  		return result;
  	}
  
  	/**
  	 * Gets a list of research buildings with available research space from a list
  	 * of buildings with the research function.
  	 * 
  	 * @param buildingList list of buildings with research function.
  	 * @return research buildings with available lab space.
  	 */
  	private static List<Building> getSettlementLabsWithAvailableSpace(List<Building> buildingList) {
  		List<Building> result = new ArrayList<Building>();
  
  		Iterator<Building> i = buildingList.iterator();
  		while (i.hasNext()) {
  			Building building = i.next();
  			Research lab = building.getResearch();
  			if (lab.getResearcherNum() < lab.getLaboratorySize()) {
  				result.add(building);
  			}
  		}
  
  		return result;
  	}
  
  	/**
  	 * Gets a list of research buildings with a given science specialty from a list
  	 * of buildings with the research function.
  	 * 
  	 * @param science      the science specialty.
  	 * @param buildingList list of buildings with research function.
  	 * @return research buildings with science specialty.
  	 */
  	private static List<Building> getSettlementLabsWithSpecialty(ScienceType science, List<Building> buildingList) {
  		List<Building> result = new ArrayList<Building>();
  
  		Iterator<Building> i = buildingList.iterator();
  		while (i.hasNext()) {
  			Building building = i.next();
  			Research lab = building.getResearch();
  			if (lab.hasSpecialty(science)) {
  				result.add(building);
  			}
  		}
  
  		return result;
  	}
  
  	/**
  	 * Gets an available lab in a vehicle. Returns null if no lab is currently
  	 * available.
  	 * 
  	 * @param vehicle the vehicle
  	 * @param science the science to research.
  	 * @return available lab
  	 */
  	private static Lab getVehicleLab(Vehicle vehicle, ScienceType science) {
  
  		Lab result = null;
  
  