def waitForConstruction(session, city_id): """ Parameters ---------- session : ikabot.web.session.Session city_id : int Returns ------- city : dict """ while True: html = session.get(city_url + city_id) city = getCity(html) construction_buildings = [building for building in city['position'] if 'completed' in building] if len(construction_buildings) == 0: break construction_building = construction_buildings[0] construction_time = construction_building['completed'] current_time = int(time.time()) final_time = int(construction_time) seconds_to_wait = final_time - current_time msg = _('{}: I wait {:d} seconds so that {} gets to the level {:d}').format(city['cityName'], seconds_to_wait, construction_building['name'], construction_building['level'] + 1) sendToBotDebug(session, msg, debugON_constructionList) wait(seconds_to_wait + 10) html = session.get(city_url + city_id) city = getCity(html) return city
def expandBuilding(session, cityId, building, waitForResources): """ Parameters ---------- session : ikabot.web.session.Session cityId : int building : dict waitForResources : bool """ current_level = building['level'] if building['isBusy']: current_level += 1 levels_to_upgrade = building['upgradeTo'] - current_level position = building['position'] time.sleep(random.randint(5, 15)) # to avoid race conditions with sendResourcesNeeded for lv in range(levels_to_upgrade): city = waitForConstruction(session, cityId) building = city['position'][position] if building['canUpgrade'] is False and waitForResources is True: while building['canUpgrade'] is False: time.sleep(60) seconds = getMinimumWaitingTime(session) html = session.get(city_url + cityId) city = getCity(html) building = city['position'][position] # if no ships are comming, exit no matter if the building can or can't upgrade if seconds == 0: break wait(seconds + 5) if building['canUpgrade'] is False: msg = _('City:{}\n').format(city['cityName']) msg += _('Building:{}\n').format(building['name']) msg += _('The building could not be completed due to lack of resources.\n') msg += _('Missed {:d} levels').format(levels_to_upgrade - lv) sendToBot(session, msg) return url = 'action=CityScreen&function=upgradeBuilding&actionRequest={}&cityId={}&position={:d}&level={}&activeTab=tabSendTransporter&backgroundView=city¤tCityId={}&templateView={}&ajax=1'.format(actionRequest, cityId, position, building['level'], cityId, building['building']) resp = session.post(url) html = session.get(city_url + cityId) city = getCity(html) building = city['position'][position] if building['isBusy'] is False: msg = _('{}: The building {} was not extended').format(city['cityName'], building['name']) sendToBot(session, msg) sendToBot(session, resp) return msg = _('{}: The building {} is being extended to level {:d}.').format(city['cityName'], building['name'], building['level']+1) sendToBotDebug(session, msg, debugON_constructionList) msg = _('{}: The building {} finished extending to level: {:d}.').format(city['cityName'], building['name'], building['level']+1) sendToBotDebug(session, msg, debugON_constructionList)
def do_it(s, cities_ids, cities_dict): for cityId in cities_ids: html = s.get(urlCiudad + cityId) city = getCity(html) cities_dict[cityId]['island'] = city['islandId'] while True: for cityId in cities_ids: donation_type = cities_dict[cityId]['donation_type'] if donation_type is None: continue # get the storageCapacity and the wood this city has html = s.get(urlCiudad + cityId) city = getCity(html) wood = city['recursos'][0] storageCapacity = city['storageCapacity'] # get the percentage percentage = cities_dict[cityId]['percentage'] percentage /= 100 # calculate what is the amount of wood that should be preserved max_wood = storageCapacity * percentage max_wood = int(max_wood) # calculate the wood that is exceeding the percentage to_donate = wood - max_wood if to_donate <= 0: continue islandId = cities_dict[cityId]['island'] # donate s.post( payloadPost={ 'islandId': islandId, 'type': donation_type, 'action': 'IslandScreen', 'function': 'donate', 'donation': to_donate, 'backgroundView': 'island', 'templateView': donation_type, 'actionRequest': 'REQUESTID', 'ajax': '1' }) msg = _('I donated automatically.') sendToBotDebug(s, msg, debugON_donationBot) # sleep a day wait(24 * 60 * 60, maxrandom=60 * 60)
def executeRoutes(session, routes): """This function will execute all the routes passed to it, regardless if there are enough ships available to do so Parameters ---------- session : ikabot.web.session.Session Session object routes : list a list of tuples, each of which represent a route. A route is defined like so : (originCity,destinationCity,islandId,wood,wine,marble,crystal,sulfur). originCity and destintionCity should be passed as City objects """ for route in routes: (origin_city, destination_city, island_id, *toSend) = route destination_city_id = destination_city['id'] while sum(toSend) > 0: ships_available = waitForArrival(session) storageCapacityInShips = ships_available * 500 html = session.get(city_url + str(origin_city['id'])) origin_city = getCity(html) html = session.get(city_url + str(destination_city_id)) destination_city = getCity(html) foreign = str(destination_city['id']) != str(destination_city_id) if foreign is False: storageCapacityInCity = destination_city[ 'freeSpaceForResources'] send = [] for i in range(len(toSend)): if foreign is False: min_val = min(origin_city['recursos'][i], toSend[i], storageCapacityInShips, storageCapacityInCity[i]) else: min_val = min(origin_city['recursos'][i], toSend[i], storageCapacityInShips) send.append(min_val) storageCapacityInShips -= send[i] toSend[i] -= send[i] resources_to_send = sum(send) if resources_to_send == 0: # no space available # wait an hour and try again wait(60 * 60) continue available_ships = int( math.ceil((Decimal(resources_to_send) / Decimal(500)))) sendGoods(session, origin_city['id'], destination_city_id, island_id, available_ships, send)
def __logout(self, html): if html is not None: idCiudad = getCity(html)['id'] token = re.search(r'actionRequest"?:\s*"(.*?)"', html).group(1) urlLogout = 'action=logoutAvatar&function=logout&sideBarExt=undefined&startPageShown=1&detectedDevice=1&cityId={0}&backgroundView=city¤tCityId={0}&actionRequest={1}'.format( idCiudad, token) self.s.get(self.urlBase + urlLogout)
def sendResourcesNeeded(s, idDestiny, origins, missingArr): #set_child_mode(s) info = _('\nTransport resources to upload building\n') try: routes = [] html = s.get(urlCiudad + idDestiny) cityD = getCity(html) for i in range(len(materials_names)): missing = missingArr[i] if missing <= 0: continue # send the resources from each origin city for cityO in origins[i]: if missing == 0: break available = cityO['recursos'][i] send = min(available, missing) missing -= send toSend = [0] * len(materials_names) toSend[i] = send route = (cityO, cityD, cityD['islandId'], *toSend) routes.append(route) executeRoutes(s, routes) except: msg = _('Error in:\n{}\nCause:\n{}').format(info, traceback.format_exc()) sendToBot(s, msg)
def study(session, studies, num_study): html = session.get() city = getCity(html) city_id = city['id'] research_type = studies['js_researchAdvisorChangeResearchType{}'.format(num_study)]['ajaxrequest'].split('=')[-1] url = 'action=Advisor&function=doResearch&actionRequest={}&type={}&backgroundView=city¤tCityId={}&templateView=researchAdvisor&ajax=1'.format(actionRequest, research_type, city_id) session.post(url)
def get_studies(session): html = session.get() city = getCity(html) city_id = city['id'] url = 'view=researchAdvisor&oldView=updateGlobalData&cityId={0}&backgroundView=city¤tCityId={0}&templateView=researchAdvisor&actionRequest={1}&ajax=1'.format(city_id, actionRequest) resp = session.post(url) resp = json.loads(resp, strict=False) return resp[2][1]
def do_it(s, hours): ids, cities = getIdsOfCities(s) while True: # getIdsOfCities is called on a loop because the amount of cities may change ids, cities_new = getIdsOfCities(s) if len(cities_new) != len(cities): cities = cities_new for cityId in cities: if 'reported' not in cities[cityId]: cities[cityId]['reported'] = False for cityId in cities: html = s.get(urlCiudad + cityId) city = getCity(html) # if the city doesn't even have a tavern built, ignore it if 'tavern' not in [ building['building'] for building in city['position'] ]: continue consumption_per_hour = city['consumo'] # is a wine city if cities[cityId]['tradegood'] == '1': wine_production = getProduccionPerSecond(s, cityId)[1] wine_production = wine_production * 60 * 60 if consumption_per_hour > wine_production: consumption_per_hour -= wine_production else: continue consumption_per_seg = Decimal(consumption_per_hour) / Decimal(3600) wine_available = city['recursos'][1] if consumption_per_seg == 0: if cities[cityId]['reported'] is False: msg = _('The city {} is not consuming wine!').format( city['name']) sendToBot(s, msg) cities[cityId]['reported'] = True continue seconds_left = Decimal(wine_available) / Decimal( consumption_per_seg) if seconds_left < hours * 60 * 60: if cities[cityId]['reported'] is False: time_left = daysHoursMinutes(seconds_left) msg = _('In {}, the wine will run out in {}').format( time_left, city['name']) sendToBot(s, msg) cities[cityId]['reported'] = True else: cities[cityId]['reported'] = False time.sleep(20 * 60)
def activateVacationMode(session): """ Parameters ---------- session : ikabot.web.session.Session """ html = session.get() city = getCity(html) data = {'action': 'Options', 'function': 'activateVacationMode', 'actionRequest': actionRequest, 'backgroundView': 'city', 'currentCityId': city['id'], 'templateView': 'options_umod_confirm'} session.post(params=data, ignoreExpire=True)
def getBuildingToExpand(session, cityId): """ Parameters ---------- session : ikabot.web.session.Session cityId : int Returns ------- building : dict """ html = session.get(city_url + cityId) city = getCity(html) banner() # show the buildings available to expand (ignore empty spaces) print(_('Which building do you want to expand?\n')) print(_('(0)\t\texit')) buildings = [ building for building in city['position'] if building['name'] != 'empty' ] for i in range(len(buildings)): building = buildings[i] level = building['level'] if level < 10: level = ' ' + str(level) else: level = str(level) if building['isBusy']: level = level + '+' print(_('({:d})\tlv:{}\t{}').format(i + 1, level, building['name'])) selected_building_id = read(min=0, max=len(buildings)) if selected_building_id == 0: return None building = buildings[selected_building_id - 1] current_level = int(building['level']) # if the building is being expanded, add 1 level if building['isBusy']: current_level += 1 banner() print(_('building:{}').format(building['name'])) print(_('current level:{}').format(current_level)) final_level = read(min=current_level, msg=_('increase to level:')) building['upgradeTo'] = final_level return building
def waitForConstruction(s, cityId, position): slp = 1 while slp > 0: html = s.get(urlCiudad + cityId) slp = getConstructionTime(s, html, position) wait(slp + 5) html = s.get(urlCiudad + cityId) city = getCity(html) building = city['position'][position] msg = _('{}: The building {} reached the level {:d}.').format( city['cityName'], building['name'], building['level']) sendToBotDebug(s, msg, debugON_constructionList) return city
def activateVacationMode(s): html = s.get() city = getCity(html) data = { 'action': 'Options', 'function': 'activateVacationMode', 'actionRequest': 'REQUESTID', 'backgroundView': 'city', 'currentCityId': city['id'], 'templateView': 'options_umod_confirm' } s.post(params=data, ignoreExpire=True)
def getCommertialCities(s): ids = getIdsOfCities(s)[0] ciudades_comerciales = [] for idCiudad in ids: html = s.get(urlCiudad + idCiudad) ciudad = getCity(html) for pos, edificio in enumerate(ciudad['position']): if edificio['building'] == 'branchOffice': ciudad['pos'] = pos html = getStoreHtml(s, ciudad) rangos = re.findall(r'<option.*?>(\d+)</option>', html) ciudad['rango'] = int(rangos[-1]) ciudades_comerciales.append(ciudad) break return ciudades_comerciales
def getBuildingToExpand(s, cityId): html = s.get(urlCiudad + cityId) city = getCity(html) banner() # show the buildings available to expand (ignore empty spaces) print(_('Which building do you want to expand?\n')) print(_('(0)\t\texit')) buildings = [ building for building in city['position'] if building['name'] != 'empty' ] for i in range(len(buildings)): building = buildings[i] level = building['level'] if level < 10: level = ' ' + str(level) else: level = str(level) if building['isBusy']: level = level + '+' print(_('({:d})\tlv:{}\t{}').format(i + 1, level, building['name'])) choise = read(min=0, max=len(buildings)) if choise == 0: return None building = buildings[choise - 1] current_level = int(building['level']) # if the building is being expanded, add 1 level if building['isBusy']: current_level += 1 banner() print(_('building:{}').format(building['name'])) print(_('current level:{}').format(current_level)) final_level = read(min=current_level, msg=_('increase to level:')) building['upgradeTo'] = final_level return building
def sendResourcesNeeded(session, destination_city_id, city_origins, missing_resources): """ Parameters ---------- session : ikabot.web.session.Session destination_city_id : int city_origins : dict missing_resources : dict[int, int] """ info = _('\nTransport resources to upload building\n') try: routes = [] html = session.get(city_url + destination_city_id) cityD = getCity(html) for i in range(len(materials_names)): missing = missing_resources[i] if missing <= 0: continue # send the resources from each origin city for cityOrigin in city_origins[i]: if missing == 0: break available = cityOrigin['recursos'][i] send = min(available, missing) missing -= send toSend = [0] * len(materials_names) toSend[i] = send route = (cityOrigin, cityD, cityD['islandId'], *toSend) routes.append(route) executeRoutes(session, routes) except Exception as e: msg = _('Error in:\n{}\nCause:\n{}').format(info, traceback.format_exc()) sendToBot(session, msg)
def getConstructionTime(s, html, position): city = getCity(html) building = city['position'][position] final_time = re.search(r'"endUpgradeTime":(\d{10})', html) if final_time is None: msg = _('{}: I don\'t wait anything so that {} gets to the level {:d}' ).format(city['cityName'], building['name'], building['level']) sendToBotDebug(s, msg, debugON_constructionList) return 0 current_time = int(time.time()) final_time = int(final_time.group(1)) seconds_to_wait = final_time - current_time if seconds_to_wait <= 0: seconds_to_wait = 0 msg = _( '{}: I wait {:d} seconds so that {} gets to the level {:d}').format( city['cityName'], seconds_to_wait, building['name'], building['level'] + 1) sendToBotDebug(s, msg, debugON_constructionList) return seconds_to_wait
def executeRoutes(s, routes): """This function will execute all the routes passed to it, regardless if there are enough ships available to do so Parameters ---------- s : Session Session object routes : list a list of tuples, each of which represent a route. A route is defined like so : (originCity,destinationCity,islandId,wood,wine,marble,crystal,sulfur). originCity and destintionCity should be passed as City objects """ for ruta in routes: (ciudadOrigen, ciudadDestino, idIsla, *toSend) = ruta destId = ciudadDestino['id'] while sum(toSend) > 0: barcosDisp = waitForArrival(s) storageCapacityInShips = barcosDisp * 500 html = s.get(urlCiudad + destId) ciudadDestino = getCity(html) storageCapacityInCity = ciudadDestino['freeSpaceForResources'] send = [] for i in range(len(toSend)): min_val = min(toSend[i], storageCapacityInShips, storageCapacityInCity[i]) send.append(min_val) storageCapacityInShips -= send[i] toSend[i] -= send[i] cantEnviada = sum(send) if cantEnviada == 0: # no space available # wait an hour and try again wait(60 * 60) continue barcos = int(math.ceil((Decimal(cantEnviada) / Decimal(500)))) sendGoods(s, ciudadOrigen['id'], ciudadDestino['id'], idIsla, barcos, send)
def sendGoods(s, originCityId, destinationCityId, islandId, ships, send): """This function will execute one route Parameters ---------- s : Session Session object originCityId : int integer representing the ID of the origin city destinationCityId : int integer representing the ID of the destination city islandId : int integer representing the ID of the destination city's island ships : int integer representing the amount of ships needed to execute the route send : array array of resources to send """ # this can fail if a random request is made in between this two posts while True: html = s.get() city = getCity(html) currId = city['id'] data = {'action': 'header', 'function': 'changeCurrentCity', 'actionRequest': 'REQUESTID', 'oldView': 'city', 'cityId': originCityId, 'backgroundView': 'city', 'currentCityId': currId, 'ajax': '1'} s.post(payloadPost=data) data = {'action': 'transportOperations', 'function': 'loadTransportersWithFreight', 'destinationCityId': destinationCityId, 'islandId': islandId, 'oldView': '', 'position': '', 'avatar2Name': '', 'city2Name': '', 'type': '', 'activeTab': '', 'transportDisplayPrice': '0', 'premiumTransporter': '0', 'minusPlusValue': '500', 'capacity': '5', 'max_capacity': '5', 'jetPropulsion': '0', 'transporters': ships, 'backgroundView': 'city', 'currentCityId': originCityId, 'templateView': 'transport', 'currentTab': 'tabSendTransporter', 'actionRequest': 'REQUESTID', 'ajax': '1'} # add amounts of resources to send for i in range(len(send)): key = 'cargo_resource' if i == 0 else 'cargo_tradegood{:d}'.format(i) data[key] = send[i] resp = s.post(payloadPost=data) resp = json.loads(resp, strict=False) if resp[3][1][0]['type'] == 10: break
def getCommercialCities(session): """ Parameters ---------- session : ikabot.web.session.Session Returns ------- commercial_cities : list[dict] """ cities_ids = getIdsOfCities(session)[0] commercial_cities = [] for city_id in cities_ids: html = session.get(city_url + city_id) city = getCity(html) for pos, building in enumerate(city['position']): if building['building'] == 'branchOffice': city['pos'] = pos html = getMarketHtml(session, city) positions = re.findall(r'<option.*?>(\d+)</option>', html) city['rango'] = int(positions[-1]) commercial_cities.append(city) break return commercial_cities
def do_it(session, hours): """ Parameters ---------- session : ikabot.web.session.Session hours : int """ was_alerted = {} while True: # getIdsOfCities is called on a loop because the amount of cities may change ids, cities = getIdsOfCities(session) for cityId in cities: if cityId not in was_alerted: was_alerted[cityId] = False for cityId in cities: html = session.get(city_url + cityId) city = getCity(html) # if the city doesn't even have a tavern built, ignore it if 'tavern' not in [ building['building'] for building in city['position'] ]: continue consumption_per_hour = city['consumo'] # is a wine city if cities[cityId]['tradegood'] == '1': wine_production = getProductionPerSecond(session, cityId)[1] wine_production = wine_production * 60 * 60 if consumption_per_hour > wine_production: consumption_per_hour -= wine_production else: was_alerted[cityId] = False continue consumption_per_seg = Decimal(consumption_per_hour) / Decimal(3600) wine_available = city['recursos'][1] if consumption_per_seg == 0: if was_alerted[cityId] is False: msg = _('The city {} is not consuming wine!').format( city['name']) sendToBot(session, msg) was_alerted[cityId] = True continue seconds_left = Decimal(wine_available) / Decimal( consumption_per_seg) if seconds_left < hours * 60 * 60: if was_alerted[cityId] is False: time_left = daysHoursMinutes(seconds_left) msg = _('In {}, the wine will run out in {}').format( time_left, city['name']) sendToBot(session, msg) was_alerted[cityId] = True else: was_alerted[cityId] = False time.sleep(20 * 60)
def chooseResourceProviders(session, cities_ids, cities, city_id, resource, missing): """ Parameters ---------- session : ikabot.web.session.Session cities_ids : list[int] cities : dict[int, dict] city_id : int resource : int missing : int """ global sendResources sendResources = True global expand expand = True banner() print( _('From what cities obtain {}?').format( materials_names[resource].lower())) tradegood_initials = [ material_name[0] for material_name in materials_names ] maxName = max([ len(cities[city]['name']) for city in cities if cities[city]['id'] != city_id ]) origin_cities = [] total_available = 0 for cityId in cities_ids: if cityId == city_id: continue html = session.get(city_url + cityId) city = getCity(html) available = city['recursos'][resource] if available == 0: continue # ask the user it this city should provide resources tradegood_initial = tradegood_initials[int( cities[cityId]['tradegood'])] pad = ' ' * (maxName - len(cities[cityId]['name'])) msg = '{}{} ({}): {} [Y/n]:'.format(pad, cities[cityId]['name'], tradegood_initial, addThousandSeparator(available)) choice = read(msg=msg, values=['Y', 'y', 'N', 'n', '']) if choice.lower() == 'n': continue # if so, save the city and calculate the total amount resources to send total_available += available origin_cities.append(city) # if we have enough resources, return if total_available >= missing: return origin_cities # if we reach this part, there are not enough resources to expand the building print(_('\nThere are not enough resources.')) if len(origin_cities) > 0: print(_('\nSend the resources anyway? [Y/n]')) choice = read(values=['y', 'Y', 'n', 'N', '']) if choice.lower() == 'n': sendResources = False print(_('\nTry to expand the building anyway? [y/N]')) choice = read(values=['y', 'Y', 'n', 'N', '']) if choice.lower() == 'n' or choice == '': expand = False return origin_cities
def distribute_unevenly(session, resource_type): """ Parameters ---------- session : ikabot.web.session.Session resource_type : int """ total_available_resources_from_all_cities = 0 (cities_ids, cities) = getIdsOfCities(session) origin_cities = {} destination_cities = {} for destination_city_id in cities_ids: is_city_mining_this_resource = cities[destination_city_id][ 'tradegood'] == str(resource_type) if is_city_mining_this_resource: html = session.get(city_url + destination_city_id) city = getCity(html) if resource_type == 1: # wine city['available_amount_of_resource'] = city['recursos'][ resource_type] - city['consumo'] - 1 else: city['available_amount_of_resource'] = city['recursos'][ resource_type] if city['available_amount_of_resource'] < 0: city['available_amount_of_resource'] = 0 total_available_resources_from_all_cities += city[ 'available_amount_of_resource'] origin_cities[destination_city_id] = city else: html = session.get(city_url + destination_city_id) city = getCity(html) city['free_storage_for_resource'] = city['freeSpaceForResources'][ resource_type] if city['free_storage_for_resource'] > 0: destination_cities[destination_city_id] = city if total_available_resources_from_all_cities <= 0: print(_('\nThere are no resources to send.')) enter() return None if len(destination_cities) == 0: print(_('\nThere is no space available to send resources.')) enter() return None remaining_resources_to_be_sent_to_each_city = total_available_resources_from_all_cities // len( destination_cities) free_storage_available_per_city = [ destination_cities[city]['free_storage_for_resource'] for city in destination_cities ] total_free_storage_available_in_all_cities = sum( free_storage_available_per_city) remaining_resources_to_send = min( total_available_resources_from_all_cities, total_free_storage_available_in_all_cities) toSend = {} while remaining_resources_to_send > 0: len_prev = len(toSend) for city_id in destination_cities: city = destination_cities[city_id] if city_id not in toSend and city[ 'free_storage_for_resource'] < remaining_resources_to_be_sent_to_each_city: toSend[city_id] = city['free_storage_for_resource'] remaining_resources_to_send -= city[ 'free_storage_for_resource'] if len(toSend) == len_prev: for city_id in destination_cities: if city_id not in toSend: toSend[ city_id] = remaining_resources_to_be_sent_to_each_city break free_storage_available_per_city = [ destination_cities[city]['free_storage_for_resource'] for city in destination_cities if city not in toSend ] if len(free_storage_available_per_city) == 0: break total_free_storage_available_in_all_cities = sum( free_storage_available_per_city) remaining_resources_to_send = min( remaining_resources_to_send, total_free_storage_available_in_all_cities) remaining_resources_to_be_sent_to_each_city = remaining_resources_to_send // len( free_storage_available_per_city) routes = [] for destination_city_id in destination_cities: destination_city = destination_cities[destination_city_id] island_id = destination_city['islandId'] missing_resources = toSend[destination_city_id] for origin_city_id in origin_cities: if missing_resources == 0: break origin_city = origin_cities[origin_city_id] resources_available_in_this_city = origin_city[ 'available_amount_of_resource'] for route in routes: origin = route[0] resource = route[resource_type + 3] if origin['id'] == origin_city_id: resources_available_in_this_city -= resource send_this_round = min(missing_resources, resources_available_in_this_city) available = destination_city['free_storage_for_resource'] if available == 0 or send_this_round == 0: continue if available < send_this_round: missing_resources = 0 send_this_round = available else: missing_resources -= send_this_round toSendArr = [0] * len(materials_names) toSendArr[resource_type] = send_this_round route = (origin_city, destination_city, island_id, *toSendArr) routes.append(route) return routes
def distribute_evenly(session, resource_type): """ Parameters ---------- session : ikabot.web.session.Session resource_type : int """ resourceTotal = 0 (cityIDs, cities) = getIdsOfCities(session) originCities = {} destinationCities = {} allCities = {} for cityID in cityIDs: html = session.get( city_url + cityID) #load html from the get request for that particular city city = getCity(html) #convert the html to a city object resourceTotal += city['recursos'][ resource_type] #the cities resources are added to the total allCities[cityID] = city #adds the city to all cities # if a city doesn't have enough storage to fit resourceAverage # ikabot will send enough resources to fill the store to the max # then, resourceAverage will be recalculated resourceAverage = resourceTotal // len(allCities) while True: len_prev = len(destinationCities) for cityID in allCities: if cityID in destinationCities: continue freeStorage = allCities[cityID]['freeSpaceForResources'][ resource_type] storage = allCities[cityID]['storageCapacity'] if storage < resourceAverage: destinationCities[cityID] = freeStorage resourceTotal -= storage resourceAverage = resourceTotal // (len(allCities) - len(destinationCities)) if len_prev == len(destinationCities): for cityID in allCities: if cityID in destinationCities: continue if allCities[cityID]['recursos'][ resource_type] > resourceAverage: originCities[cityID] = allCities[cityID]['recursos'][ resource_type] - resourceAverage else: destinationCities[cityID] = resourceAverage - allCities[ cityID]['recursos'][resource_type] break originCities = { k: v for k, v in sorted( originCities.items(), key=lambda item: item[1], reverse=True) } #sort origin cities in descending order destinationCities = { k: v for k, v in sorted(destinationCities.items(), key=lambda item: item[1]) } #sort destination cities in ascending order routes = [] for originCityID in originCities: #iterate through all origin city ids for destinationCityID in destinationCities: #iterate through all destination city ids if originCities[originCityID] == 0 or destinationCities[ destinationCityID] == 0: continue if originCities[originCityID] > destinationCities[ destinationCityID]: #if there's more resources above average in the origin city than resources below average in the destination city (origin city needs to have a surplus and destination city needs to have a deficit of resources for a route to be considered) toSend = destinationCities[ destinationCityID] #number of resources to send is the number of resources below average in destination city else: toSend = originCities[ originCityID] #send the amount of resources above average of the current origin city if toSend == 0: continue toSendArr = [0] * len(materials_names) toSendArr[resource_type] = toSend route = (allCities[originCityID], allCities[destinationCityID], allCities[destinationCityID]['islandId'], *toSendArr) routes.append(route) # ROUTE BLOCK if originCities[originCityID] > destinationCities[ destinationCityID]: originCities[originCityID] -= destinationCities[ destinationCityID] #remove the sent amount from the origin city's surplus destinationCities[ destinationCityID] = 0 #set the amount of resources below average in destination city to 0 else: destinationCities[destinationCityID] -= originCities[ originCityID] #remove the sent amount from the amount of resources below average in current destination city originCities[ originCityID] = 0 #set the amount of resources above average in origin city to 0 return routes
def do_it(session, cities_ids, cities_dict, waiting_time, max_random_waiting_time): """ Parameters ---------- session : ikabot.web.session.Session cities_ids : list[int] cities_dict : dict[int, dict] waiting_time: int max_random_waiting_time: int """ for cityId in cities_ids: html = session.get(city_url + cityId) city = getCity(html) cities_dict[cityId]['island'] = city['islandId'] while True: for cityId in cities_ids: donation_type = cities_dict[cityId]['donation_type'] if donation_type is None: continue # get the storageCapacity and the wood this city has html = session.get(city_url + cityId) city = getCity(html) wood = city['recursos'][0] storageCapacity = city['storageCapacity'] # get the percentage percentage = cities_dict[cityId]['percentage'] percentage /= 100 # calculate what is the amount of wood that should be preserved max_wood = storageCapacity * percentage max_wood = int(max_wood) # calculate the wood that is exceeding the percentage to_donate = wood - max_wood if to_donate <= 0: continue islandId = cities_dict[cityId]['island'] # donate session.post( payloadPost={ 'islandId': islandId, 'type': donation_type, 'action': 'IslandScreen', 'function': 'donate', 'donation': to_donate, 'backgroundView': 'island', 'templateView': donation_type, 'actionRequest': actionRequest, 'ajax': '1' }) msg = _('I donated automatically.') sendToBotDebug(session, msg, debugON_donationBot) # sleep a day wait(waiting_time * 60, maxrandom=max_random_waiting_time * 60)
def distribute_unevenly(s, recurso): recursoTotal = 0 (idsCiudades, ciudades) = getIdsOfCities(s) ciudadesOrigen = {} ciudadesDestino = {} for idCiudad in idsCiudades: esTarget = ciudades[idCiudad]['tradegood'] == str(recurso) if esTarget: html = s.get(urlCiudad + idCiudad) ciudad = getCity(html) if recurso == 1: ciudad['disponible'] = ciudad['recursos'][recurso] - ciudad[ 'consumo'] - 1 else: ciudad['disponible'] = ciudad['recursos'][recurso] if ciudad['disponible'] < 0: ciudad['disponible'] = 0 recursoTotal += ciudad['disponible'] ciudadesOrigen[idCiudad] = ciudad else: html = s.get(urlCiudad + idCiudad) ciudad = getCity(html) ciudad['disponible'] = ciudad['freeSpaceForResources'][recurso] if ciudad['disponible'] > 0: ciudadesDestino[idCiudad] = ciudad if recursoTotal <= 0: print(_('\nThere are no resources to send.')) enter() return None if len(ciudadesDestino) == 0: print(_('\nThere is no space available to send resources.')) enter() return None recursoXciudad = recursoTotal // len(ciudadesDestino) espacios_disponibles = [ ciudadesDestino[city]['disponible'] for city in ciudadesDestino ] totalEspacioDisponible = sum(espacios_disponibles) restanteAEnviar = min(recursoTotal, totalEspacioDisponible) toSend = {} while restanteAEnviar > 0: len_prev = len(toSend) for city in ciudadesDestino: ciudad = ciudadesDestino[city] if city not in toSend and ciudad['disponible'] < recursoXciudad: toSend[city] = ciudad['disponible'] restanteAEnviar -= ciudad['disponible'] if len(toSend) == len_prev: for city in ciudadesDestino: if city not in toSend: toSend[city] = recursoXciudad break espacios_disponibles = [ ciudadesDestino[city]['disponible'] for city in ciudadesDestino if city not in toSend ] totalEspacioDisponible = sum(espacios_disponibles) restanteAEnviar = min(restanteAEnviar, totalEspacioDisponible) recursoXciudad = restanteAEnviar // len(espacios_disponibles) rutas = [] for idCiudad in ciudadesDestino: ciudadD = ciudadesDestino[idCiudad] idIsla = ciudadD['islandId'] faltante = toSend[idCiudad] for idCiudadOrigen in ciudadesOrigen: if faltante == 0: break ciudadO = ciudadesOrigen[idCiudadOrigen] recursoDisponible = ciudadO['disponible'] for ruta in rutas: origen = ruta[0] rec = ruta[recurso + 3] if origen['id'] == idCiudadOrigen: recursoDisponible -= rec enviar = min(faltante, recursoDisponible) disponible = ciudadD['disponible'] if disponible == 0 or enviar == 0: continue if disponible < enviar: faltante = 0 enviar = disponible else: faltante -= enviar toSendArr = [0] * len(materials_names) toSendArr[recurso] = enviar ruta = (ciudadO, ciudadD, idIsla, *toSendArr) rutas.append(ruta) return rutas
def obtainMiraclesAvailable(session): """ Parameters ---------- session : ikabot.web.session.Session Returns ------- islands: list[dict] """ idsIslands = getIslandsIds(session) islands = [] for idIsland in idsIslands: html = session.get(island_url + idIsland) island = getIsland(html) island['activable'] = False islands.append(island) ids, cities = getIdsOfCities(session) for city_id in cities: city = cities[city_id] # get the wonder for this city wonder = [ island['wonder'] for island in islands if city['coords'] == '[{}:{}] '.format(island['x'], island['y']) ][0] # if the wonder is not new, continue if wonder in [ island['wonder'] for island in islands if island['activable'] ]: continue html = session.get(city_url + str(city['id'])) city = getCity(html) # make sure that the city has a temple for i in range(len(city['position'])): if city['position'][i]['building'] == 'temple': city['pos'] = str(i) break else: continue # get wonder information params = { "view": "temple", "cityId": city['id'], "position": city['pos'], "backgroundView": "city", "currentCityId": city['id'], "actionRequest": actionRequest, "ajax": "1" } data = session.post(params=params) data = json.loads(data, strict=False) data = data[2][1] available = data['js_WonderViewButton']['buttonState'] == 'enabled' if available is False: for elem in data: if 'countdown' in data[elem]: enddate = data[elem]['countdown']['enddate'] currentdate = data[elem]['countdown']['currentdate'] break # set the information on the island which wonder we can activate for island in islands: if island['id'] == city['islandId']: island['activable'] = True island['ciudad'] = city island['available'] = available if available is False: island['available_in'] = enddate - currentdate break # only return island which wonder we can activate return [island for island in islands if island['activable']]
def planTrainings(session, city, trainings, trainTroops): """ Parameters ---------- session : ikabot.web.session.Session city : dict trainings : list[list[dict]] trainTroops : bool """ buildingPos = city['pos'] # trainings might be divided in multriple rounds while True: # total number of units to create total = sum([unit['cantidad'] for training in trainings for unit in training]) if total == 0: return for training in trainings: waitForTraining(session, city, trainTroops) html = session.get(city_url + city['id']) city = getCity(html) city['pos'] = buildingPos resourcesAvailable = city['recursos'].copy() resourcesAvailable.append(city['ciudadanosDisp']) # for each unit type in training for unit in training: # calculate how many units can actually be trained based on the resources available unit['train'] = unit['cantidad'] for i in range(len(materials_names_english)): material_name = materials_names_english[i].lower() if material_name in unit['costs']: limiting = resourcesAvailable[i] // unit['costs'][material_name] unit['train'] = min(unit['train'], limiting) if 'citizens' in unit['costs']: limiting = resourcesAvailable[len(materials_names_english)] // unit['costs']['citizens'] unit['train'] = min(unit['train'], limiting) # calculate the resources that will be left for i in range(len(materials_names_english)): material_name = materials_names_english[i].lower() if material_name in unit['costs']: resourcesAvailable[i] -= unit['costs'][material_name] * unit['train'] if 'citizens' in unit['costs']: resourcesAvailable[len(materials_names_english)] -= unit['costs']['citizens'] * unit['train'] unit['cantidad'] -= unit['train'] # amount of units that will be trained total = sum([unit['train'] for unit in training]) if total == 0: msg = _('It was not possible to finish the training due to lack of resources.') sendToBot(session, msg) return train(session, city, training, trainTroops)