from brownie import CannaBudsBootleggerBall, network
from scripts.helpful_scripts import LOCAL_BLOCKCHAIN_ENVIRONMENTS, get_account
from scripts.cannabuds.deploy_contract import deploy_contract
import pytest

from web3 import Web3

def test_setting_open_close_sale():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("Test only used for local testing")

    contract = deploy_contract()
    assert contract.saleIsActive() == False
    contract.openSale({"from": get_account()})
    assert contract.saleIsActive() == True
    contract.closeSale({"from": get_account()})
    assert contract.saleIsActive() == False

def test_setting_open_close_whitelist():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("Test only used for local testing")

    contract = deploy_contract()
    assert contract.whitelistActive() == False
    contract.openWhitelist({"from": get_account()})
    assert contract.whitelistActive() == True
    contract.closeWhitelist({"from": get_account()})
    assert contract.whitelistActive() == False

def test_token_uri():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("Test only used for local testing")

    contract = deploy_contract()
    api_url = "https://www.cannabuds.io/api/"

    contract.setBaseURI(api_url)
    token_id = 5

    assert contract.baseURI() == api_url
    assert contract.tokenURI(5) == contract.baseURI() + str(5)

def test_set_token_price():
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("Test only used for local testing")

    contract = deploy_contract()
    assert contract.tokenPrice() == Web3.toWei(0.042, "ether")
    contract.setTokenPrice(Web3.toWei(0.01, "ether"), {"from": get_account()})
    assert contract.tokenPrice() == Web3.toWei(0.01, "ether")


import vlc
import argparse
import math
import time

parser = argparse.ArgumentParser(description='Convert speech audio to text using Google Speech API')
parser.add_argument('in_filename', help='Input filename (`-` for stdin)')
args = parser.parse_args()

Instance = vlc.Instance()
player = Instance.media_player_new()
media = Instance.media_new(args.in_filename)
media.add_option('start-time=120.0')
media.get_mrl()

player.set_media(media)
player.play()
time.sleep(10)
while player.is_playing():
    time.sleep(1)


# -*- coding: utf-8 -*-

from peewee import *
from config import *
from db_utils.db_init import database

class BaseModel(Model):
    class Meta:
        database = database
        order_by = ('created_at',)

class OnPoint(BaseModel):
    """
    Online Point - Point for online quest mode.
        id: Point number in order of completion. The first Point has id 0. The first and last points are just plugs
        name: Point's name by the scenario
        task: Text of task
        score: score that team getting after completing the task without mistakes
        attempts: Attempts count for current Point
        right_answer: right answer for current task
        artifacts: artifacts count for completing
    """
    id = IntegerField(unique=True)
    name = TextField()
    task = TextField()
    score = IntegerField()
    attempts = IntegerField()
    right_answer = TextField()
    artifacts = IntegerField()

class OffPoint(BaseModel):
    """
    Offline Point - Point for offline quest mode.
        id: Point number in order of completion. The first Point has id 0. The first and last points are just plugs
        name: Point's name by the scenario
        start_code: check-in code for current point
        finish_code: check-out code for current point
        task: Text of task
        score: score that team getting after completing the task without mistakes
        section: section point number for dividing in offline part
        fast: time(in minutes) for completing point in good case
        middle: time(in minutes) for completing point in middle case
        slow: time(in minutes) for completing point in bad case
    """
    id = IntegerField()
    section = IntegerField()
    name = TextField()
    start_code = TextField(unique=True)
    finish_code = TextField(unique=True)
    task = TextField()
    score = IntegerField()
    fast = IntegerField()
    middle = IntegerField()
    slow = IntegerField()

class Team(BaseModel):
    """
    Model for team.
        chat_id: telegram chat id
        name: team name
        participants: count of participants
        on_score: current score for online-mode game
        off_score: current score for offline-mode game
        on_point: current number of online-point
        off_point: current number of offline-point
        attempt_num: current point completing attempt number
        artifacts: count of artifacts
        status: game status of the team
        section: section team number for dividing teams in offline part
        cur_start_time: start date-time of current offline-mode point
        bot_reaction: users' plain text bot reactions(ON/OFF)
        responding: Flag if team is responding for a task
    """
    chat_id = IntegerField(unique=True)
    name = TextField()
    participants = IntegerField()
    on_score = IntegerField(default=0)
    off_score = IntegerField(default=0)
    on_point = IntegerField(default=0)
    off_point = IntegerField(default=0)
    attempt_num = IntegerField(default=0)
    artifacts = IntegerField(default=0)
    status = IntegerField(default=ONLINE_GAME_OFF)
    section = IntegerField(default=0)
    cur_start_time = DateTimeField(null=True)
    bot_reaction = BooleanField(default=True)
    responding = BooleanField(default=False)

class OffReaction(BaseModel):
    """
    Message as reaction on some user actions. For offline mode.
        text: Text of reaction
        point_num: point that current reaction applies to
        order_num: number in order.
                1 - RIGHT_ANSWER
                2 - WRONG_ANSWER
                3 - LOSE
    """
    id = AutoField()
    text = TextField()
    point_num = IntegerField()
    order_num = IntegerField()

class OnReaction(BaseModel):
    """
    Message as reaction on some user actions. For online mode.
        text: Text of reaction
        point_num: number of point that current reaction applies to
        order_num: number in order.
                1 - RIGHT_ANSWER
                2 - WRONG_ANSWER
                3 - LOSE
    """
    id = AutoField()
    text = TextField()
    point_num = IntegerField()
    order_num = IntegerField()

class File(BaseModel):
    """
    File Model.
        file_id: telegram file id
        point: Point that current file applies to
        order_num: file number in order
        file_type: type of file
    """
    id = AutoField()
    file_id = TextField()
    point = ForeignKeyField(OnPoint, backref='file_point')
    order_num = IntegerField()
    file_type = IntegerField()


from setuptools import setup

with open("README.md", "r") as fp:
    long_description = fp.read()

setup(
    name="bax",
    version="0.1.12",
    packages=["bax"],
    url="https://github.com/rystrauss/bax",
    license="LICENSE",
    author="Ryan Strauss",
    author_email="ryanrstrauss@icloud.com",
    description="A flexible trainer interface for Jax and Haiku.",
    python_requires=">=3.7",
    long_description=long_description,
    long_description_content_type="text/markdown",
    install_requires=[
        "dm-haiku>=0.0.6",
        "jax>=0.3.13",
        "optax>=0.1.2",
        "jmp>=0.0.2",
        "chex>=0.1.3",
        "keras>=2.9.0",
        "tensorflow>=2.9.0",
        "rich>=12.4.1",
    ],
)


from sqlalchemy.sql import select
from .db.schema import Users, UserTokens, Transactions, UserOperationStatus
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy import create_engine, func
from sqlalchemy.exc import DataError
from .settings import settings
from datetime import datetime
import pandas as pd

# configure Session class with desired options
Session = sessionmaker()

# later, we create the engine
engine = create_engine(settings['postgresql'])

# associate it with our custom Session class
Session.configure(bind=engine)

def fetch_data(user_id, model):
    session = Session()
    try:
        SQLquery = session.query(model).filter_by(user_id = user_id)
        df = pd.read_sql(SQLquery.statement, session.bind)

        if df.empty:
            return None
        return df
    except DataError:
        session.rollback()
        return None
    finally:
        session.close()

def delete_data(user_id, model):
    session = Session()
    try:
        result = session.query(model).filter_by(user_id = user_id).delete(synchronize_session=False)
        if result > 0 :
            session.commit()

        return result
    finally:
        session.close()


#
# @lc app=leetcode id=21 lang=python3
#
# [21] Merge Two Sorted Lists
#

# @lc code=start
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        time: O(S) S: sum of the all node
        space: O(S)
        """
        head = ListNode(0)
        cur_node = head
        while l1 and l2:
            if l1.val <= l2.val:
                cur_node.next = ListNode(l1.val)
                l1 = l1.next
            else:
                cur_node.next = ListNode(l2.val)
                l2 = l2.next
            cur_node = cur_node.next
        """
        if not l1:
            cur_node.next = l2
        else:
            cur_node.next = l1
        """
        cur_node.next = l1 if not l2 else l2
        return head.next

# @lc code=end


"""24.8.19 - Hacking, Learning, Adapting.

Constructing the code to cycle through the list (Testing functionality, before
moving into the main program - However, the functions in this code modify global
variables in order to save the state (Simple counter), this is not good practice,
so needed to find a better way of saving the state - incoming class definition i think.)

"""

# *****  Start: Uncomment the below for the global var altering version *****

#last_response = 0
#
#responses =  [
#             "A",
#             "E",
#             "I",
#             "O",
#             "U",
#             ]
#
#def response_cycle(lis):
#    """This function cycles through a list of responses.
#
#    Parameters:
#        lis - list passed to cycle through"""
#    global last_response
#    if last_response >= len(lis):
#        last_response = 0
#    print(lis[last_response])
#    last_response += 1
#
#def repeat_func(times, f, *args):
#    """Simple function to repeatedly call a function X times, to practice the
#    intended functionality of the program.
#
#    Parameters:
#        times - number of times to call the function in question
#        f - the function to call
#        *args - passing the argument needed for the function that is being called
#    """
#    for i in range(times):
#        f(*args)
#
#repeat_func(20, response_cycle, responses)

# *****  End:  *****

"""24.8.19 - Hacking, Learning, Adapting.

Version 1.0 Kitt has 4 lists of cycling responses, which lends me to think,
do I need 4 different Classes to do the same thing (i.e. cycle through the list), or do I create one class where
the logic is set and the list data can be imported dependent on the response themes?

So, one class needed, with the functionality to take the list data into an instantiation of responsecycle object
and perform the computation and state saving on each. Affectively the program will instantiate 4 different
objects each with their own counters, and sets of list data.

"""

# I need to replace the: (random.choice(greeting_responses)) from the check for greeting function
# with a class object that cycles through those greeting_responses.

# Cut and paste some of the list code for testing purposes.

a = responsecycle(greeting_responses)
b = responsecycle(none_responses)

greeting_responses =  [
                      "Greetings and Salutations! - I'm scanning your interrogatives quite satisfactorily.",
                      "Hi! - By the way, don't touch Turbo Boost. Something tells me you shouldn\'t touch Turbo Boost.",
                      "Hello! - Do you know Michael Knight is a living... breathing... insult.",
                      ]

none_responses = [
                 "I want Custody of me in your Divorce!",
                 "A little higher, a little lower, Stop!",
                 "If I may say so, I\'m quite pleased with my new look.",
                 "I\'m already reviewing my computer logs of our confrontation.",
                 ]

class responsecycle:
    """Class constructed to handle returning cyclical list responses, using
    object attributes, which avoids resorting to functions accessing global variables.

    attributes:
        count - A simple incremental count
        responselist - The selected data to pass to the object instance, in this
        case our responselists.
    """

    count = 0 # Every instance should have a count variable as an attribute

    def __init__(self, responselist):
        """Magic Method (Constructor) - Object is instantiated with a default count attribute value of 0,
        and with a Nul attribute waiting for data"""
        self.responselist = responselist

    def __str__(self):
        """Magic method to return the element of the list that relates to the
        count method"""
        return self.responselist[self.count]

    def inc(self):
        """Instance Method to increment the objects count attribute."""
        self.count += 1

def testgreet():
    print(a)
    a.inc()
    if a.count >= len(greeting_responses):
        a.count = 0

# Using the function to test repeated calls of the testgreet function to check it is
# working as intended.

def repeat_func(times, f, *args):
    """Simple function to repeatedly call a function X times, to practice the
    intended functionality of the program.

    Parameters:
        times - number of times to call the function in question
        f - the function to call
        *args - passing the argument needed for the function that is being called
    """
    for i in range(times):
        f(*args)

repeat_func(10, testgreet)

# Well it works, but just seems very messy/hacky way of doing it - and I am still
# using and modifying global things using a function, only this time,
# those global things are attributes of objects of type responsecycle, instead
# of globally defined variables
# There must be a better way!


def _format_date_param(params, key, format="%Y-%m-%d %H:%M:%S"):
    """
    Utility function to convert datetime values to strings.

    If the value is already a str, or is not in the dict, no change is made.

    :param params: A `dict` of params that may contain a `datetime` value.
    :param key: The datetime value to be converted to a `str`
    :param format: The `strftime` format to be used to format the date. The default value is '%Y-%m-%d %H:%M:%S'
    """
    if key in params:
        param = params[key]
        if hasattr(param, "strftime"):
            params[key] = param.strftime(format)


import os
import psycopg2
from flask import Blueprint, request
from dotenv import load_dotenv
import jwt

load_dotenv()

expense = Blueprint('expense', __name__)

url = os.environ.get("DATABASE_URL")  # gets variables from environment
connection = psycopg2.connect(url)

secret = os.environ.get("SECRET")

# CREATE ROUTE

@expense.route("/", methods=["POST"])
def create_expense():

    if request.method == 'POST':
        data = request.get_json()
        data["duration_months"] = data["duration_months"]*12
        data_list = list(data.values())
        expense_name = data["expense_name"]

        # Decode Token and get User ID
        bearer_token = request.headers.get('Authorization')
        token = bearer_token.split()[1]
        user_details = jwt.decode(token, secret, algorithms=["HS256"])
        user_id = user_details['id']

        # Put user id to the front of list
        data_list.insert(0, user_id)
        print(data_list)

        with connection:
            with connection.cursor() as cursor:
                if data.get("start_date") is not None:
                    cursor.execute(
                        "INSERT INTO user_expense (user_details_id, expense_name, expense_type, expense_status, amount, frequency, duration_months, start_date, inflation_rate) VALUES (%s, %s, %s,%s,  %s, %s, %s, %s, %s)", (
                            data_list))
                else:
                    cursor.execute(
                        "INSERT INTO user_expense (user_details_id, expense_name, expense_type, expense_status, amount, frequency, duration_months, inflation_rate) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)", (
                            data_list))
        return {"msg": f"Successfully created {expense_name}!"}, 201

# GET ALL ROUTE FOR A SPECIFIC USER
@expense.route("/", methods=["GET"])
def get_all_expense():

    if request.method == 'GET':
        # Decode Token and get User ID
        bearer_token = request.headers.get('Authorization')
        token = bearer_token.split()[1]
        user_details = jwt.decode(token, secret, algorithms=["HS256"])
        user_id = user_details['id']

        with connection:
            with connection.cursor() as cursor:
                cursor.execute(
                    f"SELECT * FROM user_expense WHERE user_details_id={user_id}")
                columns = list(cursor.description)
                result = cursor.fetchall()

                results = []
                for row in result:
                    row_dict = {}
                    for i, col in enumerate(columns):
                        row_dict[col.name] = row[i]
                    results.append(row_dict)
            return results, 201

# # GET ONE / UPDATE / DELETE ROUTE
@expense.route("/<int:id>", methods=["GET", "PUT", "DELETE"])
def get_expense(id):

    if request.method == 'GET':
        with connection:
            with connection.cursor() as cursor:
                cursor.execute(
                    f"SELECT * FROM user_expense WHERE id= {id}")
                columns = list(cursor.description)
                result = cursor.fetchone()

                row_dict = {}
                for i, col in enumerate(columns):
                    row_dict[col.name] = result[i]

            return row_dict, 201

    if request.method == 'PUT':
        data = request.get_json()
        data["duration_months"] = data["duration_months"]*12
        data_list = list(data.values())
        data_list.append(id)
        print(data)
        expense_name = data["expense_name"]

        # Decode Token and get User ID
        bearer_token = request.headers.get('Authorization')
        token = bearer_token.split()[1]
        user_details = jwt.decode(token, secret, algorithms=["HS256"])
        user_id = user_details['id']

        # Put user id to the front of list
        data_list.insert(0, user_id)
        print(data_list)

        with connection:
            with connection.cursor() as cursor:
                cursor.execute("UPDATE user_expense SET user_details_id=%s, expense_name= %s, expense_type= %s, expense_status=%s, amount= %s, frequency= %s, duration_months=%s, start_date=%s, inflation_rate=%s WHERE id = %s", (
                    data_list))
        return {"msg": f"Successfully updated{expense_name}!"}, 201

    if request.method == 'DELETE':
        with connection:
            with connection.cursor() as cursor:
                cursor.execute(
                    f"DELETE FROM user_expense WHERE id= '{id}'")

            return {"msg": f"Successfully deleted"}, 201


'''
code to send a 3 letter code (a-z) to a web server to solve a RITSEC challenge
'''

import time
import requests

CURRENT_CODE = "AAA"

def increment_code():
    '''
    increments the current code (AAA->AAB->AAC, etc)
    '''
    global CURRENT_CODE
    # string to list of 1 character strings
    chars = [*CURRENT_CODE]

    # change all to ints as per ascii table
    index = 0
    for char in chars:
        value = ord(char)
        chars[index] = value
        index += 1

    # this code is probably not as efficient as it could be
    # if last character is 90, then reset it and increment the middle character
    if chars[2] == 90:
        chars[2] = 65
        # same with middle character -> first character
        if chars[1] == 90:
            chars[1] = 65
            # if all characters are Z, then we didnt' find the code
            if chars[0] == 90:
                print("code not found.")
                exit()
            else:
                chars[0] += 1
        else:
            chars[1] += 1
    else:
        chars[2] += 1
    # convert back to letters
    index = 0
    for char in chars:
        value = chr(char)
        chars[index] = value
        index += 1
    # convert back to one solid string
    CURRENT_CODE = "".join(chars)

data = requests.get("http://localhost:9888/med1/{0}".format(CURRENT_CODE))
print("trying code {0}".format(CURRENT_CODE))

while data.json()["flag"] == "NotFound":
    increment_code()
    print("trying code {0}".format(CURRENT_CODE))
    data = requests.get("http://localhost:9888/med1/{0}".format(CURRENT_CODE))

print(data.json()["flag"])

# while data.json()["flag"] == "NotFound":


from sensor.utils.main_utils import load_numpy_array_data, save_object, load_object
from sensor.exception import SensorException
from sensor.logger import logging
import os, sys
from sensor.entity.artifact_entity import DataTransformationArtifact, ModelTrainerArtifact
from sensor.entity.config_entity import ModelTrainerConfig

from xgboost import XGBClassifier
from sensor.ml.metric.classification_metric import get_classification_score
from sensor.ml.model.estimator import SensorModel

class ModelTrainer:

    def __init__(self,
                    model_trainer_config: ModelTrainerConfig,
                         data_transformation_artifact: DataTransformationArtifact):
        try:
            self.model_trainer_config = model_trainer_config
            self.data_transformation_artifact = data_transformation_artifact
        except Exception as e:
            raise SensorException(e, sys)

    def perform_hyperparameter_tuning(self):
        pass

    def train_model(self, x_train, y_train):
        try:
            logging.info("performing XGBClassifier fit on x_train and y_train")
            xgb_clf = XGBClassifier()

            xgb_clf.fit(x_train, y_train)
            logging.info("XGBClassifier fit done")

            logging.info("returning XGBClassifier object")
            return xgb_clf
        except Exception as e:
            raise SensorException(e, sys)

    def initiate_model_trainer(self)->ModelTrainerArtifact:
        try:
            logging.info("Initiating Model Trainer for training the model...")

            train_file_path = self.data_transformation_artifact.transformed_train_file_path
            test_file_path = self.data_transformation_artifact.transformed_test_file_path

            logging.info("loading train and test array for training...")
            train_arr = load_numpy_array_data(train_file_path)
            test_arr = load_numpy_array_data(test_file_path)

            logging.info("Creating [x_train, y_train, x_test, y_test]")
            x_train, y_train, x_test, y_test = (
                train_arr[:, :-1],
                train_arr[:, -1],
                test_arr[:, :-1],
                test_arr[:, -1],
            )

            logging.info("going to train_model and Getting Object for trained_model...")
            model = self.train_model(x_train=x_train, y_train=y_train)

            logging.info("going to predict on x_train to get y_train_pred")
            y_train_pred = model.predict(x_train)

            logging.info("going to get classification score metric on y_train and y_train_pred")
            classification_train_metric =  get_classification_score(y_true=y_train,
                                                                        y_pred=y_train_pred)

            if (classification_train_metric.f1_score  <=  self.model_trainer_config.expected_accuracy):
                raise Exception("Trained model is not good to provide expected accuracy!")

            logging.info("Performing similar steps to get classification score metric on y_test and y_test_pred...")
            y_test_pred = model.predict(x_test)
            classification_test_metric =   get_classification_score(y_true=y_test,
                                                                       y_pred=y_test_pred)

            #Overfitting and Underfitting
            diff = abs(classification_train_metric.f1_score - classification_test_metric.f1_score)

            if (diff > self.model_trainer_config.overfitting_underfitting_threshold):
                raise Exception("Model is not good try to do more experimentation since model is crossing Overfitting_Underfitting_Threshold!")

            logging.info("loading preprocessor object...")
            preprocessor = load_object(file_path=self.data_transformation_artifact.transformed_object_file_path)

            logging.info("creating directory...")
            model_dir_path = os.path.dirname(self.model_trainer_config.trained_model_file_path)
            os.makedirs(model_dir_path,exist_ok=True)

            logging.info("creating object for SensorModel(preprocessor=preprocessor,model=model)...")
            sensor_model = SensorModel(preprocessor=preprocessor,model=model)

            logging.info("Saving object for SensorModel(preprocessor=preprocessor,model=model) in created directory...")
            save_object(self.model_trainer_config.trained_model_file_path, obj=sensor_model)

            #model trainer artifact

            model_trainer_artifact   =  ModelTrainerArtifact(trained_model_file_path=self.model_trainer_config.trained_model_file_path,
                                                                train_metric_artifact=classification_train_metric,
                                                                    test_metric_artifact=classification_test_metric)
            logging.info(f"Model trainer artifact: {model_trainer_artifact}\n\n")

            return model_trainer_artifact
        except Exception as e:
            raise SensorException(e, sys)


while True:
    n = int(input()) #numero de vezes jogadas
    if n == 0:
        break
    resultado = input().split()
    for i in range(0, len(resultado)):
        resultado[i] = int(resultado[i])

    cmaria = 0
    cjoao = 0

    for i in range(n):
        if resultado[i] == 0:
            cmaria += 1
        else:
            cjoao += 1

    print("Mary won %d times and John won %d times"%(cmaria, cjoao))

Programação Orientada a Objetos 1/questoes URI/1329caraoucoroa.py


# Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import absolute_import, division, print_function, unicode_literals
from collections import namedtuple, OrderedDict
import numpy as np
from astropy.table import Table
from astropy.units import Unit, Quantity
from astropy.coordinates import Angle, SkyCoord
from astropy.time import Time
from astropy.utils import lazyproperty
from ..utils.scripts import make_path
from ..utils.time import time_relative_to_ref
from ..utils.testing import Checker
from .gti import GTI

__all__ = ["ObservationTable"]

class ObservationTable(Table):
    """Observation table.

    Data format specification: :ref:`gadf:obs-index`
    """

    @classmethod
    def read(cls, filename, **kwargs):
        """Read an observation table from file.

        Parameters
        ----------
        filename : `~gammapy.extern.pathlib.Path`, str
            Filename
        """
        filename = make_path(filename)
        return super(ObservationTable, cls).read(str(filename), **kwargs)

    @property
    def pointing_radec(self):
        """Pointing positions as ICRS (`~astropy.coordinates.SkyCoord`)"""
        return SkyCoord(self["RA_PNT"], self["DEC_PNT"], unit="deg", frame="icrs")

    @property
    def pointing_galactic(self):
        """Pointing positions as Galactic (`~astropy.coordinates.SkyCoord`)"""
        return SkyCoord(
            self["GLON_PNT"], self["GLAT_PNT"], unit="deg", frame="galactic"
        )

    @lazyproperty
    def _index_dict(self):
        """Dict containing row index for all obs ids"""
        # TODO: Switch to http://docs.astropy.org/en/latest/table/indexing.html once it is more stable
        temp = zip(self["OBS_ID"], np.arange(len(self)))
        return dict(temp)

    def get_obs_idx(self, obs_id):
        """Get row index for given ``obs_id``.

        Raises KeyError if observation is not available.

        Parameters
        ----------
        obs_id : int, list
            observation ids

        Returns
        -------
        idx : list
            indices corresponding to obs_id
        """
        idx = [self._index_dict[key] for key in np.atleast_1d(obs_id)]
        return idx

    def select_obs_id(self, obs_id):
        """Get `~gammapy.data.ObservationTable` containing only ``obs_id``.

        Raises KeyError if observation is not available.

        Parameters
        ----------
        obs_id: int, list
            observation ids
        """
        return self[self.get_obs_idx(obs_id)]

    def summary(self):
        """Info string (str)"""
        obs_name = self.meta.get("OBSERVATORY_NAME", "N/A")

        return "\n".join(
            [
                "Observation table:",
                "Observatory name: {!r}".format(obs_name),
                "Number of observations: {}".format(len(self)),
                # TODO: clean this up. Make those properties?
                # ontime = Quantity(self['ONTIME'].sum(), self['ONTIME'].unit)
                #
                # ss += 'Total observation time: {}\n'.format(ontime)
                # livetime = Quantity(self['LIVETIME'].sum(), self['LIVETIME'].unit)
                # ss += 'Total live time: {}\n'.format(livetime)
                # dtf = 100. * (1 - livetime / ontime)
                # ss += 'Average dead time fraction: {:5.2f}%\n'.format(dtf)
                # time_ref = time_ref_from_dict(self.meta)
                # time_ref_unit = time_ref_from_dict(self.meta).format
                # ss += 'Time reference: {} {}'.format(time_ref, time_ref_unit)
            ]
        )

    def select_linspace_subset(self, num):
        """Select subset of observations.

        This is mostly useful for testing, if you want to make
        the analysis run faster.

        Parameters
        ----------
        num : int
            Number of samples to select.

        Returns
        -------
        table : `ObservationTable`
            Subset observation table (a copy).
        """
        indices = np.linspace(start=0, stop=len(self), num=num, endpoint=False)
        # Round down to nearest integer
        indices = indices.astype("int")
        return self[indices]

    def select_range(self, selection_variable, value_range, inverted=False):
        """Make an observation table, applying some selection.

        Generic function to apply a 1D box selection (min, max) to a
        table on any variable that is in the observation table and can
        be casted into a `~astropy.units.Quantity` object.

        If the range length is 0 (min = max), the selection is applied
        to the exact value indicated by the min value. This is useful
        for selection of exact values, for instance in discrete
        variables like the number of telescopes.

        If the inverted flag is activated, the selection is applied to
        keep all elements outside the selected range.

        Parameters
        ----------
        selection_variable : str
            Name of variable to apply a cut (it should exist on the table).
        value_range : `~astropy.units.Quantity`-like
            Allowed range of values (min, max). The type should be
            consistent with the selection_variable.
        inverted : bool, optional
            Invert selection: keep all entries outside the (min, max) range.

        Returns
        -------
        obs_table : `~gammapy.data.ObservationTable`
            Observation table after selection.
        """
        value_range = Quantity(value_range)

        # read values into a quantity in case units have to be taken into account
        value = Quantity(self[selection_variable])

        mask = (value_range[0] <= value) & (value < value_range[1])

        if np.allclose(value_range[0].value, value_range[1].value):
            mask = value_range[0] == value

        if inverted:
            mask = np.invert(mask)

        return self[mask]

    def select_time_range(self, selection_variable, time_range, inverted=False):
        """Make an observation table, applying a time selection.

        Apply a 1D box selection (min, max) to a
        table on any time variable that is in the observation table.
        It supports both fomats: absolute times in
        `~astropy.time.Time` variables and [MET]_.

        If the inverted flag is activated, the selection is applied to
        keep all elements outside the selected range.

        Parameters
        ----------
        selection_variable : str
            Name of variable to apply a cut (it should exist on the table).
        time_range : `~astropy.time.Time`
            Allowed time range (min, max).
        inverted : bool, optional
            Invert selection: keep all entries outside the (min, max) range.

        Returns
        -------
        obs_table : `~gammapy.data.ObservationTable`
            Observation table after selection.
        """
        if self.meta["TIME_FORMAT"] == "absolute":
            # read times into a Time object
            time = Time(self[selection_variable])
        else:
            # transform time to MET
            time_range = time_relative_to_ref(time_range, self.meta)
            # read values into a quantity in case units have to be taken into account
            time = Quantity(self[selection_variable])

        mask = (time_range[0] <= time) & (time < time_range[1])

        if inverted:
            mask = np.invert(mask)

        return self[mask]

    def select_observations(self, selection=None):
        """Select subset of observations.

        Returns a new observation table representing the subset.

        There are 3 main kinds of selection criteria, according to the
        value of the **type** keyword in the **selection** dictionary:

        - sky regions (boxes or circles)

        - time intervals (min, max)

        - intervals (min, max) on any other parameter present in the
          observation table, that can be casted into an
          `~astropy.units.Quantity` object

        Allowed selection criteria are interpreted using the following
        keywords in the **selection** dictionary under the **type** key.

        - ``sky_box`` and ``sky_circle`` are 2D selection criteria acting
          on sky coordinates

            - ``sky_box`` is a squared region delimited by the **lon** and
              **lat** keywords: both tuples of format (min, max); uses
              `~gammapy.catalog.select_sky_box`

            - ``sky_circle`` is a circular region centered in the coordinate
              marked by the **lon** and **lat** keywords, and radius **radius**;
              uses `~gammapy.catalog.select_sky_circle`

          in each case, the coordinate system can be specified by the **frame**
          keyword (built-in Astropy coordinate frames are supported, e.g.
          ``icrs`` or ``galactic``); an aditional border can be defined using
          the **border** keyword

        - ``time_box`` is a 1D selection criterion acting on the observation
          start time (**TSTART**); the interval is set via the
          **time_range** keyword; uses
          `~gammapy.data.ObservationTable.select_time_range`

        - ``par_box`` is a 1D selection criterion acting on any
          parameter defined in the observation table that can be casted
          into an `~astropy.units.Quantity` object; the parameter name
          and interval can be specified using the keywords **variable** and
          **value_range** respectively; min = max selects exact
          values of the parameter; uses
          `~gammapy.data.ObservationTable.select_range`

        In all cases, the selection can be inverted by activating the
        **inverted** flag, in which case, the selection is applied to keep all
        elements outside the selected range.

        A few examples of selection criteria are given below.

        Parameters
        ----------
        selection : dict
            Dictionary with a few keywords for applying selection cuts.

        Returns
        -------
        obs_table : `~gammapy.data.ObservationTable`
            Observation table after selection.

        Examples
        --------
        >>> selection = dict(type='sky_box', frame='icrs',
        ...                  lon=Angle([150, 300], 'deg'),
        ...                  lat=Angle([-50, 0], 'deg'),
        ...                  border=Angle(2, 'deg'))
        >>> selected_obs_table = obs_table.select_observations(selection)

        >>> selection = dict(type='sky_circle', frame='galactic',
        ...                  lon=Angle(0, 'deg'),
        ...                  lat=Angle(0, 'deg'),
        ...                  radius=Angle(5, 'deg'),
        ...                  border=Angle(2, 'deg'))
        >>> selected_obs_table = obs_table.select_observations(selection)

        >>> selection = dict(type='time_box',
        ...                  time_range=Time(['2012-01-01T01:00:00', '2012-01-01T02:00:00']))
        >>> selected_obs_table = obs_table.select_observations(selection)

        >>> selection = dict(type='par_box', variable='ALT',
        ...                  value_range=Angle([60., 70.], 'deg'))
        >>> selected_obs_table = obs_table.select_observations(selection)

        >>> selection = dict(type='par_box', variable='OBS_ID',
        ...                  value_range=[2, 5])
        >>> selected_obs_table = obs_table.select_observations(selection)

        >>> selection = dict(type='par_box', variable='N_TELS',
        ...                  value_range=[4, 4])
        >>> selected_obs_table = obs_table.select_observations(selection)
        """
        from ..catalog import select_sky_box, select_sky_circle

        if "inverted" not in selection.keys():
            selection["inverted"] = False

        if selection["type"] == "sky_circle":
            lon = selection["lon"]
            lat = selection["lat"]
            radius = selection["radius"] + selection["border"]
            return select_sky_circle(
                self,
                lon_cen=lon,
                lat_cen=lat,
                radius=radius,
                frame=selection["frame"],
                inverted=selection["inverted"],
            )

        elif selection["type"] == "sky_box":
            lon = selection["lon"]
            lat = selection["lat"]
            border = selection["border"]
            lon = Angle([lon[0] - border, lon[1] + border])
            lat = Angle([lat[0] - border, lat[1] + border])
            return select_sky_box(
                self,
                lon_lim=lon,
                lat_lim=lat,
                frame=selection["frame"],
                inverted=selection["inverted"],
            )

        elif selection["type"] == "time_box":
            return self.select_time_range(
                "TSTART", selection["time_range"], selection["inverted"]
            )

        elif selection["type"] == "par_box":
            return self.select_range(
                selection["variable"], selection["value_range"], selection["inverted"]
            )

        else:
            raise ValueError("Invalid selection type: {}".format(selection["type"]))

    def create_gti(self, obs_id):
        """Returns a GTI table containing TSTART and TSTOP from the table.

        TODO: This method can be removed once GTI tables are explicitly required in Gammapy.

        Parameters
        ----------
        obs_id : int
            ID of the observation for which the GTI table will be created

        Returns
        -------
        gti : `~gammapy.data.GTI`
            GTI table containing one row (TSTART and TSTOP of the observation with `obs_id`)
        """
        meta = OrderedDict(
            EXTNAME="GTI",
            HDUCLASS="GADF",
            HDUDOC="https://github.com/open-gamma-ray-astro/gamma-astro-data-formats",
            HDUVERS="0.2",
            HDUCLAS1="GTI",
            MJDREFI=self.meta["MJDREFI"],
            MJDREFF=self.meta["MJDREFF"],
            TIMEUNIT=self.meta.get("TIMEUNIT", "s"),
            TIMESYS=self.meta["TIMESYS"],
            TIMEREF=self.meta.get("TIMEREF", "LOCAL"),
        )

        obs = self.select_obs_id(obs_id)

        gti = Table(meta=meta)
        gti["START"] = obs["TSTART"].quantity.to("s")
        gti["STOP"] = obs["TSTOP"].quantity.to("s")

        return GTI(gti)

class ObservationTableChecker(Checker):
    """Event list checker.

    Data format specification: ref:`gadf:iact-events`

    Parameters
    ----------
    event_list : `~gammapy.data.EventList`
        Event list
    """

    CHECKS = {
        "meta": "check_meta",
        "columns": "check_columns",
        # "times": "check_times",
        # "coordinates_galactic": "check_coordinates_galactic",
        # "coordinates_altaz": "check_coordinates_altaz",
    }

    # accuracy = {"angle": Angle("1 arcsec"), "time": Quantity(1, "microsecond")}

    # https://gamma-astro-data-formats.readthedocs.io/en/latest/events/events.html#mandatory-header-keywords
    meta_required = [
        "HDUCLASS",
        "HDUDOC",
        "HDUVERS",
        "HDUCLAS1",
        "HDUCLAS2",
        # https://gamma-astro-data-formats.readthedocs.io/en/latest/general/time.html#time-formats
        "MJDREFI",
        "MJDREFF",
        "TIMEUNIT",
        "TIMESYS",
        "TIMEREF",
        # https://gamma-astro-data-formats.readthedocs.io/en/latest/general/coordinates.html#coords-location
        "GEOLON",
        "GEOLAT",
        "ALTITUDE",
    ]

    _col = namedtuple("col", ["name", "unit"])
    columns_required = [
        _col(name="OBS_ID", unit=""),
        _col(name="RA_PNT", unit="deg"),
        _col(name="DEC_PNT", unit="deg"),
        _col(name="TSTART", unit="s"),
        _col(name="TSTOP", unit="s"),
    ]

    def __init__(self, obs_table):
        self.obs_table = obs_table

    def _record(self, level="info", msg=None):
        return {"level": level, "hdu": "obs-index", "msg": msg}

    def check_meta(self):
        m = self.obs_table.meta

        meta_missing = sorted(set(self.meta_required) - set(m))
        if meta_missing:
            yield self._record(
                level="error", msg="Missing meta keys: {!r}".format(meta_missing)
            )

        if m.get("HDUCLAS1", "") != "INDEX":
            yield self._record(level="error", msg="HDUCLAS1 must be INDEX")
        if m.get("HDUCLAS2", "") != "OBS":
            yield self._record(level="error", msg="HDUCLAS2 must be OBS")

    def check_columns(self):
        t = self.obs_table

        if len(t) == 0:
            yield self._record(level="error", msg="Observation table has zero rows")

        for name, unit in self.columns_required:
            if name not in t.colnames:
                yield self._record(
                    level="error", msg="Missing table column: {!r}".format(name)
                )
            else:
                if Unit(unit) != (t[name].unit or ""):
                    yield self._record(
                        level="error", msg="Invalid unit for column: {!r}".format(name)
                    )


#settings for global python variables, and the computerObj class
global verbose
verbose = False
class computerObj:
	searchID = '00000000-0000-0000-0000-000000000000'#the id given by the xml lookup is cated directly to https://service.REDACTED.asu.edu/AssetManagement/HardwareAsset/Edit/
	PCN=0000000
	serial='dummy serial'
	model='dummy model'
	name = 'dummy name'
	user = 'dummy user'
	building='dummy building'
	location='dummy location (building)'
	locDetail='dummy location details (room)'
	room='dummy room'
	status='dummy status'
	assetType='dummy type'
	organization = 'dummy organization'

	def __init__(self):
		searchID = '00000000-0000-0000-0000-000000000000'#the id given by the xml lookup is cated directly to https://service.REDACTED.asu.edu/AssetManagement/HardwareAsset/Edit/
		PCN=0000000
		serial='dummy serial'
		model='dummy model'
		name = 'dummy name'
		user = 'dummy user'
		building='dummy building'
		location='dummy location (building)'
		locDetail='dummy location details (room)'
		room='dummy room'
		status='dummy status'
		assetType='dummy type'
		organization = 'dummy organization'

	def toString(self):
		return str(self.model+' '+self.serial+' '+str(self.PCN)+' '+self.status
			+' ' +self.assetType+' '+self.name+' '+self.locDetail+' '+
			self.organization+' '+self.user)
	def toStringID(self):
		return str(self.name+': '+self.searchID)
	def printDetails(self):
		#print(self.__dict__)
		print('PCN= '+str(self.PCN))
		print('serial= '+self.serial)
		print('model= '+self.model)
		print('name= '+self.name)
		print('user= '+ self.user)
		print('building= '+self.building)
		print('location= '+self.location)
		print('locDetail= '+self.locDetail)
		print('room= '+self.room)
		print('status= '+self.status)
		print('assetType= '+self.assetType)
		print('organization = '+self.organization)
#function checks if all the attributes of the computer are valid, returning a 0 if
#the computer is "complete" (has no empty entries), and various binary values corresponding
#to the errors encountered
	def isComplete(self):

		statusTypes =('Ordered','Received','In Stock','On Hold',
			'Repurpose Inventory','Repair, Test, Etc.','Salvage Inventory',
			'Deployed','Primary','Secondary','TA / FA','Computing Lab',
			'Teaching Station','Signage','Offsite','Server','Other','Virtual Machine',
			'Student Worker','Departmental','Loaned','Retired','Lost/Stolen','Disposed')

		assetTypes = ('Computer','Virtual Machine','Tablet','Computer Peripheral','Printer','Scanner',
			'Monitor','Touch Display','Projector','Camera','Digital Lab Equipment',
			'A/V Loan Equipment','Point-of-Sale Equipment','Networking Equipment')

		#define bit flags

		#Return values (bin):
		#000 000 000		fine
		#000 000 001		model error
		#000 000 010		serial error
		#000 000 100		pcn error
		#000 001 000		status error
		#000 010 000		type error
		#000 100 000		name error
		#001 000 000		location details error
		#010 000 000		organization error
		#100 000 000		user error
		modelError= int('000000001',2)
		serialError=int('000000010',2)
		pcnError=   int('000000100',2)
		statusError=int('000001000',2)
		typeError=  int('000010000',2)
		nameError=  int('000100000',2)
		locDetError=int('001000000',2)
		orgError=   int('010000000',2)
		userError=  int('100000000',2)

		flags =     int('000000000',2)
		#model
		if self.model == '' or self.model == '<None>' or self.model =='dummy model':
			self.model = '<None>'
			flags|=modelError
			#if settings.verbose:
				#print('\nModel ERROR on line: '+str(count)+ ' Read Status: ' +parts[0]+'\n')

		#serial
		if self.serial =='dummy serial':
			flags|=serialError

		if len(self.serial)<7:
			flags|=serialError
			if self.serial == '' or self.serial == '<None>':
				self.serial = '<None>'
#			if settings.verbose:
#				print('\nSerial ERROR on line: '+str(count)+ ' Read Serial: ' +parts[1]+'\n')

		#PCN
		if self.PCN == '' or self.PCN == '<None>' or self.PCN =='0000000':
			flags|=pcnError
			self.PCN = '<None>'
#			if settings.verbose:
#				print('\nPCN ERROR on line: '+str(count)+ ' Read PCN: ' +parts[2]+'\n')
		#second test to test if PCN is a number or invalid
		try:
   			val = int(self.PCN)

		except ValueError:
			flags|=pcnError
#			if settings.verbose:
#				print('\nPCN ERROR on line: '+str(count)+ ' Read PCN: ' +parts[2]+'\n')

		#status
		if self.status == '' or self.status == '<None>' or self.status=='dummy status':
			flags|=statusError
			self.status = '<None>'

		if self.status in statusTypes: #read status is valid
			1+1
		else:
			flags|=statusError

#			if settings.verbose:
#				print('\nSTATUS ERROR on line: '+str(count)+ ' Read Status: ' +parts[3]+'\n')
		#type
		if self.assetType in assetTypes: #read asset type is valid
			1+1
		else:
			flags|=typeError
#			if settings.verbose:
#				print('\nTYPE ERROR on line: '+str(count)+ ' Read type: ' +parts[4]+'\n')
		#name
		if len(self.name) <3:	#arbitrary length requirement
			if self.name == '':
				self.name = '<None>'
			flags|=nameError
		if self.name == '<None>' or self.name =='dummy name':
			flags|=nameError
#			if settings.verbose:
#				print('\nNAME ERROR on line: '+str(count)+ ' Read name: ' +parts[5]+'\n')
		#location details
		if self.locDetail == '' or self.locDetail == '<None>' or self.locDetail =='dummy location details (room)':
			self.locDetail = '<None>'
			flags|=locDetError
#			if settings.verbose:
#				print('\nLOCATION DETAIL ERROR on line: '+str(count)+ ' Read location detail: ' +parts[6]+'\n')
		#organization
		if self.organization == '' or self.organization == '<None>' or self.organization=='dummy organization':
			self.organization = '<None>'
			flags|=orgError
#			if settings.verbose:
#				print('\nORGANIZATION ERROR on line: '+str(count)+ ' Read organization: ' +parts[7]+'\n')
		#user
		if self.user == '' or self.user == '<None>' or self.user=='dummy user':
			self.user = '<None>'
			flags|=userError
#			if settings.verbose:
#				print('\nUSER ERROR on line: '+str(count)+ ' Read user: ' +parts[8]+'\n')

		#The world is not yet ready for this much cleanup
		if 'local_users' in self.user:
			flags|=userError
#			if settings.verbose:
#				print('\nUSER ERROR on line: '+str(count)+ ' Read user: ' +parts[8]+'\n')
		return flags

#returns 0 if no common errors, or sets a flag bit depending on the type of error
	def checkCommonErrors(self):
		flags=int('00',2)
		if self.building != self.location:
			print(computer.name+"'s location and building do not match")
			flags=flags|int('01',2)
		if self.room != self.locDetail:
			print(computer.name+"'s room and location detail do not match")
			flags=flags|int('10',2)

		return flags


a = set()

b = set()

a.add("Banan")
a.add("Päron")
a.add("Äpple")

b.add("Kiwi")
b.add("Ananas")
b.add("Päron")

c = set()

c = c.union(a, b)

print(c)


import requests
import streamlit as st
import sklearn

from ..data.get_split_data import get_dataset

def show_score(key1=0, key2=1, show='n'):
    # загрузка метрик
    metrics_age = (get_dataset('df_age_metrics.parquet')).reset_index(drop=True)
    metrics_gender = get_dataset('df_gender_metrics.parquet').reset_index(drop=True)

    # показ метрик
    if show == 'y':
        st.markdown("**Метрики всех моделей**")
        st.write(metrics_age, metrics_gender)

    old_f1 = metrics_age['F1_weighted'][key1]
    new_f1 = metrics_age['F1_weighted'][key2]
    old_g1 = metrics_gender['Gini'][key1]
    new_g2 = metrics_gender['Gini'][key2]

    st.markdown("**Метрики и Score**")
    # отрисовка f1, gini и score
    f1_, gini_, score_ = st.columns(3)
    f1_.metric(
        "F1_weighted",
        new_f1,
        f"{new_f1 - old_f1:.4f}"
    )
    gini_.metric(
        "Gini",
        new_g2,
        f"{new_g2 - old_g1:.4f}"
    )
    score_.metric(
        "Score",
        f"{(2 * new_f1 + new_g2):.4f}",
        f"{((2 * new_f1 + new_g2) - (2 * old_f1 + old_g1)):.4f}"
    )


"""This module contains the specification of the model responsible
of managing the orders of the employees in corporate."""
from django.db import models

class EmployeeSelection(models.Model):
    """This model contains the reference of an option
    of a menu and the employee that is the propetary
    of that order. We require this menu in order to
    store also the customization of a selected option."""
    menu_option = models.ForeignKey(
        'MenuOption',
        on_delete=models.CASCADE
    )
    employee = models.ForeignKey(
        'employees.Employee',
        on_delete=models.CASCADE
    )
    customization = models.TextField(null=True)


from functools import lru_cache
from typing import Literal, Dict

import orjson
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from rest_framework import generics
from rest_framework.exceptions import PermissionDenied
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from check import models
from check.logging import log
from check.permissions import profile_permission
from devicemanager.device import Interfaces
from devicemanager.remote.exceptions import InvalidMethod
from net_tools.models import VlanName, DevicesInfo
from ..decorators import except_connection_errors
from ..permissions import DevicePermission
from ..serializers import (
    InterfacesCommentsSerializer,
    ADSLProfileSerializer,
    PortControlSerializer,
    PoEPortStatusSerializer,
)
from ..swagger import schemas

@method_decorator(schemas.port_control_api_doc, name="post")  # API DOC
@method_decorator(profile_permission(models.Profile.REBOOT), name="dispatch")
class PortControlAPIView(generics.GenericAPIView):
    permission_classes = [IsAuthenticated, DevicePermission]
    serializer_class = PortControlSerializer

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.port_desc = ""

    @except_connection_errors
    def post(self, request, device_name: str):
        """
        ## Изменяем состояние порта оборудования
        """

        # Проверяем данные, полученные в запросе, с помощью сериализатора.
        serializer: PortControlSerializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        port_status: Literal["up", "down", "reload"] = serializer.validated_data["status"]
        port_name: str = serializer.validated_data["port"]
        save_config: bool = serializer.validated_data["save"]

        model_dev = get_object_or_404(models.Devices, name=device_name)

        # Есть ли у пользователя доступ к группе данного оборудования
        self.check_object_permissions(request, model_dev)

        # Если оборудование Недоступно
        if not model_dev.available:
            return Response({"error": "Оборудование недоступно!"}, status=500)

        # Теперь наконец можем подключиться к оборудованию :)
        session = model_dev.connect()
        # Перезагрузка порта
        if port_status == "reload":
            port_change_status = session.reload_port(
                port=port_name,
                save_config=save_config,
            )

        # UP and DOWN
        else:
            port_change_status = session.set_port(
                port=port_name,
                status=port_status,
                save_config=save_config,
            )

        if "Неверный порт" in port_change_status:
            return Response({"error": port_change_status}, status=400)

        # Логи
        log(
            request.user,
            model_dev,
            f"{port_status} port {port_name} ({self.port_desc}) \n{port_change_status}",
        )

        return Response(serializer.validated_data, status=200)

    def check_object_permissions(self, request, device) -> None:
        # Смотрим интерфейсы, которые сохранены в БД
        dev_info, _ = DevicesInfo.objects.get_or_create(dev=device)

        if dev_info.interfaces is None:
            # Собираем интерфейсы с оборудования.
            interfaces = Interfaces(device.connect().get_interfaces())
        else:
            # Преобразовываем JSON строку с интерфейсами в класс `Interfaces`
            interfaces = Interfaces(orjson.loads(dev_info.interfaces))

        # Далее смотрим описание на порту, так как от этого будет зависеть, может ли пользователь управлять им
        self.port_desc: str = interfaces[self.request.data["port"]].desc

        # Если не суперпользователь, то нельзя изменять состояние определенных портов
        if not request.user.is_superuser and settings.PORT_GUARD_PATTERN.search(self.port_desc):
            raise PermissionDenied(
                detail="Запрещено изменять состояние данного порта!",
            )

        # Если недостаточно привилегий для изменения статуса порта
        if request.user.profile.perm_level < 2 and request.data["status"] in ["up", "down"]:
            # Логи
            log(
                request.user,
                device,
                f"Tried to set port {request.data['port']} ({self.port_desc}) "
                f"to the {request.data['status']} state, but was refused \n",
            )

            raise PermissionDenied(
                detail="У вас недостаточно прав, для изменения состояния порта!",
            )

@method_decorator(profile_permission(models.Profile.BRAS), name="dispatch")
class ChangeDescriptionAPIView(APIView):
    """
    ## Изменяем описание на порту у оборудования
    """

    permission_classes = [IsAuthenticated, DevicePermission]

    @except_connection_errors
    def post(self, request, device_name: str):
        """
        ## Меняем описание на порту оборудования

        Требуется передать JSON:

            {
                "port": "порт оборудования",
                "description": "новое описание порта"
            }

        Если указанного порта не существует на оборудовании, то будет отправлен ответ со статусом `400`

            {
                "detail": "Неверный порт {port}"
            }

        Если описание слишком длинное, то будет отправлен ответ со статусом `400`

            {
                "detail": "Слишком длинное описание! Укажите не более {max_length} символов."
            }

        """

        if not self.request.data.get("port"):
            raise ValidationError({"detail": "Укажите порт!"})

        dev = get_object_or_404(models.Devices, name=device_name)

        # Проверяем права доступа пользователя к оборудованию
        self.check_object_permissions(request, dev)

        new_description = self.request.data.get("description", "")
        port = self.request.data.get("port")

        set_description_status = dev.connect().set_description(port=port, desc=new_description)

        if set_description_status.max_length:
            # Если есть данные, что описание слишком длинное.
            raise ValidationError(
                {
                    "detail": "Слишком длинное описание! "
                    f"Укажите не более {set_description_status.max_length} символов."
                }
            )

        log(request.user, dev, str(set_description_status))

        if set_description_status.error:
            return Response(
                {"detail": f"{set_description_status.error}, port={port}"},
                status=400 if set_description_status.error == "Неверный порт" else 500,
            )
        # Логи

        return Response(
            {
                "description": set_description_status.description,
                "port": set_description_status.port,
                "saved": set_description_status.saved,
            }
        )

class MacListAPIView(APIView):
    permission_classes = [IsAuthenticated, DevicePermission]

    @except_connection_errors
    def get(self, request, device_name):
        """
        ## Смотрим MAC-адреса на порту оборудования

        Для этого необходимо передать порт в параметре URL `?port=eth1`

        Если порт верный и там есть MAC-адреса, то будет вот такой ответ:

            {
                "count": 47,
                "result": [
                    {
                        "vlanID": "1051",
                        "mac": "00-04-96-51-AD-3D",
                        "vlanName": ""
                    },
                    {
                        "vlanID": "1051",
                        "mac": "00-04-96-52-A5-FB",
                        "vlanName": ""
                    },
                    ...
                ]
            }

        """

        port = self.request.GET.get("port")
        if not port:
            raise ValidationError({"detail": "Укажите порт!"})

        device = get_object_or_404(models.Devices, name=device_name)
        self.check_object_permissions(request, device)

        macs = []  # Итоговый список
        for vid, mac in device.connect().get_mac(port):  # Смотрим VLAN и MAC
            macs.append(
                {
                    "vlanID": vid,
                    "mac": mac,
                    "vlanName": self.get_vlan_name(vid),
                }
            )

        return Response({"count": len(macs), "result": macs})

    @staticmethod
    @lru_cache(maxsize=35)
    def get_vlan_name(vlan_id: int) -> str:
        try:
            return VlanName.objects.get(vid=int(vlan_id)).name
        except (ValueError, VlanName.DoesNotExist):
            return ""

class CableDiagAPIView(APIView):
    permission_classes = [IsAuthenticated, DevicePermission]

    @except_connection_errors
    def get(self, request, device_name):
        """
        ## Запускаем диагностику кабеля на порту

        Для этого необходимо передать порт в параметре URL `?port=eth1`

        Функция возвращает данные в виде словаря.
        В зависимости от результата диагностики некоторые ключи могут отсутствовать за ненадобностью.

            {
                "len": "-",         # Длина кабеля в метрах, либо "-", когда не определено
                "status": "",       # Состояние на порту (Up, Down, Empty)
                "pair1": {
                    "status": "",   # Статус первой пары (Open, Short)
                    "len": "",      # Длина первой пары в метрах
                },
                "pair2": {
                    "status": "",   # Статус второй пары (Open, Short)
                    "len": "",      # Длина второй пары в метрах
                }
            }

        """

        if not request.GET.get("port"):
            raise ValidationError({"detail": "Неверные данные"})

        # Находим оборудование
        device = get_object_or_404(models.Devices, name=device_name)
        self.check_object_permissions(request, device)

        # Если оборудование недоступно
        if not device.available:
            return Response({"detail": "Device unavailable"}, status=500)

        try:
            cable_test = device.connect().virtual_cable_test(request.GET["port"])
        except InvalidMethod:
            return Response({"detail": "Unsupported for this device"}, status=400)
        else:
            return Response(cable_test)

@method_decorator(profile_permission(models.Profile.BRAS), name="dispatch")
class SetPoEAPIView(generics.GenericAPIView):
    permission_classes = [IsAuthenticated, DevicePermission]
    serializer_class = PoEPortStatusSerializer

    @except_connection_errors
    def post(self, request, device_name):
        """
        ## Устанавливает PoE статус на порту
        """

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # Находим оборудование
        device = get_object_or_404(models.Devices, name=device_name)
        self.check_object_permissions(request, device)

        # Если оборудование недоступно
        if not device.available:
            return Response({"detail": "Device unavailable"}, status=500)

        poe_status = serializer.validated_data["status"]
        port_name = serializer.validated_data["port"]

        try:
            _, err = device.connect().set_poe_out(port_name, poe_status)
        except InvalidMethod:
            return Response({"detail": "Unsupported for this device"}, status=400)
        else:
            if not err:
                return Response({"status": poe_status})
            return Response(
                {"detail": f"Invalid data ({poe_status})"},
                status=400,
            )

class InterfaceInfoAPIView(APIView):
    permission_classes = [IsAuthenticated, DevicePermission]

    @except_connection_errors
    def get(self, request, device_name):
        """
        ## Общая информация об определенном порте оборудования

        В зависимости от типа оборудования информация будет совершенно разной

        Поле `portDetailInfo.type` указывает тип данных, которые могут быть строкой, JSON, или HTML кодом.

            {
                "portDetailInfo": {
                    "type": "text",  - Тип данных для детальной информации о порте
                    "data": ""       - Сами данные
                },
                "portConfig":   "Конфигурация порта (из файла конфигурации)",
                "portType":     "COPPER"    - (SFP, COMBO),
                "portErrors":   "Ошибки на порту",
                "hasCableDiag": true        - Имеется ли на данном типе оборудования возможность диагностики порта
            }

        """

        port = self.request.GET.get("port")
        if not port:
            raise ValidationError({"detail": "Укажите порт!"})

        device = get_object_or_404(models.Devices, name=device_name)
        self.check_object_permissions(request, device)

        # Если оборудование недоступно
        if not device.available:
            return Response({"detail": "Device unavailable"}, status=500)

        result = {}
        session = device.connect()

        result["portDetailInfo"] = session.get_port_info(port)
        result["portConfig"] = session.get_port_config(port)
        result["portType"] = session.get_port_type(port)
        result["portErrors"] = session.get_port_errors(port)
        result["hasCableDiag"] = True

        if result["portDetailInfo"].get("type") == "gpon":
            # Ищем возможные комментарии только для GPON типа
            result["portDetailInfo"]["data"]["onts_lines"] = self.create_onts_lines_with_comments(
                result["portDetailInfo"]["data"].get("onts_lines", []),
                gpon_port=port,
                device=device,
            )

        return Response(result)

    @staticmethod
    def create_onts_lines_with_comments(
            onts_lines: list, gpon_port: str, device: models.Devices
    ) -> list:
        """
        Находит комментарии созданные на ONT для порта `gpon_port` оборудования `device`.

        :param onts_lines: Текущий список данных ONT.
        :param gpon_port: Основной GPON порт.
        :param device: Оборудование, на котором надо искать комментарии.
        :return: Список данных ONT с добавлением в конец списка возможных комментариев.
        """
        if not onts_lines:
            return []

        interfaces_comments = device.interfacescomments_set.select_related("user")

        ont_interfaces_dict: Dict[str, list] = {}

        for comment in interfaces_comments:
            comment_data = {
                "text": comment.comment,
                "user": comment.user.username,
                "id": comment.id,
            }
            if ont_interfaces_dict.get(comment.interface):
                ont_interfaces_dict[comment.interface].append(comment_data)
            else:
                ont_interfaces_dict[comment.interface] = [comment_data]

        new_onts_lines = []

        for line in onts_lines:
            # Соединяем порт GPON и ONTid
            ont_full_port = f"{gpon_port}/{line[0]}"
            # Добавляем комментарии либо пустой список в конец
            new_onts_lines.append(
                line
                + [
                    ont_interfaces_dict.get(ont_full_port, []),
                ]
            )
        return new_onts_lines

@method_decorator(profile_permission(models.Profile.BRAS), name="dispatch")
class ChangeDSLProfileAPIView(APIView):
    permission_classes = [IsAuthenticated, DevicePermission]

    @except_connection_errors
    def post(self, request, device_name: str):
        """
        ## Изменяем профиль xDSL порта на другой

        Возвращаем `{ "status": status }` или `{ "error": error }`

        """

        serializer = ADSLProfileSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        device = get_object_or_404(models.Devices, name=device_name)
        self.check_object_permissions(request, device)

        # Если оборудование недоступно
        if not device.available:
            return Response({"detail": "Device unavailable"}, status=500)

        # Подключаемся к оборудованию
        session = device.connect()
        try:
            status = session.change_profile(
                serializer.validated_data["port"],
                serializer.validated_data["index"],
            )
        except InvalidMethod:
            # Нельзя менять профиль для данного устройства
            return Response({"error": "Device can't change profile"}, status=400)
        else:
            return Response({"status": status})

class CreateInterfaceCommentAPIView(generics.CreateAPIView):
    serializer_class = InterfacesCommentsSerializer

    def perform_create(self, serializer):
        dev = get_object_or_404(models.Devices, name=self.request.data.get("device"))
        serializer.save(user=self.request.user, device=dev)

class InterfaceCommentAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = models.InterfacesComments.objects.all()
    serializer_class = InterfacesCommentsSerializer
    lookup_field = "pk"
    lookup_url_kwarg = "pk"


import os
import sys
import tensorflow as tf
import subprocess
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--octree", type=str, required=False,
                    default='../../octree')
parser.add_argument("--cuda", type=str, required=False,
                    default='/usr/local/cuda-10.1')
parser.add_argument('--key64', type=str, required=False,
                    default='false')
parser.add_argument('--cc', type=str, required=False,
                    default='g++')

args = parser.parse_args()
OCTREE_DIR = args.octree
CUDA_DIR = args.cuda
CC = args.cc
KEY64 = '-DKEY64' if args.key64.lower() == 'true' else ''
LIBS_DIR = os.path.dirname(os.path.realpath(__file__))

TF_CFLAGS = " ".join(tf.sysconfig.get_compile_flags())
TF_LFLAGS = " ".join(tf.sysconfig.get_link_flags())

## g++-4.8
env_gcc = 'echo using g++ '
if CC == 'g++-4.8':
  cmds = [
    'sudo apt-get update',
    'sudo apt-get install gcc-4.8 --yes',
    'sudo apt-get install g++-4.8 --yes',]
  cmd = ' && '.join(cmds)
  print(cmd)
  os.system(cmd)
  env_gcc = 'echo using g++-4.8 && export CC=gcc-4.8 && export CXX=g++-4.8 '

## build octree
octree_ext = os.path.join(OCTREE_DIR, 'external/octree-ext')
if not os.path.exists(octree_ext):
  cmd = 'git clone --recursive https://github.com/wang-ps/octree-ext.git ' + octree_ext
  print(cmd)
  os.system(cmd)

octree_build = os.path.join(OCTREE_DIR, 'build')
if os.path.exists(octree_build):
  os.system('rm -r %s' % octree_build)

os.makedirs(octree_build)
os.chdir(octree_build)
abi = 'OFF' if '-D_GLIBCXX_USE_CXX11_ABI=1' in TF_CFLAGS else 'ON'
k64 = 'OFF' if KEY64 != '-DKEY64' else 'ON'
cmd = env_gcc + '&& cmake .. -DABI=%s -DKEY64=%s && make -j all' % (abi, k64)
print(cmd)
os.system(cmd)
os.system('./octree_test')  # run the test
os.chdir(LIBS_DIR)

## build ocnn-tf
lines = []
lines.append("TF_CFLAGS := %s" % TF_CFLAGS)
lines.append("TF_LFLAGS := %s" % TF_LFLAGS)
lines.append("OCT_CFLAGS := -I%s/octree" % OCTREE_DIR)
lines.append("OCT_LFLAGS := -L%s/build -loctree_lib" % OCTREE_DIR)
lines.append("")

lines.append("NVCC_FLAGS1 := -std=c++11 -O2 -c")
lines.append("NVCC_FLAGS2 := $(TF_CFLAGS) $(OCT_CFLAGS) -I %s/include "  \
             "-x cu -Xcompiler -fPIC -D GOOGLE_CUDA=1 -I /usr/local   "  \
             "-expt-relaxed-constexpr -DNDEBUG %s" % (CUDA_DIR, KEY64))
lines.append("CC_FLAGS1 := -std=c++11 -O2")
lines.append("CC_FLAGS2 := $(TF_CFLAGS) $(OCT_CFLAGS) -I %s/include   "  \
             "-L %s/lib64 -D GOOGLE_CUDA=1 $(TF_LFLAGS) $(OCT_LFLAGS) "  \
             "-fPIC -lcudart %s" % (CUDA_DIR, CUDA_DIR, KEY64))
lines.append("")

lines.append("CC := %s" % CC)
lines.append("NVCC := %s/bin/nvcc" % CUDA_DIR)
lines.append("")

cpu_objects = []
cpu_sources = []
gpu_objects = []
gpu_sources = []
all_headers = []
for filename in sorted(os.listdir(".")):
  if filename.endswith(".cu.cc") or filename.endswith(".cu"):
    targetname = filename + ".o"
    gpu_sources.append(filename)
    gpu_objects.append(os.path.join("object", targetname))
  elif filename.endswith(".cc") or filename.endswith(".cpp"):
    targetname = filename + ".o"
    cpu_sources.append(filename)
    cpu_objects.append(os.path.join("object", targetname))
  elif filename.endswith(".h"):
    all_headers.append(filename)

lines.append("cpu_objects := %s" % " ".join(cpu_objects))
lines.append("gpu_objects := %s" % " ".join(gpu_objects))
lines.append("")

lines.append(".PHONY : all clean")
lines.append("")

lines.append("all : libocnn.so")
lines.append("")

lines.append("libocnn.so : $(cpu_objects) $(gpu_objects)")
lines.append("\t$(CC) $(CC_FLAGS1) -shared -o libocnn.so object/*.o $(CC_FLAGS2)")
lines.append("")

for i in range(len(cpu_objects)):
  dependency = b" ".join(
      subprocess.Popen("%s -std=c++11 -MM -MG %s" % (CC, cpu_sources[i]),
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       shell=True).stdout.readlines()).decode("utf-8")
  headers = []
  for h in all_headers:
    if dependency.find(h) > 0:
      headers.append(h)
  headers = " ".join(headers)
  lines.append("%s : %s %s" % (cpu_objects[i], headers, cpu_sources[i]))
  lines.append("\t$(CC) $(CC_FLAGS1) -c %s $(CC_FLAGS2) -o %s" % \
               (cpu_sources[i], cpu_objects[i]))
  lines.append("")

for i in range(len(gpu_objects)):
  dependency = b" ".join(
      subprocess.Popen("%s -std=c++11 -MM -MG %s" % (CC, gpu_sources[i]),
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       shell=True).stdout.readlines()).decode("utf-8")
  headers = []
  for h in all_headers:
    if dependency.find(h) > 0:
      headers.append(h)
  headers = " ".join(headers)
  lines.append("%s : %s %s" % (gpu_objects[i], headers, gpu_sources[i]))
  lines.append("\t$(NVCC) $(NVCC_FLAGS1) %s $(NVCC_FLAGS2) -o %s" % \
               (gpu_sources[i], gpu_objects[i]))
  lines.append("")

lines.append("clean :")
lines.append("\t rm %s" % os.path.join("object", "*.o"))
lines.append("")

lines = [line + "\n" for line in lines]
with open("Makefile", "w") as f:
  f.writelines(lines)

# make
if os.path.exists("object"):
  os.system("rm -r object")
os.mkdir("object")
os.system("make -j all")

# test
os.chdir(LIBS_DIR + "/../test")
# env variable
cmd = 'export OCTREE_KEY=' + ('64' if KEY64 == '-DKEY64' else '32')
os.system(cmd + " && python test_all.py")


#% pip install openpyxl
import os, re, configparser
import pandas as pd
import numpy as np
from globals import glob
from utilities_database import prepare_data, prepare_database, consult_database, clear_databases, retrieve_data, rename_index, get_date, get_sigma, rename_limits_table
from utilities_analysis import mean_calculator, limits_generator, ini_generator_personalized, RyR, z_score_filter, reset_df
from utilities_plotting import plot_scatter
import _db_tools as db
import pandas as pd
from globals import glob
import matplotlib.pyplot as plt

os.chdir(os.path.dirname(os.path.realpath(__file__)))  ####Delete after debugging

def ini_generator(limits: pd.DataFrame, lenses_per_nest: int) -> None:
    '''Generates an ini file with personalized limits for every mean.
    Parameters:
    - limits (pd.DataFrame): DataFrame containing the personalized limits for each mean.
        The DataFrame is expected to have two columns, where the first column represents
        the lower limit and the second column represents the upper limit.
    - lenses_per_nest (int): Number of lenses per nest. Should be 3 or 4.
    Raises:
    ValueError: If lenses_per_nest is neither 3 nor 4.
    The function reads a template .ini file based on the lenses_per_nest parameter,
    updates the limits in the template with the provided limits DataFrame, and
    saves the modified data to a new .ini file.
    Example:
    >>> import pandas as pd
    >>> limits_data = {'LO_LIMIT': [10, 15, 20], 'HI_LIMIT': [30, 35, 40]}
    >>> limits_df = pd.DataFrame(limits_data)
    >>> ini_generator(limits_df, 3)
    '''
    class CaseSensitiveConfigParser(configparser.ConfigParser):
        '''
        A custom class to override optionxform and avoid uppercases being converted to lowercases.
        '''
        def optionxform(self, optionstr):
            return optionstr
    config = CaseSensitiveConfigParser()
    #Import a template based on the number of lenses per nest
    if lenses_per_nest == 3:
        config.read('../data/template_12_fibers.ini')
    elif lenses_per_nest == 4:
        config.read('../data/template_16_fibers.ini')
    else:
        raise ValueError("lenses_per_nest should be 3 or 4.")
    keys_list = []
    #Get a keys list with the correct uppercased keys
    for section_name in config.sections():
        section = config[section_name]
        keys_list.extend(section.keys())
    HI_LIMIT = limits.iloc[:, 1]
    LO_LIMIT = limits.iloc[:, 0]
    #Iterate through the sections and options in the .ini file
    for section in config.sections():
        keys_list = list(config[section].keys())
        j = 0
        for i in range(0, len(keys_list), 2):
            key1 = keys_list[i]
            key2 = keys_list[i + 1]
            col1 = str(limits.iloc[j, 1])
            col2 = str(limits.iloc[j, 0])
            j += 1
            config[section][key1] = col1
            config[section][key2] = col2
    #Print the five first elements of the .ini for a quick check
    for section in config.sections():
        print(f"[{section}]")
        i = 0
        for key, value in config.items(section):
            if i < 5:
                print(f"{key} = {value}")
                i += 1
            else:
                break
        print("...")
    #Save the modified data to a new .ini file
    save_path = os.path.abspath(f'../a2_output/{glob.tooling}.ini')
    with open(save_path, 'w') as configfile:
        for section in config.sections():
            configfile.write(f"[{section}]\n")
            keys = keys_list  #Recover the original keys to write them in the .ini file
            for i, key in enumerate(keys):
                configfile.write(f"{key} = {config[section][key]}\n")
                if (i + 1) % 4 == 0 and i < len(keys) - 1:  #Insert a blank line every four keys
                    configfile.write("\n")

limits_data = {'LO_LIMIT': [10, 15, 20], 'HI_LIMIT': [30, 35, 40]}
limits_df = pd.DataFrame(limits_data)
ini_generator(limits_df, 3)


#Indeed: Sarar Aseer, Hasif Ahmed
#SoftDev1 pd8
#K10 -- Jinja Tuning
#2018-09-24

import csv
import random
#source: https://realpython.com/python-csv/
#reads and returns a dictionary
def read(file):
    f = open(file) #stores file info in file object "f"
    open_f = csv.DictReader(f) #open_f is a csv.reader object (DictReader is better bc you can just use the name of the column)
    employment = {}

    #for every line
    for row in open_f:
        employment[row['Job Class']]=float(row['Percentage']) #able to use bc of DictReader

    del employment['Total'] #removing bottom layer
    return employment

def retjob(file): #returns random occupation based on percentage
    employment = read(file)
    chance = random.uniform(0,99.8) #uniform to attain random float
    for i in employment:
        chance -= employment[i]
        if chance <= 0:
            return i #return job


# import pygame as pg
class Perso:

    def __init__(self, surface, xpos, ypos, step_x, step_y):
        self.surface = surface
        self.xpos=xpos
        self.ypos=ypos
        self.step_x=step_x
        self.step_y = step_y

    def deplacement(self, xpos=None, ypos=None, largeurEcran=None, hauteurEcran=None, step_x=None,
                    step_y=None):

        if xpos > largeurEcran - 96 or xpos < 0:
            step_x = -step_x
            print(step_x)
        if ypos > hauteurEcran - 90 or ypos < 0:
            step_y = -step_y
        xpos += step_x
        ypos += step_y
        return (xpos, ypos, step_x, step_y)


# **************************************************************************
# *
# * Authors:     J.M. De la Rosa Trevin (jmdelarosa@cnb.csic.es)
# *
# * Unidad de  Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307  USA
# *
# *  All comments concerning this program package may be sent to the
# *  e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************

import os
from os.path import join
from glob import glob
import re
from datetime import datetime

import pyworkflow.utils as pwutils
import pyworkflow.protocol.params as params
from pyworkflow.utils.path import expandPattern, copyFile, createAbsLink
from pyworkflow.em.protocol import EMProtocol

class ProtImport(EMProtocol):
    """ Base class for other all Import protocols. """

class ProtImportFiles(ProtImport):
    """ Base class for other Import protocols.
    All imports protocols will have:
    1) Several options to import from (_getImportOptions function)
    2) First option will always be "from files". (for this option
      files with a given pattern will be retrieved  and the ### will
      be used to mark an ID part from the filename.
      - For each file a function to process it will be called
        (_importFile(fileName, fileId))
    """
    IMPORT_FROM_FILES = 0

    #--------------------------- DEFINE param functions ------------------------
    def _defineParams(self, form):
        importChoices = self._getImportChoices()
        filesCondition = self._getFilesCondition()

        form.addSection(label='Import')

        if len(importChoices) > 1: # not only from files
            form.addParam('importFrom', params.EnumParam,
                          choices=importChoices, default=self._getDefaultChoice(),
                          label='Import from',
                          help='Select the type of import.')
        else:
            form.addHidden('importFrom', params.EnumParam,
                          choices=importChoices, default=self.IMPORT_FROM_FILES,
                          label='Import from',
                          help='Select the type of import.')
        form.addParam('filesPath', params.PathParam,
                      condition=filesCondition,
                      label="Files directory",
                      help="Directory with the files you want to import.\n\n"
                           "The path can also contain wildcards to select"
                           "from several folders. \n\n"
                           "Examples:\n"
                           "  ~/Particles/data/day??_micrographs/\n"
                           "Each '?' represents one unknown character\n\n"
                           "  ~/Particles/data/day*_micrographs/\n"
                           "'*' represents any number of unknown characters\n\n"
                           "  ~/Particles/data/day#_micrographs/\n"
                           "'#' represents one digit that will be used as "
                           "micrograph ID\n\n"
                           "NOTE: wildcard characters ('*', '?', '#') "
                           "cannot appear in the actual path.)")
        form.addParam('filesPattern', params.StringParam,
                      label='Pattern',
                      condition=filesCondition,
                      help="Pattern of the files to be imported.\n\n"
                           "The pattern can contain standard wildcards such as\n"
                           "*, ?, etc, or special ones like ### to mark some\n"
                           "digits in the filename as ID.\n\n"
                           "NOTE: wildcards and special characters "
                           "('*', '?', '#', ':', '%') cannot appear in the "
                           "actual path.")
        form.addParam('copyFiles', params.BooleanParam, default=False,
                      expertLevel=params.LEVEL_ADVANCED,
                      label="Copy files?",
                      help="By default the files are not copied into the "
                           "project to avoid data duplication and to save "
                           "disk space. Instead of copying, symbolic links are "
                           "created pointing to original files. This approach "
                           "has the drawback that if the project is moved to "
                           "another computer, the links need to be restored.")

        self._defineImportParams(form)

        self._defineAcquisitionParams(form)

        form.addSection('Streaming')

        form.addParam('dataStreaming', params.BooleanParam, default=False,
              label="Process data in streaming?",
              help="Select this option if you want import data as it is "
                   "generated and process on the fly by next protocols. "
                   "In this case the protocol will keep running to check "
                   "new files and will update the output Set, which can "
                   "be used right away by next steps.")

        form.addParam('timeout', params.IntParam, default=43200,
              condition='dataStreaming',
              label="Timeout (secs)",
              help="Interval of time (in seconds) after which, if no new file "
                   "is detected, the protocol will end. When finished, "
                   "the output Set will be closed and no more data will be "
                   "added to it. \n"
                    "Note 1:  The default value is  high (12 hours) to avoid "
                   "the protocol finishes during the aqcuisition of the "
                   "microscope. You can also stop it from right click and press "
                   "STOP_STREAMING.\n"
                   "Note 2: If you're using individual frames when importing "
                   "movies, the timeout won't be refreshed until a whole "
                   "movie is stacked.")

        form.addParam('fileTimeout', params.IntParam, default=30,
              condition='dataStreaming',
              label="File timeout (secs)",
              help="Interval of time (in seconds) after which, if a file has "
                   "not changed, we consider it as a new file. \n")

        self._defineBlacklistParams(form)

    def _defineImportParams(self, form):
        """ Override to add options related to the different types
        of import that are allowed by each protocol.
        """
        pass

    def _defineAcquisitionParams(self, form):
        """ Override to add options related to acquisition info.
        """
        pass

    def _defineBlacklistParams(self, form):
        """ Override to add options related to blacklist info.
        """
        pass

    def _getDefaultChoice(self):
        return  self.IMPORT_FROM_FILES

    #--------------------------- INFO functions --------------------------------
    def _validate(self):
        errors = []
        if self.importFrom == self.IMPORT_FROM_FILES:
            if not self.getPattern():
                errors.append("The path and pattern can not be both empty!!!")
            else:
                # Just check the number of files matching the pattern
                self.getMatchFiles()
                if self.numberOfFiles == 0:
                    errors.append("There are no files matching the pattern %s"
                                  % self.getPattern())

        return errors

    #--------------------------- BASE methods to be overriden ------------------
    def _getImportChoices(self):
        """ Return a list of possible choices
        from which the import can be done.
        (usually packages formas such as: xmipp3, eman2, relion...etc.
        """
        return ['files']

    def _getFilesCondition(self):
        """ Return an string representing the condition
        when to display the files path and pattern to grab
        files.
        """
        return '(importFrom == %d)' % self.IMPORT_FROM_FILES

    #--------------------------- UTILS functions -------------------------------
    def getPattern(self):
        """ Expand the pattern using environ vars or username
        and also replacing special character # by digit matching.
        """
        self._idRegex = None
        filesPath = self.filesPath.get('').strip()
        filesPattern = self.filesPattern.get('').strip()

        if filesPattern:
            fullPattern = join(filesPath, filesPattern)
        else:
            fullPattern = filesPath

        pattern = expandPattern(fullPattern.replace("$", ""))
        match = re.match('[^#]*(#+)[^#]*', pattern)

        if match is not None:
            g = match.group(1)
            n = len(g)
            # prepare regex pattern - place ids, handle *, handle ?
            idregex = pattern.replace(g, '(%s)' % ('[0-9]'*n))
            idregex = idregex.replace('*','.*')
            idregex = idregex.replace('?', '.')
            self._idRegex = re.compile(idregex)
            pattern = pattern.replace(g, '[0-9]'*n)

        return pattern

    def getMatchFiles(self, pattern=None):
        """ Return a sorted list with the paths of files that
        matched the pattern.
        """
        if pattern is None:
            pattern = self.getPattern()

        filePaths = glob(pattern)
        filePaths.sort()
        self.numberOfFiles = len(filePaths)

        return filePaths

    def getCopyOrLink(self):
        # Set a function to copyFile or createLink
        # depending in the user selected option
        if self.copyFiles:
            return copyFile
        else:
            return createAbsLink

    def fileModified(self, fileName, fileTimeout):
        """ Check if the fileName modification time is less
        than a given timeout.
        Params:
            fileName: input filename that will be checked.
            fileTimeout: timeout """
        self.debug('Checking file: %s' % fileName)
        mTime = datetime.fromtimestamp(os.path.getmtime(fileName))
        delta = datetime.now() - mTime
        self.debug('   Modification time: %s' % pwutils.prettyTime(mTime))
        self.debug('   Delta: %s' % pwutils.prettyDelta(delta))

        return delta < fileTimeout

    def isBlacklisted(self, fileName):
        """ Overwrite in subclasses """
        return False

    def iterFiles(self):
        """ Iterate through the files matched with the pattern.
        Provide the fileName and fileId.
        """
        filePaths = self.getMatchFiles()

        for fileName in filePaths:
            if self._idRegex:
                # Try to match the file id from filename
                # this is set by the user by using #### format in the pattern
                match = self._idRegex.match(fileName)
                if match is None:
                    raise Exception("File '%s' doesn't match the pattern '%s'"
                                    % (fileName, self.getPattern()))

                fileId = int(match.group(1))

            else:
                fileId = None

            yield fileName, fileId

    def worksInStreaming(self):
        # Import protocols always work in streaming
        return True


from trading_ig.config import config
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# if you need to cache to DB your requests
from datetime import timedelta
import requests_cache
from getting_realtime_data.data_retrieval import Data_Retrieval
from sending_orders.order_management import Order_Management
from management_of_position.position_management import Position_Management
from predefined_functions.initialisation import Initialisation
from get_data.get_market_data import Get_Market_Data
import time
from datetime import datetime, timedelta, date
from predefined_functions.defined_functionality import Defined_Functionality
import traceback
import pandas as pd
import sys
import math

# the newest one where you make market order base on price movements 5 or more and try to catch the trend

class Algo0:
    def __init__(self):
        logging.basicConfig(level=logging.INFO)
        self.df = Defined_Functionality()

    def run(self):

        while(True):

            try:

                start_time = datetime.now()
                self.check_all_working_orders()
                end_time = datetime.now() - start_time
                print(end_time)

            except Exception as e:
                print(e, "traceback back in custom algo frame work")
                traceback.print_exc()

    def check_all_working_orders(self):
        # check if opening market has passed , if we have a position in it then close all other orders, or if only one of that order remains
        orders = self.df.get_working_orders()
        for epic in orders["epic"].unique():
            self.checking_working_order_is_present_under_epic_and_amend_orders(epic=epic)

    def checking_working_order_is_present_under_epic_and_amend_orders(self, epic):
        # check there are two orders for each epic
        created_order = True
        while(True):
            orders = self.df.get_working_orders_by_epic(epic=epic)
            if orders.index.size == 2:
                directions = orders["direction"].to_list()
                if ("BUY" in directions and "SELL" in directions):
                    data = self.df.get_market_data(epic=epic)

                    if data == None:
                        continue
                    # market is still open
                    map_of_time = data["instrument"]["openingHours"]
                    if map_of_time == None:
                        break
                    single_time = map_of_time["marketTimes"][0]["openTime"]
                    opening_market_time = datetime.strptime(single_time, '%H:%M').time()
                    diff_in_time = datetime.combine(date.today(), opening_market_time) - datetime.now()

                    # if the time is bigger than x second then we can still put orders in place
                    total_seconds = diff_in_time.total_seconds()
                    # -1 seconds
                    if total_seconds < -(0.2):
                        # delete the orders if any are pending
                        break

                    position = self.df.find_open_position_by_epic(epic=epic)
                    if len(position) != 0:
                        break

                    print("market is not open yet and orders are in place nothing needs to be done yet")
                    return created_order

            break

        print("delete orders")
        self.df.cancel_orders_by_epic(epic=epic)
        created_order = False

        return created_order