Example #1
0
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
Example #2
0
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&currentCityId={}&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)
Example #3
0
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)
Example #4
0
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)
Example #5
0
 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&currentCityId={0}&actionRequest={1}'.format(
             idCiudad, token)
         self.s.get(self.urlBase + urlLogout)
Example #6
0
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)
Example #7
0
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&currentCityId={}&templateView=researchAdvisor&ajax=1'.format(actionRequest, research_type, city_id)
	session.post(url)
Example #8
0
def get_studies(session):
	html = session.get()
	city = getCity(html)
	city_id = city['id']
	url = 'view=researchAdvisor&oldView=updateGlobalData&cityId={0}&backgroundView=city&currentCityId={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]
Example #9
0
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)
Example #10
0
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)
Example #11
0
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
Example #12
0
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
Example #13
0
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)
Example #14
0
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
Example #15
0
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
Example #16
0
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)
Example #17
0
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
Example #18
0
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)
Example #19
0
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
Example #20
0
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
Example #21
0
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)
Example #22
0
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
Example #23
0
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
Example #24
0
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
Example #25
0
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)
Example #26
0
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
Example #27
0
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']]
Example #28
0
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)