import json import os import pickle as pkl from collections import defaultdict def schedule_to_str(schedule, show_at_home=False): schedule_str = '' for event in schedule: schedule_str += f'Activity: {event["activity"]}, start_time: {event["start_time"].strftime("%H:%M")}, ' \ f'end_time: {event["end_time"].strftime("%H:%M")}' if show_at_home: schedule_str += f', at_home: {str(event["at_home"])}' schedule_str += '\n' return schedule_str class Person: def __init__(self, persona): meta_data = persona self.meta_data = persona self.family = None self.family_info = None self.event_base = None self.primary_activity_set = set() self.activity_alias = dict() # activity_set = full name list, including aliases # However, event base only include primary keys, i.e., len(activity_set) >= len(event_base) self.schedules = defaultdict(dict) self.general_plans = defaultdict(dict) self.name = meta_data['name'] self.first_name = meta_data['name'].split(' ')[0] self.age = meta_data['age'] self.gender = meta_data.get('gender', 'Unknown') self.routine = meta_data['routine'] self.personality = meta_data['personality'] self.occupation = meta_data['occupation'] self.thoughts = meta_data['thoughts'] self.lifestyle = meta_data['lifestyle'] self.default_keys = ['Name', 'Age', 'Gender', 'Routine', 'Family Info', 'Personality', 'Occupation', 'Thoughts', 'Lifestyle'] self.public_keys = ['Name', 'Age', 'Gender', 'Routine', 'Family Info'] self.init_event_base() def set_family(self, family, family_info=None): self.family = family self.family_info = family_info def init_event_base(self): ''' Event base is a hierarchical dict. activity: room: { 'room_prob': prob, 'object_effect': [ object: { 'object_prob': prob, 'receptacles': [[receptacle, prob]] } ] } ''' self.event_base = defaultdict(dict) def update_event(self, event_base): self.event_base.update(event_base) self.primary_activity_set.update(set(self.event_base.keys())) def filter_event(self, events): # find out events that are not analysed new_events = [e for e in events if e not in self.event_base and e not in self.activity_alias] return new_events def update_schedule(self, schedule, date, schedule_key='default'): self.schedules[schedule_key][date] = schedule.copy() def update_general_plan(self, general_plan, date, schedule_key='default'): self.general_plans[schedule_key][date] = general_plan.copy() def update_alias(self, alias_pairs, verbose=False): # new activities join primary_activity_set, then will be filtered out to gen prob, # then into event base, then done as a primary key # when outside code try to merge, should use primary_activity_set as reference for new_act, old_act in alias_pairs.items(): if old_act is not None and old_act != new_act: # self.activity_alias[old_act].add(new_act) self.activity_alias[new_act] = old_act else: self.primary_activity_set.add(new_act) if old_act is None and verbose: print(f"New activity: {new_act}") return self.activity_alias def get_public_information(self): return self.get_all_information(self.public_keys) def get_all_information(self, keys=None): if keys is None: keys = self.default_keys person_info = '' for key in keys: if self.family is None and key == 'Family Info': continue person_info += f'{key}: {eval("self." + key.lower().replace(" ", "_"))}\n' return person_info def get_character_dict(self): res = { 'event_base':self.event_base, 'persona':self.meta_data, 'schedule':self.schedules } return res