from api import models
from publicFunc import Response
from publicFunc import account, xmldom_parsing
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from publicFunc.weixin.weixin_pay_api import weixin_pay_api
from publicFunc.weixin.weixin_gongzhonghao_api import WeChatApi
from publicFunc.article_oper import get_ent_info
from django.db.models import F, Sum
from api.forms.withdrawal import WithdrawalForm, SelectForm
from publicFunc.base64_encryption import b64decode
import xml.dom.minidom as xmldom, datetime, time, json, os
from api.views_dir.my_celery.celery_url import celery_error_warning

@csrf_exempt
@account.is_token(models.Userprofile)
def weixin_pay(request, oper_type, o_id):
    response = Response.ResponseObj()
    weixin_pay_api_obj = weixin_pay_api()  # 实例 公共函数
    user_id = request.GET.get('user_id')

    if request.method == 'POST':
        # 预支付
        if oper_type == 'yuZhiFu':
            pay_type = request.GET.get('pay_type') # 支付方式 余额支付/微信支付
            try:
                fee_objs = models.renewal_management.objects.filter(id=o_id)
                if fee_objs:
                    models.renewal_log.objects.filter(create_user_id=user_id, isSuccess=0).delete() # 删除未付款的订单

                    userObjs = models.Userprofile.objects.filter(id=user_id)
                    user_obj = userObjs[0]
                    fee_obj = fee_objs[0]

                    price = int(fee_obj.price)                                                  # 支付钱数
                    get_the_length_display = fee_obj.get_the_length_display()                   # 续费时长 (几个月/几年)
                    renewal_number_days = fee_obj.renewal_number_days                           # 续费天数
                    overdue_date = (user_obj.overdue_date + datetime.timedelta(days=renewal_number_days))  # 续费后 到期时间
                    dingdanhao = weixin_pay_api_obj.shengcheng_dingdanhao()                     # 订单号

                    order_objs = models.renewal_log.objects.filter(pay_order_no=dingdanhao)  # 查询订单日志
                    if not order_objs:

                        # 余额支付
                        if pay_type == 'balance_payment':
                            # 创建订单
                            ren_obj = models.renewal_log.objects.create(
                                pay_order_no=dingdanhao,
                                the_length=get_the_length_display,  # 续费时长
                                renewal_number_days=renewal_number_days,
                                create_user_id=user_id,
                                price=price,
                                original_price=fee_obj.original_price,  # 原价
                                overdue_date=overdue_date,
                                status=2,
                            )
                            if float(user_obj.make_money) >= price:
                                userObjs.update(make_money=F('make_money') - price)
                                # 修改到期时间
                                userObjs.update(
                                    overdue_date=overdue_date,
                                    vip_type=2,  # 更改为高级会员
                                )
                                ren_obj.isSuccess = 1
                                response.code = 200
                                response.msg = '支付成功'
                            else:
                                ren_obj.isSuccess = 0
                                response.code = 301
                                response.msg = '余额不足'
                            ren_obj.save()

                        # 微信支付
                        else:
                            data = get_ent_info(user_id)  # 获取用户信息
                            weixin_obj = WeChatApi(data)  # 获取用户公众号信息
                            appid = weixin_obj.APPID  # appid
                            APPSECRET = weixin_obj.APPSECRET  # 商户号
                            data = {
                                'total_fee': price,  # 金额(分 为单位)
                                'openid': user_obj.openid,  # 微信用户唯一标识
                                'appid': appid,  # appid
                                'dingdanhao': dingdanhao  # 生成订单号
                            }

                            # price = price * 100                       # 单位 分
                            result = weixin_pay_api_obj.yuzhifu(data)  # 预支付
                            return_code = result.get('return_code')
                            return_msg = result.get('return_msg')
                            prepay_id = result.get('prepay_id')['prepay_id']

                            if return_code == 'SUCCESS':  # 判断预支付返回参数 是否正确
                                models.renewal_log.objects.create(
                                    pay_order_no=dingdanhao,
                                    the_length=get_the_length_display,  # 续费时长
                                    renewal_number_days=renewal_number_days,
                                    create_user_id=user_id,
                                    price=price,
                                    original_price=fee_obj.original_price,  # 原价
                                    overdue_date=overdue_date,
                                    status=1
                                )

                                # 返回数据
                                data_dict = {
                                    'appId': appid,
                                    'timeStamp': int(time.time()),
                                    'nonceStr': weixin_pay_api_obj.generateRandomStamping(),
                                    'package': 'prepay_id=' + prepay_id,
                                    'signType': 'MD5'
                                }
                                SHANGHUKEY = weixin_pay_api_obj.SHANGHUKEY
                                stringSignTemp = weixin_pay_api_obj.shengchengsign(data_dict, SHANGHUKEY)
                                data_dict['paySign'] = weixin_pay_api_obj.md5(stringSignTemp).upper()  # upper转换为大写

                                response.data = data_dict
                                response.code = 200
                                response.msg = '预支付请求成功'
                            else:
                                response.code = 301
                                response.msg = '支付失败, 原因:{}'.format(return_msg)

                else:
                    response.code = 301
                    response.msg = '请选择一项会员'
            except Exception as e:
                if pay_type=='balance_payment':
                    text = '余额支付'
                else:
                    text = '微信支付'

                msg = '警告:{}, \n错误:{}, \n时间:{}'.format(
                    '用户支付报错--->用户ID{}-充值ID{}-充值方式'.format(user_id, o_id, text),
                    e,
                    datetime.datetime.today()
                )
                celery_error_warning(msg)

        # 提现功能
        elif oper_type == 'withdrawal':
            try:
                form_data = {
                    'user_id': user_id,
                    'withdrawal_amount': request.GET.get('withdrawal_amount'), # 提现金额
                }
                form_objs = WithdrawalForm(form_data)
                if form_objs.is_valid():

                    data = get_ent_info(user_id)  # 获取用户信息
                    weixin_obj = WeChatApi(data)  # 获取用户公众号信息
                    appid = weixin_obj.APPID  # appid
                    APPSECRET = weixin_obj.APPSECRET  # 商户号

                    print(request.META)
                    # 当前路径
                    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                    # 获取访问用户IP
                    if request.META.get('HTTP_X_FORWARDED_FOR'):
                        ip = request.META['HTTP_X_FORWARDED_FOR']
                    else:
                        ip = request.META['REMOTE_ADDR']

                    user_obj, withdrawal_amount = form_objs.cleaned_data.get('withdrawal_amount')
                    dingdanhao = weixin_pay_api_obj.shengcheng_dingdanhao()
                    data = {
                        'withdrawal_amount': withdrawal_amount, # 提现金额
                        'dingdanhao': dingdanhao,               # 订单号
                        'appid': appid,                         # appid
                        'openid': user_obj.openid,              # openid
                        'user_id': user_id,                     # user_id
                        'user_name': b64decode(user_obj.name),
                        'make_money': user_obj.make_money,
                        'ip': ip,
                    }
                    response_data = weixin_pay_api_obj.withdrawal(data) # 提现

                    code = response_data.get('code')
                    return_msg = response_data.get('return_msg')

                    make_money = float(user_obj.make_money)             # 用户待提钱数
                    withdrawal_amount = withdrawal_amount    # 用户提现钱数
                    withdrawal_after = make_money - withdrawal_amount   # 待提钱数减去提现钱数

                    if code == 200:
                        is_success = 1 # 是否提现成功
                        response.code = 200
                        # 减去提现的钱数
                        user_money_obj = models.Userprofile.objects.get(id=user_id)
                        user_money_obj.make_money = F('make_money') - withdrawal_amount
                        user_money_obj.save()

                    else:
                        is_success = 0
                        response.code = 301

                    models.withdrawal_log.objects.create(           # 创建提现记录
                        user_id=user_id,
                        withdrawal_befor=make_money,           # 提现前 待提钱数
                        withdrawal_amount=withdrawal_amount,  # 提现金额
                        withdrawal_after=withdrawal_after,  # 提现后 待提钱数
                        is_success=is_success,
                        wechat_returns_data=return_msg,
                        dingdanhao=dingdanhao
                    )

                    response.msg = return_msg
                else:
                    response.code = 301
                    response.msg = json.loads(form_objs.errors.as_json())
            except Exception as e:
                msg = '警告:{}, \n错误:{}, \n时间:{}'.format(
                    '用户提现报错--->用户ID{}, 提现钱数{} '.format(user_id, request.GET.get('withdrawal_amount')),
                    e,
                    datetime.datetime.today()
                )
                celery_error_warning(msg)

    else:

        # 提现记录
        if oper_type == 'withdrawal_record':
            form_objs = SelectForm(request.GET)
            if form_objs.is_valid():
                current_page = form_objs.cleaned_data['current_page']
                length = form_objs.cleaned_data['length']
                user_obj = models.Userprofile.objects.get(id=user_id)

                objs = models.withdrawal_log.objects.filter(user_id=user_id).order_by('-create_date')

                withdrawal_amount_sum_obj = objs.filter(is_success=1).aggregate(
                    nums=Sum('withdrawal_amount')
                )

                data_count = objs.count()
                if length != 0:
                    start_line = (current_page - 1) * length
                    stop_line = start_line + length
                    objs = objs[start_line: stop_line]
                data_list = []
                for obj in objs:
                    data_list.append({
                        'dingdanhao': obj.dingdanhao,                   # 提现订单号
                        'withdrawal_amount': obj.withdrawal_amount,     # 提现金额
                        'create_date': obj.create_date.strftime('%Y-%m-%d %H:%M:%S'),     # 提现时间
                        'is_success': obj.is_success,                   # 提现是否成功
                        'wechat_returns_data': obj.wechat_returns_data, # 失败原因
                    })

                withdrawal_amount_sum = 0
                if withdrawal_amount_sum_obj:
                    withdrawal_amount_sum = withdrawal_amount_sum_obj.get('nums')

                response.code = 200
                response.msg = '查询成功'
                response.data = {
                    'data_count': data_count,
                    'withdrawal_amount_sum': withdrawal_amount_sum,
                    'cumulative_amount': user_obj.cumulative_amount,
                    'make_money': user_obj.make_money,
                    'data_list': data_list,
                }
                response.note = {
                    'withdrawal_amount_sum': '已提现钱数',
                    'cumulative_amount': '累计现金',
                    'make_money': '当前待提余额',
                    'data_list':{
                        'dingdanhao': '提现订单号',
                        'withdrawal_amount': '提现金额',
                        'create_date': '提现时间',
                        'is_success': '提现是否成功',
                        'wechat_returns_data': '失败原因'
                    }

                }
            else:
                response.code = 301
                response.msg = json.loads(form_objs.errors.as_json())

        # 支付记录
        elif oper_type == 'payment_records':
            form_objs = SelectForm(request.GET)
            if form_objs.is_valid():
                current_page = form_objs.cleaned_data['current_page']
                length = form_objs.cleaned_data['length']

                # user_obj = models.Userprofile.objects.get(id=user_id)

                objs = models.renewal_log.objects.filter(
                    create_user_id=user_id,
                    isSuccess=1
                ).order_by('-create_date')

                data_count = objs.count()
                if length != 0:
                    start_line = (current_page - 1) * length
                    stop_line = start_line + length
                    objs = objs[start_line: stop_line]
                data_list = []
                for obj in objs:
                    data_list.append({
                        'pay_order_no': obj.pay_order_no,               # 订单号
                        'price':obj.price,                              # 价钱
                        'status_id':obj.status,                         # 支付方式ID
                        'status':obj.get_status_display(),              # 支付方式
                        'the_length':obj.the_length,                    # 时长
                        # 'overdue_date':obj.overdue_date.strftime('%Y-%m-%d %H:%M:%S'),  # 过期时间
                        'create_date': obj.create_date.strftime('%Y-%m-%d %H:%M:%S'),  # 创建时间
                    })

                response.code = 200
                response.msg = '查询成功'
                response.data = {
                    'data_count': data_count,
                    'data_list': data_list,
                }
                response.note = {
                    'data_list': {
                        'pay_order_no': '订单号',
                        'price': '支付金额',
                        'the_length': '时长',
                        'create_date': '下单时间',
                    }

                }
            else:
                response.code = 301
                response.msg = json.loads(form_objs.errors.as_json())

        else:
            response.code = 402
            response.msg = '请求异常'

    return JsonResponse(response.__dict__)

# 微信回调
def payback(request):
    weixin_pay_api_obj = weixin_pay_api()  # 实例 公共函数
    response = Response.ResponseObj()
    isSuccess = 0
    response.code = 200
    DOMTree = xmldom.parseString(request.body)
    collection = DOMTree.documentElement
    data = ['mch_id', 'return_code', 'appid', 'openid', 'cash_fee', 'out_trade_no']
    resultData = xmldom_parsing.xmldom(collection, data)
    renewal_log_objs = models.renewal_log.objects.filter(pay_order_no=resultData['out_trade_no'])
    if resultData['return_code'] == 'SUCCESS' and renewal_log_objs:   # 如果支付成功 和 有订单
        renewal_log_obj = renewal_log_objs[0]
        if not renewal_log_obj.isSuccess:
            # 查询订单是否付款成功
            result_data = {
                'appid': resultData['appid'],  # appid
                'mch_id': resultData['mch_id'],  # 商户号
                'out_trade_no': resultData['out_trade_no'],  # 订单号
                'nonce_str': weixin_pay_api_obj.generateRandomStamping(),  # 32位随机值
            }
            return_code = weixin_pay_api_obj.weixin_back_pay(result_data)

            if return_code == 'SUCCESS':
                isSuccess = 1 # 支付状态
                pay_user_id = renewal_log_obj.create_user_id  # 充值人  ID
                renewal_log_objs.update(isSuccess=isSuccess)  # 修改充值成功

                # 修改会员到期时间 和高级会员
                user_objs = models.Userprofile.objects.filter(id=pay_user_id)
                user_objs.update(
                    overdue_date=renewal_log_obj.overdue_date,
                    vip_type=2, # 更改为高级会员
                )

                enter_obj = models.Enterprise.objects.get(id=user_objs[0].enterprise_id)
                primary_distribution = float(enter_obj.primary_distribution) / 100       # 一级分销占比
                secondary_distribution = float(enter_obj.secondary_distribution) /100   # 二级分销占比

                inviter_id = None  # 父级 推广人
                if user_objs[0].inviter:
                    inviter_id = user_objs[0].inviter_id

                # 判断是否首次充值 判断是否有邀请人 首次充值给 邀请人增加钱
                renewal_objs = models.renewal_log.objects.filter( # 充值人为自己 且充值成功
                    create_user_id=pay_user_id,
                    isSuccess=1
                )
                print('renewal_objs.count()-----> ', renewal_objs.count(), inviter_id)
                if renewal_objs.count() == 1 and inviter_id:  # 判断 是否首次充值 和 是否有 上线人
                    price = float(renewal_objs[0].price) / 100                                              # 首次充值钱数
                    print('--------------------------------------------=====================================', price)
                    inviter_id_user_obj = models.Userprofile.objects.get(id=inviter_id)
                    if inviter_id_user_obj.vip_type in [1, 2]:                                                   # 判断 推广人当前是否为 高级会员
                        cumulative_amount = float(price) * primary_distribution                             # 一级分享人应加钱数  30%  保留小数点后两位
                        inviter_id_user_obj.cumulative_amount = F('cumulative_amount') + cumulative_amount  # 累计钱数 + 30% # 默认
                        inviter_id_user_obj.make_money = F('make_money') + cumulative_amount                # 待提钱数 + 30% # 默认
                        inviter_id_user_obj.save()
                        print('--------chaungjian =')
                        models.distribute_money_log.objects.create( # 创建充值分销人应得钱数日志
                            user_id=renewal_log_obj.create_user_id,
                            inviter_id=inviter_id,
                            price=price,
                            money=cumulative_amount,
                            status=1,
                            renewal_id=renewal_log_obj.id
                        )

                        if inviter_id_user_obj.inviter:                     # 判断是否有二级分享人
                            two_inviter_id = inviter_id_user_obj.inviter_id # 二级 分享人ID
                            two_user_obj = models.Userprofile.objects.get(id=two_inviter_id)
                            if two_user_obj.vip_type in [1, 2]:                                  # 判断 二级分享人 是否为高级会员
                                cumulative_amount = float(price) * secondary_distribution   # 二级分享人应加钱数, 保留小数点后两位
                                two_user_obj.cumulative_amount = F('cumulative_amount') + cumulative_amount
                                two_user_obj.make_money = F('make_money') + cumulative_amount
                                two_user_obj.save()

                                models.distribute_money_log.objects.create( # 创建充值分销人应得钱数日志
                                    user_id=renewal_log_obj.create_user_id,
                                    inviter_id=two_inviter_id,
                                    price=price,
                                    money=cumulative_amount,
                                    status=2,
                                    renewal_id=renewal_log_obj.id
                                )

                print('--------------------支付成功-------------')
            else:
                objs = models.renewal_log.objects.filter(pay_order_no=result_data.get('out_trade_no'))
                if objs:
                    objs.delete()
                print('------支付失败 ----------删除订单')

            renewal_log_objs.update(isSuccess=isSuccess)  # 修改订单状态
    return JsonResponse(response.__dict__)


import krpc
import os
import time
import math

# VERTICAL_WEIGHT = 1
HORIZONTAL_WEIGHT = 1
ALTITUDE_WEIGHT = 1
AP_WEIGHT = 0.02
PE_WEIGHT = 0.02
ORBITAL_GOAL = 80000
ORBIT_WEIGHT = 10000000
FUEL_WEIGHT = 1

def calc_fitness(vessel):
    flight = vessel.flight(conn.space_center.bodies["Kerbin"].reference_frame)
    velocity = flight.horizontal_speed
    fuel = vessel.mass - vessel.dry_mass
    periapsis = vessel.orbit.periapsis_altitude
    apoapsis = vessel.orbit.apoapsis_altitude

    periapsisDiff = math.fabs(periapsis - ORBITAL_GOAL)
    apoapsisDiff = math.fabs(apoapsis - ORBITAL_GOAL)

    altitude = flight.mean_altitude
    if altitude > 70000:
        altitude = 70000

    if vessel.situation != vessel.situation.orbiting:
        return HORIZONTAL_WEIGHT * velocity + ALTITUDE_WEIGHT * altitude - (periapsisDiff * PE_WEIGHT + apoapsisDiff * AP_WEIGHT)
    else:
        return ORBIT_WEIGHT + FUEL_WEIGHT * fuel - (periapsisDiff * PE_WEIGHT + apoapsisDiff * AP_WEIGHT)

conn = krpc.connect(name='Fitness script')
vessel = conn.space_center.active_vessel

flight = vessel.flight(conn.space_center.bodies["Kerbin"].reference_frame)

while True:
    # os.system('cls' if os.name == 'nt' else 'clear')

    print(calc_fitness(vessel))

    time.sleep(5)


import RPi.GPIO as GPIO # import GPIO librery

from time import sleep

GPIO.setmode(GPIO.BCM)

Motor1A = 13 # set GPIO as Input 1 of the controller IC
Motor1B = 12 # set GPIO as Input 2 of the controller IC
Motor1E = 13 # set GPIO

GPIO.setup(Motor1A,GPIO.OUT)
GPIO.setup(Motor1B,GPIO.OUT)
GPIO.setup(Motor1E,GPIO.OUT)

pwm = GPIO.PWM(Motor1E,100) # configuring Enable pin for PWM

def test():
    print("Hi")

def dcStart():
    #pwm.start(50)
    #GPIO.output(Motor1E, GPIO.HIGH)
    GPIO.setmode(GPIO.BCM)

    Motor1A = 13 # set GPIO as Input 1 of the controller IC
    Motor1B = 12 # set GPIO as Input 2 of the controller IC
    Motor1E = 13 # set GPIO

    GPIO.setup(Motor1A,GPIO.OUT)
    GPIO.setup(Motor1B,GPIO.OUT)
    GPIO.setup(Motor1E,GPIO.OUT)

    #pwm = GPIO.PWM(Motor1E,100) # configuring Enable pin for PW
    pwm.start(50) # Thats the starting duty cycle percentage

def dcMotorCW():
    print ("GO forward")
    GPIO.output(Motor1A,GPIO.HIGH)
    GPIO.output(Motor1B,GPIO.LOW)
    GPIO.output(Motor1E,GPIO.HIGH)

# this will run your motor in forward direction for 2 seconds with 50% speed.

def setDCRPM(speed):
    pwm.ChangeDutyCycle(speed) # Changes pwm within the motor

def dcMotorCCW():
    print ("GO backward")
    GPIO.output(Motor1A,GPIO.LOW)
    GPIO.output(Motor1B,GPIO.HIGH)
    GPIO.output(Motor1E,GPIO.HIGH)

def dcStop():
    print ("Now stop")
    GPIO.output(Motor1E,GPIO.LOW)
    pwm.stop() # stop PWM from GPIO output it is necessary
    GPIO.cleanup()


from PIL import Image

def read_ppm(filename):
    with open(filename, 'r') as f:
        lines = f.readlines()

    # Remove comments
    lines = [line for line in lines if not line.startswith("#")]

    # Verify the magic number
    if lines[0].strip() != "P3":
        print("Not a P3 PPM file")
        return None

    # Get image dimensions and max color value
    width, height = map(int, lines[1].split())
    max_value = int(lines[2])

    # Read the pixel data
    pixels = []
    for line in lines[3:]:
        pixels.extend(map(int, line.split()))

    # Create an Image object
    image = Image.new("RGB", (width, height))
    for y in range(height):
        for x in range(width):
            index = 3 * (y * width + x)
            pixel = tuple(pixels[index:index + 3])
            image.putpixel((x, y), pixel)

    return image

# Read the PPM file
ppm_image = read_ppm("image.ppm")
if ppm_image:
    # Save as JPG
    ppm_image.save("image.png")


"""Classification of built-up areas based on Random Forest."""

import rasterio
import numpy as np
from scipy.ndimage import binary_dilation, uniform_filter, median_filter
from imblearn.over_sampling import RandomOverSampler
from sklearn.cluster import MiniBatchKMeans
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (f1_score, precision_score, recall_score,
                             roc_curve, accuracy_score, auc)
from sklearn.model_selection import GroupKFold

from maupp.reference import LEGEND

def _count_features(filenames):
    """Count features in a list of GeoTIFFs."""
    n_features = 0
    for fname in filenames:
        with rasterio.open(fname) as src:
            n_features += src.count
    return n_features

def _count_samples(filenames):
    """Count samples based on a list of GeoTIFFs. Return an error if the
    number of samples is not equal across the files.
    """
    n_samples_list = []
    for fname in filenames:
        with rasterio.open(fname) as src:
            n_samples_list.append(src.width * src.height)
    if len(set(n_samples_list)) == 1:
        return n_samples_list[0]
    else:
        raise ValueError('Number of samples not consistent.')

def transform(filenames, mask=None):
    """Transform input raster data to make it usable by sklearn.

    Parameters
    ----------
    filenames : list of str
        Single-band or multi-band rasters.
    mask : 2d array, optional
        Mask array.

    Returns
    -------
    X : array-like
        Output array of shape (n_samples, n_features).
    """
    use_mask = isinstance(mask, np.ndarray)
    if use_mask:
        n_samples = np.count_nonzero(mask)
    else:
        n_samples = _count_samples(filenames)
    n_features = _count_features(filenames)
    X = np.empty(shape=(n_samples, n_features), dtype='float32')
    i = 0
    for fname in filenames:
        with rasterio.open(fname) as src:
            for j in range(src.count):
                if use_mask:
                    X[:, i] = src.read(j+1)[mask].ravel()
                else:
                    X[:, i] = src.read(j+1).ravel()
                i += 1
    return X

def clustering(src_labels, class_value, **kwargs):
    """KMeans-based spatial clustering. Positive pixels are clustered
    into `k` groups based on their `x` and `y` coordinates.

    Parameters
    ----------
    src_labels : 2d array
        Input training labels.
    class_value : int
        Pixel value corresponding to the class that will be clustered.
    **kwargs
        Passed to MiniBatchKMeans().

    Returns
    -------
    dst_labels : array
        Output raster with cluster labels as pixel values.
    """
    class_mask = src_labels == class_value
    xy = np.where(class_mask)
    nb_samples = xy[0].shape[0]
    X = np.empty(shape=(nb_samples, 2))
    X[:, 0] = xy[0]
    X[:, 1] = xy[1]
    km = MiniBatchKMeans(**kwargs)
    clusters = km.fit_predict(X)
    clusters = clusters + 1
    dst_labels = np.zeros_like(src_labels)
    dst_labels[src_labels == class_value] = clusters
    return dst_labels

def random_choice(src_array, size, random_seed=None):
    """Randomly choose a given amount of pixels from a binary raster.
    Unchosen pixels are assigned the value of 0.

    Parameters
    ----------
    src_array : array-like
        Input binary raster as a 2D NumPy array.
    size : int
        Number of pixels wanted.
    random_seed : int, optional
        Numpy random seed for reproducibility.

    Returns
    -------
    dst_array : array-like
        Output binary raster.
    """
    if random_seed:
        np.random.seed(random_seed)
    if np.count_nonzero(src_array == 1) == size:
        return src_array
    candidates = np.where(src_array.ravel() == 1)[0]
    selected = np.random.choice(candidates, size=size, replace=False)
    dst_array = np.zeros_like(src_array.ravel())
    dst_array[selected] = 1
    return dst_array.reshape(src_array.shape).astype(np.bool)

def limit_samples(samples, max_samples=50000, random_seed=None):
    """Limit max. number of samples per class with random sampling.

    Parameters
    ----------
    samples : 2d array
        Input training labels.
    max_samples : int, optional
        Max. number of samples per class.
    random_seed : int, optional
        Numpy random seed for reproducbility.

    Returns
    -------
    out_samples : 2d array
        Output training labels.
    """
    out_samples = samples.copy()
    for class_ in (1, 2):
        n_samples = np.count_nonzero(out_samples == class_)
        if n_samples > max_samples:
            selected = random_choice(
                out_samples == class_, max_samples, random_seed)
            out_samples[(samples == class_) & ~selected] = 0
    return out_samples

def under_sampling(samples, random_seed=None):
    """Perform under-sampling of the majority class.

    Parameters
    ----------
    samples : 2d array
        Input training labels.
    random_seed : int, optional
        Numpy random seed for reproducibility.

    Returns
    -------
    out_samples : 2d array
        Output training labels.
    """
    out_samples = samples.copy()
    n_positive = np.count_nonzero(samples == 1)
    n_negative = np.count_nonzero(samples == 2)

    if n_positive > n_negative:
        positive = random_choice(
            samples == 1, n_negative, random_seed=random_seed)
        out_samples[(samples == 1) & ~positive] = 0

    if n_negative > n_positive:
        negative = random_choice(
            samples == 2, n_positive, random_seed=random_seed)
        out_samples[(samples == 2) & ~negative] = 0

    return out_samples

def cross_validation(filenames, training_samples, k=10, max_samples=50000,
                     random_seed=None):
    """Perform K-Fold cross-validation.

    Parameters
    ----------
    filenames : list of str
        Filenames of raster datasets.
    training_samples : 2d array
        Training labels.
    k : int, optional
        Number of folds (default=10).
    max_samples : int, optional
        Max. samples per class.
    random_seed : int, optional
        Numpy and Sklearn random seed for reproducibility.

    Returns
    -------
    scores : ndarray
        F1-scores as an array of length k.
    """
    # Spatial clustering of both positive and negative training samples
    # into k*3 clusters.
    # This is to avoid spatial autocorrelation, i.e. avoiding neighbooring
    # samples of the same class being in both the training and the testing
    # datasets.
    pos_groups = clustering(training_samples, 1, n_clusters=k*3,
                            random_state=random_seed)
    neg_groups = clustering(training_samples, 2, n_clusters=k*3,
                            random_state=random_seed)
    groups = np.maximum(pos_groups, neg_groups)
    groups = groups[groups > 0].ravel()

    # Prediction mask is larger in order to allow post-processing of the
    # classification result with a moving window filter.
    train_mask = training_samples > 0
    pred_mask = binary_dilation(train_mask, iterations=3)

    # Transform input data
    X = transform(filenames, mask=pred_mask)
    X_train = transform(filenames, mask=train_mask)
    y_train = training_samples[train_mask].ravel()

    # Perform K-Fold cross-validation using groups to avoid
    # spatial autocorrelation and including a post-processing
    # step based on a 3x3 uniform filter.
    rf = RandomForestClassifier(n_estimators=100, n_jobs=-1,
                                random_state=random_seed)
    folds = GroupKFold(n_splits=k)
    scores = []
    for train, test in folds.split(X_train, y_train, groups=groups):
        rf.fit(X_train[train], y_train[train])
        proba = rf.predict_proba(X)[:, 0]
        img = np.zeros(shape=training_samples.shape, dtype=np.float32)
        img[pred_mask] = proba
        img = uniform_filter(img, size=3)
        y_pred = img[train_mask][test] >= 0.5
        y_true = y_train[test] == 1
        scores.append(f1_score(y_true, y_pred))

    return np.array(scores)

def train(filenames, training_labels, random_seed=None, **kwargs):
    """Train a Random Forest model.

    Parameters
    ----------
    filenames : list of str
        Filenames of raster datasets.
    training_labels : 2d array
        Training labels (1=BuiltUp, 2=NonBuiltUp).
    random_seed : int, optional
        Numpy and Sklearn random seed for reproducibility.
    **kwagrs
        Passed to RandomForestClassifier().

    Returns
    -------
    model : classifier
        Sklearn classifier object (fitted).
    """
    X_train = transform(filenames, mask=training_labels > 0)
    y_train = training_labels[training_labels > 0].ravel()
    sampler = RandomOverSampler(random_state=random_seed)
    X_train, y_train = sampler.fit_resample(X_train, y_train)
    rf = RandomForestClassifier(random_state=random_seed, **kwargs)
    rf.fit(X_train, y_train)
    return rf

def predict(model, X, width, height):
    """Prediction with a fitted model.

    Parameters
    ----------
    model : classifier
        Sklearn classifier (fitted).
    X : array
        Input data.
    width : int
        Raster width.
    height : int
        Raster height.

    Returns
    -------
    proba : 2d array
        RF probabilistic output of shape (height, width).
    """
    proba = model.predict_proba(X)[:, 0]
    proba = proba.reshape((height, width))
    return proba

def validate(proba, validation_samples, threshold=0.5):
    """Compute validation metrics from an independent validation dataset.

    Parameters
    ----------
    proba : 2d array
        RF probabilities for built-up class.
    validation_samples : 2d array
        Validation dataset. Legend: 0=NA, 1=BuiltUp, 2=BareSoil,
        3=LowVegetation, 4=HighVegetation, 5=OtherNonBuiltUp.
    threshold : float, optional
        Threshold applied on the probabilities for binarization.

    Returns
    -------
    metrics
    """
    metrics = {}
    mask = validation_samples > 0

    # Binary metrics
    y_true = validation_samples[mask].ravel() == 1
    y_pred = proba[mask].ravel() >= threshold
    metrics['f1_score'] = f1_score(y_true, y_pred)
    metrics['precision'] = precision_score(y_true, y_pred)
    metrics['recall'] = recall_score(y_true, y_pred)

    # ROC Curve
    fpr, tpr, _ = roc_curve(y_true, proba[mask], pos_label=1)
    metrics['fpr'] = fpr
    metrics['tpr'] = tpr
    metrics['auc'] = auc(fpr, tpr)

    # Per landcover accuracy
    for land, value in LEGEND.items():
        # ignore "other non-built-up" land cover
        if value == 5 or not value in np.unique(validation_samples):
            continue
        mask = validation_samples == value
        y_true = validation_samples[mask].ravel() == 1
        y_pred = proba[mask].ravel() >= threshold
        metrics['{}_accuracy'.format(land)] = accuracy_score(y_true, y_pred)

    return metrics

def post_processing(probabilities, slope, water, proba_threshold=0.9,
                    max_slope=40, filter_size=5):
    """Post-process RF probabilistic output to a binary built-up
    areas raster.

    Parameters
    ----------
    probabilities : 2d array
        RF probabilistic output.
    slope : 2d array
        Slope in percents.
    water : 2d array
        Water mask.
    proba_threshold : float, optional
        Threshold on RF probabilistic output (default=0.9).
    max_slope : int, optional
        Max. slope in percents (default=40).
    filter_size : int, optional
        Size of the majority filter (default=5).

    Returns
    -------
    classes : 2d array
        Binary raster (built-up vs. non-built-up areas).
    """
    probas = probabilities.copy()
    probas = uniform_filter(probas, filter_size)
    classes = (probas >= proba_threshold).astype(np.uint8)
    classes[water] = 0
    classes[slope >= max_slope] = 0
    return classes


# погода с сайта https://openweathermap.org/city/498817
import pyowm
from pyowm.utils.config import get_default_config

owm = pyowm.OWM('1277f2a3cb8b7642fe6f9411b4f08a8d')
mgr = owm.weather_manager()

config_dict = get_default_config()
config_dict['language'] = 'ru'  # your language here, eg. French
config_dict = owm.configuration

# обявляем переменную observation и присваемем ей локацию - питер
observation = mgr.weather_at_place('saint petersburg')

# обявляем переменную w и присваеваем ей погоду в питере
w = observation.weather

# переводим ветер из мс в кмч
wind_speed_kmh = (w.wind()['speed'] * 3600) / 1000  # переводим в кмч

# присвоим переменной boufort значения в зависисмости от ветра кмч
if wind_speed_kmh < 2:
    beaufort_number = 0
    text_wind = 'Безветрие. Дым поднимается вертикально, листья деревьев неподвижны'
elif wind_speed_kmh < 5:
    beaufort_number = 1
    text_wind = 'Направление ветра заметно по относу дыма, но не по флюгеру.'
elif wind_speed_kmh < 11:
    beaufort_number = 2
    text_wind = 'Движение ветра ощущается лицом, шелестят листья,\nприводится в движение флюгер.'
elif wind_speed_kmh < 19:
    beaufort_number = 3
    text_wind = 'Листья и тонкие ветви деревьев всё время колышутся,\nветер развевает лёгкие флаги.'
elif wind_speed_kmh < 28:
    beaufort_number = 4
    text_wind = 'Ветер поднимает пыль и мусор, приводит в движение тонкие ветви деревьев.'
elif wind_speed_kmh < 38:
    beaufort_number = 5
    text_wind = 'Качаются тонкие стволы деревьев, движение ветра ощущается рукой.'
elif wind_speed_kmh < 49:
    beaufort_number = 6
    text_wind = 'Качаются толстые сучья деревьев, гудят телеграфные провода.'
elif wind_speed_kmh < 61:
    beaufort_number = 7
    text_wind = 'Гнутся стволы деревьев, трудно идти против ветра.'
elif wind_speed_kmh < 74:
    beaufort_number = 8
    text_wind = 'Ветер ломает сучья деревьев, идти против ветра очень трудно.'
elif wind_speed_kmh < 88:
    beaufort_number = 9
    text_wind = 'Небольшие повреждения, ветер начинает разрушать крыши зданий.'
elif wind_speed_kmh < 102:
    beaufort_number = 10
    text_wind = 'Значительные разрушения строений, ветер вырывает деревья с корнем.'
elif wind_speed_kmh < 117:
    beaufort_number = 11
    text_wind = 'Большие разрушения на значительном пространстве. Наблюдается очень редко.Видимость плохая.'
elif wind_speed_kmh < 118:
    beaufort_number = 12
    text_wind = 'Огромные разрушения, серьёзно повреждены здания, строения и дома, деревья вырваны с корнями,' \
                ' растительность уничтожена.\nСлучай крайне редкий.'
elif wind_speed_kmh > 118:
    beaufort_number = 12
    text_wind = 'Огромные разрушения, серьёзно повреждены здания, строения и дома, деревья вырваны с корнями,' \
                ' растительность уничтожена.\nСлучай крайне редкий.'

# присвоим каждому баллу название силы ветра через список
wind_name_beaufort_style = ['Штиль', 'Тихий', 'Легкий', 'Слабый', 'Умеренный', 'Свежий', 'Сильный', 'Крепкий',
                            'Очень крепкий', 'Шторм', 'Сильный шторм', 'Жестокий шторм', 'Ураган']

# выводим ветер по шкале бофорта с описанием
# напечатаем через метод format
print()
print('Санкт-Петербург')
print()

print('Сейчас {0}℃, {1}, облака {2}% '
      .format(round(w.temperature('celsius')['temp']), w.detailed_status, str(w.clouds)))

print('Влажность {0}%'
      .format(w.humidity))

print('Ветер "{0}" {1}м/с ({2}км/ч) направление {2}°'
      .format(wind_name_beaufort_style[beaufort_number], w.wind()['speed'], round(wind_speed_kmh), w.wind()['deg']))

print()
print('По шкале Бофорта "{0}"'
      .format(beaufort_number))

print(text_wind)
print()


import numpy as np
import pandas as pd
import nltk
import gensim
from gensim import corpora
import spacy
import re
FILE_PATH = 'data/vancouver_reviews.csv'

class CleanedData:
    def __init__(self):
        # setting variables
        # APIKEY = HEADERS['Authorization']
        # assuming that the data features will be: ['business_id', 'user_id', 'rating', 'comment', 'feedback', "time_uploaded"]

        #retrieving data
        reviews_df = pd.read_csv(FILE_PATH, index_col=0, delimiter='\t')
        print(reviews_df.shape)
        X_raw = reviews_df['comment']
        X_raw.apply(lambda x: x.replace('<br>', '')).apply(lambda x: x.replace('<br', '')).apply(lambda x: x.replace('br>', ''))
        y_raw = reviews_df['rating']

        GOOD_RATING = 4

        #cleaning the target data
        y = y_raw>=GOOD_RATING

        #print(y)

        # preprocessing the corpus
        from spacy.lang.en import English
        self.parser = English()
        nltk.download('wordnet')
        from nltk.corpus import wordnet as wn
        self.wn = wn
        from nltk.stem.wordnet import WordNetLemmatizer

        nltk.download('stopwords')
        self.en_stop = set(nltk.corpus.stopwords.words('english'))

        import random
        text_data = []
        for line in X_raw:
            tokens = self.prepare_text_for_lda(line)
            if random.random() > -1:
                #print(tokens)
                text_data.append(tokens)

        dictionary = corpora.Dictionary(text_data)

        corpus = [dictionary.doc2bow(text) for text in text_data]

        import pickle
        pickle.dump(corpus, open('corpus.pkl', 'wb'))
        dictionary.save('dictionary.gensim')

        import gensim
        NUM_TOPICS = 13
        ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics = NUM_TOPICS, id2word=dictionary, passes=15)
        ldamodel.save('model5.gensim')
        topics = ldamodel.print_topics(num_words=15)
        for topic in topics:
            print(topic)

    def prepare_text_for_lda(self, text):
        tokens = self.tokenize(text)
        tokens = [token for token in tokens if len(token) > 4]
        tokens = [token for token in tokens if token not in self.en_stop]
        tokens = [self.get_lemma(token) for token in tokens]
        return tokens

    def tokenize(self, text):
        lda_tokens = []
        tokens = self.parser(text)
        for token in tokens:
            if token.orth_.isspace():
                continue
            elif token.like_url:
                lda_tokens.append('URL')
            elif token.orth_.startswith('@'):
                lda_tokens.append('SCREEN_NAME')
            else:
                lda_tokens.append(token.lower_)
        return lda_tokens

    def get_lemma2(self, word):
        return WordNetLemmatizer().lemmatize(word)

    def get_lemma(self, word):
        lemma = self.wn.morphy(word)
        if lemma is None:
            return word
        else:
            return lemma


from functools import cache
import nltk
import string
from nltk.tokenize import word_tokenize
from nltk.stem import PorterStemmer
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
import pymongo
import pandas as pd
from sklearn.linear_model import SGDClassifier
from sklearn.pipeline import Pipeline
import pickle
import datetime
import os
import glob
import Viradb

# TextPreprocessing
porter_stemmer = PorterStemmer()
wordnet_lemmatizer = WordNetLemmatizer()

def TextPreprocessing(text, method=False, Notokenize=True):
    # Punctuation Removal
    preproces_txt = text
    preproces_txt = "".join([i for i in preproces_txt if i not in string.punctuation + '0123456789'])
    # Lowering the text
    preproces_txt = preproces_txt.lower()
    # Tokenization
    preproces_txt = word_tokenize(preproces_txt)
    # Stop word removal
    stopwords = nltk.corpus.stopwords.words('english')
    preproces_txt = [i for i in preproces_txt if i not in stopwords]
    # remove words less than three letters
    if method == 's':
        # Stemming
        preproces_txt = [porter_stemmer.stem(word) for word in preproces_txt]
    elif method == 'l':
        # Lemmatization
        preproces_txt = [wordnet_lemmatizer.lemmatize(word) for word in preproces_txt]
    elif method == False:
        pass

    if Notokenize == True:
        preproces_txt = ' '.join(preproces_txt)
        preproces_txt = ' '.join(dict.fromkeys(preproces_txt.split()))

    return preproces_txt

class Cwe_Prediction():
    # data base
    db = Viradb.Viradb()
    Score = db.Score
    Docs_Content = db.Docs_Content
    CWE = db.CWE
    Brand = db.Brand
    Product = db.Product

    now = datetime.datetime.now()

    sgd = Pipeline([('vect', CountVectorizer()),
                    ('tfidf', TfidfTransformer()),
                    ('clf', SGDClassifier(loss='modified_huber', penalty='elasticnet', alpha=1e-3, random_state=42,
                                          max_iter=1000, tol=1e-5)),
                    ])
    path = os.getcwd()
    sav_files = glob.glob(os.path.join(path, "*.sav"))
    # save the model to disk
    filename = 'SGDClassifier_model_{}_{}.sav'.format(str(now.month), str(now.day))
    try:
        # load the model from disk
        sgd = pickle.load(open(filename, 'rb'))
    except:
        cwe_meta_data = {}
        cwe_id_name = {}
        cwe_obj = CWE.find({})
        for cwe in cwe_obj:
            cweid = cwe['cwe_id']
            try:
                cwe_title_latin = cwe['cwe_title_latin']
            except:
                cwe_title_latin = ''
            try:
                cwe_detail = cwe['cwe_detail']
            except:
                cwe_detail = ''
            cwe_detail = cwe_title_latin + cwe_detail
            cwe_meta_data[str(cwe['_id'])] = cwe_detail
            cwe_id_name[str(cwe['_id'])] = cweid
        # Discripton vis CWE
        Model_data = []
        for obj in Docs_Content.find({'cwe_id': {'$ne': None}}) :
            dis = obj['discriptons']
            dis = TextPreprocessing(dis)

            try:
                if len(obj['cwe_id']) >= 1:
                    for cwe in obj['cwe_id']:
                        Model_data.append([cwe_id_name[str(cwe)], dis + cwe_meta_data[str(cwe)]])
            except:
                pass
        Model_data = pd.DataFrame(Model_data, columns=['cwe', 'text'])

        try:
            sgd.fit(Model_data.text, Model_data.cwe)
            for f in sav_files:
                os.remove(f)
            pickle.dump(sgd, open(filename, 'wb'))
        except:
            sgd = pickle.load(open(sav_files[0], 'rb'))

    def predict_cwe(self, Discripton):
        Discripton = TextPreprocessing(Discripton)
        return self.sgd.predict([Discripton])

    def update_None_CWE(self, chekdays=7):
        # try:
            end = datetime.datetime.now()
            start = end - datetime.timedelta(days=chekdays)
            none_brands = self.Docs_Content.find({'$and': [{'cwe_id': None, 'system_Cwe_Prediction':None}, {'modified_date': {'$gte': start}}]})
            print(none_brands)
            for item in none_brands:
                prdcwe = self.predict_cwe(item['discriptons'])[0]
                prd_cwe_id = self.CWE.find_one({'cwe_id': prdcwe})
                print(prd_cwe_id)
                if prd_cwe_id == None:
                    prd_cwe_id = prdcwe
                else:
                    prd_cwe_id = prd_cwe_id['cwe_title_farsi']
                self.Docs_Content.update_one({'_id': item['_id']}, {"$set": {'system_Cwe_Prediction': prd_cwe_id}})
                print('system_CWE_Prediction for CVE ID :',item['cve_id'])
        # except:
            # print("jjj")
x=Cwe_Prediction()
x.update_None_CWE(120)


import pandas as pd

import plotly.graph_objs as go

"""
Cody Whitt
pkz325
CPSC 4530 Spring 2023
Assignment 2

For Dataset 3 - 6 Dimensions (technically did 7, 6 continuous quantitative and 1 ordinal)

parse and plot steps separated into separate functions.
"""

def get_quality_grade(raw_quality: int):
    """
    Helper function for reducing range of possible values for quality attribute
    """

    if raw_quality <= 4:  # 3, 4
        return 0.0

    if raw_quality <= 6:  # 5, 6
        return 0.5

    return 1.0         # 7, 8

def parse_data():
    """
    Parsing portion of the wine quality data set.

    Writes to parsed_data.
    """

    # CSV to Dataframe, basic check
    raw_df = pd.read_csv("raw_data/winequality-red.csv")
    print(raw_df.head())
    print(raw_df.info())

    # So no nulls, 12 attributes. We want quality + 6 others
    # Lets pick the 6 w/ the observed variation by comparing the coefficient of variation for each attribute
    abs_attr_diff = []
    for attr in raw_df.columns:
        sub_df = raw_df[attr]
        cf_var_v = sub_df.std() / sub_df.mean()
        abs_attr_diff.append([attr, cf_var_v, sub_df.min(), sub_df.max()])
    abs_attr_diff.sort(key=lambda x: x[1], reverse=True)
    for v in abs_attr_diff:
        print(v)

    keep_attributes = [v[0] for v in abs_attr_diff[:6]] + ["quality"]
    print("Keep Attributes - We Want 6 + Quality")
    print(keep_attributes)

    # Remove the unused attributes
    raw_df = raw_df[keep_attributes]
    print(raw_df.info())

    # Bucket quality to 3 grades from 6, where 1 is low, 2 is medium, 3 is high
    print("Bucket Quality From 6 to 3 Levels")
    print(raw_df.head())
    print(raw_df.tail())
    raw_df["quality"] = raw_df["quality"].apply(lambda x: get_quality_grade(x))
    print(raw_df.head())
    print(raw_df.tail())

    # Write this to .csv for PCA stuff
    raw_df.to_csv("parsed_data/wine_pca.csv", index=False)

    # Reduce Complexity Further By Taking Median Values For Each Quality Level
    final_df = [raw_df.columns.tolist()]
    for quality in raw_df["quality"].unique().tolist():
        sub_df = raw_df[raw_df["quality"] == quality]
        quality_row = []
        for attr in raw_df.columns.tolist():
            median_value = sub_df[attr].median()
            quality_row.append(median_value)
        final_df.append(quality_row)

    final_df = pd.DataFrame(data=final_df[1:], columns=final_df[0])
    print(final_df.head())

    # But let's also preserve the original full ranges for use in the plot
    range_df = [["attr_key", "attr_min", "attr_max"]]
    for attr in raw_df.columns:
        sub_df = raw_df[attr]
        min_v = sub_df.min()
        max_v = sub_df.max()
        range_df.append([attr, min_v, max_v])

    range_df = pd.DataFrame(data=range_df[1:], columns=range_df[0])
    print(range_df.head())

    # Write for use in plots
    final_df.to_csv("parsed_data/wine_quality_median_values.csv", index=False)
    range_df.to_csv("parsed_data/wine_quality_original_range.csv", index=False)

def plot_data():
    """
    Plotting portion for the wine quality dataset

    https://plotly.com/python/parallel-coordinates-plot/
    """

    value_df = pd.read_csv("parsed_data/wine_quality_median_values.csv")
    range_df = pd.read_csv("parsed_data/wine_quality_original_range.csv")

    # Put range_df into a dict for easy access below
    range_dict = {}
    for i, row in range_df.iterrows():
        range_dict[row["attr_key"]] = [row["attr_min"], row["attr_max"]]

    # Plot rather manually w/ go.Figure, this avoids a continuous color_scale display w/ express.
    fig = go.Figure(data=
                    go.Parcoords(
                        line=dict(color=value_df["quality"],
                                  colorscale=[[0.0, 'red'], [0.5, 'yellow'], [1.0, 'green']]),
                        dimensions=list([
                            dict(range=[range_dict['citric acid'][0], range_dict['citric acid'][1]],
                                 label='citric acid', values=value_df['citric acid']),
                            dict(range=[range_dict['total sulfur dioxide'][0], range_dict['total sulfur dioxide'][1]],
                                 label='total sulfur dioxide', values=value_df['total sulfur dioxide']),
                            dict(range=[range_dict['free sulfur dioxide'][0], range_dict['free sulfur dioxide'][1]],
                                 label='free sulfur dioxide', values=value_df['free sulfur dioxide']),
                            dict(range=[range_dict['residual sugar'][0], range_dict['residual sugar'][1]],
                                 label='residual sugar', values=value_df['residual sugar']),
                            dict(range=[range_dict['chlorides'][0], range_dict['chlorides'][1]],
                                 label='chlorides', values=value_df['chlorides']),
                            dict(range=[range_dict['volatile acidity'][0], range_dict['volatile acidity'][1]],
                                 label='volatile acidity', values=value_df['volatile acidity'])
                        ])
                    ))

    # Set Title and add a Color/Quality Annotation
    fig.update_layout(title="Median Physicochemical Property Values and Quality For Red Wine")
    fig.add_annotation(
        text='Color: Green indicates high quality, Yellow medium quality, and Red low quality',
        align='left',
        showarrow=False,
        xref='paper',
        yref='paper',
        x=1.01,
        y=1.07,
        bordercolor='black',
        borderwidth=1)

    fig.show()

def main():

    parse_data()

    plot_data()

if __name__ == "__main__":

    main()


class User():
    def __init__(self, firstname, lastname, gender):
        self.firstname = firstname
        self.lastname = lastname
        self.gender = gender

    def describe_user(self):
        print("Vorname: ", self.firstname)
        print("Nachname: ", self.lastname)
        print("Geschlecht: ", self.gender)

    def greet_user(self):
        if self.gender == "m":
            print("Sehr geehrter Herr ", self.lastname, " \nschön Sie zu sehen!")
        elif self.gender == "w":
            print("Sehr geehrte Frau ", self.lastname, " \nschön Sie zu sehen!")
        else:
            print("Sehr geehrtes Etwas, moin.")

u1 = User("Alexander", "Nazarenus", "m")
u1.describe_user()
u1.greet_user()
u2 = User("Pipo", "Müller", "w")
u2.describe_user()
u2.greet_user()
u3 = User("Josch", "Böhm", "d")
u3.describe_user()
u3.greet_user()


from fastapi import HTTPException
from sqlmodel import Session, col, select
from app.models.report import Report
from app.schemas.report import ReportCreate, ReportUpdate
from app.crud.base import CRUDBase

class CRUDReport(CRUDBase[Report, ReportCreate, ReportUpdate]):

    def get_by_id(self, *, session: Session, id: int) -> Report:
        return session.exec(select(Report).where(col(Report.id) == id)).first()

    def create(self, *, session: Session, obj_in: ReportCreate) -> Report:

        db_obj = Report(

            resource_id=obj_in.resource_id

        )

        session.add(db_obj)
        session.commit()
        session.refresh(db_obj)
        return db_obj

    def update(self, *, session: Session, id: int, obj_in: ReportUpdate) -> Report:
        db_obj = session.exec(select(Report).where(col(Report.id) == id)).first()
        if db_obj:
            obj_data = obj_in.dict(exclude_unset=True)
            for key, value in obj_data.items():
                setattr(db_obj, key, value)
            session.add(db_obj)
            session.commit()
            session.refresh(db_obj)
        return db_obj

    def remove(self, *, session: Session, id: int) -> Report:
        db_obj = session.exec(select(Report).where(col(Report.id) == id)).first()
        if not db_obj:
            raise HTTPException(status_code=404, detail="Report not found")
        session.delete(db_obj)
        session.commit()

        return db_obj

report = CRUDReport(Report)


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

import numpy as np
import vtk
import os

class Geometry(object):
    '''
    Klasse, die einen Koerper repraesentiert.
    '''

    def __init__(self):

        # Standardwerte fuer Lage (Koerper liegt im Ursprung, unverdreht)
        self._r = np.array([0,0,0])
        self._T = np.eye(3)

        # wir haben noch keine Geometriedaten!
        self.source = None

        # actor
        self.actor = vtk.vtkLODActor()

    def _createMapper(self):
        '''
        Hier wird der Mapper fuer self.source angelegt und mit dem Actor
        verbunden. Muss im Konstruktor der erbenden Klassen aufgerufen werden.
        '''

        # pruefen, ob Quelle vorhanden ist
        if self.source is None:
            raise ValueError('Keine Geometriequelle vorhanden')

        # Mapper anlegen und verbinden
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(self.source.GetOutputPort())

        self.actor.SetMapper(mapper)

    def setColor(self, color):
        '''
        Funktion zum setzen der Farbe, nur zur Vereinfachung
        '''
        self.actor.GetProperty().SetColor(color)

    def setOpacity(self, opac):
        '''
        Funktion zum setzen der Transparenz, nur zur Vereinfachung
        '''
        self.actor.GetProperty().SetOpacity(opac)

    def setPosition(self, r):
        '''
        Nur Position uebergeben und aktualisieren.
        '''
        self._r = r
        self.update()

    def setOrientation(self, T):
        '''
        Nur Orientierung uebergeben und aktualisieren
        '''
        self._T = T
        self.update()

    def setPositionAndOrientation(self, r, T):
        '''
        Position und Orientierung uebergeben und aktualisieren
        '''
        self._r = r
        self._T = T
        self.update()

    def update(self):
        '''
        Die Lage von 3D-Objekten in vtk wird mit einer sog. Poke-Matrix
        definiert. Sie ist eine 4x4-Matrix mit folgender Gestalt:

        [          ]
        [   T     r]
        [          ]
        [0  0  0  0]

        Soll die Lage eines Koerpers aktualisiert werden, muessen die Werte der
        Poke-Matrix geaendert werden. Das geschieht mit Hilfe dieser Funktion.
        '''

        # leere Matrix anlegen (ist eine 4x4 Einheitsmatrix)
        poke = vtk.vtkMatrix4x4()

        # Matrix elementweise befuellen
        for row in range(3):

            # Positionsvektor
            poke.SetElement(row,3, self._r[row])

            # Orientierung
            for col in range(3):
                poke.SetElement(row, col, self._T[row,col])

        # Matrix an Actor übergeben
        self.actor.PokeMatrix(poke)

    @property
    def position(self):
        return self._r

    @property
    def orientation(self):
        return self._T

class Cube(Geometry):
    '''
    Klasse fuer einen Quader
    '''

    def __init__(self, xLen,yLen,zLen):

        # Konstruktor der Basisklasse aufrufen
        Geometry.__init__(self)

        # Geometriequelle
        self.source = vtk.vtkCubeSource()
        self.source.SetXLength(xLen)
        self.source.SetYLength(yLen)
        self.source.SetZLength(zLen)

        self._createMapper()

class Sphere(Geometry):
    '''
    Klasse fuer eine Kugel
    '''

    def __init__(self, radius, thetaRes=20, phiRes=20):

        # Konstruktor der Basisklasse aufrufen
        Geometry.__init__(self)

        # Geometriequelle
        self.source = vtk.vtkSphereSource()
        self.source.SetRadius(radius)
        self.source.SetThetaResolution(thetaRes)
        self.source.SetPhiResolution(phiRes)

        self._createMapper()

class File(Geometry):
    '''
    Klasse fuer ein stl-File
    '''

    def __init__(self, path):

        # kleiner Test
        if not os.path.exists(path):
            raise IOError('Datei existiert nicht')

        # Konstruktor der Basisklasse aufrufen
        Geometry.__init__(self)

        # Geometriequelle
        self.source = vtk.vtkSTLReader()
        self.source.SetFileName(path)

        self._createMapper()


from attr import attr

class Student(object):
    def __init__(self, name) -> None:
        self.name = name

    def __str__(self) -> str:
        return 'Student object (name: %s)' % self.name

    __repr__ = __str__

print(Student('xinmu'))

class Fib(object):
    def __init__(self) -> None:
        self.a, self.b = 0, 1  # 初始化两个计数器

    def __iter__(self):
        return self

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > 100000:
            raise StopIteration()
        return self.a

    def __getitem__(self, n):
        if isinstance(n, int):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice):
            start = n.start
            stop = n.stop
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L

for n in Fib():
    print(n)

f = Fib()

print(f[1], f[5], f[99])

print(list(range(100)[5:10]))

print(f[:10])

class Student(object):

    def __init__(self):
        self.name = 'xinmu'

    def __getattribute__(self, attr):
        if attr == 'score':
            return 99

s = Student()
print(s.name)
print(s.score)

class Student(object):

    def __getattribute__(self, __name: str):
        if __name == 'age':
            return lambda: 25

s = Student()
print(s.age())

class Chain(object):

    def __init__(self, path='') -> None:
        self._path = path

    def __getattr__(self, __name: str):
        return Chain('%s/%s' % (self._path, __name))

    def __str__(self) -> str:
        return self._path

    __repr__ = __str__

print(Chain().status.user.timeline.list)

class Student(object):
    def __init__(self, name) -> None:
        self.name = name

    def __call__(self):
        print('my name is %s' % self.name)

s = Student('xinmu')

s()


import math
import time
from sklearn.feature_extraction.text import CountVectorizer as CVectorizer
from sklearn.metrics.pairwise import cosine_similarity

class CountVectorizer(object):

    def __init__(self, title_list, data): ##BOW-Bags of Words
        self.title_list=title_list  ##movie name list
        self.data=data              ##movie data list
        self.CVM=[]         ##List of vector for storing each titlename/movie word count vector

    ##get count vectorizer matrix
    def get_CVM(self):
        #creating bag of words
        count=CVectorizer()
        self.CVM=count.fit_transform(self.data).toarray()

    ##Similarity Matrix for all titlename- returns a 2-D matrix
    def get_AllSimMatrix(self): ##get similarity matrix
        sim=[]
        sim=cosine_similarity(self.CVM, self.CVM)
        return sim

    ##Find the index of titlename within title_list
    def find_Index(self, titlename):
        found=-1
        for i in range (len(self.title_list)):
            if(self.title_list[i]==titlename):
                found=i
                break
        return found

    ##Similarity Matrix for a specific titlename- returns a 1-D matrix
    def get_OneSimMatrix(self, titlename):
        index=self.find_Index(titlename) ##find titlename index
        if(index!=-1):
            sim=[]
            sim=cosine_similarity(self.CVM, self.CVM)
            return sim[index]
        else:
            print(titlename," doesnot exist in DB")
            return

###################################################################################

class MovieRS(object): ##Movie Recommendation System

    def __init__(self, movie_name_list, movie_data):   ## movie name and no of movies to recommend
        self.movie_name_list=movie_name_list
        self.movie_data=movie_data
        self.R=CountVectorizer(self.movie_name_list, self.movie_data)

        print("Count vectorizer Completed: ", time.time())
        self.R.get_CVM()
        print("Count vectorizer matrix Completed: ", time.time())

    ##Method for recommending movie
    def Recommend(self, movie_name, n):
        SIM_matrix=self.R.get_OneSimMatrix(movie_name)
        print("Done: ", time.time())

        movie_sim=list()     ##List Tuple
        for i in range (len(self.movie_name_list)):
            data=(self.movie_name_list[i], SIM_matrix[i])
            movie_sim.append(data)

        movie_sim.sort(key=lambda tup: tup[1])
        for i in range (n):
            print(movie_sim[len(movie_sim)-i-2])


from FuntionsForModule import INTexam
from FuntionsForModule import FunctionsFor4HW
import pathlib

print('Скрипт с кирпичной стеной')

profile_path = pathlib.Path('profile.txt')
profile_path.absolute()
with open(profile_path, 'r') as profile:
        user_name = profile.readline()

print('Привет,' + user_name + '!!!')

Number_of_rows_in_the_wall = (input('Введите количество рядов в стене:'))
Number_of_rows_in_the_wall = INTexam.exam(Number_of_rows_in_the_wall)
Number_of_rows_in_the_wall = list(range(1,Number_of_rows_in_the_wall+1))

wall, wall_print, bricks_length  = [], [], []
for number in Number_of_rows_in_the_wall:
    Number_of_bricks = (input('Введите количество кирпичей в ряду: '))
    Number_of_bricks = INTexam.exam(Number_of_bricks)
    Number_of_bricks_list = list(range(1, Number_of_bricks + 1))

    row_of_brick, row_of_brick_print, brick_whole_length =[], [], []
    for bricks in Number_of_bricks_list:
        brick_length = (input('Введите длинну кирпича: '))
        brick_length = INTexam.exam(brick_length)
        brick_whole_length.append(brick_length+2)
        brick = '|' + '_' * (brick_length) + '|'
        row_of_brick.append(brick_length)
        row_of_brick_print.append(brick)

    wall.append(row_of_brick)
    wall_print.append(row_of_brick_print)
    brick_whole_length = sum(brick_whole_length)
    bricks_length.append(brick_whole_length)

number_for_cycle = 0
for row_of_brick in wall:
    print (wall[number_for_cycle],)
    number_for_cycle += 1

distance_matrix = FunctionsFor4HW.get_distance_matrix(wall)
conclusion = FunctionsFor4HW.get_min_joints_distance(distance_matrix)

print(distance_matrix)
print (conclusion, 'Точка(-и), в которой(-рых) линия пересекает наименьшее количество кирпичей')

highest = (max(bricks_length) + 2)
resoult = int((highest - bricks_length[0]) / 2)
up_down_edge = '+' + '-' * (highest) + '+'
roof, down = '|' + ' ' * resoult + '_' * bricks_length[0]  + ' ' * resoult + '|', '|' + ' ' * highest + '|'

print(up_down_edge)
print(roof)

number_for_cycle4 = 0
for row_of_brick in wall_print:
    row1 = ''.join(row_of_brick)
    resoult = int((highest - bricks_length[number_for_cycle4]) / 2)
    left_edge, right_edge  = '|' + ' ' * (resoult - 1) , ' ' * (resoult - 1) + '|'
    print (left_edge, row1, right_edge)
    number_for_cycle4 += 1
print (down)
print (up_down_edge)


# from wsgiref.validate import validator
from rest_framework import serializers
from watchlist_app import models

# serializers.Serializer class :
# validators ..

# def validate_name_length(value):
#     if len(value) < 2:
#         raise serializers.ValidationError("Name length must not be short")

# class MovieSerializer(serializers.Serializer):
#     id = serializers.IntegerField(read_only=True)
#     name = serializers.CharField(validators=[validate_name_length])
#     description = serializers.CharField()
#     active = serializers.BooleanField()

#     def create(self, validated_data):
#         return Movie.objects.create(**validated_data)

#     def update(self, instance, validated_data):
#         instance.name = validated_data.get('name', instance.name)
#         instance.description = validated_data.get(
#             'description', instance.description)
#         instance.active = validated_data.get('active', instance.active)
#         instance.save()
#         return instance

#     # field level validation
#     # def validate_name(self, value):

#     #     if len(value) < 3:
#     #         raise serializers.ValidationError('name is too short!')
#     #     else:
#     #         return value

#     # object level validation
#     def validate(self, data):

#         if data['name'] == data['description']:
#             raise serializers.ValidationError(
#                 'name and description should not be the same!')
#         else:
#             return data

# -----------------------------------------------------------------------------------------
# serializers.ModelSerializer class :

class ReviewSerializer(serializers.ModelSerializer):

    review_user = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = models.Review
        exclude = ('watchlist',)
        #fields = "__all__"

class WatchListSerializer(serializers.ModelSerializer):

    # length_title = serializers.SerializerMethodField()
    #reviews = ReviewSerializer(many=True, read_only=True)
    platform = serializers.CharField(source='platform.name')

    class Meta:
        model = models. WatchList
        # fields = ['id', 'title', 'storyline', 'created']
        fields = "__all__"
        # exclude = ['active']  # access to all fields except active

    # def get_length_title(self, object):
    #     return len(object.title)

    # # field level validation
    # def validate_title(self, value):

    #     if len(value) < 3:
    #         raise serializers.ValidationError('title is too short!')
    #     else:
    #         return value

    # # object level validation
    # def validate(self, data):

    #     if data['title'] == data['storyline']:
    #         raise serializers.ValidationError(
    #             'title and storyline should not be the same!')
    #     else:
    #         return data

class StreamPlatformSerializer(serializers.ModelSerializer):

    # Nested relationships return all fields for a object
    watchlist = WatchListSerializer(many=True, read_only=True)
    # StringRelatedField return single field (name or title) of a object
    # watchlist = serializers.StringRelatedField(many=True)
    # PrimaryKeyRelatedField return pk field of a object
    # watchlist = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    # HyperlinkedRelatedField return hyper link field of a object
    # watchlist = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='movie-details')
    # SlugRelatedField return slug field of a object
    # watchlist = serializers.SlugRelatedField(many=True, read_only=True, slug_field='title')
    # HyperlinkedIdentityField return hyperlinked identity field of a object
    # watchlist = serializers.HyperlinkedIdentityField(view_name='movie-details')

    class Meta:
        model = models.StreamPlatform
        fields = "__all__"

# class StreamPlatformSerializer(serializers.HyperlinkedModelSerializer):

#     # Nested relationships return all fields for a object
#     watchlist = WatchListSerializer(many=True, read_only=True)

#     class Meta:
#         model = StreamPlatform
#         fields = "__all__"


'''FIZ COM FOR, AGORA TO TENTANDO COM WHILE '''
from time import sleep
from emoji import emojize

num1 = int(input('Digite o número o qual você quer saber o fatorial: '))
num = num1
res = 1

while not num == 1:
    res *= num
    print('{}'.format(num), end='x')
    num -= 1
    if num == 1:
        print('''1
A fatorial de {}! é >> {}'''.format(num1, res))

CURSO EM VÍDEO/Python Intermediário/C.E.V. Mundo 2/EX60/USANDO WHILE.py


import numpy as np
import pandas as pd

def binned_spiketrain(
    spiketrain: np.ndarray,
    fs: float,
    t_stop: float = None,
    t_start: float = None,
    as_df: bool = False,
):
    """
    Get event counts at regular time bins.

    Args:
        spiketrain: A numpy array of spiketimes in seconds
        fs: The sampling rate used to create time bins. The number of samples per second.
        t_start: The left edge of first bin
        t_stop: The right edge of final bin
        as_df: If true, returns reseults as a pandas DataFrame
    Returns:
        edges, counts
    """
    if isinstance(spiketrain, pd.core.series.Series):
        spiketrain = spiketrain.values
    if t_start is None:
        t_start = spiketrain[0]
    if t_stop is None:
        t_stop = spiketrain[-1]
    if not isinstance(spiketrain, np.ndarray):
        spiketrain = np.array(spiketrain)

    bins = np.arange(t_start, t_stop + (1 / fs), 1 / fs)
    values, edges = np.histogram(spiketrain, bins=bins)

    if as_df:
        df = pd.DataFrame({"time": edges[:-1], "spike_count": values})
        return df
    else:
        return edges[1:], values

def binned_spiketrain_bins_provided(spiketrain: np.ndarray, bins: np.ndarray):
    """
    Get event counts at specified time bins.

    Args:
        spiketrain: A numpy array of spiketimes in seconds
        bins: A numpy array of bin edges
    Returns:
        A numpy array of spike counts per bin
    """
    values, _ = np.histogram(spiketrain, bins=bins)
    return values

def bin_to_bool(binned_arr: np.ndarray):
    """
    Convert a binned array to a binary array: 1s for nonzero elements, 0s for zeros.

    Args:
        binned_arr: A numpy array of counts
    Returns:
        A numpy array of 1s and 0s
    """
    return np.where(binned_arr != 0, 1, 0)

def which_bin(
    spiketrain: np.ndarray,
    bin_edges: np.ndarray,
    before: float = None,
    allow_before: bool = False,
    max_latency: float = None,
    as_df: bool = False,
):
    """
    Get the corresponding bin for each spike in a spiketrain.

    Useful for splitting spiketrains into trials.

    Args:
        spiketrain: A numpy array of spiketimes
        bin_edges: A numpy array of bin edges
        before: The time window before each event to include in the alignment.
        allow_before: If False, spikes occuring before the first time are returned as NaN
        max_latency: If specified, spikes occuring this quantity after the maximum bin_edge
                     are returned as NaN
        as_df: Whether to returned the result as a pandas DataFrame.
    Returns:
        bin_idx, bin_values
    """
    if before is not None:
        idx = np.digitize(spiketrain, (bin_edges - before)) - 1
    else:
        idx = np.digitize(spiketrain, bin_edges) - 1

    idx_to_use = idx.tolist()
    bin_values = (bin_edges[idx_to_use]).astype(np.float)
    if not allow_before:
        nan_mask = idx < 0
        idx = idx.astype(np.float)
        bin_values[nan_mask] = np.nan
        idx[nan_mask] = np.nan
    if max_latency is not None:
        latency_to_max = spiketrain - np.max(bin_edges)
        idx[latency_to_max > max_latency] = np.nan
        bin_values[latency_to_max > max_latency] = np.nan
    if not as_df:
        return idx, bin_values
    else:
        return pd.DataFrame({"bin_idx": idx, "bin_values": bin_values})

def spike_count_around_event(
    spiketrain: np.ndarray, events: np.ndarray, binsize: float
):
    """
    Calculate the spike count around events.

    Args:
        spiketrain: A numpy array of spiketimes
        events: A numpy array of events
        binsize: The size of window in which to count spikes
    Returns:
        A numpy array of spike counts per each event
    """
    bins = np.repeat(events, 2).astype(np.float64)
    bins[1::2] += binsize
    spikecounts = binned_spiketrain_bins_provided(spiketrain, bins)
    return spikecounts[::2]


import pytest
from fixer import utils
from fixer.modes import show_service_account_info

class ServiceAccount:
    id = 1
    login = "test-service-account@boxdeveloper.com"

def test_show_service_account_info_if_error(capsys, mocker):

    mocker.patch('boxsdk.object.user.User.get', return_value=ServiceAccount())
    opt = {"<JWT-FILE>": "/foo/bar/no-exist-file.json"}
    with pytest.raises(SystemExit) as pytest_wrapped_e:
        show_service_account_info.main(opt)

    captured = capsys.readouterr()
    assert captured.err == "Error: [Errno 2] No such file or directory: '/foo/bar/no-exist-file.json'\n"

def test_show_service_account_info_if_success(capsys, mocker):

    mocker.patch('boxsdk.object.user.User.get', return_value=ServiceAccount())

    opt = {"<JWT-FILE>": "./test_assets/test-jwt-file.json"}
    show_service_account_info.main(opt)

    captured = capsys.readouterr()
    assert captured.out == (
        "ID: 1\n"
        "Login: test-service-account@boxdeveloper.com\n"
    )


from collections import UserList
from typing import Callable

import itertools
from utils import *
from grammar import Grammar

class PhSequence(UserList):
    def __init__(self, stuff):
        super().__init__(stuff)
    def __str__(self):
        return PhSequence._polynomial_to_str(self)
    def __repr__(self):
        return str(self)
    @staticmethod
    def _polynomial_to_str(item_list : list) -> str:
        string = ''
        for item in item_list:
            if isinstance(item, Polynomial) and (len(item) > 1 or isinstance(item[0], Polynomial)):
                string = string + '[' + PhSequence._polynomial_to_str(item.ordered_children) + ']' + item[Monomial.CATEGORY] + ' '
            else:
                string = string + item[Monomial.FORM] + '_' + item[Monomial.CATEGORY] + ' '
        return string.rstrip()

class PossibilityScorer():
    def __init__(self, score_fn = None):
        #self._score_fn = score_fn if score_fn else PossibilityScorer.default_heuristic
        if score_fn:
            self.score = score_fn
    def score(self, possibility) -> float:
        return float(-len(possibility))
    # @staticmethod
    # def default_heuristic(possibility) -> float:
    #     return float(-len(possibility))

class Possibility:
    id_count = 0
    # Edge = namedtuple('Edge', ['rule', 'possibility'])
    def __init__(self, item_list: PhSequence, index, heuristic_scorer: PossibilityScorer = PossibilityScorer(),
                 parent=None, rule=None):
        self.item_list = PhSequence(item_list)
        self.index = index
        self.possibilities = None
        self.parent = parent
        self.rule = rule
        self.depth = self.parent.depth + 1 if self.parent else 0
        self.heuristic_scorer = heuristic_scorer
        self.id = Possibility.id_count
        self.error_score = sum([i.error_score for i in self.item_list])
        self.score = heuristic_scorer.score(self) - self.error_score
        Possibility.id_count += 1
    def calculate_score(self):
        self.score = self.heuristic_scorer.score(self) - self.error_score
    def __eq__(self, other):
        if not isinstance(other, Possibility):
            return False
        # this is not pythonic
        if self.index != other.index:
            return False
        if len(self.item_list) != len(other.item_list):
            return False
        for i in self.item_list:
            if i not in other.item_list:
                return False
        return True
    def __getitem__(self, item):
        return self.item_list[item]
    def __len__(self):
        return len(self.item_list)
    def expand_possibilities(self, rule_list:list):
        self.possibilities = list()
        for rule in rule_list: # let's apply the rules
            # extract elements to apply rule to
            candidates = self.item_list[self.index:self.index + len(rule)]
            if len(candidates) != len(rule): # not enough candidates
                continue
            for i in range(0, len(candidates)): # add position info
                candidates[i]['pos'] = str(i)
            # it's a free-order language, do permutations
            for permutation in itertools.permutations(candidates):
                new_phrase:Polynomial = rule.apply(permutation)
                if not new_phrase: continue
                if new_phrase.error_score == float('inf'): # infinite error score! bad
                    continue # skip this possibility
                # let's add the possibility
                new_items = self.item_list.copy()
                del(new_items[self.index:self.index + len(rule)]) # remove the nodes
                new_items.insert(self.index, new_phrase)
                new_possibility = Possibility(PhSequence(new_items), self.index, self.heuristic_scorer, self, rule)
                self.possibilities.append(new_possibility)
        # add previous and next index possibilities, applying no rule
        # if self.index > 0:
        #     self.possibilities.append(Possibility(self.item_list.copy(), self.index - 1, self))
        if self.index < len(self.item_list) - 1:
            self.possibilities.append(Possibility(self.item_list.copy(), self.index + 1, self.heuristic_scorer, self, +1))
        if self.index > 0:
            self.possibilities.append(Possibility(self.item_list.copy(), self.index - 1, self.heuristic_scorer, self, -1))
        self.possibilities.reverse() # last one gets picked first. apply rules in order
    def __str__(self):
        string = str(self.item_list)
        string = string + ' score = ' + str(self.score) + ' index = ' + str(self.index)
        return str(self.id) + ' ' + string + \
               (' parent = ' + str(self.parent.id) + '\n' if self.parent else '')
    def __repr__(self):
        # return nodelist_string(self.item_list)
        return str(self)

    def traverse(self):
        yield self
        if self.possibilities:
            for child in self.possibilities:
                for n in child.traverse():
                    yield n

def default_halt_condition(p : Possibility) -> bool:
    return len(p.item_list) == 1

class Search:
    def __init__(self, item_list, grammar : Grammar, heuristic_scorer : PossibilityScorer =PossibilityScorer()):
        Possibility.id_count = 0
        self.grammar = grammar
        self.root = Possibility(item_list, 0, heuristic_scorer, None, None)
        self.dead_end_queue = []
        self.expandable_queue : list = [self.root]
        self.finished = []
        self.heuristic_scorer = heuristic_scorer
    def all_nodes(self) -> list:
        return self.dead_end_queue + self.expandable_queue + self.finished
    def change_scorer(self, heuristic_scorer : PossibilityScorer):
        self.heuristic_scorer = heuristic_scorer
        for p in self.all_nodes():
            p.heuristic_scorer = heuristic_scorer
            p.calculate_score()
    def expand(self, node:Possibility) -> Possibility:
        """Expands the best possibility """
        if not self.expandable_queue:
            return None
        self.expandable_queue.remove(node)  # move from expandable to dead-end,
        self.dead_end_queue.append(node)    # since we're going to expand all its possibilities
        node.expand_possibilities(self.grammar) # expand
        # remove possibilities that already appear
        node.possibilities = [p for p in node.possibilities
                              if p not in self.all_nodes()]
        self.expandable_queue = self.expandable_queue + node.possibilities # add new possibilities to queue
        self.expandable_queue.sort(key=lambda p: p.score) # sort queues
        self.dead_end_queue.sort(key=lambda p: p.score)
        return node

    def search(self, halt_condition : Callable[[Possibility], bool] = default_halt_condition):
        while self.expandable_queue:
            best = self.expandable_queue[-1]
            if halt_condition(best):
                self.expandable_queue.remove(best)
                self.finished.append(best)
                return best
            # best : Possibility = self.expand()
            if not self.expand(best): # should not be necessary
                continue
            # self.dead_end_queue.remove(best)
            # self.finished.append(best)
        return self.dead_end_queue[-1]

    def __str__(self):
        return 'Expandable\n' + str(self.expandable_queue) + '\n' #\
               #+ 'Dead-End\n' + str(self.dead_end_queue) + '\n'
    def __repr__(self):
        return str(self)

    def traverse(self):
        for n in self.root.traverse():
            yield n


import random

import pytest
from brownie.convert.datatypes import HexString
from brownie.network.state import Chain
from brownie.test import given, strategy
from tests.constants import START_TIME
from tests.helpers import active_currencies_to_list, get_portfolio_array, get_settlement_date

chain = Chain()

def generate_asset_array(num_assets):
    cashGroups = [(1, 7), (2, 7), (3, 7)]
    return get_portfolio_array(num_assets, cashGroups)

@pytest.mark.portfolio
class TestPortfolioHandler:
    @pytest.fixture(scope="module", autouse=True)
    def portfolioHandler(self, MockPortfolioHandler, accounts):
        handler = MockPortfolioHandler.deploy({"from": accounts[0]})
        chain.mine(1, timestamp=START_TIME)

        return handler

    @pytest.fixture(autouse=True)
    def isolation(self, fn_isolation):
        pass

    @given(num_assets=strategy("uint", min_value=0, max_value=6))
    # TODO: why is six the max value here
    def test_portfolio_sorting(self, portfolioHandler, accounts, num_assets):
        newAssets = generate_asset_array(num_assets)
        portfolioHandler.storeAssets(accounts[1], ([], newAssets, num_assets, 0))

        computedSort = tuple([p[0:3] for p in sorted(newAssets)])
        sortedArray = portfolioHandler.getAssetArray(accounts[1])
        assert computedSort == tuple([s[0:3] for s in sortedArray])

    def test_add_repeated_new_asset(self, portfolioHandler, accounts):
        state = portfolioHandler.buildPortfolioState(accounts[1], 0)
        state = portfolioHandler.addAsset(state, 1, 1000, 1, 100e8)
        state = portfolioHandler.addAsset(state, 1, 1000, 1, 100e8)
        assert len(state[1]) == 1
        assert state[1][0][3] == 200e8

    @given(num_assets=strategy("uint", min_value=0, max_value=7))
    def test_add_delete_assets(self, portfolioHandler, accounts, num_assets):
        assetArray = generate_asset_array(num_assets + 5)
        startingAssets = assetArray[0:num_assets]
        newAssets = assetArray[num_assets:]

        portfolioHandler.storeAssets(accounts[1], ([], startingAssets, len(startingAssets), 0))
        state = portfolioHandler.buildPortfolioState(accounts[1], 0)
        # build portfolio state returns a sorted list
        startingAssets = list(state[0])

        # deletes will always come before adds
        num_deletes = random.randint(0, len(startingAssets))
        delete_indexes = sorted(random.sample(range(0, len(startingAssets)), num_deletes))

        # settling will result in indexes being deleted in order
        for d in delete_indexes:
            state = portfolioHandler.deleteAsset(state, d)
            # Assert that asset has been marked as removed
            assert state[0][d][5] == 2
            assert state[-1] == len([x for x in state[0] if x[5] != 2])
            tmp = list(startingAssets[d])
            tmp[3] = 0  # mark notional as zero
            startingAssets[d] = tuple(tmp)

        # do 5 random add asset operations
        for i in range(0, 5):
            action = random.randint(0, 2)
            activeIndexes = [i for i, x in enumerate(state[0]) if x[5] != 2]
            if len(activeIndexes) == 0:
                action = 0

            if action == 0:
                # insert a new asset
                newAsset = newAssets[i]

                state = portfolioHandler.addAsset(
                    state,
                    newAsset[0],  # currency id
                    newAsset[1],  # maturity
                    newAsset[2],  # asset type
                    newAsset[3],  # notional
                )

                assert state[1][-1] == newAsset
                startingAssets.append(newAsset)

            elif action == 1:
                # update an asset
                index = random.sample(activeIndexes, 1)[0]
                asset = state[0][index]
                if asset[2] >= 2:
                    notional = random.randint(-asset[3], 1e18)
                else:
                    notional = random.randint(-1e18, 1e18)

                state = portfolioHandler.addAsset(
                    state,
                    asset[0],  # currency id
                    asset[1],  # maturity
                    asset[2],  # asset type
                    notional,
                )

                assert state[0][index][5] == 1
                assert state[0][index][3] == asset[3] + notional
                tmp = list(startingAssets[index])
                tmp[3] += notional
                startingAssets[index] = tuple(tmp)

            elif action == 2:
                # net off an asset
                index = random.sample(activeIndexes, 1)[0]
                asset = state[0][index]
                notional = asset[3] * -1

                state = portfolioHandler.addAsset(
                    state,
                    asset[0],  # currency id
                    asset[1],  # maturity
                    asset[2],  # asset type
                    notional,
                )

                assert state[0][index][5] == 1
                assert state[0][index][3] == asset[3] + notional
                tmp = list(startingAssets[index])
                tmp[3] = 0  # mark notional as zero
                startingAssets[index] = tuple(tmp)

        txn = portfolioHandler.storeAssets(accounts[1], state)
        (context) = txn.return_value
        finalStored = portfolioHandler.getAssetArray(accounts[1])
        # Filter out the active assets with zero notional from the computed list
        finalComputed = tuple(list(filter(lambda x: x[3] != 0, startingAssets)))

        assert context[2] == len(finalComputed)  # assert length is correct

        # assert nextSettleTime is correct
        if len(finalComputed) == 0:
            assert context[0] == 0
        else:
            assert context[0] == min([get_settlement_date(x, chain.time()) for x in finalComputed])

        # assert that hasDebt is correct
        if len(finalComputed) == 0:
            assert context[1] == "0x00"
        else:
            hasDebt = (min([x[3] for x in finalComputed])) < 0
            if hasDebt:
                assert context[1] != "0x00"
            else:
                assert context[1] == "0x00"

        # assert that active currencies has all the currencies
        if len(finalComputed) == 0:
            assert context[4] == HexString("0x00", "bytes18")
        else:
            activeCurrencyList = list(
                filter(lambda x: x != 0, sorted(active_currencies_to_list(context[4])))
            )
            currencies = list(sorted(set([(x[0], True, False) for x in finalComputed])))
            assert activeCurrencyList == currencies

        assert sorted([x[0:4] for x in finalStored]) == sorted([(x[0:4]) for x in finalComputed])


# -*- coding: utf-8 -*-
# __author__:YZY
# 2020/12/8 13:38
import os
import csv
import json

def create_csv(csv_path):
    heads = ['filename', 'file_size', 'file_attributes', 'region_count', 'region_id', 'region_shape_attributes',
             'region_attributes']
    with open(csv_path, 'w', newline='') as f:
        csv_writer = csv.writer(f)
        csv_writer.writerow(heads)

def write_csv(image_path, bbox, csv_path):
    image_size = os.path.getsize(image_path)
    image_name = image_path.split('\\')[-1]
    box = bbox[0]
    if box == 0:
        print('------no box------')
    else:
        x = box[0]
        y = box[1]
        w = box[2] - box[0]
        h = box[3] - box[1]
        box_dict = {"name": "rect", "x": int(x), "y": int(y), "width": int(w), "height": int(h)}

        values = [image_name, image_size, "{}", 1, 0, json.dumps(box_dict), "{}"]

        with open(csv_path, 'a+', newline='') as f:
            csv_writer = csv.writer(f)
            csv_writer.writerow(values)
        print('------finish write_csv------')


from time import time
from random import randrange

def comparison_count_sort(array: list):
	sorted: list = array.copy()
	length: int = len(array)
	count: list = []

	for i in range(0, length):
		count.append(0)

	for i in range(0, length - 1):
		for j in range(i + 1, length):
			if array[i] < array[j]:
				count[j] = count[j] + 1
			else:
				count[i] = count[i] + 1

	for i in range(0, length):
		sorted[count[i]] = array[i]

	return sorted

def distribution_count_sort(l: int, u: int, array: list):
	count: list = []
	length: int = len(array)
	sorted: list = array.copy()

	for i in range(0, u - l + 1):
		count.append(0)

	for i in range(0, length):
		count[array[i] - l] = count[array[i] - l] + 1

	for i in range(1, u - l + 1):
		count[i] = count[i - 1] + count[i]

	for i in range(length - 1, 0 - 1, -1):
		j = array[i] - l
		sorted[count[j] - 1] = array[i]
		count[j] = count[j] - 1

	return sorted

def generate_testing_array(l: int, u: int, length: int):
	array: list = []
	for i in range(0, length):
		array.append(randrange(l, u))

	return array

l: int = 0
u: int = 10
size: int = 100000
array: list = generate_testing_array(l, u, size)

print("[+] Sorting using comparison count sort...")
comparison_start_time: float = time()
print(comparison_count_sort(array))
comparison_end_time: float = time()
comparison_count_sort_execution_time: float = comparison_end_time - comparison_start_time
print("comparison execution time: ", comparison_count_sort_execution_time)

print("[+] Sorting using distribution count sort...")
distribution_start_time: float = time()
print(distribution_count_sort(l, u, array))
distribution_end_time: float = time()
distribution_count_sort_execution_time: float = distribution_end_time - distribution_start_time

print("comparison execution time: ", comparison_count_sort_execution_time)
print("distribution execution time: ", distribution_count_sort_execution_time)


from PIL import Image, ImageDraw
im = Image.open("output.png")
d = ImageDraw.Draw(im)

top = (1594, 71)
left = (200, 225)
right = (300, 325)

line_color = (0, 0, 255)

d.line([top, left, right, top], fill=line_color, width=2)

im.save("drawn.png")