def increment_pandemic_1_day(env_dic, virus_dic):
    for i in get_infected_people(virus_dic) + get_hospitalized_people(virus_dic):
        # Contagion and decision periods are decremented
        virus_dic[CON_K][i] = virus_dic[CON_K][i] - 1
        virus_dic[HOS_K][i] = virus_dic[HOS_K][i] - 1
        virus_dic[DEA_K][i] = virus_dic[DEA_K][i] - 1
        if virus_dic[HOS_K][i] == 0 and get_r() < get_hospitalization_rate(env_dic[IAG_K][i]):
            virus_dic[STA_K][i] = HOSPITALIZED_V
        # Decide over life
        if virus_dic[DEA_K][i] == 0:
            if get_r() < get_mortalty_rate(env_dic[IAG_K][i]):
                virus_dic[STA_K][i] = DEAD_V
            else:
                virus_dic[STA_K][i] = IMMUNE_V
    for i in get_immune_people(virus_dic):
        # Losing immunity
        virus_dic[IMM_K][i] = virus_dic[IMM_K][i] - 1
        if virus_dic[IMM_K][i] == 0:
            virus_dic[STA_K][i] = HEALTHY_V
            # I am not proud of this hack, otherwise it meant changing too many APIs
            con, hos, dea, imm = virus_dic[FN_K]()
            virus_dic[CON_K][i] = con
            virus_dic[HOS_K][i] = hos
            virus_dic[DEA_K][i] = dea
            virus_dic[IMM_K][i] = imm
def propagate_to_stores(env_dic, virus_dic, probability_store_infection_arg):
    # Filter on living people because we have a random choice to make in each house
    # People who will go to their store (one person per house as imposed by lockdown)
    individuals_gotostore = get_random_choice_list([[i for i in env_dic[HA_K][h] if is_alive(i, virus_dic)]
                                                    for h in range(len(env_dic[HA_K]))])

    # Contagious people who will go to their store
    individuals_infected_gotostore = [i for i in individuals_gotostore if is_contagious(i, virus_dic)]

    # Stores that will be visited by a contagious person
    infected_stores = [env_dic[HS_K][env_dic[IH_K][i]] for i in individuals_infected_gotostore]

    # People who live in a house that goes to a contagious store
    individuals_attachedto_infected_store = flatten(flatten(
        [[env_dic[HA_K][h] for h in env_dic[SH_K][s]] for s in infected_stores]))

    # People who did go to that contagious store
    individuals_goto_infected_store = list(set(individuals_attachedto_infected_store)
                                           .intersection(set(individuals_gotostore)))

    # People who got infected from going to their store
    infected_backfromstore = [i for i in individuals_goto_infected_store if get_r() < probability_store_infection_arg]

    # INFECTION STATE UPDATE
    update_infection_period(infected_backfromstore, virus_dic)
def propagate_to_workplaces(env_dic, virus_dic, probability_work_infection_arg):
    # Contagious people who will go to work
    infected_gotowork = [i for i in get_infected_people(virus_dic) if i in env_dic[IW_K].keys()
                         and is_contagious(i, virus_dic)]
    # Infected workplaces
    infected_workplaces = [env_dic[IW_K][ind] for ind in infected_gotowork]
    infected_backfromwork = [i for i in flatten([env_dic[WI_K][k] for k in infected_workplaces])
                             if get_r() < probability_work_infection_arg]

    # INFECTION STATE UPDATE
    update_infection_period(infected_backfromwork, virus_dic)
def propagate_to_houses(env_dic, virus_dic, probability_home_infection_arg):
    # Houses that contain an infected and contagious person
    infected_houses = [env_dic[IH_K][i] for i in get_infected_people(virus_dic)
                       if is_contagious(i, virus_dic)]

    # People infected (not necessarily contagious) from a contagious person living in their house
    infected_athome = [i for i in flatten([env_dic[HI_K][hou] for hou in infected_houses])
                       if get_r() < probability_home_infection_arg]

    # INFECTION STATE UPDATE
    update_infection_period(infected_athome, virus_dic)
def propagate_to_transportation(env_dic, virus_dic, probability_transport_infection_arg):
    # Contagious people who will go to work
    infected_who_goto_work = [i for i in get_infected_people(virus_dic) if i in env_dic[IW_K].keys()
                              and is_contagious(i, virus_dic)]
    # Infected public transportation blocks
    # No more reduce in python3 ... :(
    infected_who_share_blocks = list(set(flatten([env_dic[ITI_K][ind] for ind in infected_who_goto_work])))
    infected_bad_luck_transport = [k for k in infected_who_share_blocks
                                   if get_r() < probability_transport_infection_arg]

    # INFECTION STATE UPDATE
    update_infection_period(infected_bad_luck_transport, virus_dic)
def get_virus_simulation_t0(number_of_individuals_arg,
                            infection_initialization_rate_arg,
                            contagion_bound_args, hospitalization_args,
                            death_bound_args, immunity_bound_args):
    inn_ind_cov = dict(
        zip(range(number_of_individuals_arg), [
            int(get_r() <= infection_initialization_rate_arg)
            for i in range(number_of_individuals_arg)
        ]))

    life_state = dict(
        zip(range(number_of_individuals_arg),
            [HEALTHY_V] * number_of_individuals_arg))

    def get_infection_params():
        return get_infection_parameters(
            contagion_bound_args[0], contagion_bound_args[1],
            hospitalization_args[0], hospitalization_args[1],
            death_bound_args[0], death_bound_args[1], immunity_bound_args[0],
            immunity_bound_args[1])

    time_to_contagion = dict(
        zip(range(number_of_individuals_arg), [
            get_infection_params()[0] for _ in range(number_of_individuals_arg)
        ]))
    time_to_hospital = dict(
        zip(range(number_of_individuals_arg), [
            get_infection_params()[1] for _ in range(number_of_individuals_arg)
        ]))
    time_to_death = dict(
        zip(range(number_of_individuals_arg), [
            get_infection_params()[2] for _ in range(number_of_individuals_arg)
        ]))
    time_to_end_immunity = dict(
        zip(range(number_of_individuals_arg), [
            get_infection_params()[3] for _ in range(number_of_individuals_arg)
        ]))

    infected_individual_init = [k for k, v in inn_ind_cov.items() if v == 1]

    for individual in infected_individual_init:
        life_state[individual] = INFECTED_V

    return {
        CON_K: time_to_contagion,
        HOS_K: time_to_hospital,
        DEA_K: time_to_death,
        IMM_K: time_to_end_immunity,
        STA_K: life_state,
        FN_K: get_infection_params,
        NC_K: 0
    }
def build_individual_houses_map(number_individual_arg, proba_same_house_rate):
    # Individual -> House
    all_ind_hou = {}
    i_hou = 0
    i_ind = 0
    is_first_person = True
    prob_keep_hou = get_r()
    while i_ind < number_individual_arg:
        if is_first_person:
            all_ind_hou[i_ind] = i_hou  # Attach first person to the house
            i_ind = i_ind + 1  # GOTO next person
            is_first_person = False
            continue
        if prob_keep_hou > proba_same_house_rate:
            all_ind_hou[i_ind] = i_hou  # Attach Next person
            i_ind = i_ind + 1  # GOTO next person
            prob_keep_hou = prob_keep_hou / 2  # Divide probability keep_foy
        else:
            i_hou = i_hou + 1  # GOTO next house
            prob_keep_hou = get_r()  # RESET keep_hou probability
            is_first_person = True  # New house needs a first person
    return all_ind_hou
def build_individual_work_map(individual_adult_map_arg,
                              probability_remote_work_arg):
    # Only adults work, and only half of them
    workers = list([
        ind for ind, age in individual_adult_map_arg.items()
        if get_r() < probability_remote_work_arg and age == 1
    ])
    random.shuffle(workers)
    all_ind_wor = {}
    i_wor = 0
    while len(workers) > 0:
        for j in range(pick_random_company_size()):
            if len(workers) == 0:
                break
            ind = workers.pop()
            all_ind_wor[ind] = i_wor
        i_wor = i_wor + 1
    return all_ind_wor
def build_geo_positions_store(number_store_arg):
    return [(get_r(), get_r()) for i in range(number_store_arg)]
def get_store_index(indexes, prob_preference_store):
    return [
        index[0] if get_r() < prob_preference_store else index[1]
        for index in indexes
    ]