import numpy as np
import argparse
import cv2
import os

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required=True,
                help="path to input video")
args = vars(ap.parse_args())
# load the COCO class labels our YOLO model was trained on
script_dir = os.path.dirname(os.path.abspath(__file__))
# initialize a list of colors to represent each possible class label
weights_path = os.path.sep.join([script_dir, "yolov3.weights"])
config_path = os.path.sep.join([script_dir, "yolov3-custom.cfg"])

net = cv2.dnn.readNetFromDarknet(config_path, weights_path)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

vs = cv2.VideoCapture(args["input"])
writer = None
(W, H) = (None, None)
index = 1

while True:
    # read the next frame from the file
    (grabbed, frame) = vs.read()
    # if the frame was not grabbed, then we have reached the end
    # of the stream
    if not grabbed:
        break
    # if the frame dimensions are empty, grab them
    if W is None or H is None:
        (H, W) = frame.shape[:2]
    blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),
                                 swapRB=True, crop=False)
    net.setInput(blob)
    layerOutputs = net.forward(ln)
    boxes = []
    confidences = []
    frame = {}
    # loop over each of the layer outputs
    for output in layerOutputs:
        # loop over each of the detections
        for detection in output:
            # extract the class ID and confidence (i.e., probability)
            # of the current object detection
            scores = detection[5:]
            classID = np.argmax(scores)
            confidence = scores[classID]
            # filter out weak predictions by ensuring the detected
            # probability is greater than the minimum probability
            if confidence > 0.1:
                box = detection[0:4] * np.array([W, H, W, H])
                (centerX, centerY, width, height) = box.astype("int")
                if classID not in frame:
                    frame[classID] = (centerX, centerY)
                if len(frame.keys()) > 1:
                    break

    line = ''
    for i in range(2):
        if i in frame:
            line += str(frame[i][0]) + ',' + str(frame[i][1])
        else:
            line += '#,#'
        if i == 0:
            line += ','
    print(line)
    index += 1

vs.release()


import logging
import os
from future.backports.urllib.parse import parse_qs
from future.backports.urllib.parse import urlparse

from oic.utils.http_util import extract_from_request
from oic.utils.http_util import Response
from oic.utils.http_util import Unauthorized
from oic.utils.http_util import NotFound
from oic.utils.http_util import ServiceError
from oic.utils.http_util import BadRequest
from oic.utils.webfinger import OIC_ISSUER
from oic.utils.webfinger import WebFinger

from otest import pathmap

__author__ = 'roland'

LOGGER = logging.getLogger(__name__)

HEADER = "---------- %s ----------"

def dump_log(session_info, trace):
    file_name = os.path.join("log", session_info["addr"],
                             session_info["test_id"])
    try:
        fp = open(file_name, "a+")
    except IOError:
        try:
            os.makedirs(os.path.join("log", session_info["addr"]))
        except OSError:
            pass

        try:
            fp = open(file_name, "w")
        except Exception as err:
            logging.error(
                "Couldn't dump to log file {} reason: {}").format(
                file_name, err)
            raise

    fp.write("{0}".format(trace))
    fp.write("\n\n")
    fp.close()

def find_identifier(uri):
    if uri.startswith("http"):
        p = urlparse(uri)
        return p.path[1:]  # Skip leading "/"
    elif uri.startswith("acct:"):
        a = uri[5:]
        l, d = a.split("@")
        return l

def wsgi_wrapper(environ, start_response, func, session_info, trace, **kwargs):
    kwargs = extract_from_request(environ)
    trace.request(kwargs["request"])
    args = func(**kwargs)

    try:
        resp, state = args
        trace.reply(resp.message)
        dump_log(session_info, trace)
        return resp(environ, start_response)
    except TypeError:
        resp = args
        trace.reply(resp.message)
        dump_log(session_info, trace)
        return resp(environ, start_response)
    except Exception as err:
        # LOGGER.error("%s" % err)
        trace.error("%s" % err)
        dump_log(session_info, trace)
        raise

# noinspection PyUnusedLocal
def token(environ, start_response, session_info, trace, **kwargs):
    trace.info(HEADER % "AccessToken")
    _op = session_info["op"]

    return wsgi_wrapper(environ, start_response, _op.token_endpoint,
                        session_info,
                        trace)

# noinspection PyUnusedLocal
def authorization(environ, start_response, session_info, trace, **kwargs):
    trace.info(HEADER % "Authorization")
    _op = session_info["op"]

    return wsgi_wrapper(environ, start_response, _op.authorization_endpoint,
                        session_info, trace)

# noinspection PyUnusedLocal
def userinfo(environ, start_response, session_info, trace, **kwargs):
    trace.info(HEADER % "UserInfo")
    _op = session_info["op"]
    return wsgi_wrapper(environ, start_response, _op.userinfo_endpoint,
                        session_info, trace)

# noinspection PyUnusedLocal
def op_info(environ, start_response, session_info, trace, **kwargs):
    trace.info(HEADER % "ProviderConfiguration")
    trace.request("PATH: %s" % environ["PATH_INFO"])
    try:
        trace.request("QUERY: %s" % environ["QUERY_STRING"])
    except KeyError:
        pass
    _op = session_info["op"]
    return wsgi_wrapper(environ, start_response, _op.providerinfo_endpoint,
                        session_info, trace)

# noinspection PyUnusedLocal
def registration(environ, start_response, session_info, trace, **kwargs):
    trace.info(HEADER % "ClientRegistration")
    _op = session_info["op"]

    if environ["REQUEST_METHOD"] == "POST":
        return wsgi_wrapper(environ, start_response, _op.registration_endpoint,
                            session_info, trace)
    elif environ["REQUEST_METHOD"] == "GET":
        return wsgi_wrapper(environ, start_response, _op.read_registration,
                            session_info, trace)
    else:
        resp = ServiceError("Method not supported")
        return resp(environ, start_response)

# noinspection PyUnusedLocal
def check_id(environ, start_response, session_info, trace, **kwargs):
    _op = session_info["op"]

    return wsgi_wrapper(environ, start_response, _op.check_id_endpoint,
                        session_info, trace)

# noinspection PyUnusedLocal
def endsession(environ, start_response, session_info, trace, **kwargs):
    _op = session_info["op"]
    return wsgi_wrapper(environ, start_response, _op.endsession_endpoint,
                        session_info=session_info, trace=trace)

def webfinger(environ, start_response, session_info, trace, **kwargs):
    query = parse_qs(environ["QUERY_STRING"])

    # Find the identifier
    session_info["test_id"] = find_identifier(query["resource"][0])

    trace.info(HEADER % "WebFinger")
    trace.request(environ["QUERY_STRING"])
    trace.info("QUERY: %s" % (query,))

    try:
        assert query["rel"] == [OIC_ISSUER]
        resource = query["resource"][0]
    except AssertionError:
        errmsg = "Wrong 'rel' value: %s" % query["rel"][0]
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    except KeyError:
        errmsg = "Missing 'rel' parameter in request"
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    else:
        wf = WebFinger()
        p = urlparse(resource)

        if p.scheme == "acct":
            l, _ = p.path.split("@")
            path = pathmap.IDMAP[l.lower()]
        else:  # scheme == http/-s
            try:
                path = pathmap.IDMAP[p.path[1:].lower()]
            except KeyError:
                path = None

        if path:
            _url = os.path.join(kwargs["op_arg"]["baseurl"],
                                session_info["test_id"],
                                path[1:])
            resp = Response(wf.response(subject=resource, base=_url),
                            content="application/jrd+json")
        else:
            resp = BadRequest("Incorrect resource specification")

        trace.reply(resp.message)

    dump_log(session_info, trace)
    return resp(environ, start_response)

# noinspection PyUnusedLocal
def verify(environ, start_response, session_info, trace, **kwargs):
    _op = session_info["op"]
    return wsgi_wrapper(environ, start_response, _op.verify_endpoint,
                        session_info, trace)

def static_file(path):
    try:
        os.stat(path)
        return True
    except OSError:
        return False

# noinspection PyUnresolvedReferences
def static(environ, start_response, path):
    LOGGER.info("[static]sending: %s" % (path,))

    try:
        text = open(path).read()
        if path.endswith(".ico"):
            start_response('200 OK', [('Content-Type', "image/x-icon")])
        elif path.endswith(".html"):
            start_response('200 OK', [('Content-Type', 'text/html')])
        elif path.endswith(".json"):
            start_response('200 OK', [('Content-Type', 'application/json')])
        elif path.endswith(".txt"):
            start_response('200 OK', [('Content-Type', 'text/plain')])
        elif path.endswith(".css"):
            start_response('200 OK', [('Content-Type', 'text/css')])
        else:
            start_response('200 OK', [('Content-Type', 'text/plain')])
        return [text]
    except IOError:
        resp = NotFound()
        return resp(environ, start_response)

# noinspection PyUnusedLocal
def safe(environ, start_response):
    _op = environ["oic.oas"]
    _srv = _op.server
    _log_info = _op.logger.info

    _log_info("- safe -")
    # _log_info("env: %s" % environ)
    # _log_info("handle: %s" % (handle,))

    try:
        _authz = environ["HTTP_AUTHORIZATION"]
        (_typ, code) = _authz.split(" ")
        assert _typ == "Bearer"
    except KeyError:
        resp = BadRequest("Missing authorization information")
        return resp(environ, start_response)

    try:
        _sinfo = _srv.sdb[code]
    except KeyError:
        resp = Unauthorized("Not authorized")
        return resp(environ, start_response)

    _info = "'%s' secrets" % _sinfo["sub"]
    resp = Response(_info)
    return resp(environ, start_response)

# noinspection PyUnusedLocal
def css(environ, start_response):
    try:
        _info = open(environ["PATH_INFO"]).read()
        resp = Response(_info)
    except (OSError, IOError):
        resp = NotFound(environ["PATH_INFO"])

    return resp(environ, start_response)

# ----------------------------------------------------------------------------

def display_log(environ, start_response, lookup):
    path = environ.get('PATH_INFO', '').lstrip('/')
    if path == "log":
        tail = environ["REMOTE_ADDR"]
        path = os.path.join(path, tail)
    elif path == "logs":
        path = "log"

    if os.path.isfile(path):
        return static(environ, start_response, path)
    elif os.path.isdir(path):
        item = []
        for (dirpath, dirnames, filenames) in os.walk(path):
            if dirnames:
                # item = [(fn, os.path.join(path, fn)) for fn in dirnames]
                item = [(fn, fn) for fn in dirnames]
                break
            if filenames:
                # item = [(fn, os.path.join(path, fn)) for fn in filenames]
                item = [(fn, fn) for fn in filenames]
                break

        item.sort()
        resp = Response(mako_template="logs.mako",
                        template_lookup=lookup,
                        headers=[])
        argv = {"logs": item}

        return resp(environ, start_response, **argv)
    else:
        resp = Response("No saved logs")
        return resp(environ, start_response)


import argparse
import os
import time
from distutils.util import strtobool
# Random
import random
import numpy as np
import torch
# Gym env
import gym

# Tensorboard to check training states
from torch.utils.tensorboard import SummaryWriter

def save_environment():
    # Gym environment example
    env = gym.make(
        "CartPole-v1",
        render_mode="rgb_array"
    )
    env = gym.wrappers.RecordEpisodeStatistics(
        env
    )
    env = gym.wrappers.RecordVideo(
        env,
        "videos/cartpole/",
        episode_trigger = lambda t: t%100 == 0
    )
    observation = env.reset()
    for _ in range(200):
        action = env.action_space.sample()
        observation, reward, done, _, info = env.step(action)
        if done:
            observation = env.reset()
            print(
                f'Episode finished with cumulative reward of {info["episode"]["r"]}'
            )
            print(
                f'Episode finished with length {info["episode"]["l"]} timesteps'
            )
            print(
                f'Episode finished at time {info["episode"]["t"]}s'
            )
    env.close()

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--exp-name',
                        type = str,
                        default = os.path.basename(__file__).rstrip('.py'),
                        help = 'Experiment name')
    parser.add_argument('--gym-id',
                        type = str,
                        default = 'LunarLander-v2',
                        help = 'Gym Id name')
    parser.add_argument('--learning-rate',
                        type = float,
                        default = 2.5e-4,
                        help = 'Learning rate')
    parser.add_argument('--seed',
                        type = int,
                        default = 6543210,
                        help = 'Seed')
    parser.add_argument('--total-timesteps',
                        type = int,
                        default = 25000,
                        help = 'Total of timesteps for the experiment')
    parser.add_argument('--torch-deterministic',
                        type = lambda x: bool(strtobool(x)),
                        default = True,
                        help = 'Force torch to use deterministic algorithms when possible')
    parser.add_argument('--track',
                        type = lambda x: bool(strtobool(x)),
                        default = False,
                        nargs="?",
                        const=True,
                        help = 'Track weights and biases for the NN')
    # Wandb is a software package that allows you to track your training progress (weights and biases)
    parser.add_argument('--wandb-project-name',
                        type = str,
                        default = 'CleanRL',
                        help = 'Name of the wandb project')
    parser.add_argument('--wandb-entity',
                        type = str,
                        default = None,
                        help = 'Entity team for the wandb project')
    args = parser.parse_args()
    return args

if __name__ == '__main__':
    args = parse_args()
    print(args)
    run_name = f'{args.gym_id}_{args.exp_name}_{args.seed}_{int(time.time())}'
    if args.track:
        import wandb
        wandb.init(
            entity = args.wandb_entity,
            project = run_name,
            sync_tensorboard = True,
            config = vars(args),
            name = run_name,
            monitor_gym = True,
            save_code = True
        )
    # Summary writer
    writer = SummaryWriter(
        f'runs/{run_name}'
    )
    # Introduce the hyperparameters of the experiments into the tensorboard summary
    writer.add_text(
        'hyperparameters',
        '|param|value|\n|-|-|\n%s' % (
            "\n".join(
                [
                    f"|{key}|{value}|" for key, value in vars(args).items()
                ]
            )
        )
    )
    # Random seed
    random.seed(
        args.seed
    )
    np.random.seed(
        args.seed
    )
    torch.manual_seed(
        args.seed
    )
    torch.backends.cudnn.deterministic = args.torch_deterministic

    # Set cuda if available
    device = torch.device("cuda" if torch.cuda.is_available() and args.cuda else "cpu")

    # Vectorized environmentss
    envs = gym.vector.SyncVectorEnv(
        [
            lambda: gym.wrappers.RecordEpisodeStatistics(
                gym.make(
                    args.gym_id
                )
            )
            for _ in range(3)
        ]
    )
    envs = gym.wrappers.RecordEpisodeStatistics(
        envs
    )
    observation = envs.reset()
    for _ in range(200):
        action = envs.action_space.sample()
        observation, reward, done, _, info = envs.step(action)
        if "episode" in info.keys():
            print(f'Episode information: {info["episode"]["r"]}')


from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from .views import (
    DetailEmployee, ListPost, DetailPost, SearchPost,
    RecommandByJob, RecommandByViewLog, RecommandBySearchLog,
    RecommandByFollow
)

urlpatterns = [
    path('detail_employee/<str:emp_id>/', DetailEmployee.as_view()),
    path('list_post/', ListPost.as_view()),
    path('detail_post/<int:post_id>/', DetailPost.as_view()),
    path('search_post/', SearchPost.as_view()),
    path('recommand_by_job/', RecommandByJob.as_view()),
    path('recommand_by_view_log/', RecommandByViewLog.as_view()),
    path('recommand_by_search_log/', RecommandBySearchLog.as_view()),
    path('recommand_by_follow/', RecommandByFollow.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)


import math
from functools import reduce

from django.utils.dateparse import parse_date
from django.utils.functional import cached_property

from accounting_report.helpers import QuarterParameters
from accounting_report.models import Quarter
from cabinet.base_logic.contracts.base import ContractsLogic
from cabinet.base_logic.printing_forms.helpers.base import BaseHelper
from cabinet.base_logic.scoring.base import ScoringResult, ScoringLogic
from cabinet.constants.constants import Target, FederalLaw
from cabinet.models import EgrulData
from clients.models import Bank
from conclusions_app.conclusions.common import (
    HasArrearsOnPaymentOfTaxesConclusion
)
from conclusions_app.conclusions_logic import ConclusionsLogic
from external_api.nalogru_api import NalogRu
from external_api.searchtenderhelp_api import SearchTenderhelpApi
from settings.configs.banks import BankCode

class InbankHelper(BaseHelper):

    def get_quarters(self):
        return self.client.accounting_report.get_quarters()

    def __init__(self, *args, **kwargs):
        super(InbankHelper, self).__init__(*args, **kwargs)
        self.finance = self.get_finance()

    def get_previous_year_quarter(self):
        return self.client.accounting_report.get_previous_year_quarter()

    @cached_property
    def bank(self):
        return Bank.objects.get(code=BankCode.CODE_INBANK)

    def physical_shareholders(self):
        output = []
        for person in self.profile.profilepartnerindividual_set.all():
            person_name = person.full_name
            text = '%s доля %s %%' % (person_name, person.share)
            output.append(text)
        return ', '.join(output)

    def getPropertyStatus(self):
        address = self.profile.fact_address_properies
        if address['status']:
            return 'Собственность'
        else:
            return 'Аренда с %s по %s' % (address['from'], address['to'])

    def suggested_price_procent(self):
        result = round(100 - self.request.suggested_price_percent, 2)
        return result

    def contract_type(self):
        return Target.PARTICIPANT in self.request.targets and \
               self.request.tender.federal_law in [FederalLaw.LAW_44, FederalLaw.LAW_223]

    def sro_licences(self):
        if self.profile.has_license_sro:
            return self.profile.licensessro_set.all()
        else:
            return []

    def get_target_display(self):
        if Target.PARTICIPANT in self.request.targets:
            return 'тендер'
        if Target.EXECUTION in self.request.targets:
            return 'контракт'
        return ''

    def get_need_more_display(self):
        return 'Да' if self.request.have_additional_requirement else 'Нет'

    @cached_property
    def isSmallSubject(self):
        category = NalogRu().get_subject_size(self.client.inn)
        return category in [1, 2]

    @cached_property
    def isMiddleSubject(self):
        category = NalogRu().get_subject_size(self.client.inn)
        return category in [3]

    @cached_property
    def isUnknownSubject(self):
        category = NalogRu().get_subject_size(self.client.inn)
        return category not in [1,2,3]

    def rule_answer(self, result):
        if isinstance(result, ScoringResult):
            return 1 if result.is_success else 0
        return 1 if result else 0

    def scoring(self):
        scoring = ScoringLogic(self.bank, self.request)
        sum = 0
        count = 0
        quarters = self.client.accounting_report.get_quarters_for_fill()
        for quarter in quarters:
            value = quarter.get_value(2110)
            if value != 0 and quarter.not_empty():
                sum += value
                count += 1
        quarters = self.get_quarters()
        last_period = quarters[0]
        if count > 0:
            test_9 = float(self.request.required_amount) / (sum / count) > 10
        else:
            test_9 = False
        test_10 = last_period.get_value(1150) <= 0
        return {
            'test_1': self.rule_answer(scoring.check_rules({
                'class': 'RegexFieldsMatch',
                'fields': ["request.client.inn"],
                'pattern': '01|05|06|07|09|15|20|91|92',
                'error_message': 'Банк не работает с клиентами из данного региона'
            })),
            'test_2': self.rule_answer(scoring.check_rules({
                'class': 'RegexFieldsMatch',
                'fields': ["request.tender.inn"],
                'pattern': '01|05|06|07|09|15|20|91|92',
                'error_message': 'Банк не работает с клиентами из данного региона'
            })),
            'test_3': self.rule_answer(scoring.check_rules({
                'class': 'OgrnScoring',
                'value': 183,
                'error_message': 'Компания зарегистрирована менее 6 месяцев назад'
            })),
            'test_4': self.rule_answer(scoring.check_rules({
                'class': 'NegativeQuartersValueScoring',
                'codes': [2400],
                'error_message': 'В строке 2400 бухгалтерской отчётности за завершенный'
                                 ' квартал имеют отрицательные значения.'
            })),
            'test_5': self.rule_answer(scoring.check_rules({
                'class': 'IsUnfairSupplierScoring',
                'error_message': 'Находится в реестре недобросовестных поставщиков'
            })),
            'test_6': self.rule_answer(scoring.check_rules({
                'class': 'DecisionSuspendScoring',
                'error_message': 'Имеются решения о приостановлении по счетам'
            })),
            'test_7': self.rule_answer(scoring.check_rules({
                'class': 'NalogStatusScoring',
                'error_message': 'Задолжности по налогам и сборам с сайта '
                                 'service.nalog.ru/zd.do'
            })),
            'test_8': self.rule_answer(scoring.check_rules({
                'class': 'IsBankrotScoring',
                'error_message': 'Задолжности по налогам и сборам с сайта '
                                 'service.nalog.ru/zd.do'
            })),
            'test_9': test_9,
            'test_10': test_10
        }

    def get_finance_test_1(self, period: Quarter):
        """
        Рентабельность деятельности Клиента
        (анализируется соотношение Чистой прибыли за Последний завершенный год
        к выручке за тот же период)
            - Низкая степень риска (1 балл) – рентабельность деятельности более 3%;
            - Умеренная степень риска (2 балла) – рентабельность деятельности
            от 1% до 3%;
            - Высокая степень риска (3 балла) – рентабельность деятельности
            от 0,5% до 1%;
            - Сверхвысокая степень риска (4 балла) – рентабельность деятельности
            от 0% до 0,5%.
        (Ф.2) (Стр.2400/Стр.2110)*100
        :param period:
        :return:
        """
        prev_value = period.get_value(2110)
        if prev_value != 0:
            value = period.get_value(2400) / period.get_value(2110) * 100
            percent = round(value, 2)
        else:
            value = 0
            percent = None

        if value > 3:
            score = 1
        elif 1 < value <= 3:
            score = 2
        elif 0.5 < value <= 1:
            score = 3
        else:
            score = 4

        return {
            'value1': period.get_value(2400),
            'value2': period.get_value(2110),
            'percent': percent,
            'result': score
        }

    def get_quarter_by_params(self, params):
        return self.client.accounting_report.get_quarter_by_params(params)

    def get_finance_test_2(self, last_year: Quarter):
        """
        Сокращение/прирост выручки (осуществляется сравнение выручки за Последний
        завершенный год с выручкой за предыдущий завершенный год)
            - Низкая степень риска (1 балл) – имеется рост выручки более 10 %;
            - Умеренная степень риска (2 балла) – отсутствует рост выручки или имеется
            рост выручки до 10 % включительно;
            - Высокая степень риска (3 балла) – имеется снижение выручки в диапазоне до
            20% включительно;
            - Сверхвысокая степень риска (4 балла) – имеется снижение выручки более
            чем на 20%.
        (Ф.2) (Стр.2110 последний ЗГ/Стр.2110 предыдущий ЗГ)*100
        :param last_year:
        :return:
        """
        prev_year = self.get_quarter_by_params(QuarterParameters(
            year=int(last_year.year) - 1,
            quarter=last_year.quarter
        ))

        if prev_year.not_empty() and last_year.not_empty():
            prev_value = prev_year.get_value(2110)
            if prev_value != 0:
                value = last_year.get_value(2110) / prev_value
            else:
                value = 0
            rost = value > 1
            value = math.fmod(value, 1) * 100
            if rost and value > 10:
                score = 1
            elif rost and 0 <= value <= 10:
                score = 2
            elif not rost and 0 <= value <= 20:
                score = 3
            else:
                score = 4
        else:
            score = 4

        return {
            'value1': last_year.get_value(2110),
            'value2': prev_year.get_value(2110),
            'result': score
        }

    def get_finance_test_3(self, last_period: Quarter):
        """
        Текущая прибыль/убыток (анализируется Чистая прибыль, рассчитанная нарастающим
        итогом, за последний завершенный квартал)
            - Низкая степень риска (1 балл) – имеется чистая прибыль;
            - Умеренная степень риска (2 балла) – чистая прибыль равна 0;
            - Высокая степень риска (4 балла) – имеются убытки в размере,
            не превышающем 5 % от выручки за тот же период;
            - Сверхвысокая степень риска (8 балла) – имеются убытки в размере,
            превышающем 5 % от выручки за тот же период.
        :return:
        """
        value = last_period.get_value(2110)
        value2 = last_period.get_value(2400)
        rost = abs(value) / value2 if value2 != 0 else 0
        if value > 0:
            score = 1
        elif value == 0:
            score = 2
        elif value < 0 and rost < 5:
            score = 4
        elif value < 0 and rost >= 5:
            score = 8
        else:
            score = 3
        return {
            'value1': value,
            'value2': value2,
            'result': score
        }

    def get_finance_test_4(self, last_year):
        """
        (анализируется доля Чистых активов за Последний завершенный год в
        валюте баланса за тот же период)
            - Низкая степень риска (1 балл) – доля > 30%;
            - Умеренная степень риска (2 балла) – доля в диапазоне от 15 до 30%;
            - Высокая степень риска (3 балла) – доля в диапазоне от 5 до 15%;
            - Сверхвысокая степень риска (4 балла) – доля < 5%.
        :param last_year:
        :return:
        """
        last_year_1600 = last_year.get_value(1600)
        v = last_year.get_value(1600) - (
                last_year.get_value(1400) +
                last_year.get_value(1500) +
                last_year.get_value(1530)
        )
        value = v / last_year_1600 * 100 if last_year_1600 != 0 else 0
        if value > 30:
            score = 1
        elif 15 < value <= 30:
            score = 2
        elif 5 < value <= 15:
            score = 3
        else:
            score = 4

        if last_year.get_value(1600) != 0:
            percent = round(v / last_year_1600 * 100, 2)
        else:
            percent = None
        return {
            'value1': v,
            'value2': last_year_1600,
            'percent': percent,
            'result': score
        }

    def get_finance_test_5(self):
        """
        Соответствие Контракта профильности деятельности
            - Низкая степень риска (1 балл) – контракт, в обеспечение которого
            запрашивается Гарантия, соответствует профильности деятельности Клиента,
            а так же имеется опыт исполнения контрактов аналогичного размера;
            - меренная степень риска (2 балла) – контракт, в обеспечение которого
            запрашивается Гарантия, соответствует профильности деятельности Клиента,
            при от-сутствии опыта исполнения контрактов аналогичного размера;
            - Высокая степень риска (4 балла) – контракт, в обеспечение которого
            запрашивается Гарантия,не соответствует профильности деятельности Клиента,
            но имеется опыт исполнения контрактов  аналогичного размера;
            - Сверхвысокая степень риска (6 балла) – контракт, в обеспечение которого
            запрашивается Гарантия, не соответствует профильности деятельности Клиента,
            при отсутствии опыта исполнения контрактов аналогичного размера.
        :return:
        """
        return {
            'value1': ' ',
            'value2': ' ',
            'result': 3
        }

    def get_finance_test_6(self):
        """
        Количество исполненных контрактов:
            - Низкая степень риска (1 балл) – более 7 исполненных контрактов;
            - Умеренная степень риска (2 балла) – от 5 до 7 исполненных контрактов;
            - Высокая степень риска (3 балла) – от 2 до 4 исполненных контрактов;
            - Сверхвысокая степень риска (6 баллов) – 1 исполненный контракт.
        :return:
        """
        finished_contracts = ContractsLogic(
            self.request.client
        ).get_finished_contracts_count()

        if finished_contracts > 7:
            score = 1
        elif 5 <= finished_contracts <= 7:
            score = 2
        elif 2 <= finished_contracts <= 4:
            score = 3
        else:
            score = 6

        return {
            'value1': finished_contracts,
            'value2': ' ',
            'result': score
        }

    def get_finance_test_7(self):
        """
        Кредитная история
            - Низкая степень риска (1 балл) – кредитная история положительная
            (факты просрочек отсутствуют);
            - Умеренная степень риска (2 балла) – кредитная история отсутствует
            либо имели место просрочки
            - платежей по кредитам сроком не более 30 дней (не более 1 раза);
            - Высокая степень риска (3 балла) – имели место просрочки платежей
            по кредитам (не более 2 раз);
            -Сверхвысокая степень риска (4 балла) – имели место просрочки платежей
            по кредитам (более 2 раз).
        :return:
        """
        return {
            'value1': ' ',
            'value2': ' ',
            'result': 3
        }

    @cached_property
    def finance_data(self):
        quarters = self.get_quarters()
        if quarters[0].id != quarters[1].id:
            return {
                'last_period': quarters[0],
                'last_year': quarters[1],
                'previous_year': self.get_previous_year_quarter()
            }
        return {
            'last_year': quarters[1],
            'previous_year': self.get_previous_year_quarter()

        }

    def get_last_period_name(self):
        if len(self.finance_data) > 2:
            return '%i кв %i' % (self.finance_data['last_period'].quarter,
                                 self.finance_data['last_period'].year)
        return ''

    def get_last_period_revenues(self):
        if len(self.finance_data) > 2:
            return self.finance_data['last_period'].get_value(2110)
        return ''

    def get_last_period_profit(self):
        if len(self.finance_data) > 2:
            return self.finance_data['last_period'].get_value(2400)
        return ''

    def get_last_year_name(self):
        return self.finance_data['last_year'].year

    def get_last_year_revenues(self):
        return self.finance_data['last_year'].get_value(2110)

    def get_last_year_profit(self):
        return self.finance_data['last_year'].get_value(2400)

    def get_previous_year_name(self):
        return self.finance_data['previous_year'].year

    def get_previous_year_revenues(self):
        return self.finance_data['previous_year'].get_value(2110)

    def get_previous_year_profit(self):
        return self.finance_data['previous_year'].get_value(2400)

    def get_analise_period_name(self):
        return '%i/ %s' % (self.get_previous_year_name(), self.get_last_period_name())

    def get_finance(self):
        quarters = self.get_quarters()
        last_period = quarters[0]
        last_year = quarters[1]
        data = {
            'test_1': self.get_finance_test_1(last_year),
            'test_2': self.get_finance_test_2(last_year),
            'test_3': self.get_finance_test_3(last_period),
            'test_4': self.get_finance_test_4(last_year),
            'test_5': self.get_finance_test_5(),
            'test_6': self.get_finance_test_6(),
            'test_7': self.get_finance_test_7(),
        }
        total_score = 0
        for d in data.values():
            total_score += d['result']

        if total_score > 25:
            finance_score = 'плохое'
            raiting = ''
        elif 14 < total_score <= 25:
            finance_score = 'хорошее'
            raiting = 'B'
        else:
            finance_score = 'хорошее'
            raiting = 'A'

        data['total_score'] = total_score
        data['finance_score'] = finance_score
        data['raiting'] = raiting
        return data

    @cached_property
    def executing_contracts(self):
        contracts = ContractsLogic(self.client).get_execution_contracts()
        data = {}
        for contract in contracts:
            d = parse_date(contract.get('start_date')).year
            data.setdefault(d, [])
            data[d].append(contract)

        data = [(k, data[k]) for k in sorted(data.keys())]
        result = []
        for year, d in data:
            result.append({
                'year': year,
                'count': len(d),
                'sum': reduce(lambda sum, el: sum + el.get('price'), d, 0)
            })
        return result

    @cached_property
    def _executing_contracts(self):
        return ContractsLogic(self.client).get_execution_contracts()

    def get_executing_contracts_count(self):
        return len(self._executing_contracts) or ''

    def get_executing_contracts_max(self):
        max_price = 0
        for contract in self._executing_contracts:
            if float(contract.price) > max_price:
                max_price = float(contract.price)
        return max_price or ''

    def get_executing_contracts_sum(self):
        return reduce(
            lambda sum, el: sum + float(el.price),
            self._executing_contracts, 0) or ''

    @cached_property
    def finished_contracts(self):
        contracts = ContractsLogic(self.client).get_finished_contracts()
        data = {}
        for contract in contracts:
            d = parse_date(contract.start_date).year
            data.setdefault(d, [])
            data[d].append(contract)

        data = [(k, data[k]) for k in sorted(data.keys())]
        result = []
        for year, d in data:
            result.append({
                'year': year,
                'count': len(d),
                'sum': reduce(lambda sum, el: sum + el.price, d, 0)
            })
        return result

    @cached_property
    def _finished_contracts(self):
        return ContractsLogic(self.client).get_finished_contracts()

    def get_finished_contracts_count(self):
        return len(self._finished_contracts) or ''

    def get_finished_contracts_max(self):
        max_price = 0
        for contract in self._finished_contracts:
            if float(contract.price) > max_price:
                max_price = float(contract.price)
        return max_price or ''

    def get_finished_contracts_sum(self):
        return reduce(
            lambda sum, el: sum + float(el.price),
            self._finished_contracts, 0) or ''

    def get_join_fl_shares(self):
        data = []
        for person in self.profile.profilepartnerindividual_set.filter(share__gt=0):
            data.append(person.full_name())
        return ', '.join(data)

    def has_dolg(self):
        result = ConclusionsLogic.get_conclusion_result(
            client=self.client,
            conclusion=HasArrearsOnPaymentOfTaxesConclusion
        )
        if result.result:
            return 'Негативные сведения отсутствуют'
        return 'найдены'

    def has_sro(self):
        return 1 if self.profile.has_license_sro or self.profile.is_member_sro else 0

    def last_contr_agents(self):
        limit = 3
        contracts = ContractsLogic(self.client).get_finished_contracts()
        count = 0
        output = []
        for contract in contracts:
            str = contract.issuer_name
            if str not in output:
                count += 1
                output.append(str + '\n')
            if count == limit:
                break
        return ', '.join(output)

    @property
    def organization_form(self):
        if self.client.is_individual_entrepreneur:
            return 'ИП'
        return self.profile.get_organization_form_display()

    def get_inn(self):
        return self.profile.reg_inn

    def get_reg_state_date(self):
        return self.profile.reg_state_date

    def get_authorized_capital_paid(self):
        return self.profile.authorized_capital_paid

    def get_notification_id(self):
        return self.request.tender.notification_id

    def get_federal_law(self):
        return self.request.tender.get_federal_law_display()[:-3]

    def get_interval_from(self):
        return self.request.interval_from

    def get_interval_to(self):
        return self.request.interval_to

    def get_interval(self):
        return self.request.interval

    def get_tender_subject(self):
        return self.request.tender.subject

    def get_suggested_price_amount(self):
        return '%.2f' % self.request.suggested_price_amount

    def get_suggested_price_percent(self):
        return '%.2f %%' % self.request.suggested_price_percent

    def get_beneficiar_full_name(self):
        egrul_data = EgrulData.get_info(self.request.tender.beneficiary_inn)
        if egrul_data:
            return egrul_data.get(
                'section-ur-lico', {}
            ).get('full-name-ur-lico', '') or self.profile.full_name
        return self.request.tender.beneficiary_name

    def get_beneficiar_name(self):
        return self.request.tender.beneficiary_name

    def getBeneficiars(self):
        return self.profile.beneficiars.filter(share__gte=21.5)

    def getPPersons(self):
        return self.profile.profilepartnerindividual_set.filter(share_gt=0)

    def getJPersons(self):
        return self.profile.profilepartnerlegalentities_set.filter(share_gt=0)

    def get_company_info(self):
        search = SearchTenderhelpApi()
        search_data = search.get_company_info(self.profile.reg_inn)
        fact_address = self.profile.fact_address_properies
        if not search_data:
            return {
                'inn': self.profile.reg_inn,
                'ogrn': self.profile.reg_ogrn,
                'kpp': self.profile.reg_kpp,
                'data': {
                    'inn': self.profile.reg_inn,
                    'kpp': self.profile.reg_kpp,
                    'OKPO': self.profile.reg_okpo,
                    'regNum': '',
                    'fullName': self.profile.full_name,
                    'legalForm': {},
                    'shortName': self.profile.short_name,
                    'factAddress': fact_address['address'],
                    'postAddress': self.profile.legal_address,
                    'customerCode': '',
                    'consRegistryNum': '',
                    'registrationDate': ''
                }
            }

        if not search_data['data']['fullName']:
            search_data['data']['fullName'] = self.profile.full_name
        if not search_data['data']['factAddress']:
            search_data['data']['factAddress'] = fact_address['address']
        if not search_data['data']['postAddress']:
            search_data['data']['factAddress'] = self.profile.legal_address
        return search_data

    def get_beneficiar_info(self):
        search = SearchTenderhelpApi()
        search_data = search.get_company_info(self.request.tender.beneficiary_inn)
        if not search_data:
            return {
                'inn': self.request.tender.beneficiary_inn,
                'ogrn': self.request.tender.beneficiary_ogrn,
                'kpp': self.request.tender.beneficiary_kpp,
                'data': {
                    'inn': self.request.tender.beneficiary_inn,
                    'kpp': self.request.tender.beneficiary_kpp,
                    'OKPO': '',
                    'regNum': '',
                    'fullName': self.request.tender.beneficiary_name,
                    'legalForm': {},
                    'shortName': self.request.tender.beneficiary_name,
                    'factAddress': self.request.tender.beneficiary_address,
                    'postAddress': self.request.tender.beneficiary_address,
                    'customerCode': '',
                    'consRegistryNum': '',
                    'registrationDate': ''
                }
            }

        if not search_data['data']['fullName']:
            search_data['data']['fullName'] = self.request.tender.beneficiary_name
        if not search_data['data']['factAddress']:
            search_data['data']['factAddress'] = self.request.tender.beneficiary_address
        if not search_data['data']['postAddress']:
            search_data['data']['factAddress'] = self.request.tender.beneficiary_address
        return search_data

    def getBenAddressFromEGRUL(self):
        egrul_data = EgrulData.get_info(self.request.tender.beneficiary_inn)
        if egrul_data:
            return egrul_data.get(
                'section-ur-adress', {}
            ).get('full_address', '') or self.request.tender.beneficiary_address
        return self.request.tender.beneficiary_address

    def date_last_finished_contract(self):
        max_end_date = None
        for contract in self._finished_contracts:
            end_date = contract.get('end_date')
            end_date = parse_date(end_date)
            if not max_end_date:
                max_end_date = end_date
            if end_date > max_end_date:
                max_end_date = end_date
        if max_end_date:
            return max_end_date.strftime('%d.%m.%Y')
        return ''

    def is_execution(self):
        return Target.EXECUTION in self.request.targets

    def is_participant(self):
        return Target.PARTICIPANT in self.request.targets

    def is_warranty(self):
        return Target.WARRANTY in self.request.targets

    def get_contract_type(self):
        return self.request.get_contract_type_display()

    def get_required_amount(self):
        return self.request.required_amount


import numpy as np
import matplotlib.pyplot as plt
from math import sqrt,sin,cos,asin,acos,sinh,cosh,asinh,acosh
from functools import lru_cache

def fastcross(a1,a2): #strict 3x3 vector cross product, much faster than np.cross
    return np.array([a1[1]*a2[2]-a1[2]*a2[1],a1[2]*a2[0]-a1[0]*a2[2],a1[0]*a2[1]-a1[1]*a2[0]])

def fastsum(arr):
    return arr[0]+arr[1]+arr[2]

def lambert(r1,r2,t,u=1.327e11): #km,kg,s
    r1,r2=np.asarray(r1),np.asarray(r2)
    c=r2-r1
    absr1,absr2=sqrt(fastsum(r1**2)),sqrt(fastsum(r2**2))
    absc=sqrt(fastsum(c**2))
    s=(absr1+absr2+absc)/2
    ir1,ir2=r1/absr1,r2/absr2
    ih=fastcross(ir1,ir2)
    ih/=sqrt(fastsum(ih**2)) #step not mentioned in paper
    lam=sqrt(1-round(absc/s,4))
    if ih[2]<0:
        lam*=-1
        it1,it2=fastcross(ir1,ih),fastcross(ir2,ih) #wrong in paper
    else: it1,it2=fastcross(ih,ir1),fastcross(ih,ir2) #wrong in paper
    T=sqrt(2*u/s**3)*t
    #sanity check:
    if T<=0: return np.array([np.nan,np.nan,np.nan]), np.array([np.nan,np.nan,np.nan])
    x,y=findxy(lam,T)
    gamma=sqrt(u*s/2)
    rho=(absr1-absr2)/absc
    sigma=sqrt(1-rho**2)
    vr1=gamma*((lam*y-x)-rho*(lam*y+x))/absr1
    vr2=-gamma*((lam*y-x)+rho*(lam*y+x))/absr2
    vt1,vt2=gamma*sigma*(y+lam*x)/absr1,gamma*sigma*(y+lam*x)/absr2
    v1,v2=vr1*ir1+vt1*it1,vr2*ir2+vt2*it2
    return v1,v2

def findxy(lam,T):
    T0=acos(lam)+lam*sqrt(1-lam**2)
    T1=2/3*(1-lam**3)
    if T>=T0: x=(T0/T)**(2/3)-1
    elif T<T1: x=5/2*T1*(T1-T)/T/(1-lam**5)+1
    else: x=(T0/T)**np.log2(T1/T0)-1 #T1<=T<T0
    y=sqrt(1-lam**2*(1-x**2))
    count=0
    while abs((funT(x,y,lam)-T)/T)>0.001:
        x=newton(x,y,lam,T)#Householder(x,y,lam,T)
        y=sqrt(1-lam**2*(1-x**2))
        count+=1
        if count>100: return np.nan, np.nan
    return x,y

def funT(x,y,lam): #0 is M
    if x<1:
        try: psi=acos(x*y+lam*(1-x**2))
        except ValueError: return np.nan
    #elif x>1: psi=np.arcsinh((y-x*lam)*sqrt(x**2-1))
    elif x>1: psi=acosh(x*y-lam*(x**2-1))
    else: return 2/3*(1-lam**3) # x==1
    return 1/(1-x**2)*((psi+0*np.pi)/sqrt(abs(1-x**2))-x+lam*y)

def newton(x,y,lam,T):
    fx=funT(x,y,lam)-T
    fprimex=(3*(fx+T)*x-2+2*lam**3*x/y)/(1-x**2)
    return x-fx/fprimex

def kep2cart(O,w,i,ec,a,nu,u=1.327e11): # converts orbital elements to cartesian position and velocity vectors, give inputs in deg or AU, returns in km and km/s
    w*=np.pi/180
    i*=np.pi/180
    O*=np.pi/180
    nu*=np.pi/180
    a/=6.68459e-9
    r=a*(1-ec**2)/(1+ec*cos(nu))
    h=sqrt(u*a*(1-ec**2))
    p=a*(1-ec**2)
    #~2x faster with one time calculated trig
    cosO=cos(O)
    coswnu=cos(w+nu)
    sinO=sin(O)
    sinwnu=sin(w+nu)
    cosi=cos(i)
    sini=sin(i)
    sinnu=sin(nu)
    pos=r*np.array([cosO*coswnu-sinO*sinwnu*cosi,
                    sinO*coswnu+cosO*sinwnu*cosi,
                    sini*sinwnu])
    velo=h/r*np.array([(pos[0]*ec/p*sinnu-(cosO*sinwnu+sinO*coswnu*cosi)),
                   (pos[1]*ec/p*sinnu-(sinO*sinwnu-cosO*coswnu*cosi)),
                   (pos[2]*ec/p*sinnu+coswnu*sini)])
    return pos,velo

def cart2kep(r,v,u=1.327e11): # converts cartesian coordinates to orbital elements, all inputs in m and m/s, outputs are in radians and AU, r is the periapsis position vector, v is the velocity vector at periapsis
    r,v=np.asarray(r),np.asarray(v)
    if np.isnan(v[0]): return np.nan,np.nan,np.nan,np.nan,np.nan,np.nan
    h=fastcross(r,v) # orbital momentum vector, perpendicular to orbital plane
    if h[0]==0 and h[1]==0: #zero inclination case, add slight perturbation to make math work
        v+=np.ones(3)*sqrt(fastsum(v**2))/1e7
        h=fastcross(r,v)
    evec=fastcross(v,h)/u-r/sqrt(fastsum(r**2)) #eccentricity vector
    ec=sqrt(fastsum(evec**2))
    n=fastcross([0,0,1],h) #vector to ascending node
    i=acos(h[2]/sqrt(fastsum(h**2)))
    if fastsum(r*v)>=0: nu=acos(round(fastsum(evec*r)/sqrt(fastsum(r**2)*fastsum(evec**2)),5))
    else: nu=2*np.pi-acos(round(fastsum(evec*r)/sqrt(fastsum(r**2)*fastsum(evec**2)),5))
    if n[1]>=0: O=acos(round(n[0]/sqrt(fastsum(n**2)),5))
    else: O=2*np.pi-acos(round(n[0]/sqrt(fastsum(n**2)),5))
    if evec[2]>=0: w=acos(round(fastsum(n*evec)/sqrt(fastsum(evec**2)*fastsum(n**2)),5))
    else: w=2*np.pi-acos(round(fastsum(n*evec)/sqrt(fastsum(evec**2)*fastsum(n**2)),5))
    a=1/((2/sqrt(fastsum(r**2)))-(fastsum(v**2)/u))
    return O*180/np.pi,w*180/np.pi,i*180/np.pi,ec,a*6.68459e-9,nu*180/np.pi #return O,w,i,ec,a,nu

def plotorb(O,w,i,ec,a,nu,label=''):
    plt.scatter(0,0,marker='*',c='gold',s=100)
    if ec<1:
        points=np.array([kep2cart(O,w,i,ec,a,nu)[0] for nu in np.linspace(0,360,num=360)])
        plt.plot(points[:,0],points[:,1],label=label)
        return
    else: return

def gen_ephemeris(epoch,M,O,w,inc,e,a,date,u=1.327e11):
    M=(date-epoch).item().days*24*3600/sqrt((a*1.496e8)**3/u)*180/np.pi+M
    E=M*np.pi/180 #inital guess
    count=0
    while np.abs(E-e*sin(E)-M*np.pi/180)>1e-3:
        E-=(E-e*sin(E)-M*np.pi/180)/(1-e*cos(E))
        count+=1
        if count>100: return np.array([np.nan,np.nan,np.nan]),np.array([np.nan,np.nan,np.nan])
    E=E%(2*np.pi)
    #print(E*180/np.pi)
    nu=acos((cos(E)-e)/(1-e*cos(E)))*180/np.pi
    if E>np.pi: nu=360-nu
    return kep2cart(O,w,inc,e,a,nu)

@lru_cache(maxsize=2000)
def DeltaV2Burn(epoch,M,node,peri,inc,e,a,date,tof,planet='mars',plot=0):
    if planet=='mars':
        vpark=2.1376
        vesc=3.023
        localephem=gen_ephemeris(np.datetime64('2000-01-01'),355.45332,49.57854,336.04084,1.85061,0.09341233,1.52366231,date)
    else:
        vpark=7.6723634
        vesc=10.8503604
        localephem=gen_ephemeris(np.datetime64('2000-01-01'),100.46435,-11.26064,102.94719,0.00005,0.01671022,1.00000011,date)
    targetephem=gen_ephemeris(epoch,M,node,peri,inc,e,a,date+tof)
    v1,v2=lambert(localephem[0],targetephem[0],tof*24*3600)
    vinfinity=sqrt(fastsum((localephem[1]-v1)**2))
    DeltaV1=sqrt(vinfinity**2+vesc**2)-vpark
    DeltaV2=sqrt(fastsum((targetephem[1]-v2)**2))
    if plot==1:
        print(f"{DeltaV1+DeltaV2:.3f} km/s = {DeltaV1:.3f} km/s + {DeltaV2:.3f} km/s")
        print(f"Launch date: {date}, Arrive in {tof} days")
        plt.scatter(localephem[0][0],localephem[0][1])
        plt.scatter(targetephem[0][0],targetephem[0][1])
        plt.scatter(0,0,c='gold',marker='*')
        plotorb(*cart2kep(*localephem))
        plotorb(*cart2kep(*targetephem))
        plotorb(*cart2kep(localephem[0],v1))
        plt.axis('equal')
        plt.show()
    return DeltaV1+DeltaV2

@lru_cache(maxsize=2000)
def DeltaV3Burn(epoch,M,node,peri,inc,e,a,date,tof,planet='mars',u=1.327e11,plot=0):
    if planet=='mars':
        vpark=2.1376
        vesc=3.023
        localephem=gen_ephemeris(np.datetime64('2000-01-01'),355.45332,49.57854,336.04084,1.85061,0.09341233,1.52366231,date)
    else:
        vpark=7.6723634
        vesc=10.8503604
        localephem=gen_ephemeris(np.datetime64('2000-01-01'),100.46435,-11.26064,102.94719,0.00005,0.01671022,1.00000011,date)
    targetephem=gen_ephemeris(epoch,M,node,peri,inc,e,a,date+tof)
    #set semimajor axis of transfer orbit, then execute broken plane maneuver when halfway in angle in plane of starting orbit between origin and target
    #rotate target vector into the plane of the starting orbit
    planenormal=fastcross(localephem[0],localephem[1])/sqrt(fastsum(localephem[0]**2)*fastsum(localephem[1]**2))
    targetinplane=targetephem[0]-fastsum(targetephem[0]*planenormal)*planenormal
    targetinplane*=sqrt(fastsum(targetephem[0]**2)/fastsum(targetinplane**2))
    #Calulate first burn
    v1,v2=lambert(localephem[0],targetinplane,tof*24*3600)
    vinfinity=sqrt(fastsum((localephem[1]-v1)**2))
    DeltaV1=sqrt(vinfinity**2+vesc**2)-vpark
    transorb=cart2kep(localephem[0],v1)
    if np.isnan(transorb[0]): return np.nan
    if transorb[3]>1: return np.nan #discard hyperbolic case, not worth it
    #when halfway in angle to target rotated into plane: execute broken plane manuever
    try: fullangle=acos(round(fastsum(localephem[0]*targetinplane)/sqrt(fastsum(localephem[0]**2)*fastsum(targetinplane**2)),5)) #radians
    except ValueError: return np.nan
    if fastcross(localephem[0],targetinplane)[2]<0: fullangle=2*np.pi-fullangle
    halfway=kep2cart(*transorb[:5],transorb[5]+fullangle*180/np.pi/2)
    #calculate remaining tof
    Estart=acos((transorb[3]+cos(transorb[5]*np.pi/180))/(1+transorb[3]*cos(transorb[5]*np.pi/180))) #radians
    Mstart=Estart-transorb[3]*sin(Estart) #radians
    Ehalf=acos((transorb[3]+cos(transorb[5]*np.pi/180+fullangle/2))/(1+transorb[3]*cos(transorb[5]*np.pi/180+fullangle/2))) #radians
    Mhalf=Ehalf-transorb[3]*sin(Ehalf) #radians
    meanmotion=sqrt(u/(transorb[4]*1.496e8)**3) #radians/sec
    deltat=np.abs(Mhalf-Mstart)%(2*np.pi)/meanmotion #sec
    #calculate broken plane maneuver
    v3,v4=lambert(halfway[0],targetephem[0],tof*24*3600-deltat)
    DeltaV2=sqrt(fastsum((halfway[1]-v3)**2))
    DeltaV3=sqrt(fastsum((targetephem[1]-v4)**2))
    if plot==1:
        print(f"{DeltaV1+DeltaV2+DeltaV3:.3f} km/s = {DeltaV1:.3f} km/s + {DeltaV2:.3f} km/s + {DeltaV3:.3f} km/s")
        print(f"Launch date: {date}, Arrive in {tof} days")
        #print(fullangle*180/np.pi)
        plt.scatter(localephem[0][0],localephem[0][1])
        plt.scatter(targetephem[0][0],targetephem[0][1])
        plt.scatter(halfway[0][0],halfway[0][1])
        plt.scatter(0,0,c='gold',marker='*')
        plotorb(*cart2kep(*localephem))
        plotorb(*cart2kep(*targetephem))
        plotorb(*transorb)
        plt.axis('equal')
        plt.show()
    return DeltaV1+DeltaV2+DeltaV3

def rotatevector(a,b,theta): #rotate a theta radians around b
    a=np.asarray(a).astype(float)
    b=np.asarray(b).astype(float)
    b/=sqrt(fastsum(b**2))
    projab=fastsum(a*b)*b
    perpproj=a-projab
    crossvec=fastcross(b,perpproj)
    return projab+perpproj*cos(theta)+sqrt(fastsum(perpproj**2))*crossvec/sqrt(fastsum(crossvec**2))*sin(theta)

def earth2mars(O,w,i,ec,a): #rotate orbit from earth-ecliptic orbital elements to mars-ecliptic orbital elements
    target=kep2cart(O,w,i,ec,a,0)
    marsnode=kep2cart(49.57854,336.04084-49.57854,1.85061,0.09341233,1.52366231,0-(336.04084-49.57854))
    targetmarsframe=rotatevector(target[0],marsnode[0],-1.85061*np.pi/180)
    targetvmarsframe=rotatevector(target[1],marsnode[0],-1.85061*np.pi/180)
    return cart2kep(targetmarsframe,targetvmarsframe)

# 2 Burn Method, targets both ascending and descending nodes, then chooses the one with a lower delta-v

def DeltaV2BurnTest(O,w,i,ec,a,planet='mars',u=1.327e11):
    DeltaVlist=[]
    if planet=='mars':
        vpark=2.1376
        vesc=3.023
        #rotate asteroid orbit into Mars frame of reference
        targetorb=earth2mars(O,w,i,ec,a)
    else:
        vpark=7.672363406552731
        vesc=10.850360385001911
        targetorb=np.array([O,w,i,ec,a])
    for node in [0,180]:
        targetephem=kep2cart(*targetorb[:5],node-targetorb[1])
        if planet=='mars': localephem=kep2cart(49.57854,336.04084-49.57854,0,0.09341233,1.52366231,180-node+targetorb[0]-336.04084+1e-2) #+1e-2 is to force lambert solver to work nicely
        else: localephem=kep2cart(-11.26064,102.94719,0.00005,0.01671022,1.00000011,180-node+targetorb[0]-(-11.26064+102.94719)+1e-2) #+1e-2 is to force lambert solver to work nicely
        a_transfer=0.5*(sqrt(fastsum(localephem[0]**2))+sqrt(fastsum(targetephem[0]**2)))
        tof=np.pi*sqrt(a_transfer**3/u)
        v1,v2=lambert(localephem[0],targetephem[0],tof)
        vinfinity=sqrt(fastsum((localephem[1]-v1)**2))
        DeltaV1=sqrt(vinfinity**2+vesc**2)-vpark
        DeltaV2=sqrt(fastsum((targetephem[1]-v2)**2))
        DeltaVlist.append(DeltaV1+DeltaV2)
    return min(DeltaVlist)

# 3 Burn Method, targets both apoapsis and periapsis, then chooses the one with a lower delta-v

def DeltaV3BurnTest(O,w,i,ec,a,planet='mars',u=1.327e11):
    if planet=='mars':
        vpark=2.1376
        vesc=3.023
        localperi=kep2cart(49.57854,336.04084-49.57854,1.85061,0.09341233,1.52366231,0)
    else:
        vpark=7.672363406552731
        vesc=10.850360385001911
        localperi=kep2cart(-11.26064,102.94719,0.00005,0.01671022,1.00000011,0)
    normalvec=fastcross(localperi[0],localperi[1])/np.sqrt(fastsum(localperi[0]**2)*fastsum(localperi[1]**2))
    peri=kep2cart(O,w,i,ec,a,0)
    peri_local_plane=peri[0]-fastsum(peri[0]*normalvec)*normalvec
    localnu_offset=acos(fastsum(localperi[0]*peri_local_plane)/np.sqrt(fastsum(localperi[0]**2)*fastsum(peri_local_plane**2)))*180/np.pi
    if fastcross(localperi[0],peri_local_plane)[2]<0: localnu_offset=360-localnu_offset
    DeltaVlist=[]
    for apsis in [0,180]:
        targetephem=kep2cart(O,w,i,ec,a,apsis)
        if planet=='mars': localephem=kep2cart(49.57854,336.04084-49.57854,1.85061,0.09341233,1.52366231,180-apsis+localnu_offset+1e-2) #+1e-2 is to force lambert solver to work nicely
        else: localephem=kep2cart(-11.26064,102.94719,0.00005,0.01671022,1.00000011,180-apsis+localnu_offset+1e-2) #+1e-2 is to force lambert solver to work nicely
        a_transfer=0.5*(sqrt(fastsum(localephem[0]**2))+sqrt(fastsum(targetephem[0]**2)))
        tof=np.pi*sqrt(a_transfer**3/u)
        targetinplane=targetephem[0]-fastsum(targetephem[0]*normalvec)*normalvec
        targetinplane*=sqrt(fastsum(targetephem[0]**2)/fastsum(targetinplane**2))
        v1,v2=lambert(localephem[0],targetinplane,tof)
        vinfinity=sqrt(fastsum((localephem[1]-v1)**2))
        DeltaV1=sqrt(vinfinity**2+vesc**2)-vpark
        transorb=cart2kep(localephem[0],v1)
        if transorb[3]>1: return np.nan #discard hyperbolic case, not worth it
        #when halfway in angle to target rotated into plane: execute broken plane manuever
        halfway=kep2cart(*transorb[:5],transorb[5]+90)
        #calculate remaining tof
        Estart=acos((transorb[3]+cos(transorb[5]*np.pi/180))/(1+transorb[3]*cos(transorb[5]*np.pi/180))) #radians
        Mstart=Estart-transorb[3]*sin(Estart) #radians
        Ehalf=acos((transorb[3]+cos(transorb[5]*np.pi/180+np.pi/2))/(1+transorb[3]*cos(transorb[5]*np.pi/180+np.pi/2))) #radians
        Mhalf=Ehalf-transorb[3]*sin(Ehalf) #radians
        meanmotion=sqrt(u/(transorb[4]*1.496e8)**3) #radians/sec
        deltat=np.abs(Mhalf-Mstart)%(2*np.pi)/meanmotion #sec
        #calculate broken plane maneuver
        v3,v4=lambert(halfway[0],targetephem[0],tof-deltat)
        DeltaV2=sqrt(fastsum((halfway[1]-v3)**2))
        DeltaV3=sqrt(fastsum((targetephem[1]-v4)**2))
        DeltaVlist.append(DeltaV1+DeltaV2+DeltaV3)
    return min(DeltaVlist)


from zope import schema
from zope.interface import Interface
from zope.i18nmessageid import MessageFactory

_ = MessageFactory('collective.tinymceplugins.imagebrowser')

class ITinyMCELibrariesImageResources(Interface):
    """Plone registry entries to register TinyMCE image browser resources.
    """

    imagebrowser_resources = schema.List(title=_(u"Image Resources"),
                              required=False,
                              value_type=schema.TextLine(),
                              default=[],
                              missing_value=[])


from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from .serializers import PortfolioSerializer, BusinessSerializer, Portfolio
from account.utils import BaseResponse, abort
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser

from django.http import QueryDict

# Create your views here.
class PortfolioView(APIView):
    permission_classes = (IsAuthenticated,)
    parser_classes = [MultiPartParser]
    serializer_class = PortfolioSerializer

    def post(self, request):
        print(request.user.id)

        # Create a mutable copy of request.data
        mutable_data = QueryDict('', mutable=True)
        mutable_data.update(request.data)

        # Assign the service_provider
        mutable_data['service_provider'] = request.user.id

        serializer = self.serializer_class(data=mutable_data, context={'request': request})

        print(request.data)
        try:

            serializer.is_valid(raise_exception=True)
            print(serializer.validated_data)
            serializer.save()
            base_response = BaseResponse(serializer.data, None, 'Portfolio created successfully')
            return Response(base_response.to_dict())
        except Exception as e:
            return abort(400, str(e))

class BusinessView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        print(request.user.id)
        request.data['service_provider'] = request.user.id
        serializer = BusinessSerializer(data=request.data, context={'request': request})
        try:
            serializer.is_valid(raise_exception=True)
            # print(serializer.data)
            print(serializer.validated_data)
            serializer.save()
            base_response = BaseResponse(serializer.data, None, 'Business created successfully')
            return Response(base_response.to_dict())
        except:

            return abort(400, serializer.errors)


import boto3
from .aws_boto_session import BotoSession

class SSMGlobalParameters(BotoSession):
    """Query SSM for Global Parameters.

    Methods to retrieve Global SSM data.

    Methods
    ----------
    get_regions(DetailLevel='low')
        Returns list of regions
    """

    # ==========================================================
    def __init__(self, **kwargs):

        # Global Parameters.
        self.service_name = 'ssm'
        self.path = '/aws/service/global-infrastructure/regions'
        self.info = []
        self.list = []

        # Connect to SSM
        self.boto = boto3.client('ssm')

    # ==========================================================
    def _query_ssm_for_region_data(self):

        # Query SSM for region info.
        resp = self.boto.get_parameters_by_path(
            Path=self.path
        )

        # Add response 'Parameters' to info list.
        self.info.extend(resp['Parameters'])

        # Continue to query until no NextToken present.
        while 'NextToken' in resp:
            resp = self.boto.get_parameters_by_path(
                Path=self.path,
                NextToken=resp['NextToken']
            )

            # Add response 'Parameters' to info list.
            self.info.extend(resp['Parameters'])

    # ==========================================================
    # Return low detail level
    def _get_detail_low(self):
        for i in self.info:
            self.list.append(
                i.get('Value', None)
            )

        return self.list

    # ==========================================================
    # Get regions.
    def get_regions(self, DetailLevel='low'):
        """Generates list of regions

        Parameters
        ----------
        DetailLevel : str, optional
            Level of detail in returned list, can be 'high' or 'low'
            Defaults to 'low'
        """

        # Auto-generate data.
        self._query_ssm_for_region_data()

        # Return level of data based on arguments.
        if DetailLevel.lower() == 'high':
            return self.info
        else:
            return self._get_detail_low()


import argparse
import os
from pathlib import Path
from app import *

# Parse args ('-z' for location of zip file)
# Return location of zip file and project's name
def get_from_cli():
    parser = argparse.ArgumentParser()

    parser.add_argument('-z', '--zipfile',
                        required=True,
                        help="Project's ZIP file")
    args = parser.parse_args()

    if not os.path.basename(args.zipfile).endswith('.zip'):
        print("Not in ZIP format!\nExiting...")
        exit()
    elif not os.path.isfile(args.zipfile):
        print("File does not exist!\nExiting...")
        exit()
    else:
        return args.zipfile, Path(args.zipfile).stem

if __name__ == '__main__':
    zipfile, prj_name = get_from_cli()
    test = Application(zipfile, prj_name)
    print(test.scan())


import tkinter as tk
import os
from PIL import ImageTk, Image

class ToggleButton(tk.Frame):

    def __init__(self, parent, controller, size, bg='#92D050', command=None, state='off',
                 on_command=None, off_command=None):
        super().__init__(master=parent, bg=bg, width=size[0], height=size[1])
        self.parent = parent
        self.controller = controller
        self.size = size
        self.state = state
        self.off_command = off_command
        self.on_command = on_command

        self.off_pic = ImageTk.PhotoImage(
            self.controller.pictures['toggle_off'].resize(self.size), master=self.controller)
        self.on_pic = ImageTk.PhotoImage(
            self.controller.pictures['toggle_on'].resize(self.size), master=self.controller)

        self.layout()

    def layout(self):
        current_pic = self.off_pic
        if self.state == 'on':
            current_pic = self.on_pic
        canvas = tk.Canvas(self, width=self.size[0], height=self.size[1],
                           bg='#92D050', bd=0, highlightthickness=0, relief='ridge', cursor='hand2')
        pic = canvas.create_image(0, 0, anchor=tk.NW, image=current_pic)
        canvas.image = current_pic

        canvas.pack(fill=tk.BOTH, expand=True)

        global on_p
        on_p = False

        def bind_canvas_click(*args):
            global on_p
            if on_p == False:
                return
            if self.state == 'off':
                canvas.itemconfig(pic, image=self.on_pic)
                canvas.image = self.on_pic
                self.state = 'on'
                try:
                    self.on_command()
                except Exception as ex:
                    print(ex)
                    pass

            else:
                canvas.itemconfig(pic, image=self.off_pic)
                canvas.image = self.off_pic
                self.state = 'off'
                try:
                    self.off_command()
                except Exception as ex:
                    print(ex)
                    pass

        def bind_enter(*args):
            global on_p
            on_p = True

        def bind_leave(*args):
            global on_p
            on_p = False
        canvas.bind('<ButtonRelease-1>', bind_canvas_click)
        canvas.bind('<Enter>', bind_enter)
        canvas.bind('<Leave>', bind_leave)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jun 22 14:32:24 2021

@author: ran
"""

import cv2
import numpy as np
import face_recognition
import os

path="database"
images=[]
classNames=[]
mylist= os.listdir(path)
print(mylist)

for clas in mylist:
    curImg=cv2.imread(f'{path}/{clas}')
    print(len(curImg))
    images.append(curImg)
    classNames.append(os.path.splitext(clas)[0])
print(classNames)

def findEncodings(images):
    encodeList=[]
    for img in images:
        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
        encode=face_recognition.face_encodings(img)[0]
        encodeList.append(encode)
        #faceLoc= face_recognition.face_locations(img)[0]
        return encodeList

encodeListKnown=findEncodings(images)
print(len(encodeListKnown))
#cv2.rectangle(imageElon,(faceLoc1[3],faceLoc1[0],faceLoc1[1],faceLoc1[2]),(255,0,255), 2)


import paho.mqtt.client as mqtt #import the client1
import time
from smartcard.System import readers
from smartcard.util import toHexString, toASCIIString, toBytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import time
import sys

def generateFinalKnowledge(k1, k2):
    master_key = bytes(b1 ^ b2 for (b1, b2) in zip(k1, k2)) # to have completion of final knowledge
    return master_key

def acquireK1():
    f = open(sys.argv[1], "rb")
    k1 = f.read()
    f.close()
    return k1

def waitCard(connection):
    try:
        connection.connect()
        return True
    except:
        print("Waiting smartcard")
        return False

def readCard(connection):
    end = False
    i = 1 # start from sector 1
    typefield = ""
    payload = ""
    while not end:
    # decrypt first block of sector with key. if succeed, sector is unlocked
    # if other sector is unlocked, previous sector is locked
        COMMAND = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, i*4, 0x60, 0x00]
        data, sw1, sw2 = connection.transmit(COMMAND)
        if (sw1, sw2) == (0x90, 0x0):
            #print("Status: Decryption sector "+ str(i) +" using key #0 as Key A successful.")
            print()
        elif (sw1, sw2) == (0x63, 0x0):
            #print("Status: Decryption sector "+ str(i) +" failed. Trying as Key B")
            COMMAND = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, i*4, 0x61, 0x00]
            data, sw1, sw2 = connection.transmit(COMMAND)
        if (sw1, sw2) == (0x90, 0x0):
            #print("Status: Decryption sector "+ str(i) +" using key #0 as Key B successful.")
            print()
        elif (sw1, sw2) == (0x63, 0x0):
            print("Status: Decryption sector "+ str(i) +" failed.")
            sys.exit()

        #print("---------------------------------Sector "+ str(i) +"---------------------------------")
        for block in range(i*4, i*4+3): # because last block of each sector is the key
            COMMAND = [0xFF, 0xB0, 0x00]
            COMMAND.append(block)
            COMMAND.append(16)
            data, sw1, sw2 = connection.transmit(COMMAND)
            blockdata = toHexString(data).replace(" ","")
            if(block==4): # first block

                ndefFormat = False
                j = 1
                while(not ndefFormat):
                    if(blockdata[2*(j-1):2*j]!="03"):
                        if(blockdata[2*(j-1):2*j]=="00"):
                            #print("Ignore byte #" + str(j))
                            j = j + 1
                        else:
                            print("NO ndef format found")
                            sys.exit()
                    else:
                        ndefFormat = True

                length = blockdata[j*2:(j+1)*2]
                if(length=="00"):
                    print("NO value")
                    sys.exit()
                if(length=="FF"):
                    j = j + 1
                    length = int(blockdata[j*2:(j+2)*2],16)
                else:
                    length = int(blockdata[j*2:(j+1)*2],16)
                #print("Total length = " + str(length))

                j=j+2
                typelength = blockdata[j*2:(j+1)*2]
                if(typelength=="00"):
                    print("NO type field")
                if(typelength=="FF"):
                    j = j + 1
                    typelength = int(blockdata[j*2:(j+2)*2],16)
                else:
                    typelength = int(blockdata[j*2:(j+1)*2],16)
                #print("Type length = " + str(typelength))

                j = j + 1
                payloadlength = blockdata[j*2:(j+1)*2]
                if(payloadlength=="FF"):
                    j = j + 1
                    payloadlength = int(blockdata[j*2:(j+2)*2],16)
                else:
                    payloadlength = int(blockdata[j*2:(j+1)*2],16)
                #print("Payload length = " + str(payloadlength))

                j = j + 1
                if(j<16):
                    if(typelength+j>=16):
                        typefield = typefield + blockdata[j*2:]
                    else:
                        typefield = typefield + blockdata[j*2:j*2+typelength*2]
                        payload = payload + blockdata[j*2+typelength*2:]
                        payloadlength = payloadlength - (16 - j - typelength)
                    typelength = typelength - (16 - j)
                    #print("Type length = " + str(typelength))
            else:
                #print("Payload length = " + str(payloadlength))
                if(typelength>0): # not first block but typefield to read
                    if(typelength<=16):
                        if(typelength==16):
                            typefield = typefield + blockdata
                        else:
                            typefield = typefield + blockdata[:typelength*2]
                            payload = payload + blockdata[typelength*2:]
                            payloadlength = payloadlength - (16-typelength)
                        typelength = 0
                    else:
                        typefield = typefield + blockdata
                        typelength -= 16
                else:
                    if(payloadlength<=16):
                        payload += blockdata[:payloadlength*2]
                        payloadlength = 0
                        end = True
                    else:
                        payload += blockdata
                        payloadlength -= 16

            #print("block "+ str(block) +":\t"+ toHexString(data) +" | "+''.join(chr(j) for j in data))

        #print("Status words: %02X %02X" % (sw1, sw2))
        if (sw1, sw2) == (0x90, 0x0):
            #print("Status: The operation completed successfully.")
            ok = True
        elif (sw1, sw2) == (0x63, 0x0):
            #print("Status: The operation failed. Maybe auth is needed.")
            ok = False

        i = i+1

    typestring = toASCIIString(toBytes(typefield))
    #print(payload)
    k2 = bytearray.fromhex(payload)
    return k2, typestring

k1 = acquireK1()

r = readers()
if len(r) < 1:
	print("error: No readers available!")
	sys.exit()

#print("Available readers: ", r)

reader = r[0]
#print("Using: ", reader)

connection = reader.createConnection()
while(True):
    if(waitCard(connection)):
        print("Smartcard revealed")
        break
    else:
        time.sleep(5)
        continue

k2, typestring = readCard(connection)
#print("Type: " + typestring)
print("K1 = ", k1.hex())
print("K2 = ", k2.hex())

master_key = generateFinalKnowledge(k1, k2)
print("MK = ", master_key.hex())

############
def on_message(client, userdata, message):
    decipher = AES.new(master_key, AES.MODE_ECB)
    encryptedmessage = message.payload
    paddedtext = decipher.decrypt(encryptedmessage)
    originalmessage = unpad(paddedtext, AES.block_size).decode("utf-8", "ignore")
    print("Message received =", str(encryptedmessage.hex()))
    print('Message decrypted =', str(originalmessage))
############

broker_address="broker.hivemq.com"
print("Creating new subscriber instance")
client = mqtt.Client("braintech_subscriber") #create new instance
client.on_message=on_message #attach function to callback
#print("connecting to broker")
client.connect(broker_address) #connect to broker
client.loop_start() #start the loop
print("Subscribing to topic","braintech/masterdegree/test")
client.subscribe("braintech/masterdegree/test")
time.sleep(30) #wait
client.loop_stop() #stop the loop