def _generate_state(self):

        # retrieve current state
        numDaysPassed, currentHour, currentMinute, currentDay = self.chronometer.getCurrentTime(
        )

        # get environment info (user context)
        self.lastNotificationTime = utils.getDeltaMinutes(
            numDaysPassed,
            currentHour,
            currentMinute,
            self.lastNotificationNumDays,
            self.lastNotificationHour,
            self.lastNotificationMinute,
        )
        self.stateLastNotification = utils.getLastNotificationState(
            self.lastNotificationTime)
        self.stateLocation, self.stateActivity = self.behavior.getLocationActivity(
            currentHour, currentMinute, currentDay)

        # prepare observables and get action
        self.stateTime = utils.getTimeState(currentHour, currentMinute)
        self.stateDay = utils.getDayState(currentDay)

        return (
            self.stateTime,
            self.stateDay,
            self.stateLocation,
            self.stateActivity,
            self.stateLastNotification,
        )
    def getResponseDistribution(self, hour, minute, day, stateLocation,
                                stateActivity, lastNotificationTime):

        stateDay = utils.getDayState(day)
        stateNotification = utils.getLastNotificationState(
            lastNotificationTime)
        state = (stateDay, stateLocation, stateActivity, stateNotification)

        records = self.behavior[state]

        if len(records) == 0:
            probAnswerNotification = 0.1
        else:
            timeDiffs = [
                abs(
                    utils.getDeltaMinutes(0, hour, minute, 0, r['rawHour'],
                                          r['rawMinute'])) for r in records
            ]
            weights = numpy.array([1. / (t + 5.) for t in timeDiffs])
            weightSum = numpy.sum(weights)
            probs = weights / weightSum

            chosenRecord = numpy.random.choice(a=records, p=probs)
            probAnswerNotification = (1.0 if chosenRecord['answerNotification']
                                      else 0.0)

        probDismissNotification = 1.0 - probAnswerNotification
        probIgnoreNotification = 0.0
        return (probAnswerNotification, probIgnoreNotification,
                probDismissNotification)
    def getResponseDistribution(self, hour, minute, day, stateLocation,
                                stateActivity, lastNotificationTime):
        stateTime = utils.getTimeState(hour, minute)
        stateDay = utils.getDayState(day)
        stateNotification = utils.getLastNotificationState(
            lastNotificationTime)
        state = (stateTime, stateDay, stateLocation, stateActivity,
                 stateNotification)

        probAnswerNotification = (self.probTake if self.behavior[state] else
                                  self.probNotTake)
        probDismissNotification = 1.0 - probAnswerNotification
        probIgnoreNotification = 0.0
        return (probAnswerNotification, probIgnoreNotification,
                probDismissNotification)
    def getResponseDistribution(self, hour, minute, day, stateLocation,
                                stateActivity, lastNotificationTime):
        stateDay = utils.getDayState(day)
        stateNotification = utils.getLastNotificationState(
            lastNotificationTime)
        state = (stateDay, stateLocation, stateActivity, stateNotification)

        records = self.behavior[state]

        if len(records) == 0:
            probAnswerNotification = 0.1
            probIgnoreNotification = 0.8
            probDismissNotification = 0.1
        else:
            timeDiffs = [
                abs(
                    utils.getDeltaMinutes(0, hour, minute, 0, r['rawHour'],
                                          r['rawMinute'])) for r in records
            ]
            weights = np.array([(1. / (t + 5.))**1 for t in timeDiffs])
            weightSum = np.sum(weights)
            probs = weights / weightSum

            chosenRecord = np.random.choice(a=records, p=probs)

            probAnswerNotification, probIgnoreNotification, probDismissNotification = 0.0, 0.0, 0.0
            if chosenRecord[
                    'answerNotification'] == ANSWER_NOTIFICATION_ACCEPT:
                probAnswerNotification = 1.0
            elif chosenRecord[
                    'answerNotification'] == ANSWER_NOTIFICATION_IGNORE:
                probIgnoreNotification = 1.0
            elif chosenRecord[
                    'answerNotification'] == ANSWER_NOTIFICATION_DISMISS:
                probDismissNotification = 1.0

        return (probAnswerNotification, probIgnoreNotification,
                probDismissNotification)
    def _parseCsvRow(self, row):
        """
        This function receives a line from the input file and convert it to a dictionary with
        the following keys:

            parsedRow, rawHour, rawMinute,
            rawWorkerID, rawWorkingTimeSec,
            stateDay, stateLocation, stateActivity, stateNotification,
            answerNotification

        If the line is not able to converted, or the response is invalid, `None` is returned
        instead.
        """

        workerID = row['WorkerId']
        workingTimeSec = int(row['WorkTimeInSeconds'])
        hour = int(row['Input.hour'])
        minute = int(row['Input.minute'])
        day = int(row['Input.day'])
        location = row['Input.location']
        activity = row['Input.motion']
        lastSeenNotificationTime = int(row['Input.last_notification_time'])
        response = row['Answer.sentiment']

        answerNotificationCriteria = {
            'Dismiss': ANSWER_NOTIFICATION_DISMISS,
            'Accept': ANSWER_NOTIFICATION_ACCEPT,
            'Later': ANSWER_NOTIFICATION_IGNORE,
            'Invalid': None,
        }
        answerNotification = answerNotificationCriteria[response]
        if answerNotification is None:
            return None

        locationToState = {
            'home': STATE_LOCATION_HOME,
            'work': STATE_LOCATION_WORK,
            'beach': STATE_LOCATION_OTHER,
            'friend-house': STATE_LOCATION_OTHER,
            'restaurant': STATE_LOCATION_OTHER,
            'mall': STATE_LOCATION_OTHER,
            'gym': STATE_LOCATION_OTHER,
            'park': STATE_LOCATION_OTHER,
            'movie-theater': STATE_LOCATION_OTHER,
            'market': STATE_LOCATION_OTHER,
            'others': STATE_LOCATION_OTHER,
        }

        activityToState = {
            'stationary': STATE_ACTIVITY_STATIONARY,
            'walking': STATE_ACTIVITY_WALKING,
            'running': STATE_ACTIVITY_RUNNING,
            'driving': STATE_ACTIVITY_DRIVING,
            'biking': STATE_ACTIVITY_DRIVING,
            'train': STATE_ACTIVITY_COMMUTE,
            'bus': STATE_ACTIVITY_COMMUTE,
        }

        return {
            'parsedRow':
            row,
            'rawHour':
            hour,
            'rawMinute':
            minute,
            'rawWorkerID':
            workerID,
            'rawWorkingTimeSec':
            workingTimeSec,
            'stateDay':
            utils.getDayState(day),
            'stateLocation':
            locationToState[location],
            'stateActivity':
            activityToState[activity],
            'stateNotification':
            utils.getLastNotificationState(lastSeenNotificationTime),
            'answerNotification':
            answerNotification,
        }
    def parse(self, line):
        """
        This function receives a line from the input file and convert it to a dictionary with
        the following keys:

            rawLine, rawHour, rawMinute,
            stateDay, stateLocation, stateActivity, stateNotification, answerNotification

        If the line is not able to converted, or the response is invalid, None is returned instead

        Example of a line: 16,0,0,work,walking,90,answer
            - hour (0-23)
            - minute (0-59)
            - day (0-6)
            - location {home, work, others}
            - activity {stationary, walking, running, driving}
            - last seen notification {0-integer}
            - response {ignore, dismiss, answer, later, invalid}
        """

        terms = line.strip().split(',')
        if len(terms) < 7:
            return None

        hour = int(terms[0])
        minute = int(terms[1])
        day = int(terms[2])
        location = terms[3]
        activity = terms[4]
        lastSeenNotificationTime = int(terms[5])
        response = terms[6]

        answerNotificationCriteria = {
            'ignore': False,
            'dismiss': False,
            'answer': True,
            'later': None,
            'invalid': None,
        }
        answerNotification = answerNotificationCriteria[response]
        if answerNotification is None:
            return None

        locationToState = {
            'home': STATE_LOCATION_HOME,
            'work': STATE_LOCATION_WORK,
            'others': STATE_LOCATION_OTHER,
        }

        activityToState = {
            'stationary': STATE_ACTIVITY_STATIONARY,
            'walking': STATE_ACTIVITY_WALKING,
            'running': STATE_ACTIVITY_RUNNING,
            'driving': STATE_ACTIVITY_DRIVING,
        }

        return {
            'rawLine':
            line,
            'rawHour':
            hour,
            'rawMinute':
            minute,
            'stateDay':
            utils.getDayState(day),
            'stateLocation':
            locationToState[location],
            'stateActivity':
            activityToState[activity],
            'stateNotification':
            utils.getLastNotificationState(lastSeenNotificationTime),
            'answerNotification':
            answerNotification,
        }