Exemple #1
0
    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)))
Exemple #2
0
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))
Exemple #3
0
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()
Exemple #4
0
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}
Exemple #5
0
    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)))
Exemple #6
0
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()
Exemple #7
0
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"}
Exemple #8
0
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()
Exemple #9
0
 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)
Exemple #10
0
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}
Exemple #11
0
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', ''))
Exemple #12
0
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())
Exemple #13
0
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}
Exemple #14
0
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}
Exemple #15
0
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()
Exemple #16
0
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'])
Exemple #17
0
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()
Exemple #18
0
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)
Exemple #19
0
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)
Exemple #20
0
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']}
Exemple #21
0
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)
Exemple #22
0
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)
Exemple #23
0
def freight_flight(self, params):
    """ params {flight_id: int} """
    return api_fail("Пока не реализовано")
Exemple #24
0
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
Exemple #25
0
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()
Exemple #26
0
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