async def post(self): try: body = self.request.body or "{}" try: req = json.loads(body) except JSONDecodeError: out = api_fail("JSON-запрос невалиден") else: out = self.func(self, req) self.write(json.dumps(out, indent=4)) except Exception as e: err_text = self.get_exception_text(self, e) msg = e.sql if hasattr(e, 'sql') else str(type(e)) + ":" + str(e) data = e.data if hasattr(e, 'data') else traceback.format_stack() fail_args = { "msg": err_text } if err_text else { "args": e.args, "msg": msg, "data": data } logger = get_error_logger(__name__) logger.error( "======================================================================" ) logger.exception(msg, exc_info=e) self.write(json.dumps(api_fail(**fail_args)))
def set_build_correction(self, params): """ params: {flight_id: int, node_type_code: str, correction: str}""" existing = self.db.fetchAll( """ select * from builds where flight_id = :flight_id""", params, 'node_type_code') if not existing: return api_fail( "Полет {flight_id) не существует, либо для него не зарезервировано ни одного узла!" .format(**params)) flight = self.db.fetchRow("select * from flights where id=:flight_id", params) if flight.get('status') == 'freight': return api_fail( "Ваш полет уже зафрахтован. Дальнейшая синхронизация невозможна") update_row = existing.get(params['node_type_code']) if not update_row: return api_fail( "Для полета не зарезервирован узел {node_type_code}".format( **params)) update_row['correction_func'] = params['correction'] update_row['correction'] = get_func_vector(params['correction']) update_row['total'] = xor([update_row['vector'], update_row['correction']]) update_row['params'] = calc_node_params_with_desync( update_row['total'], node_id=update_row['node_id']) update_row['params_json'] = json.dumps(update_row['params']) update_row['slots'] = count_elements_for_functext(params['correction']) update_row['slots_json'] = json.dumps(update_row['slots']) if update_row['slots_json'] == 'null': update_row['slots_json'] = '{}' self.db.update( 'builds', update_row, 'flight_id = :flight_id and node_type_code=:node_type_code') del (params['correction']) return api_ok(node_sync=get_build_data(self, params))
def unload_luggage(self, params): """ params = {flight_id: int, code: "beacon"/"mine"/"module", <company>: str (только для шахт), <planet_id>: str (только для модулей) }""" if 'company' in params and params.get('code') != 'mine': del (params['company']) if 'planet_id' in params and params.get('code') != 'module': del (params['planet_id']) if not params.get('planet_id') and params.get('code') == 'module': return api_fail( "Для выгрузки модуля необходимо указать код планеты высадки!") if 'company' not in params and params.get('code') == 'mine': return api_fail( "Для выгрузки шахты необходимо указать компанию-владельца!") where = self.db.construct_where(params) sql = "select * from flight_luggage where " + where # Проверяем, есть ли такой груз row = self.db.fetchRow(sql, params) if not row: return api_fail("Такого груза нет на борту") if int(row['amount']) == 1: self.db.query("delete from flight_luggage where " + where, params, need_commit=True) else: self.db.query("update flight_luggage set amount = amount-1 where " + where, params, need_commit=True) return api_ok()
def add_pump(self, data): """ params: {company: str, section: nodes/models/crises/markets/mines, entity_id: int/str, comment: str, is_income: 1/0, resources {code: value} } """ avail_vendors = self.db.fetchColumn('select code from companies') if not data.get('company') in avail_vendors: return api_fail("Не существует компания с кодом '{}'".format( data.get('company', ''))) avail_sections = self.db.fetchColumn('select code from pump_sections') if not data.get('section') in avail_sections: return api_fail("Неизвестная секция {}. Возможные секции: {}".format( data.get('section'), ', '.join(avail_sections))) pump_id = self.db.insert('pumps', data) insert_parameters = [{ "pump_id": pump_id, "resource_code": code, "value": def_value } for code, def_value in data.get('resources').items()] data['id'] = pump_id self.db.insert('pump_resources', insert_parameters) data['resources'] = { param['resource_code']: param['value'] for param in insert_parameters } return {"status": "ok", "data": data}
async def post(self): try: body = self.request.body or "{}" logger.info(str(self.request.arguments)) logger.info(body) try: req = json.loads(body) except JSONDecodeError: out = api_fail("JSON-запрос невалиден") else: out = self.func(self, req) self.add_header("Content-type", "application/json") self.write(json.dumps(out)) except Exception as e: err_text = self.get_exception_text(self, e) msg = e.sql if hasattr(e, 'sql') else str(type(e)) + ":" + str(e) data = e.data if hasattr(e, 'data') else '' fail_args = { "msg": err_text } if err_text else { "args": e.args, "msg": msg, "data": data } error_logger.error( "======================================================================" ) error_logger.info(body) error_logger.exception(msg, exc_info=e) self.write(json.dumps(api_fail(**fail_args)))
def boost_use(self, params): """ params = {"password": str} """ boost = self.db.fetchRow('select code, used_datetime from boosts where password=:password', params) if not boost: return api_fail("Пароль неверен") if boost['used_datetime']: return api_fail("Этот буст уже был использован") self.db.query("update boosts set used_datetime=now() where password=:password", params) return api_ok()
def check_password(self, data): """ params: {node_id: int, password: string} """ row = self.db.fetchRow('select id, password from nodes where id=:node_id', data) if not row: return api_fail("Неверный ID узла: {}".format(data.get('node_id', ''))) if row.get('password') != data.get('password'): return api_fail('Пароль неверен') return {"result": "ok"}
def skip_flight(self, params): """ params: {"flight_id": int, "flight_time": int, "az_damage": dict/int} """ flight = self.db.fetchRow("select * from flights where id=:flight_id", params) if flight['status'] != 'prepare': return api_fail( f"Полет находится в статусе {flight['status']} и не может быть пропущен" ) build = get_build_data(self, params) # Все нормально - можем фрахтовать node_ids = [item['node_id'] for item in build.values()] # "Возвращаем" полет self.db.query("update flights set status='returned' where id=:flight_id", params, need_commit=True) # Фрахтуем узлы if node_ids: self.db.query("update nodes set status='free' where id in (" + ", ".join(map(str, node_ids)) + ")", None, need_commit=True) # Выдаем компаниям KPI за фрахт узлов kpi_insert = [{ "company": item['company'], "node_id": item['node_id'], "reason": "фрахт", "amount": 5 } for item in build.values()] self.db.insert("kpi_changes", kpi_insert) logger.info("Полет {flight_id} пропущен".format(**params)) return api_ok()
def send_post(self, url, data): try: url = SERVICE_URL + url r = requests.post(url, json=data) return json.reads(r.text) except requests.exceptions.ConnectionError: return api_fail("Удаленный сервер не ответил на адрес " + url)
def add_model(self, data): """ params: {<id>, name, level, description, size, node_type_code, company, kpi_price, {params}, "upkeep"} """ avail_vendors = self.db.fetchColumn('select code from companies') if not data.get('company') in avail_vendors: return api_fail("Не существует компания с кодом '{}'".format( data.get('company', ''))) # Добавляем модель new_model_id = self.db.insert('models', data) # Устанавливаем ей вау-период self.db.query( f'update models set premium_expires = created + interval {MODEL_WOW_PERIOD_HOURS} hour where id=:id', {"id": new_model_id}) model_params = self.db.fetchDict( 'select parameter_code, def_value from model_has_parameters where node_code=:node_type_code', data, 'parameter_code', 'def_value') insert_parameters = [{ "model_id": new_model_id, "parameter_code": code, "value": data['params'].get(code, def_value) } for code, def_value in model_params.items()] data['id'] = new_model_id self.db.insert('model_parameters', insert_parameters) upkeep_parameters = [{ "model_id": new_model_id, "resource_code": code, "amount": value } for code, value in data['upkeep'].items()] self.db.insert('models_upkeep', upkeep_parameters) data['params'] = { param['parameter_code']: param['value'] for param in insert_parameters } return {"status": "ok", "data": data}
def decomm_node(self, params): """ params={node_id: int, is_auto: 0/1, reason: str} """ node = self.db.fetchRow( """select m.company, n.az_level, n.status from nodes n join models m on m.id = n.model_id where n.id=:node_id""", params) if node['status'] in ['decomm', 'lost']: return api_fail( "Узел имеет статус {status} и уже не может быть списан".format( **node)) self.db.query("update nodes set status='decomm' where id=:node_id", params, need_commit=True) if not params.get('is_auto'): self.db.insert( "kpi_changes", { "company": node['company'], "reason": "Списание узла вручную", "node_id": params['node_id'], 'amount': -15 }) stop_pump(self, {"section": "nodes", "entity_id": params['node_id']}) if params.get('is_auto'): params[ 'reason'] = f"Автоматическое списание, уровень АЗ {node['az_level']}" logger.info("Списан узел {node_id}, причина: {reason}".format(**params)) return api_ok(reason=params.get('reason', ''))
def mcc_assign_flight(self, params): """ params = {"flight_id": int, "company": mat/mst/gd/pre/kkg/ideo} """ company = params.get('company', '') if company not in ('mat', 'mst', 'gd', 'pre', 'kkg', 'ideo'): return api_fail("Неверный код компании") params['id'] = params['flight_id'] self.db.update('flights', params, "id=:id") return api_ok(updated=self.db.affected_rows())
def read_model(self, data): """ params = {id: int} """ model = self.db.fetchRow('select * from models where id=:id', data) if not model: return api_fail("Model with id {} not found".format(data.get('id'))) model['params'] = self.db.fetchDict('select parameter_code, value from v_model_params where model_id=:id', data, 'parameter_code', 'value') model = apply_companies_perks(model) return {"status": "ok", "data": model}
def get_my_reserved_nodes(self, params) -> Dict[str, Any]: """ params: {"user_id": int} """ flight = get_nearest_flight_for_supercargo(None, params.get('user_id')) if not flight: return api_fail("Суперкарго {} не назначен ни на какой полет".format( params.get('user_id'))) nodes = self.db.fetchDict( "select node_type_code, node_id from builds where flight_id=:id", flight, "node_type_code", "node_id") return {"result": "ok", "flight": flight, "nodes": nodes}
def load_luggage(self, params): """ params = {flight_id: int, code: "beacon"/"mine"/"module", <company>: str (только для шахт), <planet_id>: str (только для модулей) }""" if 'company' in params and params.get('code') != 'mine': del (params['company']) if 'planet_id' in params and params.get('code') != 'module': del (params['planet_id']) if not params.get('planet_id') and params.get('code') == 'module': return api_fail( "Для загрузки модуля необходимо указать код планеты высадки!") if 'company' not in params and params.get('code') == 'mine': return api_fail( "Для загрузки шахты необходимо указать компанию-владельца!") where = self.db.construct_where(params) # Пытаемся добавить к существующим update_sql = 'update flight_luggage set amount=amount +1 where ' + where self.db.query(update_sql, params, need_commit=True) if self.db.affected_rows() == 0: self.db.insert('flight_luggage', params) return api_ok()
def mcc_set_all_crew(self, params): """ params = {"flight_id": int, "crew": [{"role": "pilot", "user_id": 1}, {"role": "radist", "user_id": 2}] }""" if not self.db.fetchRow('select * from flights where id=:flight_id', params): return api_fail("Полет с указанным номером не существует") self.db.query("delete from flight_crews where flight_id=:flight_id", params, need_commit=True) if params['crew']: for item in params['crew']: item['flight_id'] = params['flight_id'] self.db.insert('flight_crews', params['crew']) return api_ok(crew=params['crew'])
def mcc_add_passenger(self, params): """ params = {"flight_id": 1, "user_id": 2} """ cnt = self.db.fetchOne( 'select count(*) from flight_crews where flight_id=:flight_id and role="_other"', params) if cnt >= 5: return api_fail("В полет разрешается брать не более 5 пассажиров!") params['role'] = "_other" self.db.query("""delete from flight_crews where flight_id = :flight_id and user_id=:user_id""", params, need_commit=True) self.db.insert('flight_crews', params) return api_ok()
def set_build_correction(self, params): """ params: {flight_id: int, node_type_code: str, correction: str}""" existing = self.db.fetchAll( """ select * from builds where flight_id = :flight_id""", params, 'node_type_code') if not existing: return api_fail( "Полет {flight_id) не существует, либо для него не зарезервировано ни одного узла!" .format(**params)) update_row = existing.get(params['node_type_code']) if not update_row: return api_fail( "Для полета не зарезервирован узел {node_type_code}".format( **params)) update_row['correction_func'] = params['correction'] update_row['correction'] = get_func_vector(params['correction']) update_row['total'] = xor([update_row['vector'], update_row['correction']]) update_row = get_node_params_with_desync(update_row['total'], node_id=update_row['node_id']) self.db.update( 'bulids', update_row, 'flight_id = :flight_id and node_type_code=:node_type_code') return api_ok(node_sync=update_row)
def add_node_upkeep_pump(self, node_id=None, model=None): if not model: model = self.db.fetchRow("""select m.id, m.name, m.company from models m join nodes n on m.id = n.model_id where n.id = :node_id""", {"node_id": node_id}) upkeep_price = get_model_upkeep_price(self, {"model_id": model['id']}) insufficient = get_insufficient_for_node(company=model['company'], model_id=model['id'], upkeep_price=upkeep_price) if insufficient: return api_fail("Вашего дохода не хватает для создания узла: " + dict2str(insufficient)) pump = { "company": model['company'], "section": "nodes", "entity_id": node_id, "comment": "Поддержка узла {} модели {}".format(node_id, model['name']), "is_income": 0, "resources": upkeep_price } add_pump(self, pump) return api_ok(pump=pump)
def check_reserve_node(self, data): """ data = {user_id: int, node_id: int, password: str} """ from services.mcc import get_nearest_flight_for_supercargo flight = get_nearest_flight_for_supercargo(self, data.get('user_id', 0)) if not flight: return api_fail( "Вы не назначены ни на какой полет в качестве суперкарго") flight['departure'] = modernize_date(flight['departure']) if flight.get('status', '') == 'freight': return api_fail( """Вы назначены суперкарго на полет №{id} (вылет {departure}, док №{dock}). В настоящее время ваш корабль уже зафрахтован, внесение изменений в конструкцию невозможно""" .format(**flight)) node = self.db.fetchRow( """select n.*, ns.name status_name, m.node_type_code, ((n.premium_expires > Now() or n.premium_expires = 0 or n.premium_expires is null) and (n.password is not null and n.password != "") ) as is_premium from nodes n left join node_statuses ns on n.status = ns.code left join models m on m.id = n.model_id where n.id=:node_id""", data) if not node: return api_fail( "Узел с бортовым номером {} не существует и никогда не существовал" .format(data.get('node_id'))) if node.get('status') != 'free': return api_fail( "Узел с бортовым номером {} сейчас находится в статусе '{}' и недоступен вам для резерва" .format(node.get('id'), node.get('status_name'))) if node.get('is_premium'): if not data.get('password'): return api_fail( "Этот узел находится в премиум-доступе. Выясните у создателей пароль доступа" ) elif data.get('password') != node.get('password'): return api_fail('Ваш пароль для доступа к этому узлу неверен') if node['node_type_code'] != 'hull': flight_has_hull = self.db.fetchRow( 'select * from builds where flight_id=:id and node_type_code="hull"', flight) if not flight_has_hull: return api_fail("Сначала необходимо зарезервировать корпус!") return {"flight_id": flight['id'], "node_id": data['node_id']}
def create_node(self, params): """ params: {model_id: int, password: str} """ model_id = params.get('model_id', 0) if not model_id: raise Exception("Не указан model_id!") model_id_dict = {"id": model_id} model = read_models(self, model_id_dict, read_nodes=False) if len(model) < 0: raise Exception(f"No model with id {model_id}") model = model[0] insufficient = get_insufficient_for_node(company=model['company'], model_id=model_id) if insufficient: return api_fail( "Для создания узла вам не хватает следующих ресурсов: " + dict2str(insufficient)) existing_nodes = self.db.fetchOne( 'select count(*) from nodes where model_id=:id', model_id_dict) insert_data = { "model_id": model_id, "name": "", "az_level": model['params']['az_level'], "password": params.get('password', ''), 'premium_expires': None if not existing_nodes else model['premium_expires'] } node_id = self.db.insert('nodes', insert_data) add_node_upkeep_pump(self, node_id=node_id, model=model) if model['node_type_code'] != 'hull': result = self.db.fetchRow('select * from nodes where id=:id', {"id": node_id}) return result else: return create_hull(self, model, node_id=node_id)
def develop_model(self, params): """ params = { "node_type_code": "radar", "company": "mat", "size": "large", "tech_balls": {"1": 10, "2": 5}, "name": "Азаза", "description": "", "password": "" } """ existing_model_name = self.db.fetchRow("select * from models where name=:name", params) if existing_model_name: return api_fail("Модель с названием {name} уже создана".format(**params)) # Читаем используемые технологии techs = read_techs(self, params) # Чистим неиспользуемые техи params['tech_balls'] = { int(key): value for key, value in params['tech_balls'].items() if int(key) in techs.keys() } # Считаем, сколько апкипа жрет модель model_upkeep = calc_model_upkeep(self, params['tech_balls']) # проверяем, хватает ли доходов insufficient = get_insufficient_for_both(company=params['company'], upkeep_price=model_upkeep) if insufficient: return api_fail("Для создания модели и стартового узла по этой модели вам не хватает ресурсов: "+ dict2str(insufficient)) # Вычисляем параметры model_params = calc_model_params(self, params) # Находим цену в KPI model_kpi_price = sum([ ball * techs.get(tech_id, {}).get('level', 0) ** 2 for tech_id, ball in params['tech_balls'].items() ]) model_level = get_model_level_by_technologies([ [techs[key].get('level'), value] for key, value in params['tech_balls'].items() ]) model_data = add_model(self, { "name": params['name'], "description": params.get("description", ''), "level": model_level, "kpi_price": model_kpi_price, "size": params['size'], "node_type_code": params['node_type_code'], "company": params['company'], 'params': model_params, "upkeep": model_upkeep, }) model_id = model_data['data']['id'] # Создаем временный насос model_pump = add_pump(self, { "company": params['company'], 'section': 'models', 'entity_id': model_id, 'comment': f'Разработка модели {model_id} {params["name"]}', "is_income": 0, "resources": {code: value / 2 for code, value in model_upkeep.items()} }) # Устанавливаем насосу время окончания self.db.query(f"""update pumps set date_end = Now() + interval {MODEL_WOW_PERIOD_HOURS} hour where id=:id""", model_pump['data'], need_commit=True) # Создаем стартовый узел if not params.get('password'): params['password'] = str(randint(1000, 9999)) if params['company'] != 'pre' else '' create_node(self, {"model_id": model_id, "password": params['password']}) return api_ok(params=params)
def freight_flight(self, params): """ params {flight_id: int} """ return api_fail("Пока не реализовано")
def get_flight_params(self, params): """ params = {flight_id: int}""" if not 'flight_id' in params: return api_fail( 'Этот url надо вызывать через POST и передавать в тело {"flight_id": int}' ) nodes = self.db.fetchAll( """ select b.node_type_code, n.name ship_name, m.name model_name, m.company, b.params_json from builds b join nodes n on n.id = b.node_id join models m on n.model_id = m.id where b.flight_id = :flight_id""", params, 'node_type_code') # Применить перки корпуса hull_perks = self.db.fetchAll( """select hp.node_type_code, hp.parameter_code, hp.value from hull_perks hp join builds b on hp.hull_id = b.node_id and b.node_type_code = "hull" where b.flight_id = :flight_id """, params) for node_type, node in nodes.items(): hull_perks_for_system = { perk['parameter_code']: perk['value'] for perk in hull_perks if perk['node_type_code'] == 'node_type' } node['params'] = { key: apply_percent(value['value'], hull_perks_for_system.get(key, 100)) for key, value in json.loads(node['params_json']).items() } flight = self.db.fetchRow( """ select f.id flight_id, f.departure flight_start_time, f.status, f.dock from flights f where id = :flight_id""", params) known_resources = self.db.fetchAll( "select code, name from resources where is_active=1 order by 1") cargo = self.db.fetchAll( """ select fl.code, fl.company, l.weight from flight_luggage fl join v_luggages l on fl.code = l.code and (fl.company = l.company or (fl.company is null and l.company is null)) where fl.id = :flight_id""", params) flight['ship'] = { "name": nodes['hull']['ship_name'], "nodes_weight": sum([float(node['params']['weight']) for node in nodes.values()]) } flight['params'] = { node_type: node['params'] for node_type, node in nodes.items() } flight['known_minerals'] = known_resources flight['cargo'] = {"mines": [], "beacons": [], "modules": []} for item in cargo: flight['cargo'][item['code'] + 's'].append({ "company": item['company'], "weight": item['weight'] }) return flight
def freight_flight(self, params): """ params {flight_id: int} """ flight = self.db.fetchRow("select * from flights where id=:flight_id", params) if flight['status'] == 'freight': return api_fail(f"Ваш полет уже зафрахтован") if flight['status'] != 'prepare': return api_fail( f"Полет находится в статусе {flight['status']} и не может быть зафрахтован" ) build = get_build_data(self, params) # Проверить, что корабль состоит из всех нужных узлов. nodes_not_reserved = set(NODE_NAMES.keys()) - set(build.keys()) if nodes_not_reserved: return api_fail( "Невозможно совершить фрахт. В корабле не хватает следующих узлов: " + ", ".join([NODE_NAMES[item] for item in nodes_not_reserved])) # проверить, что общий объем неотрицательный hull_volume = build['hull']['params']['volume']['value'] inner_nodes_volume = sum([ item['params']['volume']['value'] for item in build.values() if item['node_type_code'] != 'hull' ]) luggage_volume = self.db.fetchOne( """ select sum(fl.amount* vl.volume) from flight_luggage fl join v_luggages vl on fl.code = vl.code and (fl.company = vl.company or (fl.company is null and vl.company is null)) where fl.flight_id = :flight_id""", params) or 0 if hull_volume - inner_nodes_volume - luggage_volume < 0: return api_fail( f"Внутренний объем вашего корпуса {hull_volume}. Его недостаточно для размещения всех узлов " + f"(суммарный объем {inner_nodes_volume}) и багажа (суммарный объем {luggage_volume})" ) # Проверить, что всех слотов синхронизации хватает slots = defaultdict(int) for row in build.values(): for slot_type, qty in row['slots'].items(): slots[slot_type] += qty * (1 if row['node_type_code'] == 'hull' else -1) not_enough_slots = {key: val for key, val in slots.items() if val < 0} if not_enough_slots: return api_fail( "В корпусе недостаточно слотов для выбранных инженером формул синхронизации. " + "Недостающие слоты: " + dict2str(not_enough_slots)) # Все нормально - можем фрахтовать node_ids = [item['node_id'] for item in build.values()] # Фрахтуем полет self.db.query("update flights set status='freight' where id=:flight_id", params, need_commit=True) # Фрахтуем узлы self.db.query("update nodes set status='freight' where id in (" + ", ".join(map(str, node_ids)) + ")", None, need_commit=True) # Выдаем компаниям KPI за фрахт узлов kpi_insert = [{ "company": item['company'], "node_id": item['node_id'], "reason": "фрахт", "amount": 5 } for item in build.values()] self.db.insert("kpi_changes", kpi_insert) # Формируем инфу по щитам для CouchDb dock = flight['dock'] shield_value = round( build['shields']['params']['desinfect_level']['value']) url = f"https://api.alice.magellan2018.ru/ships/set_shields/{dock}/{shield_value}" requests.get(url, auth=HTTPBasicAuth(os.environ['ADMIN_USER'], os.environ['ADMIN_PASSWORD'])) return api_ok()
def get_flight_params(self, params): """ params = {flight_id: int}""" if not 'flight_id' in params: return api_fail( 'Этот url надо вызывать через POST и передавать в тело {"flight_id": int}' ) nodes = self.db.fetchAll( """ select b.node_type_code, b.node_name, b.model_name, b.company, b.params_json from v_builds b where b.flight_id = :flight_id""", params, 'node_type_code') # Применить перки корпуса hull_perks = self.db.fetchAll( """select hp.node_type_code, hp.parameter_code, hp.value from hull_perks hp join builds b on hp.hull_id = b.node_id and b.node_type_code = "hull" where b.flight_id = :flight_id """, params) params_map = { 'warp_engine': { 'distort_level': 'distort', 'distort_accel': 'distort_acc', 'distort_slowdown': 'distort_slow' }, 'shunter': { 'turn_max': 'turn', 'turn_accel': 'turn_acc' } } for node_type, node in nodes.items(): hull_perks_for_system = { perk['parameter_code']: perk['value'] for perk in hull_perks if perk['node_type_code'] == 'node_type' } pmap = params_map.get(node_type, {}) node['params'] = { pmap.get(key, key): apply_percent(value['value'], hull_perks_for_system.get(key, 0)) for key, value in json.loads(node['params_json']).items() } flight = self.db.fetchRow( """ select f.id flight_id, f.departure flight_start_time, f.status, f.company, f.dock from flights f where id = :flight_id""", params) known_resources = self.db.fetchAll( "select code as id, name from resources where is_active=1 order by 1") cargo = self.db.fetchAll( """ select fl.code, fl.company, l.weight, fl.planet_id from flight_luggage fl join v_luggages l on fl.code = l.code and (fl.company = l.company or (fl.company is null and l.company is null)) where fl.flight_id = :flight_id""", params) flight['ship'] = { "name": nodes['hull']['node_name'], "nodes_weight": sum([float(node['params']['weight']) for node in nodes.values()]) } # Поправки if 'radar' in nodes: nodes['radar']['params']['range_max'] *= 1000 if 'scaner' in nodes: nodes['scaner']['params']['scan_range'] *= 1000 nodes['scaner']['params']['drop_range'] *= 1000 flight['params'] = { node_type: node['params'] for node_type, node in nodes.items() } flight['known_minerals'] = known_resources flight['cargo'] = {"mines": [], "beacons": {}, "modules": []} for item in cargo: if item['code'] == 'mine': flight['cargo']['mines'].append({ "company": item['company'], "weight": item['weight'] }) elif item['code'] == 'beacon': if flight['cargo']['beacons']: flight['cargo']['beacons']['amount'] += 1 else: flight['cargo']['beacons'] = { "weight": item['weight'], "amount": 1 } elif item['code'] == 'module': flight['cargo']['modules'].append({ "company": flight['company'], "weight": item['weight'], "planet_id": item['planet_id'] }) return flight