import java.lang.System; import java.util.Timer; import java.util.TimerTask; abstract class MeetingTimer extends TimerTask { private Timer mRefreshTimer = null; // Timer to invoke run() periodically private int mRefreshInterval = 1000; // How often is the display updated? 1000 = 1 second private long mNumAttendees=0; // Number of people antending the meeting private long mAvAnSalary=0; // Average annual salary of antendees (dollars) private long mTotMillPerMinRate = 0; // Salary of all antendees in Mill/S private boolean mMeterRunning = false; // True when running the meter for the meeting private long mLastRefresh=System.currentTimeMillis(); // The time of the last refresh private long mCumMtgCostMill=0; // Cumulative cost of the meeting in Mills private long mCumLaborMs=0; // Cumulative labor hours of the meeting in mS // Constructor - no init public MeetingTimer() { // Set up and start the timer to refresh the display mRefreshTimer = new Timer(); mRefreshTimer.schedule(this, 0, mRefreshInterval); } //////////////////////////////////////// // Methods to access and modify settings //////////////////////////////////////// public void setSalary(long pSalary) { mAvAnSalary = pSalary; // Set member variable calcSalary(); // Recalculate salary rate } public long getSalary() { return(mAvAnSalary); } public void setAttendees(long pAttendees) { mNumAttendees = pAttendees; // Set member variable calcSalary(); // Recalculate salary rate } public void setCost(long pCost) { // Set up the baseline cost, converting from Mills to dollars mCumMtgCostMill = pCost * 1000; } public long getAttendees() { return(mNumAttendees); } ////////////////// // Control methods ////////////////// public void startTimer() { mMeterRunning = true; } public void stopTimer() { mMeterRunning = false; } public void reset() { mCumMtgCostMill=0; mCumLaborMs=0; } // Return cost of meeting in dollars public String getCost() { // Because we lack floating point, calculate dollars and cents as long ints long costDollars = mCumMtgCostMill/1000; long costCents = (mCumMtgCostMill/10) % 100; // Now, return a string with the cost return( new String("$" + costDollars + "." + (costCents<10 ? "0" : "") + costCents)); } // Return cost of meeting in labor hours public String getHours() { // Because we lack floating point, calculate hours, minutes, // and seconds with long ints long s = (mCumLaborMs/1000) % 60; // Seconds long m = (mCumLaborMs/ (1000 * 60)) % 60; // Minutes long h = mCumLaborMs/ (1000 * 60 * 60); // Hours // Now, return a string with the labor hours. Pad minutes and seconds // with zeroes if required for spacing. return( new String(h + ":" + (m<10 ? "0" : "") + m + ":" + (s<10 ? "0" : "") + s) ); } // When changed, calculate the salary of all antendees // in microdollars per second. Note that this odd unit is used // because we lack a floating point library to handle fractions. private void calcSalary() { // Calculate the annual salary of all atendees in Mills (1/1000 dollar) long totAnSalary = mNumAttendees * mAvAnSalary * 1000; // Now, divide it out for Mills per minute. Assume 50 weeks a year (52 minus 2 // weeks vacation) and a 40 hour workweek. mTotMillPerMinRate = totAnSalary / (50 * 40 * 60 ); } // The paint() method should be overloaded with the implementation to draw the // timer results on the screen. It should use getHours() and getCost() for // its display. abstract void paint(); // The method to run periodically to calculate the meeting totals public void run() { long curTime = System.currentTimeMillis(); // Current time long deltaCost; // Cost since last refresh // See if the "meter is running" for this meeting if(mMeterRunning) { // Figure out the cost deltaCost = ((curTime - mLastRefresh) * mTotMillPerMinRate)/ (1000 * 60); mCumMtgCostMill = mCumMtgCostMill + deltaCost; // Figure out the labor hours mCumLaborMs = mCumLaborMs + ((curTime - mLastRefresh) * mNumAttendees); // Now, invoke child method to repaint the screen paint(); } // Finally, record the last refresh time mLastRefresh = curTime; } }