def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_items = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "marketGroups") sde_bp_materials = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "blueprints") sde_icon_ids = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "iconIDs") # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published')==False]: del sde_bp_materials[t] # настройка Eve Online ESI Swagger interface eve_market_prices_data = None total_assets_data = [] total_blueprints_data = [] total_industry_jobs_data = [] total_ass_names_data = [] for pilot_name in argv_prms["character_names"]: auth = esi.EveESIAuth( '{}/auth_cache'.format(argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format(argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) if not character_data: continue # Public information about a corporation corporation_data = interface.get_esi_data( "corporations/{}/".format(character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() if eve_market_prices_data is None: try: # Public information about market prices eve_market_prices_data = interface.get_esi_data("markets/prices/") print("\nEVE market has {} prices".format(len(eve_market_prices_data) if not (eve_market_prices_data is None) else 0)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") eve_market_prices_data = [] else: raise except: print(sys.exc_info()) raise # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data) if corp_assets_data else "no")) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) print("\n'{}' corporation has {} blueprints".format(corporation_name, len(corp_blueprints_data) if corp_blueprints_data else "no")) sys.stdout.flush() # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("\n'{}' corporation has {} industry jobs".format(corporation_name, len(corp_industry_jobs_data) if corp_industry_jobs_data else "no")) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids(corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format(corporation_name, len(corp_ass_names_data) if corp_ass_names_data else "no")) sys.stdout.flush() del corp_ass_named_ids if corp_assets_data: total_assets_data.extend(corp_assets_data) if corp_blueprints_data: total_blueprints_data.extend(corp_blueprints_data) if corp_industry_jobs_data: total_industry_jobs_data.extend(corp_industry_jobs_data) if corp_ass_names_data: total_ass_names_data.extend(corp_ass_names_data) # находим контейнеры по заданным названиям for ro in q_capital_settings.g_report_options: if "container_templates" in ro: for tmplt in ro["container_templates"]: containers = [n["item_id"] for n in total_ass_names_data if re.search(tmplt, n['name'])] for id in containers: ro["blueprints"].append( {"id": id, "name": next((n["name"] for n in total_ass_names_data if n['item_id'] == id), None)}) ro["stock"].append( {"id": id, "name": next((n["name"] for n in total_ass_names_data if n['item_id'] == id), None)}) # перечисляем станции и контейнеры, которые были найдены print('\nFound report containters and station ids for {}...'.format(ro["product"])) for bpl in ro["blueprints"]: print(' {} = {} (blueprints)'.format(bpl["id"], bpl["name"])) for stk in ro["stock"]: print(' {} = {} (stock)'.format(stk["id"], stk.get("name", stk.get("flag")))) print("\nBuilding report...") sys.stdout.flush() render_html_capital.dump_capital_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # настройки генерации отчёта ro, # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_bp_materials, sde_market_groups, sde_icon_ids, # esi данные, загруженные с серверов CCP total_assets_data, total_industry_jobs_data, total_blueprints_data, eve_market_prices_data) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") sde_inv_items = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invItems") sde_inv_positions = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invPositions") logist_data = [] for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format( corporation_name, len(corp_assets_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids( corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print( "\n'{}' corporation has offices in {} forbidden stations : {}". format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # Построение дерева ассетов, с узлами в роли станций и систем, и листьями в роли хранящихся # элементов, в виде: # { location1: {items:[item1,item2,...],type_id,location_id}, # location2: {items:[item3],type_id} } corp_assets_tree = eve_esi_tools.get_assets_tree( corp_assets_data, foreign_structures_data, sde_inv_items) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_assets_tree.{}".format(corporation_name), corp_assets_tree) logist_data.append({ "corporation_ticker": corporation_data["ticker"], "corp_assets_tree": corp_assets_tree, "corp_assets_data": corp_assets_data, }) del corp_assets_tree del corp_assets_data del foreign_structures_data # Фильтрация (вручную) ассетов, которые расположены на станках циносети corp_cynonetwork = {} for cn in q_logist_settings.g_cynonetworks: cn_route = cn["route"] jump_num = 1 for location_id in cn_route: # если системы в цино сети повторяются, не гоняем искалочку зазря (повторно) if not (str(location_id) in corp_cynonetwork): datas = [] found_tickers = [] for corp_logist in logist_data: data = get_cyno_solar_system_details( location_id, corp_logist["corp_assets_tree"]) if data is None: continue datas.append(data) datas[-1].update({ "corporation_ticker": corp_logist["corporation_ticker"] }) found_tickers.append(corp_logist["corporation_ticker"]) # --- # signalling_level = 0 - normal, 1 - warning, 2 - danger, 3 - ошибка получения данных # оптимальный набор: 10 баджеров, 10 цин, 10'000 (по 950 на прожиг) озона # плюс: 10 вентур, 10 цин, 10'000 (по 200 на прожиг) озона, 30 риг, 10 каргохолда # минимальный набор: 1 баджер, 1 вентурка, 2 цины, 1150 озона, 3 риги, 1 каргохолд if not datas: # print('{} {}'.format(location_id, data)) system_id = None loc_name = "NO-DATA!" loc_id = location_id if int(loc_id) < 1000000000000: if str(loc_id) in sde_inv_names: loc_name = sde_inv_names[str(loc_id)] # print(loc_name) if str(loc_id) in sde_inv_items: root_item = sde_inv_items[str(loc_id)] # print("root_item", root_item) if root_item["typeID"] == 5: # Solar System system_id = loc_id # print(" >>> >>> ", loc_name) else: # not Solar System (may be Station?) loc_id = root_item["locationID"] root_item = sde_inv_items[str(loc_id)] # print(" >>> ", loc_id, root_item) if root_item[ "typeID"] == 5: # Solar System system_id = loc_id loc_name = sde_inv_names[str( loc_id)] # Solar System (name) # print(" >>> >>> ", loc_name) data = { "error": "no data" if system_id is None else "no solar system", "system_id": system_id, "solar_system": loc_name, "signalling_level": 3, # -- используется, если 'error'='no solar system' "badger": 0, "venture": 0, "liquid_ozone": 0, "indus_cyno_gen": 0, "exp_cargohold": 0, "cargohold_rigs": 0, "nitrogen_isotope": 0, "hydrogen_isotope": 0, "oxygen_isotope": 0, "helium_isotope": 0 } else: system_id = None badger_num = 0 venture_num = 0 liquid_ozone_num = 0 indus_cyno_gen_num = 0 exp_cargohold_num = 0 cargohold_rigs_num = 0 nitrogen_isotope_num = 0 hydrogen_isotope_num = 0 oxygen_isotope_num = 0 helium_isotope_num = 0 # --- for data in datas: corporation_ticker = data["corporation_ticker"] if system_id is None: system_id = data["solar_system"] badger_ids = data["badger"] venture_ids = data["venture"] liquid_ozone_ids = data["liquid_ozone"] indus_cyno_gen_ids = data["indus_cyno_gen"] exp_cargohold_ids = data["exp_cargohold"] cargohold_rigs_ids = data["cargohold_rigs"] nitrogen_isotope_ids = data["nitrogen_isotope"] hydrogen_isotope_ids = data["hydrogen_isotope"] oxygen_isotope_ids = data["oxygen_isotope"] helium_isotope_ids = data["helium_isotope"] # --- corp_assets_data = [] for corp_logist in logist_data: if corporation_ticker == corp_logist[ "corporation_ticker"]: corp_assets_data = corp_logist[ "corp_assets_data"] break # --- for a in corp_assets_data: item_id = int(a["item_id"]) quantity = int(a["quantity"]) if not (badger_ids is None) and badger_ids.count(item_id) > 0: badger_num = badger_num + quantity elif not (venture_ids is None) and venture_ids.count(item_id) > 0: venture_num = venture_num + quantity elif not ( liquid_ozone_ids is None ) and liquid_ozone_ids.count(item_id) > 0: liquid_ozone_num = liquid_ozone_num + quantity elif not ( indus_cyno_gen_ids is None ) and indus_cyno_gen_ids.count(item_id) > 0: indus_cyno_gen_num = indus_cyno_gen_num + quantity elif not ( exp_cargohold_ids is None ) and exp_cargohold_ids.count(item_id) > 0: exp_cargohold_num = exp_cargohold_num + quantity elif not ( cargohold_rigs_ids is None ) and cargohold_rigs_ids.count(item_id) > 0: cargohold_rigs_num = cargohold_rigs_num + quantity elif not ( nitrogen_isotope_ids is None ) and nitrogen_isotope_ids.count(item_id) > 0: nitrogen_isotope_num = nitrogen_isotope_num + quantity elif not ( hydrogen_isotope_ids is None ) and hydrogen_isotope_ids.count(item_id) > 0: hydrogen_isotope_num = hydrogen_isotope_num + quantity elif not ( oxygen_isotope_ids is None ) and oxygen_isotope_ids.count(item_id) > 0: oxygen_isotope_num = oxygen_isotope_num + quantity elif not ( helium_isotope_ids is None ) and helium_isotope_ids.count(item_id) > 0: helium_isotope_num = helium_isotope_num + quantity # --- del corp_assets_data if system_id is None: system_name = "NO-DATA!" signalling_level = 3 else: system_name = sde_inv_names[str(system_id)] if (badger_num >= 10) and\ (venture_num >= 10) and\ (liquid_ozone_num >= 20000) and\ (indus_cyno_gen_num >= 20) and\ (exp_cargohold_num >= 10) and\ (cargohold_rigs_num >= 30): signalling_level = 0 elif (badger_num >= 1) and \ (venture_num >= 1) and \ (liquid_ozone_num >= 1150) and \ (indus_cyno_gen_num >= 2) and \ (exp_cargohold_num >= 1) and \ (cargohold_rigs_num >= 3): signalling_level = 1 else: signalling_level = 2 # --- data = { "found_tickers": found_tickers, "system_id": system_id, "solar_system": system_name, "badger": badger_num, "venture": venture_num, "liquid_ozone": liquid_ozone_num, "indus_cyno_gen": indus_cyno_gen_num, "exp_cargohold": exp_cargohold_num, "cargohold_rigs": cargohold_rigs_num, "nitrogen_isotope": nitrogen_isotope_num, "hydrogen_isotope": hydrogen_isotope_num, "oxygen_isotope": oxygen_isotope_num, "helium_isotope": helium_isotope_num, "signalling_level": signalling_level, } if system_id is None: data.update({"error": "no solar system"}) corp_cynonetwork.update({str(location_id): data}) del datas jump_num = jump_num + 1 eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_cynonetwork", corp_cynonetwork) del logist_data del sde_inv_items del sde_inv_names print("\nBuilding cyno network report...") sys.stdout.flush() render_html_logist.dump_cynonetwork_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_inv_positions, # данные, полученные в результате анализа и перекомпоновки входных списков corp_cynonetwork) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") sde_inv_items = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") sde_bp_materials = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "blueprints") # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [ t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published') == False ]: del sde_bp_materials[t] # индексация списка модулей и ресурсов, которые ИСПОЛЬЗУЮТСЯ в производстве materials_for_bps = set( eve_sde_tools.get_materials_for_blueprints(sde_bp_materials)) research_materials_for_bps = set( eve_sde_tools.get_research_materials_for_blueprints(sde_bp_materials)) # индексация списка продуктов, которые ПОЯВЛЯЮТСЯ в результате производства products_for_bps = set( eve_sde_tools.get_products_for_blueprints(sde_bp_materials, activity="manufacturing")) reaction_products_for_bps = set( eve_sde_tools.get_products_for_blueprints(sde_bp_materials, activity="reaction")) # подготовка списка контейнеров (их содержимого, которое будет исключено из плана производства) products_to_exclude: typing.List[typing.Tuple[typing.Tuple[str, str], typing.List[int]]] = [] for manuf_dict in [ m for m in q_conveyor_settings.g_manufacturing if 'market_storage_to_exclude' in m ]: for ms2e in manuf_dict['market_storage_to_exclude']: products_to_exclude.append((ms2e, [])) conveyor_data = [] for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format( corporation_name, len(corp_assets_data))) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) corp_blueprints_data_len = len(corp_blueprints_data) print("\n'{}' corporation has {} blueprints".format( corporation_name, corp_blueprints_data_len)) sys.stdout.flush() # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("\n'{}' corporation has {} industry jobs".format( corporation_name, len(corp_industry_jobs_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids( corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Построение иерархических списков БПО и БПЦ, хранящихся в корпоративных ангарах corp_bp_loc_data = eve_esi_tools.get_corp_bp_loc_data( corp_blueprints_data, corp_industry_jobs_data) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_bp_loc_data.{}".format(corporation_name), corp_bp_loc_data) del corp_blueprints_data # Построение списка модулей и ресуров, которые имеются в распоряжении корпорации и # которые предназначены для использования в чертежах corp_ass_loc_data = eve_esi_tools.get_corp_ass_loc_data( corp_assets_data, containers_filter=None) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_ass_loc_data.{}".format(corporation_name), corp_ass_loc_data) # Выявление предметов, которые хранятся в контейнерах корпорации, и которые следует исключить из # плана производства for p2e in [ p for p in products_to_exclude if p[0][0] == corporation_name ]: market_overstock_loc_ids = [ n["item_id"] for n in corp_ass_names_data if re.search(p2e[0][1], n['name']) ] for ass_loc in corp_ass_loc_data.values(): for loc_id in market_overstock_loc_ids: items: typing.Dict[str, int] = ass_loc.get(str(loc_id)) if items: p2e[1].extend([int(itm) for itm in items.keys()]) # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print( "\n'{}' corporation has offices in {} forbidden stations : {}". format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # Построение дерева ассетов, с узлави в роли станций и систем, и листьями в роли хранящихся # элементов, в виде: # { location1: {items:[item1,item2,...],type_id,location_id}, # location2: {items:[item3],type_id} } corp_assets_tree = eve_esi_tools.get_assets_tree( corp_assets_data, foreign_structures_data, sde_inv_items, virtual_hierarchy_by_corpsag=False) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_assets_tree.{}".format(corporation_name), corp_assets_tree) # Поиск контейнеров, которые участвуют в производстве corp_conveyour_entities = [] for (__manuf_dict_num, __manuf_dict) in enumerate(q_conveyor_settings.g_manufacturing): # находим контейнеры по заданным названиям blueprint_loc_ids = [] for tmplt in __manuf_dict["conveyor_container_names"]: blueprint_loc_ids.extend([ n["item_id"] for n in corp_ass_names_data if re.search(tmplt, n['name']) ]) # строим список названий контейнеров, содержимое которых исключается из плана производства (copy as is) market_storage_to_exclude: typing.List[typing.Tuple[ str, str]] = __manuf_dict.get('market_storage_to_exclude') # кешируем признак того, что контейнеры являются стоком материалов same_stock_container = __manuf_dict.get("same_stock_container", False) fixed_number_of_runs = __manuf_dict.get("fixed_number_of_runs", None) manufacturing_activities = __manuf_dict.get( "manufacturing_activities", ["manufacturing"]) # находим станцию, где расположены найденные контейнеры for id in blueprint_loc_ids: __loc_dict = eve_esi_tools.get_universe_location_by_item( id, sde_inv_names, sde_inv_items, corp_assets_tree, corp_ass_names_data, foreign_structures_data) if not ("station_id" in __loc_dict): continue __station_id = __loc_dict["station_id"] __conveyor_entity = next( (id for id in corp_conveyour_entities if (id["station_id"] == __station_id) and ( id["num"] == __manuf_dict_num)), None) if __conveyor_entity is None: __conveyor_entity = __loc_dict __conveyor_entity.update({ "containers": [], "stock": [], "react_stock": [], "exclude": [], "num": __manuf_dict_num, 'market_storage_to_exclude': market_storage_to_exclude, # впоследствии будет найден и заменён }) corp_conveyour_entities.append(__conveyor_entity) # на этой же станции находим контейнер со стоком материалов if same_stock_container: __conveyor_entity["stock"].append({ "id": id, "name": next((n["name"] for n in corp_ass_names_data if n['item_id'] == id), None) }) else: for tmplt in __manuf_dict["stock_container_names"]: __stock_ids = [ n["item_id"] for n in corp_ass_names_data if re.search(tmplt, n['name']) ] for __stock_id in __stock_ids: __stock_loc_dict = eve_esi_tools.get_universe_location_by_item( __stock_id, sde_inv_names, sde_inv_items, corp_assets_tree, corp_ass_names_data, foreign_structures_data) if ("station_id" in __stock_loc_dict) and ( __station_id == __stock_loc_dict["station_id"]): __conveyor_entity["stock"].append({ "id": __stock_id, "name": next((n["name"] for n in corp_ass_names_data if n['item_id'] == __stock_id), None) }) # на этой же станции находим контейнеры, из которых нельзя доставать чертежи для производства материалов for tmplt in __manuf_dict["exclude_container_names"]: __exclude_ids = [ n["item_id"] for n in corp_ass_names_data if re.search(tmplt, n['name']) ] for __exclude_id in __exclude_ids: __stock_loc_dict = eve_esi_tools.get_universe_location_by_item( __exclude_id, sde_inv_names, sde_inv_items, corp_assets_tree, corp_ass_names_data, foreign_structures_data) if ("station_id" in __stock_loc_dict) and ( __station_id == __stock_loc_dict["station_id"]): __conveyor_entity["exclude"].append({ "id": __exclude_id, "name": next((n["name"] for n in corp_ass_names_data if n['item_id'] == __exclude_id), None) }) # на любой другой станции находим контейнер, в котором находится сток для нужд конвейера, но пока # ещё на нужную станцию (например с Татары на Сотию) for tmplt in __manuf_dict.get("reaction_stock_containers", []): rs_ids = [(n["item_id"], n['name']) for n in corp_ass_names_data if re.search(tmplt, n['name'])] for (rs_id, rs_name) in rs_ids: rs_loc_dict = eve_esi_tools.get_universe_location_by_item( rs_id, sde_inv_names, sde_inv_items, corp_assets_tree, corp_ass_names_data, foreign_structures_data) if "station_id" in rs_loc_dict: __conveyor_entity["react_stock"].append({ "id": rs_id, "name": rs_name, "loc": rs_loc_dict }) del rs_ids # добавляем к текущей станции контейнер с чертежами # добаляем в свойства контейнера фиксированное кол-во запусков чертежей из настроек __conveyor_entity["containers"].append({ "id": id, "name": next((n["name"] for n in corp_ass_names_data if n['item_id'] == id), None), "fixed_number_of_runs": fixed_number_of_runs, "manufacturing_activities": manufacturing_activities, }) conveyor_data.append({ "corporation_id": corporation_id, "corporation_name": corporation_name, "corp_conveyour_entities": corp_conveyour_entities, # esi данные, загруженные с серверов CCP "corp_industry_jobs_data": corp_industry_jobs_data, "corp_assets_data": corp_assets_data, "corp_bp_quantity": corp_blueprints_data_len, # данные, полученные в результате анализа и перекомпоновки входных списков "corp_ass_loc_data": corp_ass_loc_data, "corp_bp_loc_data": corp_bp_loc_data, "corp_assets_tree": corp_assets_tree, }) del corp_conveyour_entities del corp_industry_jobs_data del corp_ass_names_data del corp_ass_loc_data del corp_bp_loc_data del corp_assets_tree # постобработка списка конвейеров (из списка удаляются корпорации без коробок контейнеров), поскольку не все # корпорации подключаемые к конвейеру спользуют его (например, торговая корпа в Jita имеет лишь # ящик с market оверстоком) conveyor_data = [c for c in conveyor_data if c['corp_conveyour_entities']] # после того, как информация по всем корпорациям была загружена, перекомпонуем список с названиями контейнеров # в новый список с идентификаторами продуктов, расчёты по которым следует пропустить for cc in conveyor_data: for c in [ c for c in cc['corp_conveyour_entities'] if 'market_storage_to_exclude' in c ]: if isinstance(c['market_storage_to_exclude'], list): p2e: typing.List[int] = [] for ms2e in c['market_storage_to_exclude']: for p in [ p[1] for p in products_to_exclude if p[0] == ms2e ]: p2e.extend(p) c.update({'products_to_exclude': p2e}) del c['market_storage_to_exclude'] del products_to_exclude # перечисляем станции и контейнеры, которые были найдены print('\nFound conveyor containters and station ids...') for cd in conveyor_data: print(' corporation = {}'.format(cd["corporation_name"])) for ce in cd["corp_conveyour_entities"]: print(' {} = {}'.format(ce["station_id"], ce["station"])) print(' containers with blueprints:') for cec in ce["containers"]: print(' {} = {}'.format(cec["id"], cec["name"])) print(' stock containers:') for ces in ce["stock"]: print(' {} = {}'.format(ces["id"], ces["name"])) if ce["react_stock"]: print(' reaction stock containers:') for cess in ce["react_stock"]: print(' {} = {}'.format(cess["loc"]["station_id"], cess["loc"]["station"])) print(' {} = {}'.format(cess["id"], cess["name"])) if ce["containers"]: print(' exclude containers:') for cee in ce["exclude"]: print(' {} = {}'.format(cee["id"], cee["name"])) if ce.get('products_to_exclude'): print(' market overstock:') for type_id in ce['products_to_exclude']: print(' {} = {}'.format( type_id, eve_sde_tools.get_item_name_by_type_id( sde_type_ids, type_id))) sys.stdout.flush() print("\nBuilding report...") sys.stdout.flush() del sde_inv_names del sde_inv_items render_html_conveyor.dump_conveyor_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_bp_materials, sde_market_groups, materials_for_bps, research_materials_for_bps, products_for_bps, reaction_products_for_bps, # настройки генерации отчёта # esi данные, загруженные с серверов CCP # данные, полученные в результате анализа и перекомпоновки входных списков conveyor_data) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nConveyor v{} done".format(__version__))
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "invNames") sde_inv_items = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "marketGroups") sde_icon_ids = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "iconIDs") sde_bp_materials = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "blueprints") # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published')==False]: del sde_bp_materials[t] """ === Сведения по рассчёту цены === Данные из .yaml: 36: basePrice: 32.0 groupID: 18 iconID: 401 marketGroupID: 1857 name: en: Mexallon portionSize: 1 published: true volume: 0.01 --- Данные из https://esi.evetech.net/ui/#/Market/get_markets_prices : { "adjusted_price": 44.1, "average_price": 92.64, "type_id": 36 } --- Ситуация на рынке https://image.prntscr.com/image/0Oqy5FlqRniAstG2wvSd7A.png : Sell: 85 ISK Buy: 88.64 ISK ---- Текущая стоимость, которую показывает Евка https://image.prntscr.com/image/-8liCZ8TRHWIaSpZ6Kzhew.png : 92.6 ISK --- Полезная информация https://www.reddit.com/r/Eve/comments/5zegqw/how_does_ccp_calculate_averageadjusted_price/ : adjusted_price - средняя за 28 дней """ corps_accounting = {} eve_market_prices_data = None various_characters_data = {} for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth( '{}/auth_cache'.format(argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format(argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data( "corporations/{}/".format(character_data["corporation_id"]), fully_trust_cache=True) # The token’s character need to be a member of the corporation # corporation_members_data = interface.get_esi_data( # "corporations/{}/members/".format(character_data["corporation_id"]), # fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() if eve_market_prices_data is None: try: # Public information about market prices eve_market_prices_data = interface.get_esi_data("markets/prices/") print("\nEVE market has {} prices".format(len(eve_market_prices_data) if not (eve_market_prices_data is None) else 0)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") eve_market_prices_data = [] else: raise except: print(sys.exc_info()) raise try: # Requires role(s): Accountant, Junior_Accountant corp_wallets_data = interface.get_esi_paged_data( "corporations/{}/wallets/".format(corporation_id)) print("'{}' corporation has {} wallet divisions\n".format(corporation_name, len(corp_wallets_data))) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_wallets_data = [] else: raise except: print(sys.exc_info()) raise # Requires role(s): Accountant, Junior_Accountant corp_wallet_journal_data = [None, None, None, None, None, None, None] for w in corp_wallets_data: division = w["division"] try: corp_wallet_journal_data[division-1] = interface.get_esi_paged_data( "corporations/{}/wallets/{}/journal/".format(corporation_id, division)) print("'{}' corporation has {} wallet#{} transactions\n".format(corporation_name, len(corp_wallet_journal_data[division-1]), division)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.11.26 поломался доступ к журналу кошелька (ССР-шники "внесли правки") corp_wallet_journal_data[division-1] = None elif status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_wallets_data = [] else: raise except: print(sys.exc_info()) raise # Requires one of the following EVE corporation role(s): Director corp_divisions_data = interface.get_esi_data( "corporations/{}/divisions/".format(corporation_id), fully_trust_cache=True) print("'{}' corporation has {} hangar and {} wallet names\n".format(corporation_name, len(corp_divisions_data["hangar"]) if "hangar" in corp_divisions_data else 0, len(corp_divisions_data["wallet"]) if "wallet" in corp_divisions_data else 0)) sys.stdout.flush() # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids(corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format(corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # TODO: Получение идентификаторов коробок, в которых хранятся персональные ассеты (хардкодим тут) pers_ass_location_ids: typing.List[int] = [int(an['item_id']) for an in corp_ass_names_data if re.search(r"^{pers}.+$", an['name']) or re.search(r"^\.{pers}.+$", an['name'])] # для того, чтобы сильно не переделывать алгоритм - просто удаляем из корпассетов личные предметы pers_ass_location_ids: typing.Set[int] = set(pers_ass_location_ids) corp_assets_data = [a for a in corp_assets_data if int(a['location_id']) not in pers_ass_location_ids] del pers_ass_location_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids(corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update({str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format(corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print("\n'{}' corporation has offices in {} forbidden stations : {}".format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # Requires role(s): access token corp_contracts_data = interface.get_esi_paged_data( "corporations/{}/contracts/".format(corporation_id)) print("'{}' corporation has {} contracts\n".format(corporation_name, len(corp_contracts_data))) sys.stdout.flush() # Получение подробной информации о каждому из контракту в списке corp_contract_items_data = [] corp_contract_items_len = 0 corp_contract_items_not_found = [] corp_contract_individual = [] if len(corp_contracts_data) > 0: # Requires: access token for c in corp_contracts_data: # для удалённых контрактов нельзя загрузить items (см. ниже 404-ошибку), поэтому пропускаем запись if c["status"] == "deleted": continue # в рамках отчёта accounting, нас интересует только набор контрактов, в которых продаются Ships # ищем любые контракты типа "обмен предметами" if c["type"] != "item_exchange": continue # в рамках отчёта accounting нас интересуют только активные контракты if (c["status"] != "outstanding") and (c["status"] != "in_progress"): continue # пропускаем контракты на продажу, которые выставили не мы # эту настройку лучше не трогать, т.к. во FRT например 12'000 контрактов, следовательно # это повлечёт загрузку 12'000 items и 12'000 issuers if c['issuer_corporation_id'] != corporation_id: continue contract_id = c["contract_id"] # пропускаем контракты на продажу, которые выставлены не от имени корпорации, и доход от продажи # которых упадёт в кошелёк пилота, а не корпорации if not c['for_corporation']: corp_contract_individual.append(contract_id) continue try: __contract_items = interface.get_esi_data( "corporations/{}/contracts/{}/items/".format(corporation_id, contract_id), fully_trust_cache=True) corp_contract_items_len += len(__contract_items) corp_contract_items_data.append({str(contract_id): __contract_items}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # это нормально, что часть доп.инфы по контрактам может быть не найдена! corp_contract_items_not_found.append(contract_id) else: # print(sys.exc_info()) raise except: print(sys.exc_info()) raise # Получение сведений о пилотах, вовлечённых в работу с контрактом issuer_id = c["issuer_id"] if str(issuer_id) not in various_characters_data: # пилот м.б. быть в списке с dict=None try: # Public information about a character issuer_data = interface.get_esi_data( "characters/{}/".format(issuer_id), fully_trust_cache=True) various_characters_data.update({str(issuer_id): issuer_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 404 Client Error: Not Found ('Character has been deleted!') various_characters_data.update({str(issuer_id): None}) else: print(sys.exc_info()) raise except: print(sys.exc_info()) raise sys.stdout.flush() eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_contract_items_data.{}".format(corporation_name), corp_contract_items_data) print("'{}' corporation has {} items in contracts\n".format(corporation_name, corp_contract_items_len)) if len(corp_contract_items_not_found) > 0: print("'{}' corporation has {} contracts without details : {}\n".format(corporation_name, len(corp_contract_items_not_found), corp_contract_items_not_found)) if corp_contract_individual: print("'{}' corporation has {} individual contracts : {}\n".format(corporation_name, len(corp_contract_individual), corp_contract_individual)) sys.stdout.flush() # Построение дерева ассетов, с узлами в роли станций и систем, и листьями в роли хранящихся # элементов, в виде: # { location1: {items:[item1,item2,...],type_id,location_id}, # location2: {items:[item3],type_id} } corp_assets_tree = eve_esi_tools.get_assets_tree(corp_assets_data, foreign_structures_data, sde_inv_items, virtual_hierarchy_by_corpsag=False) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_assets_tree.{}".format(corporation_name), corp_assets_tree) # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("'{}' corporation has {} industry jobs\n".format(corporation_name, len(corp_industry_jobs_data))) sys.stdout.flush() # Построение дерева имущества (сводная информация, учитывающая объёмы и ориентировочную стоимость asset-ов) print("\nBuilding {} accounting tree and stat...".format(corporation_name)) sys.stdout.flush() corp_accounting_stat, corp_accounting_tree = __build_accounting( sde_type_ids, sde_inv_names, sde_inv_items, sde_market_groups, eve_market_prices_data, corp_ass_names_data, foreign_structures_data, foreign_structures_forbidden_ids, corp_assets_tree, corp_assets_data) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_accounting_stat.{}".format(corporation_name), corp_accounting_stat) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_accounting_tree.{}".format(corporation_name), corp_accounting_tree) corp_wallet_stat = __build_wallets_stat(corp_wallet_journal_data) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_wallet_stat.{}".format(corporation_name), corp_wallet_stat) corp_sell_contracts = __build_contracts_stat( sde_type_ids, sde_market_groups, corp_contracts_data, corp_contract_items_data, various_characters_data) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_sell_contracts.{}".format(corporation_name), corp_sell_contracts) corp_industry_jobs_stat = __build_industry_jobs_stat( sde_type_ids, sde_bp_materials, eve_market_prices_data, corp_industry_jobs_data) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_industry_jobs_stat.{}".format(corporation_name), corp_industry_jobs_stat) corps_accounting.update({str(corporation_id): { "corporation": corporation_name, "divisions": corp_divisions_data, "wallet": corp_wallets_data, "wallet_stat": corp_wallet_stat, "stat": corp_accounting_stat, "tree": corp_accounting_tree, "sell_contracts": corp_sell_contracts, "jobs_stat": corp_industry_jobs_stat }}) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corps_accounting", corps_accounting) # Построение дерева asset-ов: print("\nBuilding accounting report...") sys.stdout.flush() render_html_accounting.dump_accounting_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_icon_ids, # данные, полученные в результате анализа и перекомпоновки входных списков corps_accounting) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") # sde_inv_items = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") sde_icon_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "iconIDs") sde_bp_materials = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "blueprints") # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [ t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published') == False ]: del sde_bp_materials[t] # построение списка продуктов, которые появляются в результате производства products_for_bps = set( eve_sde_tools.get_products_for_blueprints(sde_bp_materials)) materials_for_bps = eve_sde_tools.get_materials_for_blueprints( sde_bp_materials) research_materials_for_bps = eve_sde_tools.get_research_materials_for_blueprints( sde_bp_materials) materials_for_bps.extend(research_materials_for_bps) materials_for_bps = set(materials_for_bps) del research_materials_for_bps pilot_name = argv_prms["character_names"][0] # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) # corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() market_regions = [ (int(id), sde_inv_names[id], {}) for id in sde_inv_names if sde_inv_names[id] in q_market_analyzer_settings.g_regions ] for (region_id, region_name, region_details) in market_regions: # Requires: public access markets_region_orders = interface.get_esi_paged_data( "markets/{}/orders/".format(region_id)) sys.stdout.flush() region_details.update({ "orders": { "buy": 0, "sell": 0, }, }) region_systems = {} region_trade_hubs = {} region_market = {} for o in markets_region_orders: type_id: int = o["type_id"] # проверяем к какой группе товаров относится данный type_id, если это чертежи, книжки, шкурки - пропускаем market_chain = eve_sde_tools.get_market_groups_chain_by_type_id( sde_type_ids, sde_market_groups, type_id) if market_chain: if market_chain[0] in [ 2, # пропускаем Blueprints 1659, # пропускаем Special Edition Assets 1396, # пропускаем Apparel 1954, # пропускаем Ship SKINs 150, # пропускаем Skills ]: continue semantic_market_group_id = market_chain[0] if len( market_chain) == 1 else market_chain[1] else: semantic_market_group_id = 0 # нам что 0, что None - без разницы, группы для него нет # проверяем, и пропускаем те товары, которые нельзся произвести if q_market_analyzer_settings.g_skip_non_manufacturing_products: if type_id not in products_for_bps and type_id not in materials_for_bps: continue system_id: str = o["system_id"] location_id: str = o["location_id"] system_dict = region_systems.get(system_id) if not system_dict: region_systems.update({ system_id: { "name": sde_inv_names.get(str(system_id)), "orders": { "buy": 0, "sell": 0 }, "market": {}, } }) system_dict = region_systems.get(system_id) trade_hub_dict = region_trade_hubs.get(location_id) if not trade_hub_dict: region_trade_hubs.update({ location_id: { "name": sde_inv_names.get(str(location_id)), "system": system_id, "orders": { "buy": 0, "sell": 0 }, "market": {}, } }) trade_hub_dict = region_trade_hubs.get(location_id) region_market_dict = region_market.get(semantic_market_group_id) if not region_market_dict: region_market.update({ semantic_market_group_id: { "orders": { "buy": 0, "sell": 0 }, } }) region_market_dict = region_market.get( semantic_market_group_id) system_market_dict = system_dict["market"].get( semantic_market_group_id) if not system_market_dict: system_dict["market"].update({ semantic_market_group_id: { "orders": { "buy": 0, "sell": 0 }, } }) system_market_dict = system_dict["market"].get( semantic_market_group_id) trade_hub_market_dict = trade_hub_dict["market"].get( semantic_market_group_id) if not trade_hub_market_dict: trade_hub_dict["market"].update({ semantic_market_group_id: { "orders": { "buy": 0, "sell": 0 }, } }) trade_hub_market_dict = trade_hub_dict["market"].get( semantic_market_group_id) """ debug if system_id == 30045352: print( "{:>6} {:<50} {:>4} {:>11} {:>11} {:>11} {:>6} {}". format( type_id, sde_type_ids.get(str(type_id), {"name":{"en":"?"}})["name"]["en"], "buy" if o["is_buy_order"] else "sell", o["range"], o["price"], o["volume_remain"], semantic_market_group_id if semantic_market_group_id else "?", sde_market_groups.get(str(semantic_market_group_id), {"nameID": {"en": "?"}})["nameID"]["en"] ), # o ) """ tag_order: str = "buy" if o["is_buy_order"] else "sell" region_details["orders"][tag_order] += 1 system_dict["orders"][tag_order] += 1 trade_hub_dict["orders"][tag_order] += 1 region_market_dict["orders"][tag_order] += 1 system_market_dict["orders"][tag_order] += 1 trade_hub_market_dict["orders"][tag_order] += 1 region_details.update({ "systems": region_systems, "trade_hubs": region_trade_hubs, "market": region_market, }) del region_market del region_trade_hubs del region_systems del markets_region_orders eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "market_regions", market_regions) render_html_market_analyzer.dump_market_analyzer_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_icon_ids, sde_market_groups, sde_inv_names, # данные, полученные в результате анализа и перекомпоновки входных списков market_regions) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(argv_prms["character_names"][0]) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") sde_inv_items = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids(corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print("\n'{}' corporation has offices in {} forbidden stations : {}". format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() try: # Public information about market prices eve_market_prices_data = interface.get_esi_data("markets/prices/") print("\nEVE market has {} prices".format( len(eve_market_prices_data) if not ( eve_market_prices_data is None) else 0)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") eve_market_prices_data = [] else: raise except: print(sys.exc_info()) raise # # Public information with list of public structures # universe_structures_data = eve_esi_interface.get_esi_data( # access_token, # "universe/structures/") # print("\nFound {} public structures in universe".format(len(universe_structures_data))) # sys.stdout.flush() # Построение дерева ассетов, с узлави в роли станций и систем, и листьями в роли хранящихся # элементов, в виде: # { location1: {items:[item1,item2,...],type_id,location_id}, # location2: {items:[item3],type_id} } corp_assets_tree = eve_esi_tools.get_assets_tree( corp_assets_data, foreign_structures_data, sde_inv_items, virtual_hierarchy_by_corpsag=True) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_assets_tree", corp_assets_tree) # Построение дерева asset-ов: print("\nBuilding assets tree report...") sys.stdout.flush() render_html_assets.dump_assets_tree_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_inv_names, sde_inv_items, sde_market_groups, # esi данные, загруженные с серверов CCP corp_assets_data, corp_ass_names_data, foreign_structures_data, eve_market_prices_data, # данные, полученные в результате анализа и перекомпоновки входных списков corp_assets_tree) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() various_characters_data = {} various_corporations_data = {} for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() try: # Requires role(s): Director corp_shareholders_data = interface.get_esi_paged_data( "corporations/{}/shareholders/".format(corporation_id)) print("'{}' corporation has {} shareholders\n".format( corporation_name, len(corp_shareholders_data))) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_shareholders_data = [] else: raise except: print(sys.exc_info()) raise various_characters_data.update({str(character_id): character_data}) various_corporations_data.update( {str(corporation_id): corporation_data}) for shareholder in corp_shareholders_data: # Получение сведений о пилотах, имеющих акции корпорации corp_id = None if shareholder['shareholder_type'] == 'character': pilot_id = shareholder['shareholder_id'] if str( pilot_id ) in various_characters_data: # пилот м.б. быть в списке с dict=None __pilot_dict = various_characters_data.get(str(pilot_id)) if __pilot_dict: corp_id = __pilot_dict.get("corporation_id") else: try: # Public information about a character pilot_data = interface.get_esi_data( "characters/{}/".format(pilot_id), fully_trust_cache=True) corp_id = pilot_data["corporation_id"] various_characters_data.update( {str(pilot_id): pilot_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 404 Client Error: Not Found ('Character has been deleted!') various_characters_data.update( {str(pilot_id): None}) else: print(sys.exc_info()) raise except: print(sys.exc_info()) raise sys.stdout.flush() elif shareholder['shareholder_type'] == 'corporation': corp_id = shareholder['shareholder_id'] # Получение сведений о корпорациях, которым принадлежат акции, либо в которых состоят пилоты if corp_id: if str(corp_id) not in various_corporations_data: # Public information about a character corp_data = interface.get_esi_data( "corporations/{}/".format(corp_id), fully_trust_cache=True) various_corporations_data.update({str(corp_id): corp_data}) sys.stdout.flush() shareholders_data = { "corporation": corporation_data, "shareholders": corp_shareholders_data, "characters": various_characters_data, "corporations": various_corporations_data, } eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_shareholders_data.{}".format(corporation_name), shareholders_data) # Построение дерева shareholders-ов: print("\nBuilding shareholders report...") sys.stdout.flush() render_html_shareholders.dump_shareholders_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # данные, полученные в результате анализа и перекомпоновки входных списков shareholders_data) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(argv_prms["character_names"][0]) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_bp_materials = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "blueprints") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") sde_icon_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "iconIDs") # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [ t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published') == False ]: del sde_bp_materials[t] # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data))) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) print("\n'{}' corporation has {} blueprints".format( corporation_name, len(corp_blueprints_data))) sys.stdout.flush() # Построение дерева market-групп с элементами, в виде: # { group1: {items:[sub1,sub2,...]}, # group2: {items:[sub3],parent_id} } market_groups_tree = eve_sde_tools.get_market_groups_tree( sde_market_groups) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "market_groups_tree", market_groups_tree) print("\nBuilding report...") sys.stdout.flush() found_blueprints = [] glf = open('{dir}/corp_bpo.csv'.format( dir=argv_prms["workspace_cache_files_dir"]), "wt+", encoding='utf8') try: glf.write( 'Blueprint\tBase Price\tMaterial Efficiency\tTime Efficiency\n') for a in corp_assets_data: if not (str(a["type_id"]) in sde_bp_materials): continue if ("is_blueprint_copy" in a) and a["is_blueprint_copy"]: continue item_id = a["item_id"] blueprint = None for b in corp_blueprints_data: if b["item_id"] == item_id: blueprint = b break if blueprint is None: continue type_id = sde_type_ids[str(a["type_id"])] glf.write('{nm}\t{prc}\t{me}\t{te}\n'.format( nm=type_id["name"]["en"], prc=type_id["basePrice"] if "basePrice" in type_id else "", me=blueprint["material_efficiency"], te=blueprint["time_efficiency"])) found_blueprints.append(int(a["type_id"])) glf.write('\nGenerated {}'.format( datetime.fromtimestamp( time.time(), g_local_timezone).strftime('%a, %d %b %Y %H:%M:%S %z'))) finally: glf.close() glf = open('{dir}/corp_absent_bpo.csv'.format( dir=argv_prms["workspace_cache_files_dir"]), "wt+", encoding='utf8') try: glf.write( 'Blueprint\tBase Price\tPresent\tManufacturing Impossible\tAbsent Materials\n' ) bpo_keys = sde_bp_materials.keys() for tid in bpo_keys: type_id = int(tid) sde_type_id = sde_type_ids[str(type_id)] found = next((True for b in found_blueprints if b == type_id), False) glf.write('{nm}\t{prc}\t{fnd}\t{impsbl}\t{absnt}\n'.format( nm=sde_type_id["name"]["en"], prc=sde_type_id["basePrice"] if "basePrice" in sde_type_id else "", fnd="yes" if found else "no", impsbl="yes" if not ("activities" in sde_bp_materials[tid]) or not ("manufacturing" in sde_bp_materials[tid]["activities"]) else "no", absnt="yes" if not ("activities" in sde_bp_materials[tid]) or not ("manufacturing" in sde_bp_materials[tid]["activities"]) or not ("materials" in sde_bp_materials[tid]["activities"] ["manufacturing"]) else "no")) glf.write('\nGenerated {}'.format( datetime.fromtimestamp( time.time(), g_local_timezone).strftime('%a, %d %b %Y %H:%M:%S %z'))) finally: glf.close() print("\nBuilding BPOs report...") sys.stdout.flush() render_html_bpos.dump_bpos_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_market_groups, sde_icon_ids, sde_bp_materials, # esi данные, загруженные с серверов CCP corp_assets_data, corp_blueprints_data, # данные, полученные в результате анализа и перекомпоновки входных списков market_groups_tree) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") sde_inv_items = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invItems") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") corps_blueprints = {} eve_market_prices_data = None various_characters_data = [] for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() various_characters_data.append({str(corporation_id): character_data}) if eve_market_prices_data is None: try: # Public information about market prices eve_market_prices_data = interface.get_esi_data( "markets/prices/") print("\nEVE market has {} prices".format( len(eve_market_prices_data) if not ( eve_market_prices_data is None) else 0)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") eve_market_prices_data = [] else: raise except: print(sys.exc_info()) raise # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format( corporation_name, len(corp_assets_data))) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) print("\n'{}' corporation has {} blueprints".format( corporation_name, len(corp_blueprints_data))) sys.stdout.flush() # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("\n'{}' corporation has {} industry jobs".format( corporation_name, len(corp_industry_jobs_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids( corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print( "\n'{}' corporation has offices in {} forbidden stations : {}". format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # Requires role(s): access token corp_contracts_data = interface.get_esi_paged_data( "corporations/{}/contracts/".format(corporation_id)) print("\n'{}' corporation has {} contracts".format( corporation_name, len(corp_contracts_data))) sys.stdout.flush() # Получение подробной информации о каждому из контракту в списке corp_contract_items_data = [] corp_contract_items_len = 0 corp_contract_items_not_found = [] if len(corp_contracts_data) > 0: # Requires: access token for c in corp_contracts_data: # для удалённых контрактов нельзя загрузить items (см. ниже 404-ошибку), поэтому пропускаем запись if c["status"] == "deleted": continue # в рамках работы с чертежами, нас интересует только набор контрактов, в которых продаются чертежи # ищем публичные контракты типа "обмен предметами" if (c["availability"] != "public") or (c["type"] != "item_exchange"): continue # пропускаем контракты на продажу, которые выставили не мы # эту настройку лучше не трогать, т.к. во FRT например 12'000 контрактов, следовательно # это повлечёт загрузку 12'000 items и 12'000 issuers if c['issuer_corporation_id'] != corporation_id: continue contract_id = c["contract_id"] try: __contract_items = interface.get_esi_data( "corporations/{}/contracts/{}/items/".format( corporation_id, contract_id), fully_trust_cache=True) corp_contract_items_len += len(__contract_items) corp_contract_items_data.append( {str(contract_id): __contract_items}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # это нормально, что часть доп.инфы по контрактам может быть не найдена! corp_contract_items_not_found.append(contract_id) else: raise except: print(sys.exc_info()) raise # Получение сведений о пилотах, вовлечённых в работу с контрактом issuer_id = c["issuer_id"] __issuer_dict = next( (i for i in various_characters_data if int(list(i.keys())[0]) == int(issuer_id)), None) if __issuer_dict is None: # Public information about a character issuer_data = interface.get_esi_data( "characters/{}/".format(issuer_id), fully_trust_cache=True) various_characters_data.append( {str(issuer_id): issuer_data}) sys.stdout.flush() eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_contract_items_data.{}".format(corporation_name), corp_contract_items_data) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "various_characters_data", various_characters_data) # сохраняем м.б. многократно print("\n'{}' corporation has {} items in contracts".format( corporation_name, corp_contract_items_len)) if len(corp_contract_items_not_found) > 0: print("'{}' corporation has {} contracts without details : {}". format(corporation_name, len(corp_contract_items_not_found), corp_contract_items_not_found)) sys.stdout.flush() # Построение дерева ассетов, с узлави в роли станций и систем, и листьями в роли хранящихся # элементов, в виде: # { location1: {items:[item1,item2,...],type_id,location_id}, # location2: {items:[item3],type_id} } corp_assets_tree = eve_esi_tools.get_assets_tree( corp_assets_data, foreign_structures_data, sde_inv_items, virtual_hierarchy_by_corpsag=False) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_assets_tree.{}".format(corporation_name), corp_assets_tree) # Построение дерева имущества (сводная информация, учитывающая объёмы и ориентировочную стоимость asset-ов) print("\nBuilding {} blueprints stat...".format(corporation_name)) sys.stdout.flush() corp_blueprints, blueprints_locations = __build_blueprints( corp_blueprints_data, corp_industry_jobs_data, eve_market_prices_data, corp_contracts_data, corp_contract_items_data, various_characters_data, sde_type_ids, sde_inv_names, sde_inv_items, sde_market_groups, corp_assets_tree, corp_ass_names_data, foreign_structures_data) corp_blueprints.sort(key=lambda bp: bp["name"]) corps_blueprints.update({ str(corporation_id): { "corporation": corporation_name, "blueprints": corp_blueprints, "locations": blueprints_locations } }) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corps_blueprints", corps_blueprints) print("\nBuilding blueprints reports...") sys.stdout.flush() render_html_blueprints.dump_blueprints_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # данные, полученные в результате анализа и перекомпоновки входных списков corps_blueprints) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): qidb = __get_db_connection() try: module_settings = qidb.load_module_settings(g_module_default_settings, g_module_default_types) db_monthly_jobs = qidb.select_all_rows( "SELECT wmj_quantity,wmj_eft,wmj_conveyor " "FROM workflow_monthly_jobs " "WHERE wmj_active;") db_factory_containers = qidb.select_all_rows( "SELECT wfc_id,wfc_name,wfc_active,wfc_disabled,wfc_station_num " "FROM workflow_factory_containers;") db_monthly_jobs = [{ "eft": wmj[1], "quantity": wmj[0], "conveyor": bool(wmj[2]) } for wmj in db_monthly_jobs] db_factory_containers = [{ "id": wfc[0], "name": wfc[1], "active": wfc[2], "disabled": wfc[3], "station_num": wfc[4] } for wfc in db_factory_containers] # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(argv_prms["character_names"][0]) character_id = authz["character_id"] character_name = authz["character_name"] sde_type_ids = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") sde_bp_materials = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "blueprints") sde_market_groups = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "marketGroups") sde_named_type_ids = eve_sde_tools.convert_sde_type_ids(sde_type_ids) # удаление из списка чертежей тех, которые не published (надо соединить typeIDs и blueprints, отбросив часть) for t in [ t for t in sde_type_ids if t in sde_bp_materials.keys() and sde_type_ids[t].get('published') == False ]: del sde_bp_materials[t] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("\n'{}' corporation has {} industry jobs".format( corporation_name, len(corp_industry_jobs_data))) sys.stdout.flush() # строим данные для генерации отчёта corp_industry_stat = __build_industry( # настройки и подключение к БД qidb, module_settings, # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_bp_materials, sde_market_groups, sde_named_type_ids, # esi данные, загруженные с серверов CCP corp_industry_jobs_data) eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_industry_stat", corp_industry_stat) except: print(sys.exc_info()) sys.exit(1) # errno.h : EPERM=1 /* Operation not permitted */ del qidb # вывод отчёта на экран print("\n'{}' corporation has {} new jobs since last update".format( corporation_name, corp_industry_stat["new_jobs_found"])) sys.stdout.flush() # для того, чтобы получить названия коробок и в каком ангаре они расположены, надо загрузить # данные по ассетам, т.к. только в этих данных можно учитывая иерархию пересчитать коробки # в нужном ангаре # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids(corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print("\n'{}' corporation has offices in {} foreign stations".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print("\n'{}' corporation has offices in {} forbidden stations : {}". format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() factories_containers = __get_blueprints_containers( module_settings, sde_type_ids, sde_inv_names, corp_assets_data, foreign_structures_data, corp_ass_names_data) # обновление данных в БД (названия контейнеров, и первичное автозаполнение) for factory_containers in factories_containers: station_num = factory_containers["station_num"] __actualize_factory_containers(db_factory_containers, factory_containers["containers"], station_num) print( '\nFound factory station {} with containers in hangars...'.format( factory_containers["station_name"])) print(' {} = {}'.format(factory_containers["station_id"], factory_containers["station_name"])) print(' blueprint hangars = {}'.format( factory_containers["hangars_filter"])) print(' blueprint containers = {}'.format( len(factory_containers["containers"]))) print(' database containers = {}'.format( len([ dfc["id"] for dfc in db_factory_containers if dfc['station_num'] == station_num ]))) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) print("\n'{}' corporation has {} blueprints".format( corporation_name, len(corp_blueprints_data))) sys.stdout.flush() # формирование набора данных для построения отчёта corp_manufacturing_scheduler = __get_monthly_manufacturing_scheduler( # данные полученные из БД db_monthly_jobs, db_factory_containers, # sde данные загруженные из .converted_xxx.json файлов sde_type_ids, sde_named_type_ids, sde_bp_materials, sde_market_groups, # esi данные загруженные с серверов CCP corp_blueprints_data, corp_industry_jobs_data, # данные полученные в результате анализа и перекомпоновки входных списков factories_containers) eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_manufacturing_scheduler", corp_manufacturing_scheduler) print('\nFound in {} stations...'.format(len(factories_containers))) print(' scheduled blueprints = {}'.format( len(corp_manufacturing_scheduler["scheduled_blueprints"]))) print(' factory repository = {}'.format( len(corp_manufacturing_scheduler["factory_repository"]))) print(' factory blueprints = {}'.format( len(corp_manufacturing_scheduler["factory_blueprints"]))) sys.stdout.flush() print("\nBuilding workflow report...") sys.stdout.flush() render_html_workflow.dump_workflow_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_market_groups, # данные, полученные в результате анализа и перекомпоновки входных списков corp_manufacturing_scheduler) print("\nBuilding industry report...") sys.stdout.flush() render_html_industry.dump_industry_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, # данные, полученные в результате анализа и перекомпоновки входных списков corp_industry_stat) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): try: # работа с параметрами командной строки, получение настроек запуска программы, как то: имена пилотов ранее # зарегистрированных и для которыйх имеется аутентификационные токены, регистрация нового и т.д. # настройка offline_mode игнорируется, скрипт всегда работает в --online режиме argv_prms = console_app.get_argv_prms() except: sys.exit(22) # Unit errno.h : EINVAL=22 /* Invalid argument */ # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nStarting preload commonly used data...\n") try: eve_market_prices_data = None various_characters_data = {} various_corporations_data = {} markets_analyzer_first_time = True for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=False ) # здесь обычно находится параметр argv_prms["offline_mode"] authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data( "corporations/{}/".format(character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("{} is from '{}' corporation\n".format( character_name, corporation_name)) sys.stdout.flush() various_characters_data.update({str(character_id): character_data}) various_corporations_data.update( {str(corporation_id): corporation_data}) if eve_market_prices_data is None: try: # Public information about market prices eve_market_prices_data = interface.get_esi_data( "markets/prices/") print("\nEVE market has {} prices".format( len(eve_market_prices_data) if not ( eve_market_prices_data is None) else 0)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") eve_market_prices_data = [] else: raise except: print(sys.exc_info()) raise try: # Requires role(s): Accountant, Junior_Accountant corp_wallets_data = interface.get_esi_paged_data( "corporations/{}/wallets/".format(corporation_id)) print("'{}' corporation has {} wallet divisions\n".format( corporation_name, len(corp_wallets_data))) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_wallets_data = [] else: raise except: print(sys.exc_info()) raise # Requires role(s): Accountant, Junior_Accountant corp_wallet_journal_data = [ None, None, None, None, None, None, None ] for w in corp_wallets_data: division = w["division"] try: corp_wallet_journal_data[ division - 1] = interface.get_esi_paged_data( "corporations/{}/wallets/{}/journal/".format( corporation_id, division)) print("'{}' corporation has {} wallet#{} transactions\n". format(corporation_name, len(corp_wallet_journal_data[division - 1]), division)) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.11.26 поломался доступ к журналу кошелька (ССР-шники "внесли правки") corp_wallet_journal_data[division - 1] = None elif status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_wallet_journal_data[division - 1] = None else: raise except: print(sys.exc_info()) raise # Requires one of the following EVE corporation role(s): Director corp_divisions_data = interface.get_esi_data( "corporations/{}/divisions/".format(corporation_id), fully_trust_cache=True) print( "'{}' corporation has {} hangar and {} wallet names\n".format( corporation_name, len(corp_divisions_data["hangar"]) if "hangar" in corp_divisions_data else 0, len(corp_divisions_data["wallet"]) if "wallet" in corp_divisions_data else 0)) sys.stdout.flush() try: # Requires role(s): Director corp_shareholders_data = interface.get_esi_paged_data( "corporations/{}/shareholders/".format(corporation_id)) print("'{}' corporation has {} shareholders\n".format( corporation_name, len(corp_shareholders_data))) sys.stdout.flush() except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 500: # 2021.01.28 поломался доступ к кошелькам, Internal Server Error corp_shareholders_data = [] else: raise except: print(sys.exc_info()) raise for shareholder in corp_shareholders_data: # Получение сведений о пилотах, имеющих акции корпорации corp_id = None if shareholder['shareholder_type'] == 'character': pilot_id = shareholder['shareholder_id'] if str( pilot_id ) in various_characters_data: # пилот м.б. быть в списке с dict=None __pilot_dict = various_characters_data[str(pilot_id)] if __pilot_dict: corp_id = __pilot_dict.get("corporation_id") else: try: # Public information about a character pilot_data = interface.get_esi_data( "characters/{}/".format(pilot_id), fully_trust_cache=True) corp_id = pilot_data["corporation_id"] various_characters_data.update( {str(pilot_id): pilot_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 404 Client Error: Not Found ('Character has been deleted!') various_characters_data.update( {str(pilot_id): None}) else: print(sys.exc_info()) raise except: print(sys.exc_info()) raise sys.stdout.flush() elif shareholder['shareholder_type'] == 'corporation': corp_id = shareholder['shareholder_id'] # Получение сведений о корпорациях, которым принадлежат акции, либо в которых состоят пилоты if corp_id and (str(corp_id) not in various_corporations_data): # Public information about a corporation corp_data = interface.get_esi_data( "corporations/{}/".format(corp_id), fully_trust_cache=True) various_corporations_data.update({str(corp_id): corp_data}) sys.stdout.flush() # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("'{}' corporation has {} assets\n".format( corporation_name, len(corp_assets_data))) sys.stdout.flush() # Requires role(s): Director corp_blueprints_data = interface.get_esi_paged_data( "corporations/{}/blueprints/".format(corporation_id)) print("'{}' corporation has {} blueprints\n".format( corporation_name, len(corp_blueprints_data))) sys.stdout.flush() # Requires role(s): Factory_Manager corp_industry_jobs_data = interface.get_esi_paged_data( "corporations/{}/industry/jobs/".format(corporation_id)) print("'{}' corporation has {} industry jobs\n".format( corporation_name, len(corp_industry_jobs_data))) sys.stdout.flush() # # Requires role(s): Station_Manager # corp_structures_data = interface.get_esi_paged_data( # "corporations/{}/structures/".format(corporation_id)) # print("'{}' corporation has {} structures\n".format(corporation_name, len(corp_structures_data))) # sys.stdout.flush() # # Requires role(s): Director # corp_starbases_data = interface.get_esi_paged_data( # "corporations/{}/starbases/".format(corporation_id)) # print("'{}' corporation has {} starbases\n".format(corporation_name, len(corp_starbases_data))) # sys.stdout.flush() # # Requires role(s): Factory_Manager # corp_facilities_data = interface.get_esi_paged_data( # "corporations/{}/facilities/".format(corporation_id)) # print("'{}' corporation has {} facilities\n".format(corporation_name, len(corp_facilities_data))) # sys.stdout.flush() # # Requires role(s): Director # corp_customs_offices_data = interface.get_esi_paged_data( # "corporations/{}/customs_offices/".format(corporation_id)) # print("'{}' corporation has {} customs offices\n".format(corporation_name, len(corp_customs_offices_data))) # sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids( corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format( corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids( corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update( {str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append( structure_id) else: # print(sys.exc_info()) raise except: print(sys.exc_info()) raise print( "'{}' corporation has offices in {} foreign stations\n".format( corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print( "'{}' corporation has offices in {} forbidden stations : {}\n" .format(corporation_name, len(foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # Requires role(s): access token corp_contracts_data = interface.get_esi_paged_data( "corporations/{}/contracts/".format(corporation_id)) print("'{}' corporation has {} contracts\n".format( corporation_name, len(corp_contracts_data))) sys.stdout.flush() # Получение подробной информации о каждому из контракту в списке corp_contract_items_data = [] corp_contract_items_len = 0 corp_contract_items_not_found = [] if len(corp_contracts_data) > 0: # Requires: access token for c in corp_contracts_data: # для удалённых контрактов нельзя загрузить items (см. ниже 404-ошибку), поэтому пропускаем запись if c["status"] == "deleted": continue # в рамках работы с чертежами, нас интересует только набор контрактов, в которых продаются чертежи # ищем публичные контракты типа "обмен предметами" if c["type"] != "item_exchange": continue # пропускаем контракты на продажу, которые выставили не мы # эту настройку лучше не трогать, т.к. во FRT например 12'000 контрактов, следовательно # это повлечёт загрузку 12'000 items и 12'000 issuers if c['issuer_corporation_id'] != corporation_id: continue contract_id = c["contract_id"] try: __contract_items = interface.get_esi_data( "corporations/{}/contracts/{}/items/".format( corporation_id, contract_id), fully_trust_cache=True) corp_contract_items_len += len(__contract_items) corp_contract_items_data.append( {str(contract_id): __contract_items}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # это нормально, что часть доп.инфы по контрактам может быть не найдена! corp_contract_items_not_found.append(contract_id) else: # print(sys.exc_info()) raise except: print(sys.exc_info()) raise # Получение сведений о пилотах, вовлечённых в работу с контрактом issuer_id = c["issuer_id"] if str(issuer_id) not in various_characters_data: try: # Public information about a character issuer_data = interface.get_esi_data( "characters/{}/".format(issuer_id), fully_trust_cache=True) various_characters_data.update( {str(issuer_id): issuer_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 404 Client Error: Not Found ('Character has been deleted!') various_characters_data.update( {str(issuer_id): None}) else: print(sys.exc_info()) raise except: print(sys.exc_info()) raise sys.stdout.flush() eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "corp_contract_items_data.{}".format(corporation_name), corp_contract_items_data) print("'{}' corporation has {} items in contracts\n".format( corporation_name, corp_contract_items_len)) if len(corp_contract_items_not_found) > 0: print( "'{}' corporation has {} contracts without details : {}\n". format(corporation_name, len(corp_contract_items_not_found), corp_contract_items_not_found)) sys.stdout.flush() # Requires: public access if markets_analyzer_first_time: markets_analyzer_first_time = False sde_inv_names = eve_sde_tools.read_converted( argv_prms["workspace_cache_files_dir"], "invNames") market_regions = [(int(id), sde_inv_names[id]) for id in sde_inv_names if sde_inv_names[id] in q_market_analyzer_settings.g_regions] del sde_inv_names try: # Public information about market prices for (region_id, region_name) in market_regions: markets_region_orders = interface.get_esi_paged_data( "markets/{}/orders/".format(region_id)) print("\n{} market has {} orders".format( region_name, len(markets_region_orders) if markets_region_orders else 0)) sys.stdout.flush() del markets_region_orders except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 404: # 2020.12.03 поломался доступ к ценам маркета (ССР-шники "внесли правки") pass else: raise except: print(sys.exc_info()) raise del market_regions eve_esi_tools.dump_debug_into_file( argv_prms["workspace_cache_files_dir"], "various_characters_data", various_characters_data) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone\n") except: print(sys.exc_info()) sys.exit(1) # errno.h : EPERM=1 /* Operation not permitted */ sys.exit(0) # code 0, all ok
def main(): qidb = __get_db_connection() try: db_regroup_stock = qidb.select_all_rows( "SELECT rs_quantity,rs_eft,rs_station,rs_container " "FROM regroup_stock " "WHERE rs_active;") db_regroup_stock = [{"eft": wmj[1], "q": wmj[0], "station": wmj[2], "container": wmj[3]} for wmj in db_regroup_stock] except: print(sys.exc_info()) sys.exit(1) # errno.h : EPERM=1 /* Operation not permitted */ del qidb # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() sde_type_ids = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "typeIDs") sde_inv_names = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "invNames") sde_market_groups = eve_sde_tools.read_converted(argv_prms["workspace_cache_files_dir"], "marketGroups") sde_named_type_ids = eve_sde_tools.convert_sde_type_ids(sde_type_ids) corp_regroup_stats = [] for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth( '{}/auth_cache'.format(argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format(argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data( "corporations/{}/".format(character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() # для того, чтобы получить названия коробок и в каком ангаре они расположены, надо загрузить # данные по ассетам, т.к. только в этих данных можно учитывая иерархию пересчитать коробки # в нужном ангаре # Requires role(s): Director corp_assets_data = interface.get_esi_paged_data( "corporations/{}/assets/".format(corporation_id)) print("\n'{}' corporation has {} assets".format(corporation_name, len(corp_assets_data))) sys.stdout.flush() # Получение названий контейнеров, станций, и т.п. - всё что переименовывается ingame corp_ass_named_ids = eve_esi_tools.get_assets_named_ids(corp_assets_data) # Requires role(s): Director corp_ass_names_data = interface.get_esi_piece_data( "corporations/{}/assets/names/".format(corporation_id), corp_ass_named_ids) print("\n'{}' corporation has {} custom asset's names".format(corporation_name, len(corp_ass_names_data))) sys.stdout.flush() del corp_ass_named_ids # Поиск тех станций, которые не принадлежат корпорации (на них имеется офис, но самой станции в ассетах нет) foreign_structures_data = {} foreign_structures_ids = eve_esi_tools.get_foreign_structures_ids(corp_assets_data) foreign_structures_forbidden_ids = [] if len(foreign_structures_ids) > 0: # Requires: access token for structure_id in foreign_structures_ids: try: universe_structure_data = interface.get_esi_data( "universe/structures/{}/".format(structure_id), fully_trust_cache=True) foreign_structures_data.update({str(structure_id): universe_structure_data}) except requests.exceptions.HTTPError as err: status_code = err.response.status_code if status_code == 403: # это нормально, что часть структур со временем могут оказаться Forbidden foreign_structures_forbidden_ids.append(structure_id) else: raise except: print(sys.exc_info()) raise print( "\n'{}' corporation has offices in {} foreign stations".format(corporation_name, len(foreign_structures_data))) if len(foreign_structures_forbidden_ids) > 0: print("\n'{}' corporation has offices in {} forbidden stations : {}".format(corporation_name, len( foreign_structures_forbidden_ids), foreign_structures_forbidden_ids)) sys.stdout.flush() # строим данные для генерации отчёта corp_regroup_stat = __build_regroup( # настройки из БД db_regroup_stock, # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_inv_names, sde_market_groups, sde_named_type_ids, # esi данные, загруженные с серверов CCP corp_assets_data, foreign_structures_data, corp_ass_names_data) # обновление данных в БД (названия контейнеров, и первичное автозаполнение) for stock_containers in corp_regroup_stat["regroup_containers"]: cntnrs = stock_containers["containers"] print('\nFound station {} with containers...'.format(stock_containers["station_name"])) print(' {} = {}'.format(stock_containers["station_id"], stock_containers["station_name"])) print(' regroup containers = {}'.format([(c['id'], c['name']) for c in cntnrs])) sys.stdout.flush() eve_esi_tools.dump_debug_into_file(argv_prms["workspace_cache_files_dir"], "corp_regroup_stat.{}".format(corporation_name), corp_regroup_stat) corp_regroup_stat.update({"corporation_name": corporation_name}) corp_regroup_stats.append(corp_regroup_stat) # освобождаем память от ненужных более списков del sde_inv_names del sde_named_type_ids print("\nBuilding regroup report...") sys.stdout.flush() render_html_regroup.dump_regroup_into_report( # путь, где будет сохранён отчёт argv_prms["workspace_cache_files_dir"], # sde данные, загруженные из .converted_xxx.json файлов sde_type_ids, sde_market_groups, # данные, полученные в результате анализа и перекомпоновки входных списков corp_regroup_stats ) # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")
def main(): # работа с параметрами командной строки, получение настроек запуска программы, как то: работа в offline-режиме, # имя пилота ранее зарегистрированного и для которого имеется аутентификационный токен, регистрация нового и т.д. argv_prms = console_app.get_argv_prms() for pilot_name in argv_prms["character_names"]: # настройка Eve Online ESI Swagger interface auth = esi.EveESIAuth('{}/auth_cache'.format( argv_prms["workspace_cache_files_dir"]), debug=True) client = esi.EveESIClient( auth, keep_alive=True, debug=argv_prms["verbose_mode"], logger=True, user_agent='Q.Industrialist v{ver}'.format(ver=__version__)) interface = esi.EveOnlineInterface( client, q_industrialist_settings.g_client_scope, cache_dir='{}/esi_cache'.format( argv_prms["workspace_cache_files_dir"]), offline_mode=argv_prms["offline_mode"]) authz = interface.authenticate(pilot_name) character_id = authz["character_id"] character_name = authz["character_name"] # Public information about a character character_data = interface.get_esi_data( "characters/{}/".format(character_id), fully_trust_cache=True) # Public information about a corporation corporation_data = interface.get_esi_data("corporations/{}/".format( character_data["corporation_id"]), fully_trust_cache=True) corporation_id = character_data["corporation_id"] corporation_name = corporation_data["name"] print("\n{} is from '{}' corporation".format(character_name, corporation_name)) sys.stdout.flush() # Public access solar_systems = interface.get_esi_data("universe/systems/", fully_trust_cache=True) print("Found {} solar systems on Tranquility".format( len(solar_systems))) sys.stdout.flush() # Public access region_ids = interface.get_esi_data("universe/regions/", fully_trust_cache=True) # Public access regions_data = [] for region_id in region_ids: region_desc = interface.get_esi_data( "universe/regions/{}/".format(region_id), fully_trust_cache=True) regions_data.append(region_desc) print("Found {} regions on Tranquility".format(len(regions_data))) sys.stdout.flush() # Public access system_jumps = interface.get_esi_paged_data("universe/system_jumps/") print("Found {} solar systems with jumps statistic on Tranquility". format(len(system_jumps))) sys.stdout.flush() # Public access low_sec_systems = [] for system_id in solar_systems: system_desc = interface.get_esi_data( "universe/systems/{}/".format(system_id), fully_trust_cache=True) if system_desc: security_status = system_desc["security_status"] if security_status > 0 and security_status < 0.5: low_sec_systems.append(system_desc) print("Found {} low sec systems on Tranquility".format( len(low_sec_systems))) for system_desc in low_sec_systems: constellation_id: int = system_desc["constellation_id"] system_id: int = system_desc["system_id"] ship_jumps: int = next( (sj["ship_jumps"] for sj in system_jumps if sj["system_id"] == system_id), 0) region_name: str = next( (r["name"] for r in regions_data if constellation_id in r["constellations"]), None) system_desc.update({ "ship_jumps": ship_jumps, "region": region_name }) low_sec_systems.sort(key=lambda s: s['ship_jumps'], reverse=False) print("Region\tSystem\tJumps\tGates\sSecurity") for system_desc in low_sec_systems: if system_desc["ship_jumps"] >= 10: break print("{}\t{}\t{}\t{}\t{:.1f}".format( system_desc["region"], system_desc["name"], system_desc["ship_jumps"], len(system_desc["stargates"]), system_desc["security_status"])) break # Вывод в лог уведомления, что всё завершилось (для отслеживания с помощью tail) print("\nDone")