package metab; import metab.*; import java.io.*; /** * The NMSubject class handles the bulk of the computations for the * compartmental model. An instance of the class is representative of one human * subject. The subject contains exactly one Stomach, Intestine, * and LeanBodyMass compartment. See the constructor for the information * required for using this class. Values for the bitFlag argurment need to be * or'd ( | ) together, with one option set for each category. The categories are * food present in the stomach, drinking history, and units of measurement. When * _METRIC is selected as the units of measurement, cm and kg should be used for * the height and weight arguments, and when _IMPERIAL is selected, in and lbs * should be used. When returning the bitFlag, the user should check to see if * the _ERROR bit is checked. If so, then the user constructed the object incorrectly * and should re-initialize it appropriately. This class keeps track of BAC during * each minute time interval and final BAC should be determined from the array * determined by the getBAC method. * @author Levi Blackstone, Matthew Woller * @version 1.29 * @see metab.Stomach * @see metab.Intestine * @see metab.LeanBodyMass * @see metab.Subject * @see metab.Drink * @see metab.DrinkTime * @see metab.TDSubject */ public class NMSubject implements Serializable { /** * Standard value representing a light meal was eaten recently. */ public static final int _LIGHT_MEAL = 1; /** * Standard value representing an average meal was eaten recently. */ public static final int _AVERAGE_MEAL = 1 << 1; /** * Standard value representing a large meal was eaten recently. */ public static final int _LARGE_MEAL = 1 << 2; /** * Standard value representing no meal was eaten recently. */ public static final int _NO_MEAL = 1 << 3; /** * Standard value representing that the subject is a light drinker. */ public static final int _LIGHT_DRINKER = 1 << 4; /** * Standard value representing that the subject is a moderate drinker. */ public static final int _MODERATE_DRINKER = 1 << 5; /** * Standard value representing that the subject is a heavy drinker. */ public static final int _HEAVY_DRINKER = 1 << 6; /** * Standard value representing that input units are in metric units. */ public static final int _METRIC = 1 << 7; /** * Standard value representing that input units are in Imperial units. */ public static final int _IMPERIAL = 1 << 8; /** * Standard value representing that an error occured while retrieving info. */ public static final int _ERROR = 1 << 9; /** * Amount of liquid exiting the stomach through pyloric sphincter (L/min). */ private static final double squirtVolume = 0.0111; /** * Amount of liquid exiting the intestine through the villi (L/min). */ private static final double absorbVolume = 0.01; /** * Amount of gastric fluid being produced in the stomach (L/min). */ private static final double newFluid = .002; /** * Bitflag representing all set switches. */ private int bitFlag; /** * Age in years. */ private int age; /** * Represents number of minutes after the specified amount at which point * the BAC would become zero. */ private int timeForZeroEthanol; /** * Total number of minutes in drinking interval. */ private int totalMinutes; /** * Array of the value for the BAC at every time interval. */ private double BACvalues[]; /** * Height (cm). */ private double height; /** * Weight (kg). */ private double weight; /** * Represents the highest BAC achieved during the time interval. */ private double peakBAC; /** * Represents the total amount of ethanol to be introduced (g). */ private double totalEthanol; /** * Represents the total amount of liquid to be introduced (L). */ private double totalVolume; /** * Represents the total water content of the body (L). */ private double TBW; /** * Represents the amount of ethanol to be introduced each cycle (g/min). */ private double passingEthanol; /** * Represents the amount of liquid to be introduced each cycle (L/min). */ private double passingVolume; /** * Represents the gender of the subject ('M' or 'F'). */ private char gender; /** * Represents the name and/or description of the subject. */ private String subjectName; /** * Array of all the drinks consumed by the subject. */ private Drink drinks[]; /** * Represents the time that the subject started consuming their drinks. */ private DrinkTime start; /** * Represents the time that the subject stopped consuming their drinks. */ private DrinkTime end; /** * Represents the subject's stomach. */ private Stomach stomach; /** * Represents the subject's small intestine. */ private Intestine intestine; /** * Represents the subject's non-fatty body mass. */ private LeanBodyMass body; /** * Constructor for the New Model subject class. * @param age int representing the age of the subject in years. * @param height double representing the height of the subject. * @param gender char representing the gender of the subject. * @param weight double representing the weight of the subject. * @param drinks Drink array representing all the drinks drank * by the subject. * @param start DrinkTime representing the time that the * subject started drinking. * @param end DrinkTime representing the time that the subject * stopped drinking. * @param subjectName String representing the subjects name and * / or description. * @param bitFlag int representing all set switches. */ NMSubject(int age, double height, char gender, double weight, Drink [] drinks, DrinkTime start, DrinkTime end, String subjectName, int bitFlag){ this.age = age; this.gender = gender; this.drinks = drinks; this.start = start; this.end = end; this.subjectName = subjectName; this.bitFlag = bitFlag; this.peakBAC = 0.00; if ((bitFlag & _METRIC) != 0) { this.weight = weight; this.height = height; } else if ((bitFlag & _IMPERIAL) != 0) { this.weight = weight / 2.20462262; // lb to kg this.height = height * 2.54; // in to cm } if (this.gender == 'M'){ this.TBW = (-0.09516 * (this.age)) + (0.1074 * (this.height)) + (0.3362 * (this.weight)) + 2.447; } else if (this.gender == 'F'){ this.TBW = (0.1069 * (this.height)) + (0.2466 * (this.weight)) - 2.097; } //System.out.println(this.TBW); for (int i=0; i < drinks.length; i++){ this.totalVolume += drinks[i].getVolume() * 0.0295735297; // Liters this.totalEthanol += (drinks[i].getVolume() * (drinks[i].getConcentration()/100)) * 23.36; // Grams } //System.out.println(this.totalVolume); //System.out.println(this.totalEthanol); // if drinking period crosses 12 o' clock if ((end.getAMorPM() == DrinkTime._AM && start.getAMorPM() == DrinkTime._PM) || (end.getAMorPM() == DrinkTime._PM && start.getAMorPM() == DrinkTime._AM)) { this.totalMinutes = (((12 - start.getHours()) * 60) + (0 - start.getMinutes())) + (end.getHours() * 60) + end.getMinutes(); } else { if (start.getHours() == 12) this.totalMinutes = (end.getHours() * 60) + (end.getMinutes() - start.getMinutes()); else { this.totalMinutes = (end.getHours() - start.getHours()) * 60 + (end.getMinutes() - start.getMinutes()); } } this.BACvalues = new double[this.totalMinutes]; this.passingEthanol = this.totalEthanol / this.totalMinutes; this.passingVolume = this.totalVolume / this.totalMinutes; //System.out.println(this.passingEthanol); //System.out.println(this.passingVolume); } /** * Retrieves the age of the subject. * @return int representing the subject's age (yrs). */ public int getAge() { return this.age; } /** * Retrieves the list of BACvalues recorded while the model was running. * One value will have been recorded for each minute the subject was drinking. * @return Array of doubles containing the chronological list of * BAC values. */ public double [] getBAC() { double BAC[] = new double[this.BACvalues.length]; System.arraycopy(this.BACvalues, 0, BAC, 0, this.BACvalues.length); return BAC; } /** * Retrieves the options set in the subject's bit flag. * @return int representing the bit flag. */ public int getBitF() { return this.bitFlag; } /** * Retrieves the list of drinks consumed by the subject. * @return Array of Drinks containing the drink objects. */ public Drink [] getDrinks() { Drink drinks[] = new Drink[this.drinks.length]; System.arraycopy(this.drinks, 0, drinks, 0, this.drinks.length); return drinks; } /** * Retrieves the time when the subject stopped drinking. * @return DrinkTime representing the end time. */ public DrinkTime getEndTime() { return this.end.getCopy(); } /** * Retrieves the height of the subject depending on the system of * measurement selected. * @return double representing the height (cm or in). */ public double getHeight() { if ((bitFlag & _METRIC) != 0) { return this.height; } else if ((bitFlag & _IMPERIAL) != 0) { return this.height / 2.54; // cm to in } else { return 0; } } /** * Retrieves the gender of the subject. * @return char representing gender ('M' or 'F'). */ public char getGender() { return this.gender; } /** * Retrieves the total number of minutes for the drinking time. * @return int representing the total number of minutes. */ public int getMinutes() { return totalMinutes; } /** * Retrieves the name and description of the subject. * @return String containing the subject name. */ public String getName() { return this.subjectName; } /** * Retrieves the peak BAC achieved during the drinking period. * @return double representing the peak BAC. */ public double getPeakBAC() { return this.peakBAC; } /** * Retrieves the time when the subject stopped drinking. * @return DrinkTime representing the end time. */ public DrinkTime getStartTime() { return this.start.getCopy(); } /** * Retrieves the Total Body Water (TBW) for the subject. * @return double representing the TBW. */ public double getTBW() { return this.TBW; } /** * Retrieves the weight of the subject depending on the system of * measurement selected. * @return double representing the weight (kg or lb). */ public double getWeight() { if ((bitFlag & _METRIC) != 0) { return this.weight; } else if ((bitFlag & _IMPERIAL) != 0) { return this.weight * 2.20462262; // cm to in } else { return 0; } } /** * Checks to see if a new peak BAC has been reached. */ private void peakBAC() { if (this.peakBAC < (body.getContents() / this.TBW) / 10) { this.peakBAC = (body.getContents() / this.TBW) / 10; } } /** * Runs the compartmental model. This method should only be run if all * values have already been declared and initialized, otherwise, unexpected * results may occur. * @return boolean value that represents whether the method * executed successfully. true if successful, * otherwise, unsuccessful. */ public boolean runModel() { /* * Initializes the stomach compartment. Initial volume is equal to the * gastric fluid already present (depending on meal). */ stomach = new Stomach(0.00, ((bitFlag & NMSubject._NO_MEAL) != 0) ? .150 : ((bitFlag & NMSubject._LIGHT_MEAL) != 0) ? .600 : ((bitFlag & NMSubject._AVERAGE_MEAL) != 0) ? 1.000 : ((bitFlag & NMSubject._LARGE_MEAL) != 0) ? 1.400 : 0.00); intestine = new Intestine(0.000, 0.000); int drinkingHistory = ((bitFlag & NMSubject._LIGHT_DRINKER) != 0) ? NMSubject._LIGHT_DRINKER : ((bitFlag & NMSubject._MODERATE_DRINKER) != 0) ? NMSubject._MODERATE_DRINKER : ((bitFlag & NMSubject._HEAVY_DRINKER) != 0) ? NMSubject._HEAVY_DRINKER : NMSubject._MODERATE_DRINKER; body = new LeanBodyMass(0.000, this.TBW, drinkingHistory); int min = 0; while (min < this.totalMinutes) { double firstPass = stomach.computeMMMetab() * .04607 * stomach.getLiquid(); // grams of ethanol metabolized. double toIntestine = stomach.computeEthanolRelease(); // grams of ethanol leaving through pyloric sphincter. double toBody = intestine.computeEthanolAbsorption(); // grams of ethanol leaving through villi double fromBody = body.computeMMMetab() * .04607 * this.TBW; // grams of ethanol metabolized. //System.out.println(this.passingEthanol); //System.out.println(this.passingVolume); //System.out.println(firstPass); //System.out.println(squirtVolume); //System.out.println(toIntestine); //System.out.println(stomach.getLiquid()); //System.out.println(intestine.getLiquid()); //System.out.println(stomach.getContents()); //System.out.println(intestine.getContents()); //System.out.println(intestine.getContents()); //System.out.println(body.getContents()); // adjust stomach transfer values. stomach.addContents(this.passingEthanol); stomach.addLiquid(this.passingVolume); stomach.addContents(-firstPass); stomach.addLiquid(-this.squirtVolume); stomach.addContents(-toIntestine); // adjust intestine transfer values. intestine.addContents(toIntestine); intestine.addLiquid(this.squirtVolume); intestine.addContents(-toBody); intestine.addLiquid(-this.absorbVolume); // adjust body transfer values. body.addContents(toBody); body.addContents(-fromBody); BACvalues[min] = (body.getContents() / this.TBW) / 10; min++; this.peakBAC(); } return true; } }