import numpy as np
import pandas as pd
import codecademylib3
import matplotlib.pyplot as plt
import seaborn as sns

# ---------------
# Task 1: Drop nan values.
# ---------------

# Read the csv data as a DataFrame
df = pd.read_csv('./telescope_data.csv', index_col=0)

# Remove null and na values
df.dropna()

# Print the DataFrame head
print('Task 1:')
print(df.head())

# ---------------
# Task 2: Extract class column.
# ---------------
# Extract the class classes
classes = df['class']
data_matrix = df.drop(columns='class')

print('Task 2:')
print(data_matrix)

# ---------------
# Task 3: Create a correlation matrix.
# ---------------
# Use the `.corr()` method on `data_matrix` to get the correlation matrix
correlation_matrix = data_matrix.corr()

ax = plt.axes()
sns.heatmap(correlation_matrix, cmap='Greens', ax=ax)
ax.set_title('Task 3:')
plt.show()

# ---------------
# Task 4: Perform eigendecomposition.
# ---------------
print('Task 4:')

# Perform eigendecomposition using `np.linalg.eig`
eigenvalues, eigenvectors = np.linalg.eig(correlation_matrix)
print(f'Eigenvalues length: {eigenvalues.size}, Original Number of Features: {data_matrix.shape[1]}')

# Order the eigenvalues by ordering the indices of the eigenvalues using `argsort`, and use [::-1] to order them from greatest to smallest
indices = eigenvalues.argsort()[::-1]
eigenvalues = eigenvalues[indices]
eigenvectors = eigenvectors[:, indices]

print(eigenvalues.shape, eigenvectors.shape)

# ---------------
# Task 5: Find the variance/information percentages for each eigenvalue.
# ---------------
# Find the percentages of information for each eigenvector, which is generated by the proportion of its eigenvalues to the sum of all eigenvalues
information_proportions = eigenvalues / eigenvalues.sum()
information_percents = information_proportions * 100

# Plot the principal axes vs the information proportions for each principal axis
plt.figure()
plt.plot(information_percents, 'ro-', linewidth=2)
plt.title('Task 5: Scree Plot')
plt.xlabel('Principal Axes')
plt.ylabel('Percent of Information Explained')
plt.show()

# ---------------
# Task 6: Find the cumulative variance/information percentages for each eigenvalue.
# ---------------
# Find the cumulative sum of the percentages
cumulative_information_percents = np.cumsum(information_percents)

# Plot the cumulative percentages array
plt.figure()
plt.plot(cumulative_information_percents, 'ro-', linewidth=2)

# Also plot a horizontal line indicating the 95% mark, and a vertical line for the third principal axis
plt.hlines(y=95, xmin=0, xmax=15)
plt.vlines(x=6, ymin=0, ymax=100)
plt.title('Task 6: Cumulative Information percentages')
plt.xlabel('Principal Axes')
plt.ylabel('Cumulative Proportion of Variance Explained')
plt.show()


import DataReceive
import DataProcess
import time
# http://10.42.0.156:8000/
# '10.42.0.156:8000' #eth0 @ Lab
# '10.42.0.111:8000' #eth0 @Ashmore, Second RPi3B+

PHOTO_FOLDER = 'test_stream'
PREDICTION_RESULT_FOLDER = 'test_stream_result'

### SAVE DELTAS ON RECEIVE AND PREDICT OBJECT MUST BE THE SAME CURRENTLY.
#receive_object_1 = DataReceive.RPiVideoStream(pi_address='10.42.0.111:8000', framerate=30, save_folder=PHOTO_FOLDER)
#time.sleep(1)
predict_object_1 = DataProcess.ActivePredict(search_folder='./' + PHOTO_FOLDER, save_folder=PREDICTION_RESULT_FOLDER)

predict_object_1.start_prediction_pipeline(verbose=True)
time.sleep(5)
#receive_object_1.start_streaming_pipeline()

while(True):
    time.sleep(1)
#receive_object_1.stop_streaming()
predict_object_1.stop_predicting(finish_processing=False)


from flask import Blueprint, flash
from flask import Flask, render_template, redirect, request, url_for
from flask_sqlalchemy  import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
import new_user_credentials as nuc
from werkzeug.security import generate_password_hash, check_password_hash
from flask import current_app as app
from models import individual,labs,doctor
from flask_mail import Mail, Message

register_bp = Blueprint('register_bp', __name__)

login_manager = LoginManager()
login_manager.init_app(app)
mail = Mail(app)

db = SQLAlchemy(app)
db.create_all()
SQLALCHEMY_TRACK_MODIFICATIONS = False

@login_manager.user_loader
def load_user(user_id):
	return individual.query.get(user_id)

@register_bp.route('/individual_form_submit', methods = ['GET' , 'POST'])
def sub():
	if request.method == 'POST':
		try:
			fname = request.form['fname']
			lname = request.form['lname']
			email = request.form['email']
			mob = request.form['mob']
			dob = str(request.form['dob'])
			gender = request.form['gender']
			aadhaar = request.form['aadhaar']
			blood = request.form['blood']
			state = request.form['state']
			city = request.form['city']
			district = request.form['district']
			pin = request.form['pincode']
			addr1=request.form['add1']
			addr2=request.form['add2']

			nu = nuc.New_user(city, dob)
			h_id, pasw = nu.create_user()
			temp = individual(id=h_id, pasw=generate_password_hash(pasw) ,
				fname=fname, lname =lname, email=email, mob =mob, dob=dob,gender=gender,aadhaar=aadhaar, blood=blood,
				state=state, city=city, district=district, pin=pin, addr1=addr1, addr2=addr2 )
			temp.send_pdf_indi()
			db.session.add(temp)
			db.session.commit()

			thank_msg = "Record successfully added"
			message = "Hi "+fname+" " +lname+"\nThank You for registering with National Digital Health Portal.\nYour login credentials are - \nUsername - " + h_id + "\nPassword - " + pasw
			msg = Message('NDHP Registration', sender = 'ndhp.gov@gmail.com', recipients = [email])
			msg.body = message
			path = "C:\\minor_project\\static\\"
			with app.open_resource("GFG.pdf") as fp:
				msg.attach("GFG.pdf", "file/pdf", fp.read())
			mail.send(msg)
			return render_template('thank.html',namee=thank_msg)

		except Exception as e:
			msg = e
			return render_template('thank.html',namee=msg)

#############################################################################      doctor
@register_bp.route('/doctor_form_submit', methods = ['GET' , 'POST'])
def doctor_reg_sub():
	if request.method == 'POST':
		try:
			indi_id = request.form['uid']
			fname = request.form['fname']
			lname = request.form['lname']
			email = request.form['email']
			mob = request.form['mob']
			dob = str(request.form['dob'])
			gender = request.form['gender']
			regnum = request.form['regnum']
			Specialization = request.form['Specialization']
			##add3=request.form['add3']  Please remove this
			state = request.form['state']
			city = request.form['city']
			district = request.form['district']
			pin = request.form['pincode']
			addr1=request.form['add1']
			addr2=request.form['add2']

			h_id="D"+indi_id[1:]
			y,m,d = dob.split("-")
			pasw = d+m+y

			temp = doctor(id=h_id, pasw=generate_password_hash(pasw) ,
				fname=fname, lname =lname, email=email, mob =mob, dob=dob,gender=gender,regnum=regnum, Specialization=Specialization,
				state=state, city=city, district=district, pin=pin, addr1=addr1, addr2=addr2 )

			db.session.add(temp)
			db.session.commit()

			thank_msg = "Record successfully added"
			message = "Hi "+fname+" " +lname+"\nThank You for registering with National Digital Health Portal.\nYour login credentials are - \nUsername - " + h_id + "\nPassword - " + pasw
			msg = Message('NDHP Registration', sender = 'ndhp.gov@gmail.com', recipients = [email])
			msg.body = message
			path = "C:\\minor_project\\static\\"
			#with app.open_resource("GFG.pdf") as fp:
				#msg.attach("GFG.pdf", "file/pdf", fp.read())
			mail.send(msg)
			return render_template('thank.html',namee=thank_msg)

		except Exception as e:
			msg = e
			return render_template('thank.html',namee=msg)
###########################################################################

@register_bp.route('/labs_form_submit', methods = ['GET' , 'POST'])
def lab_form_sub():
	if request.method == 'POST':
		try:
			lab_name = request.form['lab_name']
			tests_avlbl = request.form['tests_avlbl']
			email = request.form['email']
			mob = request.form['mob']
			licenseno = request.form['licenseno']
			owner_name=request.form['owner_name']
			state = request.form['state']
			city = request.form['city']
			district = request.form['district']
			pin = request.form['pincode']
			addr1=request.form['add1']
			addr2=request.form['add2']

			#nu = lc.Labs(city, dob)
			nu = nuc.New_user(city, owner_name)
			h_id, pasw = nu.create_user()
			temp = labs(id = id, licenseno=licenseno, pasw=generate_password_hash(pasw) ,
				labname=lab_name, tests_avlbl =tests_avlbl, email=email, mob =mob, owner_name=owner_name,
				state=state, city=city, district=district, pin=pin, addr1=addr1, addr2=addr2 )
			db.session.add(temp)
			db.session.commit()

			thank_msg = "Record successfully added"
			message = "Hi "+lab_name+"\nThank You for registering with National Digital Health Portal.\nYour login credentials are - \nUsername - " + h_id + "\nPassword - " + pasw
			msg = Message('NDHP Registration', sender = 'ndhp.gov@gmail.com', recipients = [email])
			msg.body = message
			path = "C:\\minor_project\\static\\"
			with app.open_resource("GFG.pdf") as fp:
				msg.attach("GFG.pdf", "file/pdf", fp.read())
			mail.send(msg)
			return render_template('thank.html',namee=thank_msg)

		except Exception as e:
			msg = e
			return render_template('thank.html',namee=msg)
			mail.send(msg)
			return render_template('thank.html',namee=thank_msg)

@register_bp.route('/doctor_indi_check', methods = ['GET' , 'POST'])
def doctor_indi_check():
	if request.method == 'POST':
		try:
			indi_id = request.form['indi']
			if(indi_id[0]=="I"):
					temp = individual.query.filter_by(id = indi_id).first()
					if temp:
						return render_template('doctor_register.html', temp_obj=temp)
					else:
						msg = "User not registered"
						flash("User not registered!")
						return redirect(url_for('register_bp.doctor_indi_check'))

			else:
				msg = "Invalid User ID!"
				flash("Invalid User ID!")
				return redirect(url_for('register_bp.doctor_indi_check'))

		except Exception as e:
			flash(e)
			return render_template('doctor_indi_check.html')
			#msg = "Error in insert operation"


# Uses python3
import sys

def lcm_naive(a, b):
    for l in range(1, a*b + 1):
        if l % a == 0 and l % b == 0:
            return l

    return a*b

def euclidean_gcd(a,b):
    if a == 0:
        return b
    elif b == 0:
        return a
    else:
        return euclidean_gcd(b,a%b)

x = list(map(int,input().split(" ")))
a = x[0]
b = x[1]
lcm = (a*b)//euclidean_gcd(a,b)
print(lcm)
#print(lcm_naive(a,b))


import logging
from typing import Dict, Set, Tuple
import numpy as np
import pandas as pd
from pyranges import PyRanges, read_gtf
from ..utils import get_frame_complement, i8_0, i8_2, validate_strand

GFF_FIELDS = [
    'Chromosome',
    'Strand',
    'Start',
    'End',
    'Frame',
    'Feature',
    'gene_id',
    'transcript_id'
]

GFF_FEATURES = {
    'CDS',
    'stop_codon',
    'UTR'
}

def get_exon_indices(g: pd.core.groupby.generic.DataFrameGroupBy) -> pd.Series:

    # Validate strand information
    strand_counts: pd.Series = g.Strand.value_counts()

    n = strand_counts.shape[0]
    if n == 0:
        raise ValueError("No strand information available!")
    if n > 1:
        raise ValueError("Inconsistent strand information for transcript!")

    strand: str = strand_counts.index.get_level_values(1).to_numpy()[0]
    validate_strand(strand)

    # Assign indices based on strand
    is_plus_strand: bool = strand == '+'
    return g.cumcount(ascending=is_plus_strand).astype(np.int32)

def _get_last_cds_indices(cds_ranges: pd.DataFrame, strand: str) -> np.ndarray:
    return cds_ranges[cds_ranges.Strand == strand].groupby('transcript_id', sort=False).exon_index.idxmax()

def _get_frames(frame: pd.Series) -> pd.Series:
    # Convert frame
    try:
        frame = frame.astype(np.int8)
    except ValueError:
        raise ValueError("Invalid frame in GTF/GFF2 file: not an integer!")

    # Validate frame range
    if not frame.between(i8_0, i8_2, inclusive=True).all():
        raise ValueError("Invalid frame in GTF/GFF2 file: out of range!")

    # Transform frame to its complement
    return get_frame_complement(frame)

def load_gff_cds(fp: str) -> Tuple[PyRanges, PyRanges]:

    # Load necessary fields from GTF/GFF2 file
    ranges: pd.DataFrame = read_gtf(fp, as_df=True)[GFF_FIELDS].rename(columns={
        'Frame': 'frame'
    })

    logging.debug("GTF/GFF2 file: %d features found." % ranges.shape[0])

    # Drop unnecessary features
    ranges = ranges[ranges.Feature.isin(GFF_FEATURES)]

    logging.debug("GTF/GFF2 file: %d CDS features found." % ranges.shape[0])

    # Compress identifiers
    ranges.transcript_id = ranges.transcript_id.astype('category')
    ranges.gene_id = ranges.gene_id.astype('category')

    # Extract UTR features
    utr_mask: pd.Series = ranges.Feature == 'UTR'
    utr_ranges: PyRanges = PyRanges(df=ranges[utr_mask].drop('Feature', axis=1))
    ranges = ranges[~utr_mask]
    del utr_mask

    # Transform frames
    ranges.frame = _get_frames(ranges.frame)
    assert ranges.frame.dtype == 'int8'

    # Extract stop codon features
    stop_mask: pd.Series = ranges.Feature == 'stop_codon'
    stop_codons: Dict[str, int] = {
        r.transcript_id: r.End if r.Strand == '+' else r.Start
        for r in ranges[stop_mask].itertuples()
    }
    ranges = ranges[~stop_mask]
    del stop_mask

    # Sort CDS features by genomic coordinates
    ranges = ranges.drop('Feature', axis=1).sort_values(by=[
        'gene_id', 'transcript_id', 'Chromosome', 'Strand', 'Start', 'End'
    ], ignore_index=True)

    # Validate number of gene and transcript identifiers
    gene_n: int = ranges.gene_id.cat.categories.size
    transcript_n: int = ranges.transcript_id.cat.categories.size

    logging.debug("GTF/GFF2 file: %d genes found." % gene_n)
    logging.debug("GTF/GFF2 file: %d transcripts found." % transcript_n)

    if gene_n == 0 or transcript_n == 0:
        raise ValueError("No gene or transcript ID found in GTF/GFF file!")

    if transcript_n > gene_n:
        raise ValueError("Multiple transcripts per gene in GTF/GFF file are not supported!")

    # Check for missing identifiers
    if ranges.gene_id.isnull().values.any():
        raise ValueError("Missing gene ID in GTF/GFF2 file!")
    if ranges.transcript_id.isnull().values.any():
        raise ValueError("Missing transcript ID in GTF/GFF2 file!")

    # Check only one transcript per gene is present
    gene_transcript_counts: pd.DataFrame = ranges.groupby([
        'gene_id',
        'transcript_id'
    ], sort=False).size().reset_index(name='counts')
    gene_transcript_counts = gene_transcript_counts[gene_transcript_counts.counts > 0]
    if gene_transcript_counts.shape[0] > gene_n:
        raise ValueError("Multiple transcripts per gene in GTF/GFF file are not supported!")

    # Assign a sequential index to each CDS feature (5' to 3')
    ranges['exon_index'] = ranges.groupby(
        ['transcript_id'], sort=False).pipe(get_exon_indices)

    # Append the stop codons to the last CDS features
    strands: Set[str] = set(ranges.Strand.cat.categories.values)

    if '+' in strands:
        last_cds_plus: np.ndarray = _get_last_cds_indices(ranges, '+')
        ranges.loc[last_cds_plus, 'End'] += 3
        del last_cds_plus

    if '-' in strands:
        last_cds_minus: np.ndarray = _get_last_cds_indices(ranges, '-')
        ranges.loc[last_cds_minus, 'Start'] -= 3
        del last_cds_minus

    # TODO: validate with stop codon features
    del stop_codons

    # Convert to PyRanges
    cds_ranges: PyRanges = PyRanges(df=ranges)

    return cds_ranges, utr_ranges


# -*- coding: utf-8 -*-
"""
参数列表：
    参数1         -->    参数2
    files         -->    文件全路径
    dirs          -->    目录全路径
参数描述:
    False         -->    未变更
    True          -->    被修改
标准输出: 布尔值
作者: zz
版本: v4.0.0
"""

## 导入python模块
import os, sys, time, socket
import logging

## 获取根目录并添加到全局路径变量中
nowPath  = os.path.dirname(os.path.abspath(__file__))
homePath = os.path.join(nowPath, '../../')
sys.path.append(homePath)

## 从全局变量文件中引用相应变量
from monitor import cfg, osCfg, socketTimeout

## 从全局函数文件中引用相应函数
from function import load_json_file, get_index, get_sec_index, get_initdata

## 设置socket执行超时
socket.setdefaulttimeout(socketTimeout)

## 指定日志格式
cfg.logFormat

## 主程序
def main(**kwargs):
    ## 获取项目标签
    label = cfg.fileLabel

    ## 获取缓存文件路径
    cachePath   = os.path.join(cfg.cachePath, label)
    curFileName = cfg.curCache.format(label)
    preFileName = cfg.preCache.format(label)
    curFile     = os.path.join(cachePath, curFileName)
    preFile     = os.path.join(cachePath, preFileName)

    ## 获取索引
    keyList = get_index(jsonFile = curFile)

    ## 获取结果数据
    try:
        arg1 = kwargs.get('arg1') or sys.argv[1].lower()
        arg2 = kwargs.get('arg2') or sys.argv[2].lower()
    except IndexError:
        logging.error(
            '参数错误, 需要两个参数. '
        )
    else:
        secKeyList = get_sec_index( jsonFile = curFile, arg1 = arg1)

        if keyList and secKeyList:
           if arg1 in keyList and arg2 in secKeyList:
               curValue = get_initdata(
                   arg1     = arg1,
                   arg2     = arg2,
                   jsonFile = curFile
               )
               preValue = get_initdata(
                   arg1     = arg1,
                   arg2     = arg2,
                   jsonFile = preFile
               )
               if curValue != None and preValue != None :
                   if curValue == preValue:
                       result = False
                   else:
                       result = True
               else:
                   logging.warning(
                       '当前值或之前值不存在: preValue={}, curValue={}, preFile={}, curFile'.format(
                       preValue, curValue, preFile, curFile)
                   )
                   result = None
           else:
               logging.error(
                   '参数错误: arg1={}, arg2={}, curFile={}, preFile={}'.format(
                   arg1, arg2, curFile, preFile)
               )
               result = None
           return result

## 调试
if __name__ == '__main__':
    if main() is None:
        print(__doc__)
    else:
        print(main())


"""
# Slack Block Message Builder

TODO:
    - track number of characters, raise error after 4k
    - attach text, fields

This class is intended to be used with a channel-specific slack webhook.
More information can be found here: https://app.slack.com/block-kit-builder.

## Messages are not configured to send in development

Messages or alerts sent using `send_message` or `on_failure_callback` will only
send if a Slack connection is defined and we are running in production. You can
manually override this for testing purposes by setting the `SLACK_MESSAGE_OVERRIDE`
variable to `true` in the Airflow UI.

## Send multiple messages - payload is reset after sending

>>> slack = SlackMessage(username="Multi-message Test")

>>> slack.add_text("message 1")
>>> slack.send()

>>> slack.add_text("message 2")
>>> slack.send()

## Embed images, plus context

>>> slack = SlackMessage(username="Blocks - Referenced Images")

>>> slack.add_context(":pika-love: context stuff *here*")

>>> msg = "Example message with new method of embedding images and divider below."

>>> slack.add_text(msg)
>>> slack.add_divider()
>>> slack.add_image(url1, title=img1_title, alt_text="img #1")
>>> slack.add_image(url2, title=img2_title, alt_text="img #2")
>>> slack.send()

## Dev Tools
>>> # prints current payload
>>> slack.display()

>>> # get payload dict
>>> payload = slack.payload

"""

import json
import logging
import re
from collections.abc import Callable
from os.path import basename
from typing import Any

from airflow.exceptions import AirflowNotFoundException
from airflow.models import Variable
from airflow.providers.http.hooks.http import HttpHook
from requests import Response
from typing_extensions import NotRequired, TypedDict

SLACK_NOTIFICATIONS_CONN_ID = "slack_notifications"
SLACK_ALERTS_CONN_ID = "slack_alerts"
JsonDict = dict[str, Any]
log = logging.getLogger(__name__)

class SilencedSlackNotification(TypedDict):
    """
    Configuration for a silenced Slack notification.

    issue: A link to a GitHub issue which describes why the notification
           is silenced and tracks resolving the problem.
    predicate: Slack notifications whose text or username contain the
               predicate will be silenced. Matching is case-insensitive.
    task_id_pattern: A regex pattern that matches the task_id of the task
                     that triggered the notification. (Optional)
    """

    issue: str
    predicate: str
    task_id_pattern: NotRequired[str | None]

class SlackMessage:
    """Slack Block Message Builder"""

    def __init__(
        self,
        username: str = "Airflow",
        icon_emoji: str = ":airflow:",
        unfurl_links: bool = True,
        unfurl_media: bool = True,
        http_conn_id: str = SLACK_NOTIFICATIONS_CONN_ID,
    ):
        self.http = HttpHook(method="POST", http_conn_id=http_conn_id)
        self.blocks = []
        self._context = {}
        self._payload: dict[str, Any] = {
            "username": username,
            "unfurl_links": unfurl_links,
            "unfurl_media": unfurl_media,
        }

        if icon_emoji:
            self._payload["icon_emoji"] = icon_emoji

        self._base_payload = self._payload.copy()

    @staticmethod
    def _text_block(message: str, plain_text: bool) -> JsonDict:
        text_type = "plain_text" if plain_text else "mrkdwn"
        return {"type": text_type, "text": message}

    @staticmethod
    def _image_block(
        url: str, title: str | None = None, alt_text: str | None = None
    ) -> JsonDict:
        img = {"type": "image", "image_url": url}
        if title:
            img.update({"title": {"type": "plain_text", "text": title}})
        if alt_text:
            img["alt_text"] = alt_text
        else:
            img["alt_text"] = basename(url)
        return img

    def clear(self) -> None:
        """Clear all stored data to prime the instance for a new message."""
        self.blocks = []
        self._context = {}
        self._payload = self._base_payload.copy()

    def display(self) -> None:
        """Print current payload, intended for local development only."""
        if self._context:
            self._append_context()
        self._payload.update({"blocks": self.blocks})
        print(json.dumps(self._payload, indent=4))

    @property
    def payload(self) -> JsonDict:
        payload = self._payload.copy()
        payload.update({"blocks": self.blocks})
        return payload

    ####################################################################################
    # Context
    ####################################################################################

    def _append_context(self) -> None:
        self.blocks.append(self._context.copy())
        self._context = {}

    def _add_context(
        self, body_generator: Callable, main_text: str, **options: Any
    ) -> None:
        if not self._context:
            self._context = {"type": "context", "elements": []}
        body = body_generator(main_text, **options)
        if len(self._context["elements"]) < 10:
            self._context["elements"].append(body)
        else:
            raise ValueError("Unable to include more than 10 context elements")

    def add_context(self, message: str, plain_text: bool = False) -> None:
        """Display context above or below a text block."""
        self._add_context(
            self._text_block,
            message,
            plain_text=plain_text,
        )

    def add_context_image(self, url: str, alt_text: str | None = None) -> None:
        """Display context image inline within a text block."""
        self._add_context(self._image_block, url, alt_text=alt_text)

    ####################################################################################
    # Blocks
    ####################################################################################

    def _add_block(self, block: JsonDict) -> None:
        if self._context:
            self._append_context()
        self.blocks.append(block)

    def add_divider(self) -> None:
        """Add a divider between blocks."""
        self._add_block({"type": "divider"})

    def add_text(self, message: str, plain_text: bool = False) -> None:
        """Add a text block, using markdown or plain text."""
        text = self._text_block(message, plain_text)
        self._add_block({"type": "section", "text": text})

    def add_image(
        self, url, title: str | None = None, alt_text: str | None = None
    ) -> None:
        """Add an image block, with optional title and alt text."""
        self._add_block(self._image_block(url, title, alt_text))

    ####################################################################################
    # Send
    ####################################################################################

    def send(self, notification_text: str = "Airflow notification") -> Response:
        """
        Send message payload to the channel configured by the webhook.

        Any notification text provided will only show up as the content within
        the notification pushed to various devices.
        """
        if not self._context and not self.blocks:
            raise ValueError("Nothing to send!")

        if self._context:
            self._append_context()
        self._payload.update({"blocks": self.blocks})
        self._payload["text"] = notification_text

        response = self.http.run(
            endpoint=None,
            data=json.dumps(self._payload),
            headers={"Content-type": "application/json"},
            extra_options={"verify": True},
        )

        self.clear()
        response.raise_for_status()
        return response

def should_silence_message(
    text: str,
    username: str,
    dag_id: str,
    task_id: str | None = None,
):
    """
    Determine if a Slack message should be silenced.

    Checks the `SILENCED_SLACK_NOTIFICATIONS` Airflow variable to see if the message
    should be silenced for this DAG.
    """
    # Match on message text and username
    message = username + text

    # Get the configuration for silenced messages for this DAG
    silenced_notifications: list[SilencedSlackNotification] = Variable.get(
        "SILENCED_SLACK_NOTIFICATIONS", default_var={}, deserialize_json=True
    ).get(dag_id, [])

    if not bool(silenced_notifications):
        # No silenced notifications for this DAG, exit early
        return False
    matches = []
    for notification in silenced_notifications:
        # Check that the predicate matches whatever message was raised
        predicate_matches = notification["predicate"].lower() in message.lower()
        # Check that the task ID matches the predicate _if both were supplied_,
        # not all messages supply a task ID but all exception-based alerts do.
        pattern = notification.get("task_id_pattern")
        task_id_matches = (task_id is None or pattern is None) or (
            task_id and pattern and re.search(pattern, task_id)
        )
        matches.append(predicate_matches and task_id_matches)
    return any(matches)

def should_send_message(
    text: str,
    username: str,
    dag_id: str,
    http_conn_id: str = SLACK_NOTIFICATIONS_CONN_ID,
    task_id: str | None = None,
):
    """
    Determine if a Slack message should actually be sent.

    Returns True if:
      * A Slack connection is defined
      * The DAG is not configured to silence messages of this type
      * We are in the prod env OR the message override is set.
    """
    # Exit early if no slack connection exists
    hook = HttpHook(http_conn_id=http_conn_id)
    try:
        hook.get_conn()
    except AirflowNotFoundException:
        return False

    # Exit early if this DAG is configured to skip Slack messaging
    if should_silence_message(text, username, dag_id, task_id):
        log.info(f"Skipping Slack notification for {dag_id}::{task_id}.")
        return False

    # Exit early if we aren't on production or if force alert is not set
    environment = Variable.get("ENVIRONMENT", default_var="dev")
    force_message = Variable.get(
        "SLACK_MESSAGE_OVERRIDE", default_var=False, deserialize_json=True
    )
    return environment == "prod" or force_message

def send_message(
    text: str,
    dag_id: str,
    username: str = "Airflow",
    icon_emoji: str = ":airflow:",
    markdown: bool = True,
    unfurl_links: bool = False,
    unfurl_media: bool = False,
    http_conn_id: str = SLACK_NOTIFICATIONS_CONN_ID,
    task_id: str | None = None,
) -> None:
    """Send a simple slack message, convenience message for short/simple messages."""
    log.info(text)
    if not should_send_message(
        text, username, dag_id, http_conn_id=http_conn_id, task_id=task_id
    ):
        return

    environment = Variable.get("ENVIRONMENT", default_var="dev")
    s = SlackMessage(
        f"{username} | {environment}",
        icon_emoji,
        unfurl_links,
        unfurl_media,
        http_conn_id=http_conn_id,
    )
    s.add_text(text, plain_text=not markdown)
    s.send(text)

def send_alert(
    text: str,
    dag_id: str,
    username: str = "Airflow Alert",
    icon_emoji: str = ":airflow:",
    markdown: bool = True,
    unfurl_links: bool = False,
    unfurl_media: bool = False,
    task_id: str | None = None,
):
    """
    Send a slack alert.

    Wrapper for send_message that allows sending a message to the configured alerts
    channel instead of the default notification channel.
    """
    send_message(
        text,
        dag_id,
        username,
        icon_emoji,
        markdown,
        unfurl_links,
        unfurl_media,
        http_conn_id=SLACK_ALERTS_CONN_ID,
        task_id=task_id,
    )

def on_failure_callback(context: dict) -> None:
    """
    Send an alert out regarding a failure to Slack.

    Errors are only sent out in production and if a Slack connection is defined.
    """
    # Get relevant info
    ti = context["task_instance"]
    dag_id = ti.dag_id
    task_id = ti.task_id
    logical_date = context["logical_date"]
    exception: Exception | None = context.get("exception")
    exception_message = ""

    if exception:
        # Forgo the alert on upstream failures
        if (
            isinstance(exception, Exception)
            and "Upstream task(s) failed" in exception.args
        ):
            log.info("Forgoing Slack alert due to upstream failures")
            return
        exception_message = f"""
*Exception*: {exception}
*Exception Type*: `{exception.__class__.__module__}.{exception.__class__.__name__}`
"""

    message = f"""
*DAG*: `{dag_id}`
*Task*: `{task_id}`
*Logical Date*: {logical_date.strftime('%Y-%m-%dT%H:%M:%SZ')}
*Log*: {ti.log_url}
{exception_message}
"""
    send_alert(
        message,
        dag_id=dag_id,
        task_id=task_id,
        username="Airflow DAG Failure",
    )


import sys
input=sys.stdin.readline
n,atk=map(int,input().split())
room=[tuple(map(int,input().split())) for _ in range(n)]

def paramin(F,l,r):
    while l<=r:
        mid=(l+r)//2
        if F(mid): ans,r=mid,mid-1
        else: l=mid+1
    return ans

def pwn(maxhp):
    h=maxhp; a=atk
    for t,ai,hi in room:
        if t==1:
            h-=ai*(hi//a-(hi%a==0))
            if h<=0: return False
        else: a+=ai; h=min(maxhp,h+hi)
    return True

print(paramin(pwn,1,10**18))


'''
Given an array of integers arr.
We want to select three indices i, j and k where (0 <= i < j <= k < arr.length).
Let's define a and b as follows:
a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]
b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k]
Note that ^ denotes the bitwise-xor operation.
Return the number of triplets (i, j and k) Where a == b.

Example 1:
Input: arr = [2,3,1,6,7]
Output: 4
Explanation: The triplets are (0,1,2), (0,2,2), (2,3,4) and (2,4,4)

Example 2:
Input: arr = [1,1,1,1,1]
Output: 10

Example 3:
Input: arr = [2,3]
Output: 0

Example 4:
Input: arr = [1,3,5,7,9]
Output: 3

Example 5:
Input: arr = [7,11,12,9,5,2,7,17,22]
Output: 8

Constraints:
1 <= arr.length <= 300
1 <= arr[i] <= 10^8
'''
class Solution:
    def countTriplets(self, arr) -> int:
        l = len(arr)
        pre_xors = [0]
        for i in range(l):
            pre_xors.append(pre_xors[-1] ^ arr[i])
        assert len(pre_xors) == l + 1
        res = []
        for i in range(l):
            for j in range(i + 1, l):
                for k in range(j, l):
                    if pre_xors[j] ^ pre_xors[i] == pre_xors[k+1] ^ pre_xors[j]:
                        res.append((i,j,k))
        # print(res)
        return len(res)

s = Solution()
arr = [7,11,12,9,5,2,7,17,22]
# arr = [2,3,1,6,7]
res = s.countTriplets(arr)
print(res)


import os
import time
import sys

from unittest import skip

from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException

from django.test import LiveServerTestCase
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.core import mail
from django.conf import settings

from .server_tools import reset_database
from .server_tools import create_session_on_server
from .management.commands.create_session import create_pre_authenticated_session

BASE_DIR   = os.path.dirname(os.path.abspath(__file__))
PARENT_DIR = os.path.dirname(os.path.dirname(BASE_DIR))

GECKODRIVER_BIN = os.path.join( PARENT_DIR, 'bin' )
os.environ["PATH"]+=":"+GECKODRIVER_BIN

class Browser(webdriver.Firefox):
    firefox_path = "/usr/local/firefox/firefox"

    def __init__(self,wait_time=1):
        webdriver.Firefox.__init__(self,firefox_binary=FirefoxBinary(firefox_path=self.firefox_path))
        self.wait_time=1

    def wait_page(self):
        time.sleep(self.wait_time)

    def add_session(self,email,session_key,final_url):
        ## to set a cookie we need to first visit the domain.
        ## 404 pages load the quickest!
        self.get(final_url+"/404-not-found")
        self.wait_page()
        self.add_cookie(dict(
            name=settings.SESSION_COOKIE_NAME,
            value=session_key,
            path='/',
        ))
        self.get(final_url)
        self.wait_page()

class FunctionalTest(StaticLiveServerTestCase):
    wait_time=1

    def build_browser(self):
        browser = Browser(wait_time=self.wait_time)
        return browser

    def restart_browser(self):
        self.browser.quit()
        self.browser = Browser(wait_time=self.wait_time)

    @classmethod
    def setUpClass(cls):
        cls.emaildir=None
        cls.liveserver=False
        for arg in sys.argv:
            if 'liveserver' in arg:
                cls.server_host = arg.split('=')[1]
                cls.server_url = 'http://' + cls.server_host
                cls.liveserver=True
                cls.emaildir = "/srv/test.costruttoridimondi.org/var/mail"
        if cls.liveserver:
            return
        super().setUpClass()
        cls.server_url = cls.live_server_url
        cls.liveserver=False
        cls.emaildir=None

    @classmethod
    def tearDownClass(cls):
        if cls.liveserver: return
        #print(type(cls.live_server_url))
        # if cls.server_url == cls.live_server_url:
        super().tearDownClass()

    def setUp(self):
        if self.liveserver:
            reset_database(self.server_host)
        self.browser = Browser(wait_time=self.wait_time)

    def tearDown(self):
        self.browser.quit()

    def wait_for(self, function_with_assertion, timeout=-1):
        if timeout<=0: timeout=self.wait_time
        start_time = time.time()
        while time.time() - start_time < timeout:
            try:
                return function_with_assertion()
            except (AssertionError, WebDriverException):
                time.sleep(0.1)
        # one more try, which will raise any errors if they are outstanding
        return function_with_assertion()

    def wait_browser(self):
        time.sleep(self.wait_time)

    def wait_for_email(self, test_email, subject):
        if not self.liveserver:
            email = mail.outbox[0]
            self.assertIn(test_email, email.to)
            self.assertEqual(email.subject, subject)
            return email.body
        if self.emaildir:
            return self.wait_for_email_onfile(test_email,subject)
        return self.wait_for_email_pop3(test_email,subject)

    def wait_for_email_onfile(self, test_email, subject):
        subject_line = 'Subject: {}'.format(subject)
        email_list=os.listdir(self.emaildir)
        email_list.sort()
        if not email_list: return None
        email_file=os.path.join(self.emaildir,email_list[-1])
        fd=open(email_file,"r")
        body=fd.read()
        fd.close()
        return body

    def wait_for_email_pop3(self, test_email, subject):
        subject_line = 'Subject: {}'.format(subject)
        email_id = None
        start = time.time()
        inbox = poplib.POP3_SSL('pop.mail.yahoo.com')
        try:
            inbox.user(test_email)
            inbox.pass_(os.environ['YAHOO_PASSWORD'])
            while time.time() - start < 60:
                count, _ = inbox.stat()
                for i in reversed(range(max(1, count - 10), count + 1)):
                    print('getting msg', i)
                    _, lines, __ = inbox.retr(i)
                    lines = [l.decode('utf8') for l in lines]
                    print(lines)
                    if subject_line in lines:
                        email_id = i
                        body = '\n'.join(lines)
                        return body
                time.sleep(5)
        finally:
            if email_id:
                inbox.dele(email_id)
            inbox.quit()

    def get_session_key(self,email):
        if self.liveserver:
            session_key = create_session_on_server(self.server_host, email)
        else:
            session_key = create_pre_authenticated_session(email)
        return session_key

    def create_session(self,email):
        session_key=self.get_session_key(email)
        self.browser.add_session(email,session_key,self.server_url)

    def create_pre_authenticated_session(self, browser, email, final_url=None):
        if final_url==None: final_url=self.server_url
        session_key=self.get_session_key(email)
        browser.add_session(email,session_key,final_url)

class MultiuserFunctionalTest(FunctionalTest):
    def create_user_browser_with_session(self,email,size=None,position=None):
        user_browser = Browser(wait_time=self.wait_time)
        if email in self.browsers.keys():
            self.browsers[email].quit()
        if size:
            w,h=size
            user_browser.set_window_size(w,h)
        if position:
            x,y=position
            user_browser.set_window_position(x,y)
        session_key=self.get_session_key(email)
        user_browser.add_session(email,session_key,self.server_url)
        self.browsers[email]=user_browser
        return user_browser

    def set_browser(self,email,size=None,position=None):
        if email in self.browsers.keys():
            self.browser=self.browsers[email]
            if size:
                w,h=size
                self.browser.set_window_size(w,h)
            if position:
                x,y=position
                self.browser.set_window_position(x,y)
            return
        kwargs={}
        if size: kwargs["size"]=size
        if position: kwargs["position"]=position
        self.browser=self.create_user_browser_with_session(email,**kwargs)

    def setUp(self):
        if self.liveserver:
            reset_database(self.server_host)
        self.browsers = {}
        self.browser = None

    def tearDown(self):
        for browser in self.browsers.values():
            try:
                browser.quit()
            except:
                pass


from rlbot.agents.base_agent import BaseAgent, SimpleControllerState
from rlbot.messages.flat.QuickChatSelection import QuickChatSelection
from rlbot.utils.structures.game_data_struct import GameTickPacket

from util.ball_prediction_analysis import find_slice_at_time
from util.boost_pad_tracker import BoostPadTracker
from util.drive import steer_toward_target
from util.sequence import Sequence, ControlStep
from util.vec import Vec3
import math, random

'''
Section: Numeral Mathematics
'''
# Solve a quadratic equation
def solve_quadratic(a, b, c, ans, side):
    rt = (ans - c) / a + b**2 / (4 * a**2)
    if rt < 0:
        return None
    else:
        return -b / (2 * a) + math.sqrt(rt) * sign(side)
# Get the smallest
def get_smallest(li):
    smallest = math.inf
    for i in li:
        if i < smallest:
            smallest = i
    return smallest
# Get the index of the smallest
def get_smallest_i(li):
    smallest = math.inf
    smi = 0
    for i in range(len(li)):
        if li[i] < smallest:
            smallest = li[i]
            smi = i
    return smi
# Division without risk of division by 0 error (divided by(Number))
def safe_div(x):
    if x != 0:
        return 1 / x
    else:
        return math.inf
# Set limits on a value (value(Number), min value(Number), max value(Number))
def clamp(x, m, M):
    if x >= M:
        return M
    elif x <= m:
        return m
    else:
        return x
# Direction of a number (value(Number))
def sign(x):
    if x < 0:
        return -1
    elif x > 0:
        return 1
    else:
        return 0
# Direction of a number with preference (value(Number), preference(Number))
def pref_sign(x, pref):
    if x < 0:
        return -1
    elif x > 0:
        return 1
    elif pref < 0:
        return -1
    elif pref > 0:
        return 1
    else:
        return 0
# Flip val
def flip_value(x):
    if x > 0.5:
        return 1
    elif x < -0.5:
        return -1
    else:
        return 0
'''
Section: Vector Mathematics
'''
# Get if an object is going to enter the range
def will_intersect(r_pos, r_vel, r):
    if r_pos.length() <= r:
        return True
    elif get_angle(r_pos, -r_vel) <= math.sqrt(r**2 / (r_pos.length()**2 - r**2)):
        return get_angle(r_pos, -r_vel) <= math.sqrt(r**2 / (r_pos.length()**2 - r**2))
# Get the position after a freefall
def freefall(pos, vel, g, t):
    return pos + vel * t - Vec3(0, 0, g / 2) * t**2
# Get direction with offset
def direction_offset(dir, circlev, offset):
    angle_pitch = math.asin(dir.z)
    angle_yaw = math.acos(dir.x * safe_div(Vec3(dir.x, dir.y, 0).length())) * sign(dir.y)
    if circlev - Vec3(0, 0, sign(circlev.z)) == Vec3(0, 0, 0):
        angle_yaw += offset * sign(circlev.z)
    elif circlev - Vec3(sign(circlev.x), 0, 0) == Vec3(0, 0, 0):
        angle_pitch += offset * sign(circlev.x)
    return Vec3(math.cos(angle_yaw) * math.cos(angle_pitch), math.sin(angle_yaw) * math.cos(angle_pitch), math.sin(angle_pitch))
# Get acceleration
def get_accel(vel):
    if vel < 0:
        return 3500
    elif vel <= 1400:
        return 1600 - vel * 1440 / 1400
    elif vel <= 1410:
        return (1410 - vel) * 16
    else:
        return 0
# Plane smoothening
def flat_on_surface(pos1, pos2, dropshot):
    offset = pos1 - surface_pos(pos1, dropshot)
    offset = dir_convert(offset)
    pitch = math.asin(offset.z)
    yaw = math.acos(offset.x * safe_div(Vec3(offset.x, offset.y, 0).length())) * sign(offset.y)
    Vec3(-math.cos(yaw) * math.sin(pitch) * math.cos(roll) + math.sin(yaw) * math.sin(roll), -math.sin(yaw) * math.sin(pitch) * math.cos(roll) - math.cos(yaw) * math.sin(roll), math.cos(roll) * math.cos(pitch))
# Drive outside the goal
def outside_goal(pos1, pos2):
    if abs(pos1.y) >= 5090 and pos1.z < 40:
        y_offset = abs(pos2.y - pos1.y)
        indented = abs(pos1.y) - 5090
        x_offset = pos2.x - pos1.x
        return Vec3(clamp(pos1.x + x_offset * indented * safe_div(y_offset), -800, 800), sign(pos1.y) * 5090, pos1.z)
    else:
        return pos2
# Direction of position (position(Vec3))
def dir_convert(pos):
    return pos * safe_div(pos.length())
# Get the angle between two places (position 1(Vec3), position 2(Vec3))
def get_angle(p1, p2):
    d = (p1 * safe_div(p1.length()) - p2 * safe_div(p2.length())).length()
    angle = 2 * math.asin(d / 2)
    return angle
# Position on Surface (position(Vec3), dropshot mode(Bool))
def surface_pos(pos, dropshot):
    nearest_dist = pos.z
    new_pos = Vec3(pos.x, pos.y, 0)
    if dropshot == True:
        b_dist = Vec3(pos.x, pos.y, 0).length()
        if b_dist > 0:
            ball_angle = math.acos(pos.x * safe_div(b_dist)) * sign(pos.y)
            surface_angle = math.floor(ball_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
            if 4555 - b_dist * math.cos(ball_angle - surface_angle) < nearest_dist:
                new_pos = Vec3(4555 * math.cos(surface_angle), 4555 * math.sin(surface_angle), pos.z) + Vec3(math.cos(ball_angle) * b_dist, math.sin(ball_angle) * b_dist, 0) * safe_div(math.cos(ball_angle - surface_angle)) - Vec3(math.cos(surface_angle) * b_dist, math.sin(surface_angle) * b_dist, 0)
                nearest_dist = 4555 - b_dist * math.cos(ball_angle - surface_angle)
    else:
        if 4096 - clamp(abs(pos.x), 0, 4096) < nearest_dist:
            new_pos = Vec3(sign(pos.x) * 4096, pos.y, pos.z)
            nearest_dist = 4096 - clamp(abs(pos.x), 0, 4096)
        if 5120 - clamp(abs(pos.y), 0, 5120) < nearest_dist and (abs(pos.x) > 846 or pos.z > 596):
            new_pos = Vec3(pos.x, sign(pos.y) * 5120, pos.z)
            nearest_dist = 5120 - clamp(abs(pos.y), 0, 5120)
    return new_pos
# Position on Surface (position(Vec3), dropshot mode(Bool))
def surface_pos_two(pos, from_pos, freshhold, dropshot):
    nearest_dist = math.inf
    new_pos = pos
    from_posN = surface_pos(from_pos, dropshot)
    # First check: If both can be placed on the same surface with reasonable freshhold
    if dropshot == True:
        b_dist = Vec3(pos.x, pos.y, 0).length()
        from_b_dist = Vec3(from_pos.x, from_pos.y, 0).length()
        if b_dist > 0:
            ball_angle = math.acos(pos.x * safe_div(b_dist)) * sign(pos.y)
            from_angle = math.acos(from_pos.x * safe_div(from_b_dist)) * sign(from_pos.y)
            surface_angle = math.floor(ball_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
            from_surface_angle = math.floor(from_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
            if 4555 - b_dist * math.cos(ball_angle - surface_angle) <= freshhold and 4555 - from_b_dist * math.cos(from_angle - from_surface_angle) < nearest_dist:
                new_pos = Vec3(4555 * math.cos(surface_angle), 4555 * math.sin(surface_angle), pos.z) + Vec3(math.cos(ball_angle) * b_dist, math.sin(ball_angle) * b_dist, 0) * safe_div(math.cos(ball_angle - surface_angle)) - Vec3(math.cos(surface_angle) * b_dist, math.sin(surface_angle) * b_dist, 0)
                nearest_dist = 4555 - b_dist * math.cos(ball_angle - surface_angle)
    else:
        if 4096 - clamp(abs(pos.x), 0, 4096) <= freshhold and from_posN.x == sign(pos.x) * 4096:
            new_pos = Vec3(sign(pos.x) * 4096, pos.y, pos.z)
            nearest_dist = 4096 - clamp(abs(pos.x), 0, 4096)
        if 5120 - clamp(abs(pos.y), 0, 5120) <= freshhold and (abs(pos.x) > 846 or pos.z > 596) and from_posN.y == sign(pos.y) * 5120:
            new_pos = Vec3(pos.x, sign(pos.y) * 5120, pos.z)
            nearest_dist = 5120 - clamp(abs(pos.y), 0, 5120)
    if pos.z <= freshhold and from_posN.z == 0:
        new_pos = Vec3(pos.x, pos.y, 0)
        nearest_dist = pos.z
    if nearest_dist != math.inf:
        return new_pos
    # Second check
    new_pos = surface_pos(pos, dropshot)
    return new_pos
# Position on Surface (position(Vec3), dropshot mode(Bool))
def surface_pos_twox(pos, from_pos, freshhold, dropshot):
    nearest_dist = math.inf
    new_pos = pos
    from_posN = surface_pos(from_pos, dropshot)
    # First check: If both can be placed on the same surface with reasonable freshhold
    if dropshot == True:
        b_dist = Vec3(pos.x, pos.y, 0).length()
        from_b_dist = Vec3(from_pos.x, from_pos.y, 0).length()
        if b_dist > 0:
            ball_angle = math.acos(pos.x * safe_div(b_dist)) * sign(pos.y)
            from_angle = math.acos(from_pos.x * safe_div(from_b_dist)) * sign(from_pos.y)
            surface_angle = math.floor(ball_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
            from_surface_angle = math.floor(from_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
            if 4555 - b_dist * math.cos(ball_angle - surface_angle) <= freshhold and 4555 - from_b_dist * math.cos(from_angle - from_surface_angle) < nearest_dist:
                new_pos = Vec3(4555 * math.cos(surface_angle), 4555 * math.sin(surface_angle), pos.z) + Vec3(math.cos(ball_angle) * b_dist, math.sin(ball_angle) * b_dist, 0) * safe_div(math.cos(ball_angle - surface_angle)) - Vec3(math.cos(surface_angle) * b_dist, math.sin(surface_angle) * b_dist, 0)
                nearest_dist = 4555 - b_dist * math.cos(ball_angle - surface_angle)
        if pos.z <= freshhold and from_posN.z == 0:
            new_pos = Vec3(pos.x, pos.y, 0)
            nearest_dist = pos.z
    else:
        if 1022 - abs(from_pos.z - 1022) < nearest_dist and 4096 - abs(from_pos.x) >= 1022 - abs(from_pos.z - 1022) <= 5120 - abs(from_pos.y) and 1022 - abs(pos.z - 1022) <= freshhold and sign(from_pos.z - 1022) == sign(pos.z - 1022):
            new_pos = Vec3(pos.x, pos.y, 1022 + sign(from_pos.z - 1022) * 1022)
            nearest_dist = 1022 - abs(from_pos.z - 1022)
        if 4096 - abs(from_pos.x) < nearest_dist and 1022 - abs(from_pos.z - 1022) >= 4096 - abs(from_pos.x) <= 5120 - abs(from_pos.y) and 4096 - abs(pos.x) <= freshhold and sign(from_pos.x) == sign(pos.x):
            new_pos = Vec3(4096 * sign(pos.x), pos.y, pos.z)
            nearest_dist = 4096 - abs(from_pos.x)
        if 5120 - abs(from_pos.y) < nearest_dist and 1022 - abs(from_pos.z - 1022) >= 5120 - abs(from_pos.y) <= 4096 - abs(from_pos.x) and 5120 - abs(pos.y) <= freshhold and sign(from_pos.y) == sign(pos.y):
            new_pos = Vec3(pos.x, 5120 * sign(pos.y), pos.z)
            nearest_dist = 5120 - abs(from_pos.y)
    if nearest_dist != math.inf:
        return new_pos
    # Second check
    new_pos = surface_pos(pos, dropshot)
    return new_pos
# Driving path for wall transitions
def wall_transition_path(pos1, pos2, dropshot):
    rp1 = surface_pos(pos1, dropshot)
    rp2 = surface_pos(pos2, dropshot)
    if dropshot == True:
        if rp1.z == 0:
            if rp2.z == 0:
                return rp2
            else:
                b_dist = Vec3(rp2.x, rp2.y, 0).length()
                ball_angle = math.acos(rp2.x * safe_div(b_dist)) * sign(rp2.y)
                surface_angle = math.floor(ball_angle / math.pi * 3) * math.pi / 3 + math.pi / 6
                return Vec3(rp2.x, rp2.y, 0) + Vec3(rp2.z * math.cos(surface_angle), rp2.z * math.sin(surface_angle), 0)
        return rp2
    else:
        if rp1.z == 0:
            if abs(rp2.x) == 4096:
                return Vec3((4096 + rp2.z) * sign(rp2.x), rp2.y, rp1.z)
            elif abs(rp2.y) == 5120:
                if abs(pos1.x + (pos2.x - pos1.x) * abs(5120 * sign(rp2.y) - rp1.y) * safe_div(abs((5120 + abs(rp2.z)) * sign(rp2.y) - rp1.y)) > 893):
                    return Vec3(rp2.x, (5120 + abs(rp2.z)) * sign(rp2.y), rp1.z)
        elif abs(rp1.x) == 4096:
            if rp2.z == 0:
                return Vec3(rp1.x, rp2.y, -abs(rp1.x - rp2.x))
            elif abs(rp2.y) == 5120:
                return Vec3(rp1.x, (5120 + abs(rp2.x - rp1.x)) * sign(rp2.y), rp2.z)
        elif abs(rp1.y) == 5120:
            if rp2.z == 0:
                return Vec3(rp2.x, rp1.y, -abs(rp1.y - rp2.y))
            elif abs(rp2.x) == 4096:
                return Vec3((4096 + abs(rp2.y - rp1.y)) * sign(rp2.x), rp1.y, rp2.z)
        return rp2
# Predict bounce with formulas
def predict_surface_bounce(pos, vel, height, g):
    pred_x = (4096 - height - pos.x * sign(vel.x)) * safe_div(vel.x) * sign(vel.x)
    pred_y = (5120 - height - pos.y * sign(vel.y)) * safe_div(vel.y) * sign(vel.y)
    pred_z1 = solve_quadratic(-g / 2, vel.z, pos.z, height, 1)
    if pred_z1 == None:
        pred_z1 = 0
    pred_z2 = solve_quadratic(-g / 2, vel.z, pos.z, 2044 - height, -1)
    if pred_z2 == None:
        pred_z2 = math.inf
    return get_smallest([pred_x, pred_y, pred_z1, pred_z2])
# Direction to point (position ref(Vec3), point to(Vec3))
def dir_to_point(pos1, pos2):
    return (pos2 - pos1) * safe_div((pos2 - pos1).length())
# Determine when the car can intersect a bounce (offset time(Number), self.get_ball_prediction_struct(), car location(Vec3), car velocity(Vec3), max ball distance from surface allowed(Number), distance to point to target(Number), target(Vec3), dropshot mode(Bool), packet)
def next_bounce(t_offset, ball_prediction, pos, vel, g_offset, target, dropshot, packet):
    ref = surface_pos(pos, dropshot)
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    for i in range(1, 101):
        bp = predict_ball(t_offset + i / 20)
        pbp = predict_ball(t_offset + (i - 1) / 20)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), target) * g_offset
        point_pos = wall_transition_path(pos, point_pos, dropshot)
        if (point_pos - ref).length() <= vel * i / 20 and bp.physics.velocity.z >= 0 and pbp.physics.velocity.z <= 0:
            return i / 20
    return 0
# Determine when the car can intersect the ball (offset time(Number), self.get_ball_prediction_struct(), car location(Vec3), car velocity(Vec3), max ball distance from surface allowed(Number), distance to point to target(Number), target(Vec3), dropshot mode(Bool), packet)
def intersect_time(t_offset, ball_prediction, pos, vel, height_threshold, g_offset, target, dropshot, surface, boost, packet):
    ref = pos
    if surface == True:
        ref = surface_pos(ref, dropshot)
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    # Ball prediction
    for i in range(1, 101):
        bp = predict_ball(t_offset + i / 20)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), target) * g_offset
        point_pos2 = point_pos
        if surface == True:
            point_pos = wall_transition_path(pos, point_pos, dropshot)
        if True:
            if (point_pos - ref).length() <= vel * i / 20 and (point_pos2 - surface_pos(point_pos2, dropshot)).length() <= height_threshold:
                return i / 20
        else:
            if (point_pos2 - ref).length() <= vel * i / 20 and (point_pos - surface_pos(point_pos, dropshot)).length() <= height_threshold:
                return i / 20
    return 0
# Determine when the car can intersect the ball (offset time(Number), self.get_ball_prediction_struct(), car location(Vec3), car velocity(Vec3), max ball distance from surface allowed(Number), distance to point to target(Number), target(Vec3), dropshot mode(Bool), packet)
def intersect_time_x(t_offset, ball_prediction, pos, vel, height_threshold, g_offset, target, dropshot, surface, boost, boost_strength, packet):
    ref = pos
    if surface == True:
        ref = surface_pos(ref, dropshot)
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    # Formulas for speed
    vel_after_boost = vel
    tv = 0
    # First step of acceleration
    a1 = 1440 / 1400
    b1 = (1600 + boost_strength) * 1400 / 1440
    b1n = 1600 * 1400 / 1440
    if vel < 1400:
        tv = -math.log(1 - vel / b1) / a1
    tc1 = -math.log(1 - 1400 / b1) / a1
    tc1n = -math.log(1 - 1400 / b1n) / a1
    # Second step of acceleration
    a2 = 16
    b2 = 1410 + boost_strength / 16
    b2n = 1410
    if vel < 1410 and tv == 0:
        tv = tc1 - math.log(1 - vel / b2) / a2 + math.log(1 - 1400 / b2) / a2
    tc2 = tc1 - math.log(1 - 1410 / b2) / a2 + math.log(1 - 1400 / b2) / a2
    # Added acceleration with boost
    if vel < 2300 and tv == 0:
        tv = tc2 - (1410 - vel) / boost_strength
    tc3 = tc2 + 534 / 595
    # Time with boost (Verifyably functional)
    tb = tv + boost / 100 * 3
    # Velocity with boost (Verifyably functional)
    velB = 0
    if tb < tc1:
        velB = (1 - math.e**(-a1 * tb)) * b1
    if tb < tc2 and velB == 0:
        velB = (1 - math.e**(-a2 * (tb - tc1 + math.log(1 - 1400 / b2) / a2))) * b2
    if tb < tc3 and velB == 0:
        velB = 1410 + boost_strength * (tb - tc2)
    if tb >= tc3 and velB == 0:
        velB = 2300
    # Ball prediction
    for i in range(1, 101):
        cc1, cc2, cc3, cc1n = clamp(tc1, 0, tb), clamp(tc2, 0, tb), clamp(tc3, 0, tb), clamp(tc1n, tb, math.inf)
        # Distance covered with boost
        dist_wb = b1 * ((math.e**(-a1 * 0) / a1 + 0) - (math.e**(-a1 * clamp(tv + i / 20, 0, cc1)) / a1 + clamp(tv + i / 20, 0, cc1))) + b2 * ((math.e**(-a2 * cc1) / a2 + cc1) - (math.e**(-a2 * clamp(tv + i / 20, cc1, cc2)) / a2 + clamp(tv + i / 20, cc1, cc2))) + 1410 * (clamp(tv + i / 20, cc2, cc3) - cc2) + (boost_strength / 2) * (clamp(tv + i / 20, cc2, cc3)**2 - cc2**2) + 2300 * (clamp(tv + i / 20, cc3, math.inf) - cc3)
        # Distance covered without boost
        dist_wob = velB * (clamp(tv + i / 20, tb, math.inf) - tb)

        bp = predict_ball(t_offset + i / 20)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), target) * g_offset
        point_pos2 = point_pos
        if surface == True:
            point_pos = wall_transition_path(pos, point_pos, dropshot)
        if True:
            if (point_pos - ref).length() <= dist_wb + dist_wob and (point_pos2 - surface_pos(point_pos2, dropshot)).length() <= height_threshold:
                return i / 20
        else:
            if (point_pos2 - ref).length() <= dist_wb + dist_wob and (point_pos - surface_pos(point_pos, dropshot)).length() <= height_threshold:
                return i / 20
    return 0
# Determine when the car is closest to the ball (offset time(Number), self.get_ball_prediction_struct(), car location(Vec3), car velocity(Vec3), max ball distance from surface allowed(Number), distance to point to target(Number), target(Vec3), dropshot mode(Bool), packet)
def nearest_intersection(t_offset, vel, ball_prediction, pos, height_threshold, g_offset, target, dropshot, surface, packet):
    ref = pos
    nearest_t = 0
    nearest_dist = math.inf
    engaged = False
    if surface == True:
        ref = surface_pos(ref, dropshot)
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    for i in range(1, 101):
        bp = predict_ball(t_offset + i / 20)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), target) * g_offset
        point_pos2 = point_pos
        if (point_pos - surface_pos(point_pos, dropshot)).length() <= height_threshold:
            if engaged == True:
                if vel**2 / 7000 < (point_pos - pos).length() < nearest_dist:
                    nearest_dist = (point_pos - pos).length()
                    nearest_t = i / 20
                else:
                    return nearest_t
            else:
                if (point_pos - pos).length() < nearest_dist and nearest_dist != math.inf:
                    engaged = True
                nearest_dist = (point_pos - pos).length()
                nearest_t = i / 20
    if engaged == True:
        return nearest_t
    else:
        return 0.05
'''
Section: Jumps
'''
def jump_time(h, double):
    if h <= 74.6:
        return -292 / 810 + math.sqrt(h / 405 + (292 / 810)**2), 1
    elif h <= -29.2 + 584 * 292 / 325 - 325 * 292**2 / 325**2:
        return 292 / 325 - math.sqrt(-h / 325 - 29.2 / 325 + (292 / 325)**2), 1
    elif h <= 876 * 438 / 325 - 325 * (438 / 325)**2 - 584 / 6 and double:
        return 438 / 325 - math.sqrt(-h / 325 + (438 / 325)**2 - 584 / 1950), 2
    else:
        return 0, 0
def jump_time_x(h, g, double):
    def fx(x):
        return (292 * 5 - g) / 2 * x**2 + 292 * x
    def hx(x):
        return -g / 2 * x**2 + 584 * x - 292 / 10
    def qx(x):
        return -g / 2 * x**2 + 876 * x - (365 / 3 - 292 / 10)
    if h <= fx(12 / 60):
        return solve_quadratic((292 * 5 - g) / 2, 292, 0, h, 1), 1
    elif h <= hx(584 / g):
        return solve_quadratic(-g / 2, 584, -292 / 10, h, -1), 1
    elif h <= qx(876 / g) and double:
        return solve_quadratic(-g / 2, 876, -(365 / 3 - 292 / 10), h, -1), 2
    else:
        return 0, 0
def max_jump_height(g, double):
    def hx(x):
        return -g / 2 * x**2 + 584 * x - 292 / 10
    def qx(x):
        return -g / 2 * x**2 + 876 * x - (365 / 3 - 292 / 10)
    if double:
        return qx(876 / g)
    else:
        return hx(584 / g)
'''
Section: Aerials
'''
# Get the direction to intersect the ball in the air (car location(Vec3), car velocity(Vec3), offset time(Number), self.get_ball_prediction_struct(), target(Vec3), boost quantity(Number), packet)
def aerial_dir(pos, vel, t_offset, ball_prediction, send_location, boost, offset, boost_power, gravity, begin_tick, search_dir, packet):
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    nearest_time = 0
    nearest_val = math.inf
    prev_disparity = -math.inf
    for i in range(begin_tick, (101 * (1 + sign(search_dir))) // 2, search_dir):
        t = i / 20
        bp = predict_ball(t_offset + t)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), send_location) * offset
        int_dist = ((pos + vel * t - Vec3(0, 0, gravity / 2) * t**2) - point_pos).length()
        if t <= boost * 3 / 100:
            if int_dist <= boost_power / 2 * t**2:
                return point_pos - (pos + vel * t - Vec3(0, 0, gravity / 2) * t**2), t + prev_disparity / (prev_disparity + boost_power / 2 * t**2 - int_dist) / 20
        prev_disparity = int_dist - boost_power / 2 * t**2
    return Vec3(predict_ball(t_offset).physics.location), 0
# Get the direction to intersect the ball in the air (car location(Vec3), car velocity(Vec3), offset time(Number), self.get_ball_prediction_struct(), target(Vec3), boost quantity(Number), packet)
def aerial_dir_x(pos, vel, t_offset, ball_prediction, send_location, boost, offset, boost_power, gravity, begin_tick, search_dir, front_dir, packet):
    def predict_ball(t):
        ball_in_future = find_slice_at_time(ball_prediction, t)
        if ball_in_future is not None:
            return ball_in_future
        else:
            return packet.game_ball
    nearest_time = 0
    nearest_val = math.inf
    prev_disparity = -math.inf
    for i in range(begin_tick, (101 * (1 + sign(search_dir))) // 2, search_dir):
        t = i / 20
        bp = predict_ball(t_offset + t)
        point_pos = Vec3(bp.physics.location) - dir_to_point(Vec3(bp.physics.location), send_location) * offset
        int_vector = point_pos - (pos + vel * t - Vec3(0, 0, gravity / 2) * t**2)
        t2 = t - get_angle(front_dir, int_vector) / 5.5
        int_dist = int_vector.length()
        if t <= boost * 3 / 100:
            if int_dist <= boost_power / 2 * t**2:
                return int_vector, t + prev_disparity / (prev_disparity + boost_power / 2 * t**2 - int_dist) / 20
        prev_disparity = int_dist - boost_power / 2 * t**2
    return Vec3(predict_ball(t_offset).physics.location), 0
# Control of aerial (Intended point direction(Vec3), Current point direction(Vec3))
def aerial_control(front, orig, k, lim):
    car_direction = Vec3(math.cos(orig.yaw) * math.cos(orig.pitch), math.sin(orig.yaw) * math.cos(orig.pitch), math.sin(orig.pitch))
    to_attack = get_aerial_control(dir_convert(front), orig)
    # Roll
    '''
    controls.roll = 1
    '''
    # Controls
    p_c = math.cos(to_attack)
    p_y = -math.sin(to_attack)
    # Pitch & Yaw
    return (p_c * math.cos(orig.roll) + p_y * math.sin(orig.roll)) * clamp(get_angle(front, car_direction) * k, -1 * safe_div(bool(lim)), 1 * safe_div(bool(lim))), (p_y * math.cos(orig.roll) - p_c * math.sin(orig.roll)) * clamp(get_angle(front, car_direction) * k, -1 * safe_div(bool(lim)), 1 * safe_div(bool(lim)))
# Get the controls (Intended point direction(Vec3), Current point direction(Vec3))
def get_aerial_control(dir, orig):
    # The problem
    ref_pitch = orig.pitch
    target_pitch = math.asin(dir.z)
    target_yaw = math.acos(dir.x * safe_div(Vec3(dir.x, dir.y, 0).length())) * sign(dir.y)
    offset_yaw = target_yaw - orig.yaw
    # Extra variables
    dist = math.sqrt((math.cos(ref_pitch) - math.cos(target_pitch) * math.cos(offset_yaw))**2 + (math.cos(target_pitch) * math.sin(offset_yaw))**2 + (math.sin(ref_pitch) - math.sin(target_pitch))**2)
    travel_angle = math.asin(dist / 2) * 2
    # Breakdown
    aa = math.cos(ref_pitch) * math.cos(travel_angle)
    ab = math.sin(ref_pitch) * math.sin(travel_angle)
    ac = math.cos(target_pitch) * math.cos(offset_yaw)
    ar_1 = (aa - ac) * safe_div(ab)

    ad = math.sin(travel_angle)
    ae = math.cos(target_pitch) * math.sin(offset_yaw)
    ar_2 = ae * safe_div(ad)

    af = math.sin(ref_pitch) * math.cos(target_pitch)
    ag = math.cos(ref_pitch) * math.sin(travel_angle)
    ah = math.sin(target_pitch)
    ar_3 = -(af - ah) * safe_div(ag)
    # Solution
    if abs(ar_1) <= 1:
        found_angle = math.acos(ar_1)
    elif abs(ar_3) <= 1:
        found_angle = math.acos(ar_3)
    else:
        found_angle = 0
        if False:
            print("B: " + str(travel_angle) + ", Ref(p): " + str(ref_pitch) + ", Target(p): " + str(target_pitch) + ", Offset(y): " + str(offset_yaw))
    return found_angle * sign(abs(ad * math.sin(found_angle) - ae) - abs(ad * math.sin(-found_angle) - ae))
# Get the angular velocity based on two points (previous frame, current frame)
def get_angular_velocity(previous, current):
    pitch_1, pitch_2 = math.asin(previous.z * safe_div(previous.length())), math.asin(current.z * safe_div(current.length()))
    yaw_1, yaw_2 = math.acos(previous.x * safe_div(Vec3(previous.x, previous.y).length())) * sign(previous.y), math.acos(current.x * safe_div(Vec3(current.x, current.y).length())) * sign(current.y)
    return pitch_2 - pitch_1, yaw_2 - yaw_1
'''
Section: Dropshot
'''
# Get the row of a tile based on index
def get_row(index):
    if index == clamp(math.floor(index), 0, 139):
        if index < 70:
            return math.floor(-6.5 + math.sqrt(2 * index + 6.5**2))
        else:
            return math.floor(20.5 - math.sqrt(2 * (140 - index) + 6.5**2))
# Get the index minimum of a tile based on row
def get_index_minimum(row):
    if row < 7:
        return (row**2 + 13 * row) // 2
    else:
        return 161 - (row - 21) * (row - 20) // 2
# Get the position of a tile
def get_pos(index):
    row = get_row(index)
    y = (122 + 576 / math.cos(math.pi / 6) * clamp(abs(6.5 - row) - 0.5, 0, 7)) * sign(row - 6.5)
    x = 768 * 3 - 384 * (abs(row - 6.5) - 6.5) - 768 * (index - get_index_minimum(row))
    return Vec3(x, y, 0)
'''
# Update damage to tiles
def damage_tile(li, pos, power):
    new_li = li
    if abs(pos.y) > 122:
        aff_row = 6.5 + sign(pos.y) * (0.5 + math.floor((abs(pos.y) - 122) / (576 / math.cos(math.pi / 6)) - 122))
        row_min = math.floor(aff_row)
        row_max = math.ceil(aff_row)
        index_min = get_index_minimum(row_min)
        pos_min = get_pos(index_min)
        index_max = get_index_minimum(row_max)
        pos_max = get_pos(index_max)
        if (pos_min - pos).length() < (pos_max - pos).length():
            index = index_min
        else:
            index = index_max
        row = get_row(index)
        new_li[index] = clamp(new_li[index] + 1, 0, 2)
        # Damage multiple tiles
        if 3 >= power >= 2:
            for i in range(row - (power - 1), row + power):
                index_in_row =
                for l in range():
    return new_li
'''
# Reset tiles after goal
def reset_side(li, team):
    new_li = li
    for i in range(70):
        new_li[i + team * 70] = 0
    return new_li


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.contrib.postgres.fields

class Migration(migrations.Migration):

    dependencies = [
        ('patients', '0027_auto_20160517_1559'),
    ]

    operations = [
        migrations.AlterField(
            model_name='profilesuser',
            name='thresholdHr_min_max',
            field=django.contrib.postgres.fields.ArrayField(null=True, size=2, base_field=models.PositiveIntegerField(), verbose_name='Soglie Pulsazioni', blank=True, default=list),
        ),
    ]


if __name__ == "login_pdu":
    from pdu_common import *
else:
    from .pdu_common import *

#Byte/     0        |       1       |       2       |       3       |
#    /              |               |               |               |
#  |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
#  +---------------+---------------+---------------+---------------+
# 0|.|1| 0x03       |T|C|.|.|CSG|NSG| Version-max   | Version-min   |
#  +---------------+---------------+---------------+---------------+
# 4|TotalAHSLength | DataSegmentLength                              |
#  +---------------+---------------+---------------+---------------+
# 8| ISID                                                           |
#  +                                +---------------+---------------+
#12|                                | TSIH                          |
#  +---------------+---------------+---------------+---------------+
#16| Initiator Task Tag                                             |
#  +---------------+---------------+---------------+---------------+
#20| CID                            | Reserved                      |
#  +---------------+---------------+---------------+---------------+
#24| CmdSN                                                          |
#  +---------------+---------------+---------------+---------------+
#28| ExpStatSN   or    Reserved                                     |
#  +---------------+---------------+---------------+---------------+
#32| Reserved                                                       |
#  +---------------+---------------+---------------+---------------+
#36| Reserved                                                       |
#  +---------------+---------------+---------------+---------------+
#40/ Reserved                                                       /
# +/                                                                /
#  +---------------+---------------+---------------+---------------+
#48/ DataSegment - Login Parameters in Text request Format          /
# +/                                                                /
#  +---------------+---------------+---------------+---------------+
class LoginCmnPDU(PDU):
    # logger for Login pdu
    logger = logging.getLogger("Login PDU")
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    logger.addHandler(ch)

    TRANSIT_MASK = 0x80
    CONTINUE_MASK = 0x40
    CURRENT_STAGE_MASK = 0x0C
    NEXT_STAGE_MASK = 0x03
    # stages
    SECURITY_NEG = 0
    LOGIN_OPERATIONAL_NEG = 1
    FULL_FEATURE_PHASE = 3

    __stages = (SECURITY_NEG, LOGIN_OPERATIONAL_NEG, FULL_FEATURE_PHASE)

    @property
    def Transit(self):
        if ntoi(self.bhs[1]) & self.TRANSIT_MASK:
            return True
        else:
            return False
    @Transit.setter
    def Transit(self, t):
        if t:
            self.bhs[1] |= self.TRANSIT_MASK
        else:
            self.bhs[1] &= ~self.TRANSIT_MASK

    @property
    def Continue(self):
        if ntoi(self.bhs[1]) & self.CONTINUE_MASK:
            return True
        else:
            return False
    @Continue.setter
    def Continue(self, c):
        if c:
            self.bhs[1] |= self.CONTINUE_MASK
        else:
            self.bhs[1] &= ~self.CONTINUE_MASK

    @property
    def CurrentStage(self):
        return (ntoi(self.bhs[1]) & self.CURRENT_STAGE_MASK) >> 2

    @CurrentStage.setter
    def CurrentStage(self, cs):
        if cs not in self.__stages:
            raise ValueError
        self.bhs[1] |= cs << 2

    @property
    def NextStage(self):
        return ntoi(self.bhs[1]) & self.NEXT_STAGE_MASK

    @NextStage.setter
    def NextStage(self, ns):
        if ns not in self.__stages:
            raise ValueError
        self.bhs[1] |= ns

    @property
    def VersionMax(self):
        return ntoi(self.bhs[2])

    @VersionMax.setter
    def VersionMax(self,vmax):
        if vmax > 0xFF or vmax < 0:
            self.logger.warn("VersionMax(%d) i bigger than 1 byte" % vmax)
        self.bhs[2] = vmax

    @property
    def ISID(self):
        return ISID(raw = self.bhs[8:14])

    @ISID.setter
    def ISID(self, isid):
        if not isinstance(isid, ISID):
            raise TypeError
        self.bhs[8:14] = isid.raw_data

    @property
    def TSIH(self):
        return ntoi(self.bhs[14:16])

    @TSIH.setter
    def TSIH(self, tsih):
        if tsih > 0xFFFF or tsih < 0:
            self.logger.warn("TSIH(%d) is bigger than 2 bytes" % tsih)
        self.bhs[14:16] = iton(tsih, 2)

#Byte/     0       |       1        |      2       |        3      |
#    /             |                |              |               |
#  |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
#  +---------------+---------------+---------------+---------------+
# 8| T |     A     |              B                |      C        |
#  +---------------+---------------+---------------+---------------+
#12|               D                |
#  +---------------+---------------+
#00b OUI-Format
#    A&B are a 22 bit OUI
#    (the I/G & U/L bits are omitted)
#    C&D 24 bit qualifier
#01b EN - Format (IANA Enterprise Number)
#    A - Reserved
#    B&C EN (IANA Enterprise Number)
#    D - Qualifier
#10b "Random"
#    A - Reserved
#    B&C Random
#    D - Qualifier
#11b A,B,C&D Reserved

class ISID():
    LENGTH = 6
    T_OUI = 0
    T_EN = 1
    T_RANDOM = 2
    T_RESERVED = 3

    __types = (T_OUI, T_EN, T_RANDOM, T_RESERVED)
    def __init__(self, raw = None, seq = None):# seq = (T, A, B, C, D)
        if raw == None:
            if len(seq) != 5:
                raise ValueError
            self.__raw = bytearray(self.LENGTH)
            self.T = seq[0]
            self.A = seq[1]
            self.B = seq[2]
            self.C = seq[3]
            self.D = seq[4]
        else:
            if not isinstance(raw, (str, bytes, bytearray)):
                raise TypeError
            if len(raw) != self.LENGTH:
                raise ValueError
            self.__raw = raw

    def __getitem__(self, key):
        self.__raw.__getitem__(key)

    def __eq__(self, other):
        if not isinstance(other, (str, bytes, bytearray, ISID)):
            raise TypeError
        if isinstance(other, (str, bytes, bytearray)) and len(other) != self.LENGTH:
            raise ValueError
        if other == self.__raw:
            return True
        return False

    def __ne__(self, other):
        return not self == other

    @property
    def T(self):
        return ntoi(self.__raw[0]) >> 6

    @T.setter
    def T(self, t):
        if t not in self.__types:
            raise ValueError
        self.__raw[0] |= t << 6

    @property
    def A(self):
        return ntoi(self.__raw[0]) & 0x3F

    @A.setter
    def A(self, a):
        self.__raw[0] |= a & 0x3F

    @property
    def B(self):
        return ntoi(self.__raw[1:3])

    @B.setter
    def B(self, b):
        self.__raw[1:3] = iton(b, 2)

    @property
    def C(self):
        return ntoi(self.__raw[3])

    @C.setter
    def C(self, c):
        self.__raw[3] = c

    @property
    def D(self):
        return ntoi(self.__raw[4:6])

    @B.setter
    def D(self, d):
        self.__raw[4:6] = iton(d, 2)

    @property
    def raw_data(self):
        return self.__raw

class LoginPDU(LoginCmnPDU):
    def __init__(self, data = None, header_digest = None, data_digest= None):
        super().__init__(data, header_digest, data_digest)
        if data == None:
            self.Opcode = BHS.OPCODE_LOGIN_REQ
            self.Immediate = True

    @property
    def VersionMin(self):
        return ntoi(self.bhs[3])

    @VersionMin.setter
    def VersionMin(self, vmin):
        if vmin > 0xFF or vmin < 0:
            self.logger.warn("VersionMin(%d) is bigger than 1 byte" % vmin)
        self.bhs[3] = vmin

    @property
    def CID(self):
        return ntoi(self.bhs[20:22])

    @CID.setter
    def CID(self, cid):
        if cid > 0xFFFF or cid < 0:
            self.logger.warn("CID(%d) is bigger than 2 bytes" % cid)
        n_cid = iton(cid, 2)
        self.bhs[20:22] = n_cid

    @property
    def CmdSN(self):
        return ntoi(self.bhs[24:28])

    @CmdSN.setter
    def CmdSN(self, cmdsn):
        if cmdsn > 0xFFFFFFFF or cmdsn < 0:
            self.logger.warn("cmdsn(%d) is bigger than 4 bytes" % cmdsn)
        n_cmdsn = iton(cmdsn, 4)
        self.bhs[24:28] = n_cmdsn

    @property
    def ExpStatSN(self):
        return ntoi(self.bhs[28:32])

    @ExpStatSN.setter
    def ExpStatSN(self, expstatsn):
        if expstatsn > 0xFFFFFFFF or expstatsn < 0:
            self.logger.warn("expstatsn(%d) is bigger than 4 bytes" % expstatsn)
        n_expstatsn = iton(expstatsn, 4)
        self.bhs[28:32] = n_expstatsn

#Byte/      0      |       1       |       2       |       3       |
#    /             |               |               |               |
#  |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
#  +---------------+---------------+---------------+---------------+
# 0|.|.| 0x23      |T|C|.|.|CSG|NSG| Version-max   | Version-active|
#  +---------------+---------------+---------------+---------------+
# 4|TotalAHSLength | DataSegmentLength                             |
#  +---------------+---------------+---------------+---------------+
# 8| ISID                                                          |
#  +                               +---------------+---------------+
#12|                               | TSIH                          |
#  +---------------+---------------+---------------+---------------+
#16| Initiator Task Tag                                            |
#  +---------------+---------------+---------------+---------------+
#20| Reserved                                                      |
#  +---------------+---------------+---------------+---------------+
#24| StatSN                                                        |
#  +---------------+---------------+---------------+---------------+
#28| ExpCmdSN                                                      |
#  +---------------+---------------+---------------+---------------+
#32| MaxCmdSN                                                      |
#  +---------------+---------------+---------------+---------------+
#36| Status-Class | Status-Detail | Reserved                       |
#  +---------------+---------------+---------------+---------------+
#40/ Reserved                                                      /
# +/                                                               /
#  +---------------+---------------+---------------+---------------+
#48/ DataSegment - Login Parameters in Text request Format         /
# +/                                                               /
#  +---------------+---------------+---------------+---------------+
class LoginRespPDU(LoginCmnPDU):
    STATUS_CLASS_SUCCESS = 0

    STATUS_CLASS_REDIR = 1
    STATUS_DETAIL_REDIR_TGT_MV_TMP = 1 # target moved temporarily
    STATUS_DETAIL_REDIR_TGT_MV_PERM = 1 # target moved permanently

    STATUS_CLASS_INIT_ERR = 2
    STATUS_DETAIL_INIT_MISC_ERR = 0 # miscellaneous initiator error
    STATUS_DETAIL_INIT_AUTHEN_FAIL = 1 # authentication failure
    STATUS_DETAIL_INIT_AUTHOR_FAIL = 2 # authorisation failure
    STATUS_DETAIL_INIT_NOT_FOUND = 3
    STATUS_DETAIL_INIT_TGT_REM = 4 # target removed
    STATUS_DETAIL_INIT_UNSUP_VER = 5 # unsupported version
    STATUS_DETAIL_INIT_MANY_CONN = 6 # too many connections
    STATUS_DETAIL_INIT_PARAM = 7 # missing parameter
    STATUS_DETAIL_INIT_CANT_INC_SESSIION = 8 # can't include in session
    STATUS_DETAIL_INIT_SESSION_UNSUP = 9 # session type not supported
    STATUS_DETAIL_INIT_SESSION_NOT_EXIST = 10 # session doesn't exists
    STATUS_DETAIL_INIT_INV_DURING_LOGIN = 11 # invalid during login

    STATUS_CLASS_TGT_ERR = 3
    STATIS_DETAIL_TGT_ERR = 0 # target error
    STATUS_DETAIL_TGT_SERV_NA = 1 # service unavailable
    STATUS_DETAIL_TGT_OUT_RESC = 2 # out of resources

    @property
    def VersionActive(self):
        return ord(self.bhs[3])

    @property
    def StatSN(self):
        return ntoi(self.bhs[24:28])

    @property
    def ExpCmdSN(self):
        return ntoi(self.bhs[28:32])

    @property
    def MaxCmdSN(self):
        return ntoi(self.bhs[32:36])

    @property
    def StatusClass(self):
        return ord(self.bhs[36:37])

    @property
    def StatusDetail(self):
        return ord(self.bhs[37:38])


import uuid
from django.db import models
from resorts.models import Resort

class Forecast(models.Model):
	id = models.UUIDField(
		primary_key=True,
		default=uuid.uuid4,
		editable=False
	)
	created_at = models.DateTimeField(auto_now=True)
	resort = models.ForeignKey(
		Resort,
		related_name='resort_forecast',
		on_delete=models.CASCADE
	)
	weather = models.JSONField(blank=True, null=True)

	def __str__(self):
		return '{0} ({1})'.format(str(self.resort), str(self.created_at))

class ForecastDetail(models.Model):
	id = models.UUIDField(
		primary_key=True,
		default=uuid.uuid4,
		editable=False
	)
	created_at = models.DateTimeField(auto_now=True)
	forecast = models.ForeignKey(
		Forecast,
		related_name='forecast_details',
		on_delete=models.CASCADE
	)
	forecasted_at = models.DateTimeField(auto_now=False)
	temp = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	feels_like = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	temp_min = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	temp_max = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	pressure = models.IntegerField()
	sea_level = models.IntegerField()
	grnd_level = models.IntegerField()
	humidity = models.IntegerField()
	temp_kf = models.IntegerField()
	weather = models.CharField(max_length=50)
	weather_id = models.IntegerField()
	weather_description = models.CharField(max_length=200)
	weather_icon_name = models.CharField(max_length=10)
	clouds = models.IntegerField()
	wind_speed = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	wind_deg = models.IntegerField()
	visibility = models.IntegerField()
	pop = models.DecimalField(
		max_digits=7,
		decimal_places=3
	)
	rain = models.DecimalField(
		blank=True,
		null=True,
		max_digits=7,
		decimal_places=3
	)
	snow = models.DecimalField(
		blank=True,
		null=True,
		max_digits=7,
		decimal_places=3
	)
	sys = models.CharField(max_length=1)

	def __str__(self):
		return str(self.forecast)


import requests
from bs4 import BeautifulSoup

LIMIT = 50
URL = f"https://www.indeed.com/jobs?q=python&limit={LIMIT}"

#indeed 페이지를 추출하는 함수
def extract_indeed_pages():
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")
    pagination = soup.find("div", {"class" : "pagination"})

    links = pagination.find_all("a")
    pages = []

    for link in links[:-1] :
        pages.append(int(link.string))

    max_page = pages[-1]
    return max_page

#2번째 request : indeed 페이지의 마지막 페이지까지 낱개로 배열
def extract_indeed_jobs(last_page):
    jobs = []
    #for page in range(last_page):  이렇게 하니까 모든 페이지의 h2 class="title"이 나와서 주석달고 다른 for문 만들거임
    result = requests.get(f"{URL}&start={0*LIMIT}") #for문 없앴으니까 page*LIMIT -> 0*LIMIT으로 변경
    soup = BeautifulSoup(result.text, "html.parser") #soup 이용해서 html 데이터 중 제목 부분을 추출할거임
    results = soup.find_all("div", {"class" : "jobsearch-SerpJobCard"}) # soup의 find_all 기능이 div class="jobsearch-SerpJobCard" 요소를 찾음
    #print(results)
    #for문을 사용해서 div class="title 안의 a title=""만 가져와서 제목만 추출할거임
    for result in results:
        title = result.find("h2",{"class":"title"}).find("a")["title"] #[]하면 attribute 써주기
        print(title)
    # print(result.status_code) / 작동이 잘 되는지만 확인
    return jobs


def primes():
    found, x = [2], 3
    yield 2
    while True:
        for prim in found:
            if not x % prim:
                break
        else:
            yield x
            found.append(x)
        x += 2

def run(position):
    for index, prime in enumerate(primes(), 1):
        if index == position:
            print(prime)
            break

if __name__ == "__main__":
    run(10001)


"""
How many strings equal to a can be constructed using letters from the string b? Each letter can be used only once and in one
string only.

Example

For a = "abc" and b = "abccba", the output should be
stringsConstruction(a, b) = 2.

We can construct 2 strings a with letters from b.
"""
def stringsConstruction(a, b):
    c = []
    for char in a:
        if char not in b:
            return 0
        else:
            if a.count(char) == 1:
                c.append(b.count(char))
            else:
                ths = a.count(char)
                store = b.count(char) // a.count(char)
                c.append(store)
    return min(min(c),len(a))


# coding: utf-8
import os
import cv2
import requests
import json
import base64
import numpy as np
import time
import threading
import re

#分割服务的地址
IMAGE_SEG_URL = 'http://xxx.xxx.xxx.xxx:8010/ImageSegService/inference'

class ClientThread(threading.Thread):
    def __init__(self, thread_id, image_data_repo):
        threading.Thread.__init__(self)
        self.__thread_id = thread_id
        self.__image_data_repo = image_data_repo

    def run(self):
        self.__request_image_seg_service()

    def __request_image_seg_service(self):
        # 持续发送150个请求
        for i in range(1, 151):
            print("Epoch %d, thread %d" % (i, self.__thread_id))
            self.__benchmark_test()

    # benchmark test
    def __benchmark_test(self):
        start = time.time()
        for image_filename in self.__image_data_repo:
            mask_mat_list = self.__request_predictor_server(image_filename)
            input_img = self.__image_data_repo.get_image_matrix(image_filename)
            # 将获得的mask matrix转换成可视化图像，并在当前目录下保存为图像文件
            # 如果进行压测，可以把这句话注释掉
            for j in range(len(mask_mat_list)):
                self.__visualization(mask_mat_list[j], image_filename, 2, input_img)
        latency = time.time() - start
        print("total latency = %f s" % (latency))

    # 对预测结果进行可视化
    # input_raw_mask 是server返回的预测结果
    # output_img 是可视化结果存储路径
    def __visualization(self, mask_mat, output_img, num_cls, input_img):
        # ColorMap for visualization more clearly
        n = num_cls
        color_map = []
        for j in range(n):
            lab = j
            a = b = c = 0
            color_map.append([a, b, c])
            i = 0
            while lab:
                color_map[j][0] |= (((lab >> 0) & 1) << (7 - i))
                color_map[j][1] |= (((lab >> 1) & 1) << (7 - i))
                color_map[j][2] |= (((lab >> 2) & 1) << (7 - i))
                i += 1
                lab >>= 3
        im = cv2.imdecode(mask_mat, 1)
        w, h, c = im.shape
        im2 = cv2.resize(im, (w, h))
        im = im2
        # I = aF + (1-a)B
        a = im / 255.0
        im = a * input_img + (1 - a) * [255, 255, 255]
        cv2.imwrite(output_img, im)

    def __request_predictor_server(self, input_img):
        data = {"instances": [self.__get_item_json(input_img)]}
        response = requests.post(IMAGE_SEG_URL, data=json.dumps(data))
        try:
            response = json.loads(response.text)
            prediction_list = response["prediction"]
            mask_response_list = [mask_response["info"] for mask_response in prediction_list]
            mask_raw_list = [json.loads(mask_response)["mask"] for mask_response in mask_response_list]
        except Exception as err:
            print("Exception[%s], server_message[%s]" % (str(err), response.text))
            return None
        # 使用 json 协议回复的包也是 base64 编码过的
        mask_binary_list = [base64.b64decode(mask_raw) for mask_raw in mask_raw_list]
        m = [np.fromstring(mask_binary, np.uint8) for mask_binary in mask_binary_list]
        return m

    # 请求预测服务
    # input_img 要预测的图片列表
    def __get_item_json(self, input_img):
        # 使用 http 协议请求服务时, 请使用 base64 编码发送图片
        item_binary_b64 = str(base64.b64encode(self.__image_data_repo.get_image_binary(input_img)), 'utf-8')
        item_size = len(item_binary_b64)
        item_json = {
            "image_length": item_size,
            "image_binary": item_binary_b64
        }
        return item_json

def create_thread_pool(thread_num, image_data_repo):
    return [ClientThread(i + 1, image_data_repo) for i in range(thread_num)]

def run_threads(thread_pool):
    for thread in thread_pool:
        thread.start()

    for thread in thread_pool:
        thread.join()

class ImageDataRepo:
    def __init__(self, dir_name):
        print("Loading images data...")
        self.__data = {}
        pattern = re.compile(".+\.(jpg|jpeg)", re.I)
        if os.path.isdir(dir_name):
            for image_filename in os.listdir(dir_name):
                if pattern.match(image_filename):
                    full_path = os.path.join(dir_name, image_filename)
                    fp = open(full_path, mode="rb")
                    image_binary_data = fp.read()
                    image_mat_data = cv2.imread(full_path)
                    self.__data[image_filename] = (image_binary_data, image_mat_data)
        else:
            raise Exception("Please use directory to initialize");
        print("Finish loading.")
    def __iter__(self):
        for filename in self.__data:
            yield filename

    def get_image_binary(self, image_name):
        return self.__data[image_name][0]

    def get_image_matrix(self, image_name):
        return self.__data[image_name][1]

if __name__ == "__main__":
    #preprocess
    IDR = ImageDataRepo("images")
    thread_pool = create_thread_pool(thread_num=1, image_data_repo=IDR)
    run_threads(thread_pool)