def prepopulate_task(task):
    if task["_action"] == 'countPlaced':
        item = lookup_item_by_code(task["_item"])
        if 'stateMachineValues' in item:
            state_machine = lookup_state_machine(item['stateMachineValues']['-stateMachineName'],
                                                 item['stateMachineValues'].get('define', []))
        else:
            state_machine = None
        objects = lookup_objects_by_item_name(item['-name'])
        built_objects = [e for e in objects if
                 int(e.get('state', 0)) >= (int(state_machine['-builtState']) if state_machine else 0)]
        number_built = len(built_objects)
        return min(number_built, int(task["_total"])), number_built >= int(task["_total"])
    if task["_action"] == 'countPlacements':
        item = lookup_item_by_code(task.get("_item", task.get('_code')))
        objects = lookup_objects_by_item_name(item['-name'])
        number_placed = len(objects)
        return min(number_placed, int(task["_total"])), number_placed >= int(task["_total"])
    elif task["_action"] == 'inventoryCount':
        item_inventory = session['user_object']["userInfo"]["player"]["inventory"]["items"]
        return min(item_inventory.get(task["_item"], 0), int(task["_total"])), item_inventory.get(task["_item"], 0) >= int(task["_total"])
    elif task["_action"] == 'population':
        return min(session['population'], int(task["_total"])), session['population'] >= int(task["_total"])
    elif task["_action"] == 'neighborsAdded':
        neighbor_count = len([ally for ally in allies.values() if ally.get("friend") and ally.get("neighbor")])
        return min(neighbor_count, int(task["_total"])), neighbor_count >= int(task["_total"])
    elif task["_action"] == 'countUpgrades':
        research = session['user_object']["userInfo"]["world"]["research"]
        total = 0
        unit = task["unit"]
        for k, v in research.items():
            if "_item" in unit:
                if k == unit["_item"]:
                    total += len(v)
            elif "_unitClass" in unit:
                item = lookup_item_by_code(k)
                if item["-unitClass"] == unit["_unitClass"]:
                    total += len(v)
            elif "_subtype" in unit:
                item = lookup_item_by_code(k)
                if item["-subtype"] == unit["_subtype"]:
                    total += len(v)

        return min(total, int(task["_total"])), total >= int(task["_total"])
    elif task["_action"] == 'autoComplete':
        return 1, True
    else:
        return 0, False
def click_next_state(do_click, id, meta, step, reference_item, speed_up=False, tending=False, save=None, playback_tend=False, tend_type=None, cancel=True):
    cur_object = lookup_object(id) if not tending else lookup_object_save(save, id)
    print("cur_object used:", repr(cur_object))
    tend = tending or playback_tend

    game_item = lookup_item_by_name(cur_object['itemName'])
    print("item used:", repr(game_item))

    timestamp = datetime.now().timestamp()
    if 'stateMachineValues' in game_item:
        state_machine = lookup_state_machine(game_item['stateMachineValues']['-stateMachineName'],
                                             game_item['stateMachineValues'].get('define', []),
                                             (lookup_reference_item(cur_object) or {}).get('referenceValues',{}).get('define'))

        print("state_machine used:", repr(state_machine))
        state = lookup_state(state_machine, cur_object.get('state', 0), cur_object, True)
        print("cur state:", repr(state))

        while '-autoNext' in state and state['-stateName'] != state['-autoNext']:   # '-clientDuration': '2.0s', '-duration': '0' respect duration for harvest?
            duration =  parse_duration(state.get('-duration', '0'))
            if cur_object.get('lastUpdated', 0) / 1000 +  duration <= timestamp or speed_up or tend:
                if cur_object.get('lastUpdated', 0) / 1000 + duration > timestamp:
                    speed_up = False  # consumes speed up
                    tend = False
                    print("speed up used")
                next_state_id = state['-autoNext']  # not all states have this!! end states? autostate after time?
                previous_state = state
                state = lookup_state(state_machine, next_state_id, cur_object, True)
                check_state(state_machine, state, cur_object, tending)
                if not tending:
                    do_state_rewards(state, cur_object.get('referenceItem'), meta, playback_tend=playback_tend)
                if 'lastUpdated' not in cur_object:
                    cur_object['lastUpdated'] = 0  #init?
                cur_object['lastUpdated'] += duration * 1000
                cur_object['state'] = next_state_id
                print("pre auto_next_state:", repr(state), 'time', cur_object['lastUpdated'], "duration", duration)
                if not tending:
                    handle_world_state_change(meta, state, state_machine, game_item, step, previous_state, cur_object.get('referenceItem'), cur_object.get('referenceItem'))
            else:
                print("state has autoNext, but not enough time was passed")
                break

        if (do_click or tend):
            try:
               next_state_id = state['-clickNext'] if not cancel else state['-cancelNext']
            except:
                next_state_id = state['-clickNext']
            if reference_item != cur_object.get('referenceItem'):
                state_machine = lookup_state_machine(game_item['stateMachineValues']['-stateMachineName'],
                                                     game_item['stateMachineValues'].get('define', []),
                                                     (lookup_item_by_code(reference_item.split(":")[0]) if reference_item else {})
                                                     .get('referenceValues', {}).get('define'))
            next_click_state = lookup_state(state_machine, next_state_id, cur_object, True)
            check_state(state_machine, next_click_state, cur_object, tending)
            print("next_click_state:", repr(next_click_state))
            if cancel:
                print("canceled state")
            if not tending:
                do_state_rewards(next_click_state, cur_object.get('referenceItem'), meta, playback_tend=playback_tend)
                handle_world_state_change(meta, next_click_state, state_machine, game_item, step, state, reference_item, cur_object.get('referenceItem'))
            else:
                if tend_type == "mine":
                    standard_resources = ["coins", "oil", "wood", "aluminum", "copper", "gold", "iron", "uranium"]
                    tend_type += standard_resources[save['user_object']["userInfo"]["player"]["playerResourceType"]]
                elif tend_type == "harvest":
                    tend_type += "_" + game_item['stateMachineValues']['-referenceType'] if '-referenceType' in game_item['stateMachineValues'] else ""
                    tend_type += "_" + game_item['stateMachineValues']['-referenceSubtype'] if '-referenceSubtype' in game_item['stateMachineValues'] else ""
                elif tend_type == "clear":
                    tend_type += game_item['-subtype']
                #TODO Crew tax

                reward = lookup_visitor_reward(tend_type)
                do_state_rewards(reward, cur_object.get('referenceItem'), meta)

            while '-autoNext' in next_click_state and next_state_id != next_click_state['-autoNext'] and next_click_state.get('-duration', '0') in ['0', '0s']:   #'-clientDuration': '2.0s', '-duration': '0' respect duration for harvest?
                next_state_id = next_click_state['-autoNext']
                previous_state = next_click_state
                next_click_state = lookup_state(state_machine, next_state_id, cur_object, True)
                check_state(state_machine, next_click_state, cur_object, tending)
                print("auto_next_state:", repr(next_click_state))
                if not tending:
                    do_state_rewards(next_click_state, reference_item, meta, playback_tend=playback_tend)
                    handle_world_state_change(meta, next_click_state, state_machine, game_item, step, previous_state, reference_item, reference_item)

            cur_object['state'] = next_state_id
            cur_object['lastUpdated'] = timestamp * 1000
        else:
            print("state has no clicknext, click does nothing" if do_click else "not clicking, only autonexts")
            cur_object['lastUpdated'] = timestamp * 1000
    else:
        print("object has no statemachine, click does nothing")
        cur_object['lastUpdated'] = timestamp * 1000
        if not tending:
            handle_world_state_change(meta, {}, None, game_item, step, {}, reference_item, reference_item)