package metab;
import metab.*;
import java.io.*;
/**
* The <code>NMSubject</code> 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 <code>Stomach</code>, <code>Intestine</code>,
* and <code>LeanBodyMass</code> 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 <code>int</code> representing the age of the subject in years.
* @param height <code>double</code> representing the height of the subject.
* @param gender <code>char</code> representing the gender of the subject.
* @param weight <code>double</code> representing the weight of the subject.
* @param drinks <code>Drink</code> array representing all the drinks drank
* by the subject.
* @param start <code>DrinkTime</code> representing the time that the
* subject started drinking.
* @param end <code>DrinkTime</code> representing the time that the subject
* stopped drinking.
* @param subjectName <code>String</code> representing the subjects name and
* / or description.
* @param bitFlag <code>int</code> 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 <code>int</code> 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 <code>double</code>s 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 <code>int</code> representing the bit flag.
*/
public int getBitF() {
return this.bitFlag;
}
/**
* Retrieves the list of drinks consumed by the subject.
* @return Array of <code>Drink</code>s 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 <code>DrinkTime</code> 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 <code>double</code> 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 <code>char</code> representing gender ('M' or 'F').
*/
public char getGender() {
return this.gender;
}
/**
* Retrieves the total number of minutes for the drinking time.
* @return <code>int</code> representing the total number of minutes.
*/
public int getMinutes() {
return totalMinutes;
}
/**
* Retrieves the name and description of the subject.
* @return <code>String</code> containing the subject name.
*/
public String getName() {
return this.subjectName;
}
/**
* Retrieves the peak BAC achieved during the drinking period.
* @return <code>double</code> representing the peak BAC.
*/
public double getPeakBAC() {
return this.peakBAC;
}
/**
* Retrieves the time when the subject stopped drinking.
* @return <code>DrinkTime</code> representing the end time.
*/
public DrinkTime getStartTime() {
return this.start.getCopy();
}
/**
* Retrieves the Total Body Water (TBW) for the subject.
* @return <code>double</code> representing the TBW.
*/
public double getTBW() {
return this.TBW;
}
/**
* Retrieves the weight of the subject depending on the system of
* measurement selected.
* @return <code>double</code> 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 <code>boolean</code> value that represents whether the method
* executed successfully. <code>true</code> 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;
}
}