Skip to content

Instantly share code, notes, and snippets.

@Kaminate
Created August 6, 2013 06:12
Show Gist options
  • Save Kaminate/6162442 to your computer and use it in GitHub Desktop.
Save Kaminate/6162442 to your computer and use it in GitHub Desktop.
Describes a person and (alcoholic) drink class. When a person drinks a drink, it takes the timestamp into account when calculating the person's BAC (blood alcohol concentration). I made this for 2013 Angelhack in Seattle.
// 2013 Nathan Park
// Angelhack in Seattle
#include <iostream>
#include <string>
#include <vector>
typedef float Date;
const float grams_per_lb = 453.592f;
const float lbs_per_gram = 1.0f / grams_per_lb;
const float oz_per_cg = 0.000352739619f;
const float cg_per_oz = 1.0f / oz_per_cg;
struct Drink // stored in a database
{
Drink(
const std::string & name,
float volumeInOunces,
float calories,
float percentAlchohol)
: mName(name)
, mVolumeInOunces(volumeInOunces)
, mCalories(calories)
, mPercentAlchohol(percentAlchohol)
{}
std::string mName;
float mVolumeInOunces;
float mCalories;
float mPercentAlchohol; // [0,100] <-- scale is important
};
// made some adjustments, based off
// http://dogsbody.psych.mun.ca/Tools/BAL/tutorial.html and wikipedia
// to account for the changing time
// mostly the same though
// -Nate
class Person
{
public:
Person(bool isMale, float weightLbs)
: mCaloriesDrank(0)
, mOuncesOfAlchoholInSystem(0)
, mHasStartedDrinking(false)
{
mMetabolismLbs = weightLbs;
mMetabolismLbs *= isMale ? sMaleGenderConstant : sFemaleGenderConstant;
}
void Consume(const Drink & drink, Date currTime)
{
mConsumed.push_back(drink);
mCaloriesDrank += drink.mCalories;
UpdateBAC(currTime);
// divide the percentage[0,100] by 100 to go to [0,1]
float drinkAlOz = drink.mVolumeInOunces * drink.mPercentAlchohol / 100.0f;
mOuncesOfAlchoholInSystem += drinkAlOz;
mHasStartedDrinking = true;
mLastUpdateTime = currTime;
// cg oz cg lbs
// / / * / * /
// g lbs oz g
//mBAC += ( drinkAlOz / mMetabolismLbs ) * ( 1 / oz_per_cg) * (1 / grams_per_lb);
}
/*
@param alchohol
measured in oz
@return float
bac, measured in cg alchohol/g metabolism
*/
float AlchoholToBAC(float alchohol)
{
return alchohol * cg_per_oz * lbs_per_gram / mMetabolismLbs;
}
/*
@param bac
measured in cg alchohol/g metabolism
@return float
alchohol, measured in oz
*/
float BACToAlchohol(float bac)
{
return bac * mMetabolismLbs * grams_per_lb * oz_per_cg;
}
void UpdateBAC(Date currTime)
{
if (!mHasStartedDrinking) return;
Date currentTime = currTime;
float hourDifference = currentTime - mLastUpdateTime;
mLastUpdateTime = currentTime;
// account for the time difference
float alchoholElimination = hourDifference * sNaturalBACReductionPerHr;
float bac = AlchoholToBAC(mOuncesOfAlchoholInSystem);
bac -= alchoholElimination;
if (bac < 0)
{
mOuncesOfAlchoholInSystem = 0;
return;
}
// recalculate the alchohol in system
mOuncesOfAlchoholInSystem = BACToAlchohol(bac);
}
float GetBAC(Date currTime)
{
UpdateBAC(currTime);
return AlchoholToBAC(mOuncesOfAlchoholInSystem);
}
float GetCaloriesDrunk()const{return mCaloriesDrank;}
private:
// ( total blood in the body measured in lbs) * genderConstant
float mMetabolismLbs;
float mCaloriesDrank;
float mOuncesOfAlchoholInSystem;
// http://en.wikipedia.org/wiki/Blood_alcohol_content
//float mBAC; // measured in mass 1/100 g/g = 1 cg alchohol/g metabolism
Date mLastUpdateTime;
bool mHasStartedDrinking;
std::vector<Drink> mConsumed; // for reference
static const float sNaturalBACReductionPerHr;
static const float sConversionRate;
static const float sMaleGenderConstant;
static const float sFemaleGenderConstant;
};
// how much BAC the body removes per/hr
const float Person::sNaturalBACReductionPerHr = 0.015f;
const float Person::sConversionRate = 5.14f;
const float Person::sMaleGenderConstant = 0.73f;
const float Person::sFemaleGenderConstant = 0.66f;
int main()
{
std::cout << std::endl;
// name vol cal al%
Drink milk ("milk" , 8, 136, 0);
Drink parrotBay ("parrot bay" , 1.5, 87, 20);
Drink budlightplat ("budlightplat", 12, 137, 6);
Drink captMorganBlk("captmorgblk" , 1.5, 117, 47.3f);
float weightInLbs = 190.0f;
bool isMale = true;
Person person(isMale, weightInLbs);
float currTimeInHrs = 0.0f;
person.Consume(parrotBay , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(parrotBay , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(parrotBay , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(parrotBay , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(parrotBay , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(budlightplat , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(budlightplat , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(budlightplat , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(budlightplat , currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(captMorganBlk, currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(captMorganBlk, currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(captMorganBlk, currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
person.Consume(captMorganBlk, currTimeInHrs); currTimeInHrs += 5.0f / 14.0f;
//std::cout << std::endl << person.GetCaloriesDrunk();
std::cout << std::endl << person.GetBAC(currTimeInHrs);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment