def decay_work_commute(self, p): """ This decays the satiation level in order to commute to work. For the satiation to decay the \ person needs the following: #. the agent should leave the home to go to work #. the agent should leave work to go home :param person.Person p: the person of interest :return: None """ leave_home = False leave_work = False # do not commute if working at home if (p.socio.job.location.local != location.HOME): # commute from Home to Work (leave early to take into account commute) if (p.location.local == location.HOME): leave_home = occupation.is_work_time(p.clock, p.socio.job, is_commute_to_work=True) # commute from Work to Home (when it is no longer work time) elif (p.location.local == p.socio.job.location.local): leave_work = not occupation.is_work_time( p.clock, p.socio.job, is_commute_to_work=False) # assign the travel magnitude if (leave_work or leave_home): p.travel.magnitude = need.MAG_COMMUTE return
def perceive(self, clock, job): """ This gives the satiation of income **if** the income need is addressed now. #. find out if the time associated with clock implies a work time for the person #. If it should be work time * the perceived satiation is :math:`\eta_{work} \le \lambda` * else, the perceived satiation is :math:`1.0` :param temporal.Temporal clock: the future time the activity the should be perceived to be done :param occupation.Occupation job: the job :return: the satiation at the perceived time :rtype: float """ # flag indicating whether it is work time or not is_work_time = occupation.is_work_time(clock, job) # do not set the work need exactly to zero. This way, # if a super important need can interrupt the work activity if (is_work_time): mag = need.MAG_WORK else: mag = 1.0 return mag
def perceive(self, clock, job): """ This function gives the satiation for Travel if the Travel need is addressed now. :Note: going to work can only happen according to work hours of the job. :param temporal.Temporal clock: the time the need to travel is perceived :param occupation.Occupation job: the job of the person :return mag: the perceived magnitude of the need :rtype: float """ # indicate if it is the work time (True) or not (False) is_work_time = occupation.is_work_time(clock, job, is_commute_to_work=True) # do not set the work need exactly to zero. This way, # if a super important need can interrupt the work activity if (is_work_time): mag = need.MAG_COMMUTE else: # it's not time to commute mag = 1.0 return mag
def advertise(self, p): """ This function calculates the score of an activities advertisement to a person. The activity \ advertise to the agent if the following conditions are met: #. the current meal is lunch #. the agent's location is at home (:const:`location.HOME`) or the agent's location is at the \ workplace (:const:`location.OFF_SITE`) #. calculate the score :math:`S` .. math:: S = \\begin{cases} 0 & n_{hunger}(t) > \\lambda \\\\ W( n_{hunger}(t) ) - W( n_{hunger}(t + \\Delta{t} )) & n_{hunger}(t) \\le \\lambda \\end{cases} where * :math:`t` is the current time * :math:`\\Delta{t}` is the duration of eating lunch [minutes] * :math:`n_{hunger}(t)` is the satiation for Hunger at time :math:`t` * :math:`\\lambda` is the threshold value of Hunger * :math:`W(n)` is the weight function for Hunger If the threshold is not met, score is 0. The advertisements assume that the duration \ of the activity is the mean duration. :param person.Person p: the person of interest :return score: the advertised score of doing the eat lunch activity :rtype: float """ # adjust the range of start times score = 0.0 # find the meal that is advertised. the_meal = p.socio.get_current_meal(p.clock.time_of_day) # need to add something for limiting advertisements at work during non-lunch time # if breakfast is skipped, need to make sure lunch is advertised at the correct time. If a meal is advertised, # n < lambda. if (the_meal is not None) and (the_meal.id == meal.LUNCH): # set flags for if it's time to work is_work_time = occupation.is_work_time(p.clock, p.socio.job) # set flag to see if the time is before lunch starts is_before_lunch = p.clock.time_of_day < the_meal.t_start # if agent is at work and before lunch time, do NOT eat lunch if (is_work_time and is_before_lunch): score = 0.0 else: score = self.advertise_help(p, the_meal.dt) return score
def decay(self, p): """ This function decays the magnitude of the need. Income only decays after the job start time. #. Find out if it is time to work #. If it's time to work, set the satiation :math:`n_{income} = \eta_{work}` :param person.Person p: the person of interest :return: None """ # is it time for work? is_work_time = occupation.is_work_time(p.clock, p.socio.job) # decay by income need dropping to WORK_MAG if (is_work_time): self.magnitude = need.MAG_WORK return
def duration_to_next_commute_event(self, clock): """ This function is called in in order to calculate the amount of time until the next commute event by \ doing the following. #. If the agent is unemployed, return infinity #. If the time indicates that the agent should be currently working, set the duration to be the \ length of time remaining at work #. If the time indicates that the agent should be currently commuting to work, set the duration to be \ the duration until the commute to work should start #. If the time indicates that the agent should be currently commuting from work, set the duration to be \ the amount of time until the commute from work should end #. Else, calculate the amount of time until the next commute to work event .. note:: The only reason this code is place here is because the work activity and the commute activity use it. :param temporal.Temporal clock: the current time :return: the duration in time [minutes] until the next commute event :rtype: int """ DAY_2_MIN = temporal.DAY_2_MIN # if the person is unemployed, set the duration to infinity if not self.job.is_employed: dt = np.inf else: # should the agent be working work_time = occupation.is_work_time(clock, self.job, is_commute_to_work=False) # is it time for the person to be commuting to work commute_to_work_time = occupation.is_work_time( clock, self.job, is_commute_to_work=True) # is it time to commute from work t = max(0, clock.t_univ - self.job.commute_from_work_dt) temp_clock = temporal.Temporal() temp_clock.t_univ = t temp_clock.set_time() commute_from_work_time = occupation.is_work_time( temp_clock, self.job, is_commute_to_work=False) # if the agent is currently working, set the duration to be the length of time remaining at work if (work_time): t_end = self.job.t_end dt = (t_end - clock.time_of_day + DAY_2_MIN) % DAY_2_MIN # if the person should be commuting to work, set the duration to be the length of time remaining until # the commute starts elif (commute_to_work_time): t_start = self.job.commute_to_work_start dt = (t_start - clock.time_of_day + DAY_2_MIN) % DAY_2_MIN # if the person should be commuting from work, set the time to be the time when the commute should end elif (commute_from_work_time): t_start = self.job.t_end dt = (t_start + self.job.commute_from_work_dt - self.clock.time_of_day + DAY_2_MIN) % DAY_2_MIN # else, calculate the amount of time until the next commute event else: # time until the next work event dt = self.duration_to_work_event( clock) - self.job.commute_to_work_dt return dt