import os
import re
import urllib.request
import requests
import time
import sys
from requests_html import HTML
from bs4 import BeautifulSoup

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':RC4-SHA'

overall_user_push={}
overall_user_boo={}
overall_image_url=[]
overall_keyword_image_url=[]
def fetch(url):
    time.sleep(0.4)
    response=requests.get(url=url,cookies={'over18':'1'})
    if response.status_code != 200:  #回傳200代表正常
        print('Invalid url:', response.url)
        return None
    else:
        return response

def article(content,counter):
    output_all_file = open("all_articles.txt", "a",encoding='utf8')
    output_popular_file = open("all_popular.txt", "a",encoding='utf8')

    fixed='https://www.ptt.cc'
    end_flag=0
    soup=BeautifulSoup(content,'html.parser')
    all_page_elements=soup.find('div','btn-group btn-group-paging')
    all_meta_data_divs=soup.find_all('div','r-ent')
    post_page=all_page_elements.find_all('a')[2]['href']

    for meta_data in all_meta_data_divs:
        if meta_data.find('a'):
            push_information=meta_data.find('div','nrec').string
            hyper_link=fixed+meta_data.find('a')['href']
            title=meta_data.find('a').string
            dates=int(meta_data.find("div", {"class": "date"}).string.strip().replace('/',''))
            if title!=None and len(title)>3:
                classification=title[1:3]
                title=title.replace(',',' ')
            if hyper_link!=None and title!=None and dates!=None and len(title)>3 and classification!=None and classification!="公告":
                if counter==0:
                    if dates<800:
                        output_all_file.write(str(dates)+","+str(title)+","+str(hyper_link)+"\n")
                        if push_information!=None and push_information=="爆":
                            output_popular_file.write(str(dates)+","+str(title)+","+str(hyper_link)+"\n")
                elif counter>100 and dates<105:
                    end_flag=1
                    return end_flag,None
                else:
                    output_all_file.write(str(dates)+","+str(title)+","+str(hyper_link)+"\n")
                    if push_information!=None and push_information=="爆":
                        output_popular_file.write(str(dates)+","+str(title)+","+str(hyper_link)+"\n")

    output_all_file.close()
    return end_flag,fixed+post_page
def like_boo_count(content):
    likes=0
    boos=0
    soup=BeautifulSoup(content,'html.parser')
    all_meta_data_divs=soup.find_all('div','push')
    for meta_data in all_meta_data_divs:
        if meta_data.find('span', 'push-tag') and meta_data.find('span','push-userid'):
            information = meta_data.find('span', 'push-tag').string.strip(' \t\n\r')
            user_name=meta_data.find('span','push-userid').string.strip(' \t\n\r')
            current_item=[]
            if information=="推":
                likes+=1
                if user_name not in overall_user_push:
                    overall_user_push[user_name]=1
                else:
                    overall_user_push[user_name]+=1

            elif information=="噓":
                boos+=1
                current_item.append(user_name)
                current_item.append("boo")
                if user_name not in overall_user_boo:
                    overall_user_boo[user_name]=1
                else:
                    overall_user_boo[user_name]+=1
    return likes,boos
def get_image_url(content):
    pattern=re.compile("^(http).*((\.jpg)|(\.jpeg)|(\.png)|(\.gif))$")

    soup=BeautifulSoup(content,'html.parser')
    all_meta_data_divs=soup.find_all('a')
    for meta_data in all_meta_data_divs:
        current_url=meta_data.string
        if current_url!=None:
            match_result=pattern.match(current_url)

            if match_result:
                overall_image_url.append(current_url)
def get_keyword_image_url(content):
    pattern=re.compile("^(http).*((\.jpg)|(\.jpeg)|(\.png)|(\.gif))$")

    soup=BeautifulSoup(content,'html.parser')
    all_meta_data_divs=soup.find_all('a')
    for meta_data in all_meta_data_divs:
        current_url=meta_data.string
        if current_url!=None:
            match_result=pattern.match(current_url)

            if match_result:
                overall_keyword_image_url.append(current_url)
def check_keyword(content,keyword):
    pattern=re.compile("^[ ]*(<){1}")
    overall_results=[]
    find_start_result=content.find("作者")
    find_end_result=content.find("<span class=\"f2\">")
    if find_start_result==-1 or find_end_result==-1:
        return False
    total_string=content[find_start_result:find_end_result]
    soup=BeautifulSoup(total_string,'html.parser')
    total_result=soup.prettify()
    overall_strings=total_result.split('\n')
    for current_string in overall_strings:
        match_result=pattern.match(current_string)
        if not match_result:
            overall_results.append(current_string)

    for current_result in overall_results:#剩這裡
        if current_result.find(keyword)!=-1:
            #print(current_result,keyword)
            return True
    #print(total_string)
    #print(find_start_result,find_end_result)

    return False
if __name__=='__main__':
    if len(sys.argv)<2:
        print("No command line input argument found, please look at the readme file.")
    choice=sys.argv[1]
    if choice=="crawl":
        tStart = time.time()
        if os.path.exists("all_articles.txt"):
            os.remove("all_articles.txt")
        if os.path.exists("all_popular.txt"):
            os.remove("all_popular.txt")
        end_flag=0
        current_url='https://www.ptt.cc/bbs/Beauty/index3150.html' #3150至今
        current_response=fetch(current_url)
        counter=0
        if current_response!=None:
            contents=current_response.text
            if contents!=None:
                end_flag,post_page=article(contents,counter)
                counter+=1
                while post_page!=None and end_flag==0:
                    current_response=fetch(post_page)
                    contents=current_response.text
                    end_flag,post_page=article(contents,counter)
                    counter+=1
        tEnd=time.time()
        print(tEnd-tStart)
    elif choice=="push":
        if len(sys.argv)<4:
            print("Too less command line input arguments! Start_date and end_date are required.")
        start_date=int(sys.argv[2])
        end_date=int(sys.argv[3])

        tStart = time.time()

        like_counter=0
        boo_counter=0
        file_name="push["+str(start_date)+"-"+str(end_date)+"].txt"

        if os.path.exists(file_name):
            os.remove(file_name)

        output_result_file=open(file_name,"a",encoding='utf8')

        with open("all_articles.txt",encoding='utf8') as f:
            content=f.readlines()
        overall_date=[]
        overall_title=[]
        overall_url=[]

        flag_start=0
        flag_end=0
        start_index=-1
        end_index=-1

        for i in range(0,len(content)):
            temp_line=content[i].split(',')
            overall_date.append(temp_line[0])
            overall_title.append(temp_line[1])
            overall_url.append(temp_line[2].replace('\n',''))

        for i in range(0,len(content)):
            if flag_start==0 and int(overall_date[i])>=start_date:
                start_index=i
                flag_start=1
            if int(overall_date[i])==end_date:
                end_index=i
            if flag_end==0 and end_index==-1 and int(overall_date[i])>end_date:
                end_index=i-1
                flag_end=1

        for i in range(start_index,end_index+1):
            response=fetch(overall_url[i])
            if response!=None:
                article_content=response.text
                likes,boos=like_boo_count(article_content)
                like_counter+=likes
                boo_counter+=boos

        overall_user_push=sorted(overall_user_push.items(), key=lambda kv: kv[0])
        overall_user_boo=sorted(overall_user_boo.items(), key=lambda kv: kv[0])
        overall_user_push=sorted(overall_user_push, key=lambda kv: kv[1],reverse=True)
        overall_user_boo=sorted(overall_user_boo, key=lambda kv: kv[1],reverse=True)

        output_result_file.write("all like: "+str(like_counter)+"\n")
        output_result_file.write("all boo: "+str(boo_counter)+"\n")

        for i in range(0,10):
            output_result_file.write("like #"+str(i+1)+": "+str(overall_user_push[i][0])+" "+str(overall_user_push[i][1])+"\n")

        for i in range(0,10):
            output_result_file.write("boo #"+str(i+1)+": "+str(overall_user_boo[i][0])+" "+str(overall_user_boo[i][1])+"\n")

        output_result_file.close()
        tEnd=time.time()
        print(tEnd-tStart)
    elif choice=="popular":
        if len(sys.argv)<4:
            print("Too less command line input arguments! Start_date and end_date are required.")
        start_date=int(sys.argv[2])
        end_date=int(sys.argv[3])

        tStart = time.time()
        popular_counter=0

        file_name="popular["+str(start_date)+"-"+str(end_date)+"].txt"

        if os.path.exists(file_name):
            os.remove(file_name)

        output_result_file=open(file_name,"a",encoding='utf8')

        with open("all_popular.txt",encoding='utf8') as f:
            content=f.readlines()

        overall_date=[]
        overall_title=[]
        overall_url=[]

        flag_start=0
        flag_end=0
        start_index=-1
        end_index=-1

        for i in range(0,len(content)):
            temp_line=content[i].split(',')
            overall_date.append(temp_line[0])
            overall_title.append(temp_line[1])
            overall_url.append(temp_line[2].replace('\n',''))

        for i in range(0,len(content)):
            if flag_start==0 and int(overall_date[i])>=start_date:
                start_index=i
                flag_start=1
            if int(overall_date[i])==end_date:
                end_index=i
            if flag_end==0 and end_index==-1 and int(overall_date[i])>end_date:
                end_index=i-1
                flag_end=1

        popular_counter=end_index-start_index+1

        for i in range(start_index,end_index+1):
            response=fetch(overall_url[i])
            if response!=None:
                article_content=response.text
                get_image_url(article_content)

        output_result_file.write("number of popular articles: "+str(popular_counter)+"\n")
        for i in range(0,len(overall_image_url)):
            output_result_file.write(overall_image_url[i]+"\n")
        output_result_file.close()
        tEnd=time.time()
        print(tEnd-tStart)
    elif choice=="keyword":
        if len(sys.argv)<5:
            print("Too less command line input arguments! Keyword, start_date and end_date are required.")
        keyword=sys.argv[2]
        start_date=int(sys.argv[3])
        end_date=int(sys.argv[4])

        keyword="正妹"
        start_date=505
        end_date=1101

        tStart = time.time()

        file_name="keyword("+keyword+")["+str(start_date)+"-"+str(end_date)+"].txt"

        if os.path.exists(file_name):
            os.remove(file_name)

        output_result_file=open(file_name,"a",encoding='utf8')

        with open("all_articles.txt",encoding='utf8') as f:
            content=f.readlines()

        overall_date=[]
        overall_title=[]
        overall_url=[]

        flag_start=0
        flag_end=0
        start_index=-1
        end_index=-1

        for i in range(0,len(content)):
            temp_line=content[i].split(',')
            overall_date.append(temp_line[0])
            overall_title.append(temp_line[1])
            overall_url.append(temp_line[2].replace('\n',''))

        for i in range(0,len(content)):
            if flag_start==0 and int(overall_date[i])>=start_date:
                start_index=i
                flag_start=1
            if int(overall_date[i])==end_date:
                end_index=i
            if flag_end==0 and end_index==-1 and int(overall_date[i])>end_date:
                end_index=i-1
                flag_end=1

        for i in range(start_index,end_index+1):
            response=fetch(overall_url[i])
            if response!=None:
                article_content=response.text

                find_keyword=check_keyword(article_content,keyword)
                if find_keyword:
                    get_keyword_image_url(article_content)

        for i in range(0,len(overall_keyword_image_url)):
            output_result_file.write(overall_keyword_image_url[i]+"\n")
        output_result_file.close()
        tEnd=time.time()
        print(tEnd-tStart)


import os
import logging
from logging.handlers import TimedRotatingFileHandler

def mkdir(path):
    folder = os.path.exists(path)

    if not folder:
        os.makedirs(path)

def get_logger():
    mkdir("./app_log")
    log = logging.getLogger("logger.log")
    if not log.handlers:
        file_hdlr = TimedRotatingFileHandler(filename="./app_log/logger.log", when="D", interval=10, backupCount=2)
        file_hdlr.setLevel(logging.INFO)
        stream_hdlr = logging.StreamHandler()
        # stream_hdlr.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        file_hdlr.setFormatter(formatter)
        # stream_hdlr.setFormatter(formatter)
        log.addHandler(file_hdlr)
        # log.addHandler(stream_hdlr)
        logging.basicConfig(level=logging.INFO)
    return log


from flask import Flask
from threading import Thread
import datetime as dtime
import pytz

time_start_old = dtime.datetime.now()
time_start = time_start_old.strftime("%d.%m.%Y %H:%M:%S")

app = Flask("app")

@app.route("/")
def main():
	time = dtime.datetime.now(tz=pytz.timezone("Europe/Moscow"))
	time = time.strftime("%d.%m.%Y %H:%M:%S")
	output = f"Start: {time_start} Now: {time}"
	return output

def run():
	app.run(host="0.0.0.0", port=8080)

def keep():
	serv = Thread(target=run)
	serv.start()


from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .models import *
from .forms import *
from django.conf import settings
from django.shortcuts import render, get_object_or_404
from django.shortcuts import redirect
from django.db.models import Sum
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import CustomerSerializer
from decimal import *
from django.http import HttpResponse, HttpResponseNotFound
from django.views.generic import View
from django.contrib.auth.models import User
from django.template.loader import get_template
from .fusioncharts import FusionCharts
from portfolio.utils import render_to_pdf
# email
from django.core.files.storage import FileSystemStorage
from django.core.mail import send_mail
from django.core.mail import EmailMessage

now = timezone.now()

def home(request):
    return render(request, 'portfolio/home.html',
                  {'portfolio': home})

def register(request):
    print("entered into register view method")
    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            form.save()
            return render(request,
                          'registration/registerdone.html',
                          {'form': form})
    else:
        form = RegisterForm()
    return render(request, "registration/register.html", {"form": form})

@login_required
def customer_list(request):
    customer = Customer.objects.filter(created_date__lte=timezone.now())
    return render(request, 'portfolio/customer_list.html', {'customers': customer})

@login_required
def customer_edit(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    if request.method == "POST":
        # update
        form = CustomerForm(request.POST, instance=customer)
        if form.is_valid():
            customer = form.save(commit=False)
            customer.updated_date = timezone.now()
            customer.save()
            customer = Customer.objects.filter(created_date__lte=timezone.now())
            return render(request, 'portfolio/customer_list.html', {'customers': customer})
    else:
        # edit
        form = CustomerForm(instance=customer)
    return render(request, 'portfolio/customer_edit.html', {'form': form})

@login_required
def customer_delete(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    customer.delete()
    return redirect('portfolio:customer_list')

@login_required
def stock_list(request):
    stocks = Stock.objects.filter(purchase_date__lte=timezone.now())
    return render(request, 'portfolio/stock_list.html', {'stocks': stocks})

@login_required
def stock_new(request):
    if request.method == "POST":
        form = StockForm(request.POST)
        if form.is_valid():
            stock = form.save(commit=False)
            stock.created_date = timezone.now()
            stock.save()
            stocks = Stock.objects.filter(purchase_date__lte=timezone.now())
            return render(request, 'portfolio/stock_list.html',
                          {'stocks': stocks})
    else:
        form = StockForm()
        # print("Else")
    return render(request, 'portfolio/stock_new.html', {'form': form})

@login_required
def stock_edit(request, pk):
    stock = get_object_or_404(Stock, pk=pk)
    if request.method == "POST":
        form = StockForm(request.POST, instance=stock)
        if form.is_valid():
            stock = form.save()
            # stock.customer = stock.id
            stock.updated_date = timezone.now()
            stock.save()
            stocks = Stock.objects.filter(purchase_date__lte=timezone.now())
            return render(request, 'portfolio/stock_list.html', {'stocks': stocks})
    else:
        # print("else")
        form = StockForm(instance=stock)
    return render(request, 'portfolio/stock_edit.html', {'form': form})

@login_required
def stock_delete(request, pk):
    stock = get_object_or_404(Stock, pk=pk)
    stock.delete()
    return redirect('portfolio:stock_list')

@login_required
def investment_list(request):
    investments = Investment.objects.filter(recent_date__lte=timezone.now())
    return render(request, 'portfolio/investment_list.html', {'investments': investments})

@login_required
def investment_new(request):
    if request.method == "POST":
        form = InvestmentForm(request.POST)
        if form.is_valid():
            investment = form.save(commit=False)
            investment.created_date = timezone.now()
            investment.save()
            investments = Investment.objects.filter(recent_date__lte=timezone.now())
            return render(request, 'portfolio/investment_list.html',
                          {'investments': investments})
    else:
        form = InvestmentForm()
        # print("Else")
    return render(request, 'portfolio/investment_new.html', {'form': form})

@login_required
def investment_edit(request, pk):
    investment = get_object_or_404(Investment, pk=pk)
    if request.method == "POST":
        form = InvestmentForm(request.POST, instance=investment)
        if form.is_valid():
            investment = form.save()
            # investment.customer = investment.id
            investment.updated_date = timezone.now()
            investment.save()
            investments = Investment.objects.filter(recent_date__lte=timezone.now())
            return render(request, 'portfolio/investment_list.html', {'investments': investments})
    else:
        # print("else")
        form = InvestmentForm(instance=investment)
    return render(request, 'portfolio/investment_edit.html', {'form': form})

@login_required
def investment_delete(request, pk):
    investment = get_object_or_404(Investment, pk=pk)
    investment.delete()
    return redirect('portfolio:investment_list')

@login_required
def portfolio(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    customers = Customer.objects.filter(created_date__lte=timezone.now())
    investments = Investment.objects.filter(customer=pk)
    stocks = Stock.objects.filter(customer=pk)

    sum_recent_value = Investment.objects.filter(customer=pk).aggregate(Sum('recent_value'))
    # print("sum_recent_value: " + str(sum_recent_value))

    sum_acquired_value = Investment.objects.filter(customer=pk).aggregate(Sum('acquired_value'))
    # print("sum_acquired_value: " + str(sum_acquired_value))

    # overall_investment_results = sum_recent_value - sum_acquired_value
    overall_investment_results = sum_recent_value['recent_value__sum'] - sum_acquired_value['acquired_value__sum']
    # overall_investment_results = Decimal(sum_recent_value['recent_value__sum']) - Decimal(sum_acquired_value['acquired_value__sum'])
    # print(" overall_investment_results:" + str(overall_investment_results))

    # Initialize the value of the stocks
    sum_current_stocks_value = 0
    sum_of_initial_stock_value = 0

    # Loop through each stock and add the value to the total
    for stock in stocks:
        sum_current_stocks_value += stock.current_stock_value()
        # print(type((stock.current_stock_value())))
        sum_of_initial_stock_value += stock.initial_stock_value()
        # print(type(int(stock.initial_stock_value())))

    overall_stocks_results = Decimal(sum_current_stocks_value) - Decimal(sum_of_initial_stock_value)
    # print(overall_stocks_results)

    return render(request, 'portfolio/customer_portfolio.html', {'customers': customer,
                                                                 'investments': investments,
                                                                 'stocks': stocks,
                                                                 'sum_acquired_value': sum_acquired_value[
                                                                     'acquired_value__sum'],
                                                                 'sum_recent_value': sum_recent_value[
                                                                     'recent_value__sum'],
                                                                 'sum_current_stocks_value': sum_current_stocks_value,
                                                                 'sum_of_initial_stock_value': sum_of_initial_stock_value,
                                                                 'overall_investment_results': overall_investment_results,
                                                                 'overall_stocks_results': overall_stocks_results, })

# List at the end of the views.py
# Lists all customers
class CustomerList(APIView):
    def get(self, request):
        customers_json = Customer.objects.all()
        serializer = CustomerSerializer(customers_json, many=True)
        return Response(serializer.data)

@login_required()
def portfolio_pdf(request, pk):
    template = get_template('portfolio/customer_portfolio_pdf.html')
    customer = get_object_or_404(Customer, pk=pk)
    customers = Customer.objects.filter(created_date__lte=timezone.now())
    investments = Investment.objects.filter(customer=pk)
    stocks = Stock.objects.filter(customer=pk)

    sum_recent_value = Investment.objects.filter(customer=pk).aggregate(Sum('recent_value'))
    print("sum_recent_value: " + str(sum_recent_value))
    sum_acquired_value = Investment.objects.filter(customer=pk).aggregate(Sum('acquired_value'))
    print("sum_acquired_value: " + str(sum_acquired_value))
    overall_investment_results = sum_recent_value['recent_value__sum'] - sum_acquired_value['acquired_value__sum']
    print(" overall_investment_results:" + str(overall_investment_results))
    # Initialize the value of the stocks
    sum_current_stocks_value = 0
    sum_of_initial_stock_value = 0

    # Loop through each stock and add the value to the total
    for stock in stocks:
        sum_current_stocks_value += stock.current_stock_value()
        print(type((stock.current_stock_value())))
        print("sum_current_stocks_value " + str(sum_current_stocks_value))
        sum_of_initial_stock_value += stock.initial_stock_value()
        print(type(int(stock.initial_stock_value())))
        print("sum_of_initial_stock_value " + str(sum_of_initial_stock_value))

        overall_stocks_results = float(sum_current_stocks_value) - float(sum_of_initial_stock_value)
        print("overall_stocks_results" + str(overall_stocks_results))
        context = {'customers': customer,
                   'investments': investments,
                   'stocks': stocks,
                   'sum_acquired_value': sum_acquired_value['acquired_value__sum'],
                   'sum_recent_value': sum_recent_value['recent_value__sum'],
                   'sum_current_stocks_value': sum_current_stocks_value,
                   'sum_of_initial_stock_value': sum_of_initial_stock_value,
                   'overall_investment_results': overall_investment_results,
                   'overall_stocks_results': overall_stocks_results,
                   }
        html = template.render(context)
        pdf = render_to_pdf('portfolio/customer_portfolio_pdf.html', context)
        if pdf:
            response = HttpResponse(pdf, content_type='application/pdf')
            filename = 'Portfolio_' + str(customer.name) + '.pdf'
            content = "inline; filename='%s'" % filename
            download = request.GET.get("download")
            if download:
                content = "attachment; filename='%s'" % filename
                response['Content-Disposition'] = content
            return response
        return HttpResponseNotFound("not found")

@login_required
def generate_portfolio_pdf(request, pk, context):
    customer = get_object_or_404(Customer, pk=pk)
    template = get_template('portfolio/customer_portfolio_pdf.html')

    html = template.render(context)
    pdf = render_to_pdf('portfolio/customer_portfolio_pdf.html', context)
    if pdf:
        response = HttpResponse(pdf, content_type='application/pdf')
        response['Content-Disposition'] = 'filename= "Portfolio_{}.pdf"'.format(customer.name)
        # return response
        # return HttpResponse(pdf, content_type='application/octet-stream')
        return pdf
    return HttpResponse("Not Found")

def email(request, pk):
    customer = get_object_or_404(Customer, pk=pk)
    print(customer)
    if request.method == "POST":
        form = EmailForm(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.published_date = timezone.now()
            post.save()
            email = request.POST.get('email')
            subject = request.POST.get('subject')
            message = request.POST.get('message')
            document = request.FILES.get('document')
            email_from = 'admin@efs.com'
            recipient_list = [email]
            email = EmailMessage(subject, message, email_from, recipient_list)
            base_dir = '/Users/rajeshkumarpanigrahi/Downloads/'
            email.attach_file('/Users/rajeshkumarpanigrahi/Downloads/' + str(document))
            email.send()
            return render(request, 'portfolio/sent.html')
    else:
        form = EmailForm()

    return render(request, 'portfolio/email.html', {'form': form})

def summary(request, pk):
    investments = Investment.objects.filter(customer=pk)
    stocks = Stock.objects.filter(customer=pk)
    customers = get_object_or_404(Customer, pk=pk)
    dataSource = {}
    dataSource['chart'] = {
        "caption": "Stock Details",
        "subCaption": "EFS",
        "xAxisName": "Stock",
        "yAxisName": "Value (In USD)",
        "numberPrefix": "$",
        "theme": "zune"
    }

    # The data for the chart should be in an array where each element of the array is a JSON object
    # having the `label` and `value` as key value pair.
    dataSource['categories'] = []
    categories = {}
    categories['category'] = []

    for stock_name in stocks:
        category = {}
        category['label'] = stock_name.name
        print(category)
        categories['category'].append(category)

    dataSource['categories'].append(categories)
    dataSource['dataset'] = []
    seriesname = {}
    seriesname['seriesname'] = 'Initial value'
    seriesname['data'] = []
    for key in stocks:
        data = {}
        # data['label'] = key.name
        data['value'] = float(key.initial_stock_value())
        seriesname['data'].append(data)

    dataSource['dataset'].append(seriesname)

    seriesname_1 = {}
    seriesname_1['seriesname'] = 'Current value'
    seriesname_1['data'] = []
    for key in stocks:
        data = {}
        # data['label'] = key.name
        data['value'] = float(key.current_stock_value())
        seriesname_1['data'].append(data)

    dataSource['dataset'].append(seriesname_1)

    print('datasource', str(dataSource))

    dataSource_1 = {}
    dataSource_1['chart'] = {
        "caption": "Investment Details",
        "subCaption": "EFS",
        "xAxisName": "Investment",
        "yAxisName": "Value (In USD)",
        "numberPrefix": "$",
        "theme": "fusion"
    }

    # The data for the chart should be in an array where each element of the array is a JSON object
    # having the `label` and `value` as key value pair.
    dataSource_1['categories'] = []
    categories = {}
    categories['category'] = []

    for invest_name in investments:
        category = {}
        category['label'] = invest_name.category
        categories['category'].append(category)

    dataSource_1['categories'].append(categories)
    dataSource_1['dataset'] = []
    seriesname = {}
    seriesname['seriesname'] = 'Acquired value'
    seriesname['data'] = []
    for key in investments:
        data = {}
        # data['label'] = key.name
        data['value'] = float(key.acquired_value)
        seriesname['data'].append(data)

    dataSource_1['dataset'].append(seriesname)

    seriesname_1 = {}
    seriesname_1['seriesname'] = 'Recent value'
    seriesname_1['data'] = []
    for key in investments:
        data = {}
        # data['label'] = key.name
        data['value'] = float(key.recent_value)
        seriesname_1['data'].append(data)

    dataSource_1['dataset'].append(seriesname_1)

    print('dataSource_1', str(dataSource_1))

    sum_current_stocks_value = 0
    sum_of_initial_stock_value = 0
    for stock in stocks:
        # print('1...', stock.result_by_stock(stock.current_stock_value(), stock.initial_stock_value()))
        sum_current_stocks_value += stock.current_stock_value()
        sum_of_initial_stock_value += stock.initial_stock_value()

    total_stock_result = round((float(sum_current_stocks_value) - float(sum_of_initial_stock_value)), 2)
    sum_acquired_value = Investment.objects.filter(customer=pk).aggregate(Sum('acquired_value')).get(
        'acquired_value__sum', 0.00)
    sum_recent_value = Investment.objects.filter(customer=pk).aggregate(Sum('recent_value')).get('recent_value__sum',
                                                                                0.00)
    total_invest_result = sum_recent_value - sum_acquired_value
    portfolio_result = float(total_invest_result) + float(total_stock_result)

    dataSource_2 = {
        "chart": {
            "caption": "Split of portfolio result by stock and investment",
            "subCaption": "",
            "numberPrefix": "$",
            "showPercentInTooltip": "0",
            "decimals": "1",
            "useDataPlotColorForLabels": "1",
            "theme": "fusion"
        },
        "data": [
            {
                "label": "Stock",
                "value": float(total_stock_result)
            },
            {
                "label": "Investment",
                "value": float(total_invest_result)
            }
        ]
    }
    print('dataSource_2', str(dataSource_2))
    # Create an object for the Column 2D chart using the FusionCharts class constructor
    # column2D = FusionCharts("column2D", "ex1" , "600", "350", "chart-1", "json", dataSource)
    mscolumn2d = FusionCharts("mscolumn2d", "ex1", "600", "350", "chart-1", "json", dataSource)
    viewchart2 = FusionCharts("mscolumn2d", "ex2", "600", "350", "chart-2", "json", dataSource_1)
    viewchart3 = FusionCharts("pie2d", "chart-container", "550", "350", "chart-3", "json", dataSource_2)

    return render(request, 'portfolio/customer_summary.html', {'output': mscolumn2d.render(),
                                                               'output2': viewchart2.render(),
                                                               'output3': viewchart3.render(),
                                                               'customers': customers})


import torch

def PartialLogLikelihood(logits, durations, events):
    """Compute the partial log likelihood as defined in DeepSurv

    Args:
        logits (Tensor): risk function, model output (1D)
        events (Tensor): Event indicator, 1 = death, 0=censored (1D)
        durations (Tensor): failure event time (1D)

    Returns:
        Tensor: [description]

    Risk set: R = {T_j >= T_i}
    Risk set approximation with cumsum on sorted tensor
    """
    # sort risk and events based on decreasing time
    idx = torch.argsort(durations, descending=True)
    logits = logits[idx].view(-1)
    events = events[idx]

    # not really the Risk set but good approximation
    # from pytorch doc The computation is numerically stabilized.
    partial_L = logits.logcumsumexp(dim=0)
    return (-1.0 * (logits - partial_L).mul(events).sum()) / events.sum()


from django.contrib.auth.models import User
from django.core import serializers
from django.http import HttpResponse, HttpResponseForbidden

from versescanner.util.filemanager import sync_files, sync_db
from versescanner.models import Author, Genre, Opus, Period

def sync_files(request):
    if request.user.is_superuser:
        sync_files()
        return HttpResponse(status=204)
    return HttpResponseForbidden()

def sync_db(request):
    if request.user.is_superuser:
        sync_db()
        return HttpResponse(status=204)
    return HttpResponseForbidden()

def get_member_list(request):
    if request.user.is_superuser:
        objects = User.objects.all()
        for d in objects:
            d.password = ''
        data = serializers.serialize('json', objects)
        return HttpResponse(data, content_type='application/json')
    return HttpResponseForbidden()

def post_meta(request):
    if not (request.user.is_superuser and request.method == 'POST'):
        return HttpResponseForbidden()
    dct = request.POST.dict()
    if 'period' in dct:
        dct['period'] = Period.objects.get(id=dct['period'])
        model = Author(**dct)
    else:
        dct['author'] = Author.objects.get(id=dct['author'])
        dct['genre'] = Genre.objects.get(id=dct['genre'])
        model = Opus(**dct)
    model.save()
    return HttpResponse(status=200)


import discord
import json

pinned_file_path = "./web_page/src/database/pinnedChannel.json"
pin_able_file_path = "./web_page/src/database/pinAbleChannel.json"
discord_token = ''

intents = discord.Intents.default()
intents.message_content = True

client = discord.Client(intents=intents)
channel_list = {}
with open(pinned_file_path, 'r', encoding='utf8') as file:
    channel_list = json.load(file)
all_text_channel = {}

@client.event
async def on_ready():
    print('We have logged in as {}'.format(client))
    print('Bot name: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    else:
        if message.content == "!동기화":
            sync_data()
            await message.delete()

        if message.channel.name in channel_list:
            embed = discord.Embed(title="채널 사용 안내", description=channel_list[message.channel.name], color=0x0aa40f)
            await message.channel.purge(limit=2, check=checker)
            await message.channel.send(embed=embed)

def checker(m):
    return m.author == client.user

def sync_data():
    global channel_list
    with open(pinned_file_path, 'r', encoding='utf8') as file:
        data = json.load(file)
        channel_list = data
    load_channels()
    with open(pin_able_file_path, 'w', encoding='utf8') as file:
        json.dump(all_text_channel, file, ensure_ascii=False)

def load_channels():
    global all_text_channel
    all_text_channel = {}
    text_channel_list = []
    for guild in client.guilds:
        for channel in guild.text_channels:
            if channel.name in channel_list:
                pass
            else:
                text_channel_list.append(channel.name)
    for text_channel in text_channel_list:
        all_text_channel[text_channel] = '0'

client.run(discord_token)


from __future__ import absolute_import
from __future__ import division
# Standard __future__ imports
from __future__ import print_function

import apache_beam as beam
from tensorflow_model_analysis.evaluators.query_metrics import query_types
from tensorflow_model_analysis.post_export_metrics import metric_keys

from typing import Any, Dict, List, NamedTuple, Text

_State = NamedTuple('_State', [('total_queries', int), ('total_documents', int),
                               ('min_documents', int), ('max_documents', int)])

class QueryStatisticsCombineFn(beam.CombineFn):
  """Computes simple statistics about queries."""

  LARGE_INT = 1000000000

  def create_accumulator(self):
    return _State(
        total_queries=0,
        total_documents=0,
        min_documents=self.LARGE_INT,
        max_documents=0)

  def add_input(self, accumulator: _State,
                query_fpl: query_types.QueryFPL) -> _State:
    return _State(
        total_queries=accumulator.total_queries + 1,
        total_documents=accumulator.total_documents + len(query_fpl.fpls),
        min_documents=min(accumulator.min_documents, len(query_fpl.fpls)),
        max_documents=max(accumulator.max_documents, len(query_fpl.fpls)))

  def merge_accumulators(self, accumulators: List[_State]) -> _State:
    total_queries = 0
    total_documents = 0
    min_documents = self.LARGE_INT
    max_documents = 0
    for acc in accumulators:
      total_queries += acc.total_queries
      total_documents += acc.total_documents
      min_documents = min(min_documents, acc.min_documents)
      max_documents = max(max_documents, acc.max_documents)
    return _State(
        total_queries=total_queries,
        total_documents=total_documents,
        min_documents=min_documents,
        max_documents=max_documents)

  def extract_output(self, accumulator: _State) -> Dict[Text, Any]:
    return {
        metric_keys.base_key('total_queries'): accumulator.total_queries,
        metric_keys.base_key('total_documents'): accumulator.total_documents,
        metric_keys.base_key('min_documents'): accumulator.min_documents,
        metric_keys.base_key('max_documents'): accumulator.max_documents
    }


from typing import Callable, List
from tfl_arrivals import db_uri, db_cache
from tfl_arrivals.models import Arrival, MonitoredStop
import time
from threading import Thread
from datetime import datetime, timedelta
import logging
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy import create_engine

module_logger = logging.getLogger(__name__)

class arrivals_collector(object):
    """Scheduled the data collection, and saves data to the database"""
    def __init__(self, fetcher: Callable[[],str]):
        self.running = False
        self.logger = logging.getLogger(__name__)

    def start_collecting(self):
        self.logger.info("Start collecting")
        self.running = True
        self.collector_thread = Thread(target=self._run_loop)
        self.collector_thread.start()

    def stop_collecting(self):
        self.running = False

    def _run_loop(self):
        engine = create_engine(db_uri)
        session_factory = sessionmaker(bind=engine)
        session = scoped_session(session_factory)
        while self.running:
            start_time = datetime.utcnow()
            db_cache.refresh_recently_requested_stop_ids(session)
            end_time = datetime.utcnow()
            d = end_time - start_time
            self.logger.info(f"Checking/updating arrival db took {d.microseconds / 1000} ms")
            if d > timedelta(seconds=15):
                self.logger.warning(f"Updating arrival db is too slow")
            else:
                sleep_for = 15 - d.microseconds / (1000 * 1000)
                self.logger.info(f"Sleeping for {sleep_for} s")
                time.sleep(sleep_for)


import time
import gym
import random
from IPython.display import clear_output
import numpy as np

env = gym.make("FrozenLake-v0")

action_column_size = env.action_space.n
observation_column_size = env.observation_space.n

q_table = np.zeros((observation_column_size, action_column_size))

num_ep = 10000
num_step = 100

discount_rate = 0.99
learning_rate = 0.1
exploration_rate = 1
max_exp_rate = 1
min_exp_rate = 0.01
exp_rate_decay = 0.001

all_ep_reward = []

def time_step(episodes, steps, exp_rate):
    for episode in range(episodes):
        state = env.reset()
        done = False
        current_ep_reward = 0

        for step in range(steps):
            exploration_rate_threshold = random.uniform(0, 1)
            if exploration_rate_threshold > exp_rate:
                action = np.argmax(q_table[state,:])
            else:
                action = env.action_space.sample()

            new_state, reward, done, info = env.step(action)

            q_table[state, action] = q_table[state, action] * (1 - learning_rate) + \
                                     learning_rate * (reward + discount_rate * np.max(q_table[new_state, :]))

            state = new_state
            current_ep_reward += reward

            if done == True:
                break

        exp_rate = min_exp_rate + \
                           (max_exp_rate - min_exp_rate) * np.exp(-exp_rate_decay*episode)

        all_ep_reward.append(current_ep_reward)

time_step(num_ep, num_step, exploration_rate)

rewards_per_thousand_episodes = np.split(np.array(all_ep_reward),num_ep/1000)
count = 1000

print("-------------Average reward per thousand episodes-------------\n")
for r in rewards_per_thousand_episodes:
    print(count, ": ", str(sum(r/1000)))
    count += 1000
print(q_table)


from enum import IntEnum
import copy

class BuildingType(IntEnum):
    Settlement = 0
    City = 1

class PlayerId(IntEnum):
    White = 1
    Blue = 2
    Orange = 3
    Red = 4

class Terrain(IntEnum):
    Desert = 0
    Hills = 1
    Forest = 2
    Mountains = 3
    Pastures = 4
    Fields = 5

class Resource(IntEnum):
    Empty = 0
    Brick = 1
    Wood = 2
    Ore = 3
    Sheep = 4
    Wheat = 5

class DevelopmentCard(IntEnum):
    Knight = 0
    VictoryPoint = 1
    YearOfPlenty = 2
    RoadBuilding = 3
    Monopoly = 4

class ActionTypes(IntEnum):
    PlaceSettlement = 0
    PlaceRoad = 1
    UpgradeToCity = 2
    BuyDevelopmentCard = 3
    PlayDevelopmentCard = 4
    ExchangeResource = 5
    ProposeTrade = 6
    RespondToOffer = 7
    MoveRobber = 8
    RollDice = 9
    EndTurn = 10
    StealResource = 11
    DiscardResource = 12

TILE_ADJACENCY_INDS = [
    [[1, "R"], [3, "BL"], [4, "BR"]],
    [[0, "L"], [2, "R"], [4, "BL"], [5, "BR"]],
    [[1, "L"], [5, "BL"], [6, "BR"]],
    [[0, "TR"], [4, "R"], [7, "BL"], [8, "BR"]],
    [[0, "TL"], [1, "TR"], [3, "L"], [5, "R"], [8, "BL"], [9, "BR"]],
    [[1, "TL"], [2, "TR"], [4, "L"], [6, "R"], [9, "BL"], [10, "BR"]],
    [[2, "TL"], [5, "L"], [10, "BL"], [11, "BR"]],
    [[3, "TR"], [8, "R"], [12, "BR"]],
    [[3, "TL"], [4, "TR"], [7, "L"], [9, "R"], [12, "BL"], [13, "BR"]],
    [[4, "TL"], [5, "TR"], [8, "L"], [10, "R"], [13, "BL"], [14, "BR"]],
    [[5, "TL"], [6, "TR"], [9, "L"], [11, "R"], [14, "BL"], [15, "BR"]],
    [[6, "TL"], [10, "L"], [15, "BL"]],
    [[7, "TL"], [8, "TR"], [13, "R"], [16, "BR"]],
    [[8, "TL"], [9, "TR"], [12, "L"], [14, "R"], [16, "BL"], [17, "BR"]],
    [[9, "TL"], [10, "TR"], [13, "L"], [15, "R"], [17, "BL"], [18, "BR"]],
    [[10, "TL"], [11, "TR"], [14, "L"], [18, "BL"]],
    [[12, "TL"], [13, "TR"], [17, "R"]],
    [[13, "TL"], [14, "TR"], [16, "L"], [18, "R"]],
    [[14, "TL"], [15, "TR"], [17, "L"]]
]

TILE_NEIGHBOURS = []
for inds in TILE_ADJACENCY_INDS:
    tile_dict = {}
    for ind_lab in inds:
        tile_dict[ind_lab[1]] = ind_lab[0]
    TILE_NEIGHBOURS.append(copy.copy(tile_dict))

"""
making sure we don't recreate extra corners/edges when generating the map:
prev_corner_lookup: corner: [[placed_neighbouring_tile, which corner in that tile]]

prev_edge_lookup: edge: [placed_neighbouring_tile, which edge]
"""
PREV_CORNER_LOOKUP = {
    "T": [["TR", "BL"], ["TL", "BR"]],
    "TR": [["TR", "B"]],
    "TL": [["TL", "B"], ["L", "TR"]],
    "BL": [["L", "BR"]],
    "BR": [[None, None]],
    "B": [[None, None]]
}
PREV_EDGE_LOOKUP = {
    "L": ["L", "R"],
    "TL": ["TL", "BR"],
    "TR": ["TR", "BL"],
    "R": [],
    "BR": [],
    "BL": []
}
CORNER_NEIGHBOURS_IN_TILE = {
    "T": {"TR": "TR", "TL": "TL"},
    "TL": {"BL": "L", "T": "TL"},
    "BL": {"TL": "L", "B": "BL"},
    "B": {"BL": "BL", "BR": "BR"},
    "BR": {"B": "BR", "TR": "R"},
    "TR": {"BR": "R", "T": "TR"}
}

"""Harbour corners/edges - first ind is harbour ind.
Then tile_ind, corner_1 loc, corner_2 loc, edge loc
"""
HARBOUR_CORNER_AND_EDGES = {
    0: [0, "TL", "T", "TL"],
    1: [1, "T", "TR", "TR"],
    2: [6, "T", "TR", "TR"],
    3: [11, "TR", "BR", "R"],
    4: [15, "BR", "B", "BR"],
    5: [17, "BR", "B", "BR"],
    6: [16, "B", "BL", "BL"],
    7: [12, "TL", "BL", "L"],
    8: [3, "TL", "BL", "L"]
}


#!/usr/bin/env python2
import fileinput
import select, sys
import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from math import hypot

totalLine = 0
nCorrects = 0
start = []
yLocPlot = []
xLocPlot = []
xCorPlot = []
yCorPlot = []
trips = []
corrects = []
timestamps = []

xmax = float('-inf')
ymax = float('-inf')
xmin = float('inf')
ymin = float('inf')

for line in fileinput.input():
    totalLine+=1
    if line == '\n':
        continue
    line = line.split()
    if line[0] != '0':
        corrects+= [1]
        xCorPlot+= [int(line[1])]
        yCorPlot+= [int(line[2])]
    else:
        corrects+= [0]
    trip = line[-1]
    if line[1] != '0' and line[2] != '0':
        xmax = max(xmax, int(line[1]))
        xmin = min(xmin, int(line[1]))
        ymax = max(ymax, int(line[2]))
        ymin = min(ymin, int(line[2]))
    xLocPlot+= [int(line[1])]
    yLocPlot+= [int(line[2])]
    timestamps+= [int(line[-3])]
    if totalLine > 2 and len(xLocPlot) >= 2:
        dist = hypot(xLocPlot[-2] - xLocPlot[-1], yLocPlot[-2] - yLocPlot[-1])
        if dist > 50:
            xLocPlot.pop()
            yLocPlot.pop()
    trips+= [int(line[-1])]

def heardEnter():
    i,o,e = select.select([sys.stdin],[],[],0.0001)
    for s in i:
        if s == sys.stdin:
            input = sys.stdin.readline()
            return True
    return False

def simData():
    paused = False
    percentageCorrect = 0.
    cummulativePercentage = 0
    l = 0
    x = []
    y = []
    while l < totalLine:
        if paused:
            paused = raw_input()
        if heardEnter():
            paused = not paused
        l+=1
        x += [xLocPlot[l]]
        y += [yLocPlot[l]]
        cummulativePercentage+= corrects[l]
        percentageCorrect = float(cummulativePercentage)/l
        yield x, y, trips[l], corrects[l], percentageCorrect, timestamps[l]

def simPoints(simData):
    x, y = simData[0], simData[1]
    lines[0][0].set_data(x, y)
    lines[1][0].set_data(x[-1], y[-1])
    tripText.set_text('Trip: ' + str(simData[2]))
    correctText.set_text('Correct: ' + str('%.3f' % (100*simData[4])) + '%')
    periodText.set_text('Period: ' + (datetime.datetime.utcfromtimestamp(simData[5])).strftime("%d/%m/%Y %H:%M"))
    if (simData[3] == 1):
        lines[1][0].set_color('blue')
    else:
        lines[1][0].set_color('red')
    return lines

fig = plt.figure()
ax = fig.add_subplot(111)

ax.set_ylim(ymin, ymax)
ax.set_xlim(xmin, xmax)
tripText = ax.text(0.05, 0.9, '', transform=ax.transAxes)
correctText = ax.text(0.05, 0.85, '', transform=ax.transAxes)
periodText = ax.text(0.05, 0.80, '', transform=ax.transAxes)

lines = [ax.plot([], [], 'g-', ms=10), ax.plot([], [], 'bo', ms=10)]

lineAni = animation.FuncAnimation(fig, simPoints, simData, interval=1, blit=False)

plt.show()


from pyad import *
from treelib import Node, Tree
import pyad.adquery, pyad.adsearch, pyad.adcomputer, pyad.adbase, pyad.adcontainer, pyad.addomain, pyad.adgroup, pyad.aduser, pyad.pyad

def get_aduser(name: str=None) -> pyad.aduser.ADUser:
    """
    Function to get a pyad.ADUser object from a string

    Args:
        name (str, optional): String of the searched user. Defaults to None.

    Raises:
        Exception: Exception when user can not be resolved in AD

    Returns:
        pyad.ADUser: ADUser Object matching to given string.
    """
    query: pyad.adquery.ADQuery= pyad.adquery.ADQuery()
    query.execute_query(
        attributes=["name"],
        where_clause=f"SamAccountName = '{name}'"
    )
    name = query.get_single_result()["name"]
    try:
        user = pyad.aduser.ADUser.from_cn(name)
    except:
        raise Exception("User not found")
    return user

def get_groups(user: pyad.aduser.ADUser=None) -> list:
    """
    Function to get all groups of a user

    Args:
        user (pyad.ADUser, optional): ADUser object to get the memberships from. Defaults to None.

    Raises:
        Exception: Exception when user is not an pyad.ADUser object

    Returns:
        list: list of all distinguishedNames the user is a member of
    """
    try:
        return user.get_attribute(attribute="memberOf")
    except:
        raise Exception("User is no PYAD user object")

def get_adgroup(name: str=None) -> pyad.adgroup.ADGroup:
    """
    Get a specified group by its name

    Args:
        name (str, optional): Name of the group. Defaults to None.

    Raises:
        Exception: When group can not be resolbved

    Returns:
        pyad.ADGroup: Group matching to name
    """
    try:
        group = pyad.adgroup.ADGroup.from_dn(name)
    except:
        raise Exception("Group not found")
    return group

def create_tree(tree: Tree=Tree(), parent: Node=None, ad_object=None) -> Tree:
    """
    Generate a hierarchical tree a given ad_object is member of.

    Args:
        tree (Tree, optional): Tree object for recursion, leave empty! Defaults to Tree().
        parent (Node, optional): Parent for recursion, leave empty! Defaults to None.
        ad_object (pyad.ADObject, optional): ADObject, should be root element. Defaults to None.

    Returns:
        treelib.Tree: Hierarchical tree of memberships
    """

    # Root Element
    if parent is None:
        name: str = "".join(ad_object.get_attribute("SamAccountName"))
        tree.create_node(data=name, identifier=name, tag=name)
        parent = name

    memberOf: list = ad_object.get_attribute(attribute="memberOf")
    for membership in memberOf:
        group: pyad.adgroup.ADGroup = get_adgroup(membership)
        name: str = "".join(group.get_attribute("SamAccountName"))

        # Duplicate identifier prevention
        id: str = name
        i: int = 1
        while tree.get_node(id) is not None:
            id += f" (DUPLICATE {i})"
            i += 1

        tree.create_node(data=name, identifier=id, parent=parent, tag=id)

        # Check if child nodes have groups and start recursion
        if group.get_attribute("memberOf") is not []:
            tree = create_tree(tree=tree, parent=id, ad_object=group)
    return tree


#£¡/usr/bin/env python
#-*- coding:utf-8 -*-
# author: qiuxiang
# datetime: 2018/10/31 20:23
# software: PyCharm
# project: adminset
from django.urls import path
from navi import views

urlpatterns = [
    path('', views.index, name='navi'),
    path('add/', views.add, name='add'),
    path('manage/', views.manage, name='manage'),
    path('delete/', views.delete, name='delete'),
    path('edit/', views.edit, name='edit'),
    path('save/', views.save, name='save'),
]


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# import tools.DataFrame_preprocess
# import FinanceDataReader as fdr

pd.set_option('display.max_seq_items', None)
pd.set_option('display.max_rows', None)

# Using data from csv file
path = '/workspace/AI-Trade_/datas/AAPL.csv'
dataframe = pd.read_csv(path, index_col='Date', parse_dates=['Date'])

# Using data from FinanceDataReader
# fdr.DataReader(Stock code, time spans)
# dataframe = fdr.DataReader('293490', '2020')

# When using option 'inplace', original dataframe is modified.
# Filling missing value(NaN, inf, -inf)

dataframe['daily_return'] = dataframe['Adj Close'].pct_change()

# replace infinity value to null value.
dataframe.replace([np.inf, -np.inf], np.nan, inplace=True)
dataframe.fillna(method='pad', inplace=True)
dataframe.fillna(method='bfill', inplace=True)

# DataFrame_preprocess.del_NaN_padbfill(dataframe)
# ^same function with above three lines

# print rows that have NaN or infinity value least 1
print(dataframe[dataframe.isin([np.nan, np.inf, -np.inf]).any(1)])

# dataframe.fillna(method='pad')  # forward filling
# dataframe.fillna(method='bfill') # backward filling

print(dataframe.head())

price_dataframe = dataframe.loc[:, ['Adj Close']].copy()
return_dataframe = dataframe.loc[:, ['daily_return']].copy()

# print(price_dataframe)
price_dataframe.plot(figsize=(16, 9), title='Adj Close')
plt.savefig('./plots/Adj_Close.png')

# print(return_dataframe)
return_dataframe.plot(figsize=(16, 9), title='return')
plt.savefig('./plots/return.png')


from django.db import models
from apps.db.models import BaseModel
# Create your models here.

class OrderInfo(BaseModel):
    """订单模型类"""
    PAY_METHOD_CHOICES = (
        (1,"货到付款"),
        (2,"微信支付"),
        (3,"支付宝"),
        (4,"银联支付"),
    )

    ORDER_STATUS_CHOICES = (
        (1,"待支付"),
        (2,"待发货"),
        (3,"待收货"),
        (4,"待评论"),
        (5,"已完成"),
    )

    order_id = models.IntegerField(primary_key=True,verbose_name="订单id",help_text="订单id")
    user = models.ForeignKey("user.User", on_delete=models.CASCADE, verbose_name="用户id", help_text="用户id")
    addr = models.ForeignKey("user.Address", on_delete=models.CASCADE, verbose_name="地址id", help_text="地址id")
    pay_meihod = models.SmallIntegerField(choices=PAY_METHOD_CHOICES,default=3,verbose_name="支付方式",help_text="支付方式")
    total_count = models.IntegerField(default=1,verbose_name="商品数量",help_text="商品数量")
    total_price = models.FloatField(verbose_name="支付金额",help_text="支付金额")
    transit_price = models.FloatField(verbose_name="运费",help_text="运费")
    order_status = models.SmallIntegerField(default=1,choices=ORDER_STATUS_CHOICES,verbose_name="支付状态",help_text="支付状态")
    trade_no = models.CharField(max_length=120,verbose_name="支付编码",help_text="支付编码")

    class Meta:
        db_table = "db_order_info"
        verbose_name = "订单"
        verbose_name_plural = verbose_name

class OrderGoods(BaseModel):
    """订单商品模型类"""
    order = models.ForeignKey("OrderInfo",on_delete=models.CASCADE)
    sku = models.ForeignKey("goods.GoodsSKU", on_delete=models.CASCADE)
    count = models.IntegerField(default=1,verbose_name="商品数量",help_text="商品数量")
    price = models.FloatField(verbose_name="商品价格",help_text="商品价格")
    comment = models.CharField(max_length=250,verbose_name="评论")

    class Meta:
        db_table = "db_order_goods"
        verbose_name = "订单商品"
        verbose_name_plural = verbose_name


"""Sensor component classes."""

# stdlib
import logging
import math

# external
import astropy.units as unit
import numpy as np
from astropy.units import Quantity

# project
from architect import luts
from architect.luts import LUT
from architect.systems import Component

LOG = logging.getLogger(__name__)

class Sensor(Component):
    """Generic focal plane array sensor component.

    Args:
        dimensions: Dimensions of component bounding box. Elements are ordered as (x, y, z) in the cubesat frame.
        integration_time: Integration time.
        efficiency: Quantum efficiency of the sensor.
        i_dark: Dark current.
        mass: Component mass.
        n_bin: Number of binning operations performed on image aquisition.
        n_bit: Sensor bit depth.
        n_px: Pixel count in the (x, y) dimensions in cubesat frame.
        n_well: Sensor well depth.
        noise_read: Readout noise.
        pitch: Pixel pitch. The distance between the centerpoints of adjacent pixels.
        waveband: Waveband. The range of wavelengths the sensor is able to measure.

    """

    def __init__(
        self,
        dimensions: tuple[Quantity[unit.m], Quantity[unit.m], Quantity[unit.m]] = None,
        integration_time: Quantity[unit.s] = None,
        efficiency: LUT = None,
        i_dark: unit.electron / unit.pix / unit.s = None,
        mass: unit.kg = None,
        n_bin=None,
        n_bit=None,
        n_px: tuple[int, int] = None,
        n_well=None,
        noise_read=None,
        pitch: unit.m = None,
        waveband: unit.m = None,
    ):
        super().__init__(dimensions=dimensions, mass=mass)
        self.integration_time = integration_time
        self.efficiency = efficiency
        self.i_dark = i_dark
        self.n_bin = n_bin
        self.n_bit = n_bit
        self.n_px = n_px
        self.n_well = n_well
        self.noise_read = noise_read
        self.waveband = waveband
        self.pitch = pitch

    def get_pitch(self):
        """Get the pixel pitch."""
        if self.pitch is not None:
            return self.pitch
        else:
            raise ValueError("Pixel pitch not set.")

    def get_n_px(self):
        """Get the pixel count."""
        if self.n_px is not None:
            return self.n_px
        else:
            raise ValueError("Pixel count not set.")

    def get_n_bin(self):
        """Get the number of binning operations."""
        if self.n_bin is not None:
            return self.n_bin
        else:
            raise ValueError("bin is not set.")

    def get_shape(self) -> tuple:
        """Get the dimensions of the sensor face."""
        assert self.n_px is not None, "n_px must be specified."
        assert self.pitch is not None, "Pitch must be specified."

        size = (self.n_px[0] * self.pitch, self.n_px[1] * self.pitch)

        return size

    def get_noise_read(self):
        """Get the noise read."""
        if self.noise_read is not None:
            return self.noise_read
        else:
            raise ValueError("Noise read not set.")

    def get_area(self):
        """Get the area of the sensor face."""

        shape = self.get_shape()

        area = shape[0] * shape[1]

        return area

    def get_pixel_area(self):
        """Get the area of a single detector element (pixel).

        Assumes square pixels.

        """
        assert self.pitch is not None, "Pitch must be specified."

        pixel_area = self.pitch**2

        return pixel_area

    def get_mean_dark_signal(self) -> Quantity[unit.electron / unit.pix]:
        """Get the mean dark signal.

        Ref: https://www.notion.so/utat-ss/Mean-Dark-Signal-55519f6c43654fae9464b578da2965d9

        """
        assert self.i_dark is not None, "i_dark must be specified."
        assert self.integration_time is not None, "Integration time must be specified."

        dark_noise = self.i_dark * self.integration_time

        return dark_noise

    def get_dark_shot_noise(self):
        """Get the dark shot noise.

        Ref: https://www.notion.so/utat-ss/Dark-Shot-Noise-d0632bd2a0444d7eb814beed1224ba06

        """

        dark_shot_noise = np.sqrt(self.get_mean_dark_signal())

        return dark_shot_noise

    def get_quantization_noise(self):
        """Get the quantization noise of the sensor."""
        assert self.n_well is not None, "n_well must be specified."
        assert self.n_bit is not None, "n_bit must be specified."

        quant_noise = (1 / math.sqrt(12)) * self.n_well / 2**self.n_bit.value

        return quant_noise

    def get_noise(self, signal):
        """Get the net noise of the sensor."""
        assert self.n_bin is not None, "n_bin must be specified."
        assert self.noise_read is not None, "noise_read must be specified."

        noise = np.sqrt(
            signal * unit.electron
            + self.n_bin * (self.get_mean_dark_signal() * unit.pix) ** 2
            + self.get_quantization_noise() ** 2
            + self.n_bin * self.noise_read**2
        )

        return noise

    def get_integration_time(self) -> Quantity[unit.s]:
        """Get the integration time."""
        if self.integration_time is not None:
            return self.integration_time
        else:
            raise ValueError("Integration time is not set.")

    def get_efficiency(self, wavelength: Quantity[unit.m]):
        """Get the quantum efficiency of the sensor."""
        if self.efficiency is not None:
            return self.efficiency(wavelength)
        else:
            raise ValueError("Quantum efficiency is not set.")

    def get_waveband(self) -> Quantity[unit.m]:
        """Get the waveband of the sensor."""
        if self.waveband is not None:
            return self.waveband
        else:
            raise ValueError("Waveband is not set.")

class TauSWIR(Sensor):
    """Teledyne FLIR Tau SWIR sensor.

    Ref: https://www.notion.so/utat-ss/FLIR-Tau-SWIR-407ea145ffea4d188c777f3b17a9be2b

    """

    def __init__(self):
        ke = 1e3 * unit.electron
        super().__init__(
            dimensions=(38, 38, 36) * unit.mm,
            integration_time=166.7 * unit.ms,
            efficiency=luts.load("sensors/tauswir_quantum_efficiency"),
            i_dark=140 * (ke / unit.pix / unit.s),
            mass=81 * unit.g,
            n_bin=1 * unit.dimensionless_unscaled,
            n_bit=14 * unit.bit,
            n_px=(640, 512) * unit.pix,
            n_well=19 * ke,
            noise_read=500 * unit.electron,
            pitch=15 * unit.um,
            waveband=800 * unit.nm,
        )


import os

import argparse
import logging
import torch
from torch.utils.data import DataLoader
from pytorch_msssim import ssim

from datasets.dataset import LocVisVC
from models.alexnet import SiameseAlexNet
from transforms.display_model import gamma_EOTF
from transforms.pu2_encode import pu2_encode

def rgb2gray(image):
    # shape (b, 3, h, w)
    result = 0.2989 * image[:, 0, :, :] + 0.5870 * image[:, 1, :, :] + 0.1140 * image[:, 2, :, :]
    return result.unsqueeze(1)

def PSNR(pred, label, max_val=255):
    mse = torch.mean((pred - label) ** 2)
    return 10 * torch.log10(max_val ** 2 / mse)

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--batch_size", type=int, default=32)
    parser.add_argument("--device", type=int, default=0)
    parser.add_argument("--lr", type=float, default=1e-5)
    parser.add_argument("--gamma", type=float, default=0.9)
    parser.add_argument("--epochs", type=int, default=10)
    parser.add_argument("--log_interval", type=int, default=100)
    parser.add_argument("--save_interval", type=int, default=10)
    parser.add_argument("--save_dir", type=str, default="checkpoints")
    parser.add_argument("--dataset_dir", type=str, default="dataset")
    args = parser.parse_args()
    return args

def train(model, dataloader, criterion, optimizer, device, log_interval, epoch):
    model.train()
    for batch_index, data in enumerate(dataloader):
        optimizer.zero_grad()
        reference = data["reference"].to(device)
        distortion = data["distortion"].to(device)
        label = data["label"].to(device)
        lumin = data["lumin"].to(device)
        ppd = data["ppd"].to(device)
        n = data["n"].to(device)
        likelihood = data["likelihood"].to(device)

        reference = gamma_EOTF(reference, lumin)
        distortion = gamma_EOTF(distortion, lumin)
        ref_lumin = rgb2gray(reference)
        dis_lumin = rgb2gray(distortion)
        ref_ratio = pu2_encode(ref_lumin) / (ref_lumin + 1e-8)
        dis_ratio = pu2_encode(dis_lumin) / (dis_lumin + 1e-8)
        reference = reference * ref_ratio
        distortion = distortion * dis_ratio

        pred = model(reference, distortion, ppd)
        loss = criterion(pred, label)
        loss.backward()
        optimizer.step()
        if (batch_index + 1) % log_interval == 0:
            print(f"Epoch {epoch + 1}, Batch {batch_index + 1}, Loss {loss.item()}, PSNR {PSNR(pred, label).item()}, SSIM {ssim(pred, label).item()}")

def test(model, dataloader, criterion, device, epoch):
    model.eval()
    total_loss = 0
    total_psnr = 0
    total_ssim = 0
    with torch.no_grad():
        for batch_index, data in enumerate(dataloader):
            reference = data["reference"].to(device)
            distortion = data["distortion"].to(device)
            label = data["label"].to(device)
            lumin = data["lumin"].to(device)
            ppd = data["ppd"].to(device)
            n = data["n"].to(device)
            likelihood = data["likelihood"].to(device)

            reference = gamma_EOTF(reference, lumin)
            distortion = gamma_EOTF(distortion, lumin)
            ref_lumin = rgb2gray(reference)
            dis_lumin = rgb2gray(distortion)
            ref_ratio = pu2_encode(ref_lumin) / (ref_lumin + 1e-8)
            dis_ratio = pu2_encode(dis_lumin) / (dis_lumin + 1e-8)
            reference = reference * ref_ratio
            distortion = distortion * dis_ratio
            pred = model(reference, distortion, ppd)
            loss = criterion(pred, label)

            total_loss += loss.item()
            total_psnr += PSNR(pred, label).item()
            total_ssim += ssim(pred, label).item()
        print(f"Epoch {epoch + 1}, Test Loss {total_loss / (batch_index + 1)} PSNR {total_psnr / (batch_index + 1)} SSIM {total_ssim / (batch_index + 1)}")

def main(args):
    if not os.path.exists(args.save_dir):
        os.makedirs(args.save_dir)
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
    device = f"cuda:{args.device}" if args.device != -1 else "cpu"
    train_dataset = LocVisVC("dataset", is_training=True)
    test_dataset = LocVisVC("dataset", is_training=False)
    train_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=0)
    test_loader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, num_workers=0)
    model = SiameseAlexNet().to(device)
    optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=args.gamma)
    criterion = torch.nn.MSELoss()
    for epoch in range(args.epochs):
        train(model, train_loader, criterion, optimizer, device, args.log_interval, epoch)
        test(model, test_loader, criterion, device, epoch)
        scheduler.step()
        if (epoch + 1) % args.save_interval == 0:
            torch.save(model.state_dict(), os.path.join(args.save_dir, f"model_{epoch + 1}.pth"))

if __name__ == "__main__":
    args = parse_args()
    main(args)


#!/usr/bin/python

import face_recognition
import cv2

video_path = "resources/short_hamilton_clip.mp4"
input_movie = cv2.VideoCapture(video_path)
count = int(input_movie.get(cv2.CAP_PROP_FRAME_COUNT))
height = int(input_movie.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(input_movie.get(cv2.CAP_PROP_FRAME_WIDTH))

print("Video:{} is {}*{} with frame number:{}".format(video_path, width, height, count))

fourcc = cv2.VideoWriter_fourcc(*"XVID")
cv2.VideoWriter()
output_movie = cv2.VideoWriter('/tmp/output.avi', fourcc, 29.97, (width, height))

face_locations = []
frame_number = 0

while True:
    # Grab a single frame of video
    ret, frame = input_movie.read()
    frame_number += 1

    # Quit when the input video file endsz
    if not ret:
        break

    # print(ret)
    # print(len(frame[0]))

    # Convert the image from BGR color (which OpenCV uses) to RGB color
    # (which face_recognition uses)
    rgb_frame = frame[:, :, ::-1]
    # Find all the faces and face encodings in the current frame of video
    face_locations = face_recognition.face_locations(rgb_frame, model="cnn")
    # face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)

    for (top, right, bottom, left) in face_locations:
        # Draw a box around the face
        cv2.rectangle
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

    output_movie.write(frame)
    print("完成度:{}/{}, 含有face数量:{}".format(frame_number, count, len(face_locations)))

# All done!
input_movie.release()
cv2.destroyAllWindows()


from collections import deque
class Solution:
  def left(self,arr,n):
    # search for the nearest smaller height on left side ..
    result = [-1]*n
    stack = deque()
    stack.append(0)
    for i in range(1,n):
      currH = arr[i]
      if stack and arr[stack[-1]]<currH:
        result[i] = stack[-1]
      else:
        while stack and arr[stack[-1]]>=currH:
          stack.pop()
        if stack:
          result[i] = stack[-1]
      stack.append(i)
    return result

  def right(self,arr,n):
    # search for the nearest smaller on the right side..to get width..
    stack = deque()
    stack.append(n-1)
    result=[n]*n
    for i in range(n-2,-1,-1):
      currH = arr[i]
      if stack and arr[stack[-1]]<currH:
        result[i] = stack[-1]
      else:
        while stack and arr[stack[-1]]>=currH:
          stack.pop()

        if stack:
          result[i] = stack[-1]
      stack.append(i)
    return result

  def getMaxArea(self,arr,n):
    left = self.left(arr,n)
    right = self.right(arr,n)
    maxArea = 0
    for i in range(n):
      currArea = ((right[i]-left[i])-1)*(arr[i])
      maxArea = max(maxArea,currArea)
    return maxArea

  def maximalRectangle(self,matrix):
    n = len(matrix)
    m = len(matrix[0])
    maxArea = 0
    height=[0]*m
    for i in range(n):

      for j in range(m):
        if matrix[i][j] == "0":
          height[j] = 0
        else:
          height[j]+= int(matrix[i][j])
      maxArea = max(maxArea, self.getMaxArea(height,m))
    return maxArea

arr = [[0,1],[1,0]]
n = len(arr)
m = len(arr[0])
res = Solution().maximalRectangle(arr)
print(res)


from approxeng.task import task, TASKS, resource, RESOURCES, register_resource, run, TaskException
import logging
import cachetools.func
from time import sleep

LOG = logging.getLogger('demo')

logging.basicConfig(level=logging.INFO)

@resource(name='list_resource')
def bar():
    return ['a', 'b', 'c']

register_resource('string_resource', 'a value')

@resource(name='dep_test_resource')
def foo(list_resource):
    return list(reversed(list_resource))

@task(name='first_task')
def root(dep_test_resource, task_count):
    sleep(0.1)
    LOG.info(task_count)
    LOG.info(dep_test_resource)
    if task_count > 2:
        return 'second_task'

@task
def second_task(string_resource):
    LOG.info('Ooh, a string "%s", too exciting, sleeping for a bit', string_resource)
    # LOG.info(world._dict)
    sleep(0.5)
    raise Exception("foo")

LOG.info(TASKS)
LOG.info(RESOURCES)

run(root_task='first_task', raise_exceptions=False)


#coding=utf-8
import jieba,re,os,io
from gensim.models import word2vec
import logging
#jieba.load_userdict("data\\userdict.txt")

# logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO,filename='test_01.log')
#测试原数据
filename = 'test_01.txt'
pre,ext = os.path.splitext(filename)   #输入文件分开前缀，后缀   pre=test_01   ext=.txt
corpus = pre + '_seg' + ext    #训练语料为按行分词后的文本文件    corpus=test_01_seg.txt
fin = io.open(filename,encoding='utf8').read().strip(' ').strip('\n').replace('\n\n','\n')   #strip()取出首位空格，和换行符，用\n替换\n\n
stopwords = set(io.open('stop_list.txt',encoding='utf8').read().strip('\n').split('\n'))   #读入停用词

# 第二：分词，将训练文本中的词做处理，不能包含停用词中的词，以及长度少于等于1的词，去标点，
#去掉停用词中的词，去掉长度小于等于1的词
text = ' '.join([x for x in jieba.lcut(fin) if x not in stopwords and len(x)>1 and x != '\n'])
print(text)
#去标点，将【】里面的标点全部替换为‘，’
# results = re.sub('[（）：:？“”《》，。！·、\d ]+',' ',text)
#按行分词后存为训练语料
io.open(corpus,'w+',encoding='utf8').write(text)

#3.训练模型
# 加载语料,LineSentence用于处理分行分词语料
sentences = word2vec.LineSentence(corpus)
#用来处理按文本分词语料
#sentences1 = word2vec.Text8Corpus(corpus)
# print('=--=-=-=-=-=',sentences)
# 训练skip-gram模型; 第一个参数是训练预料，min_count是小于该数的单词会被踢出，默认值为5，
# size是神经网络的隐藏层单元数，在保存的model.txt中会显示size维的向量值。默认是100。默认window=5
#训练模型就这一句话  去掉出现频率小于2的词
model = word2vec.Word2Vec(sentences, size=12,window=25,min_count=2,workers=5,sg=1,hs=1)

# 4保存模型，以便重用
# model.save("test_01.model")
# 将模型保存成文本，model.wv.save_word2vec_format()来进行模型的保存的话，会生成一个模型文件。里边存放着模型中所有词的词向量。这个文件中有多少行模型中就有多少个词向量。
# model.wv.save_word2vec_format('test_01.model.txt','test_01.vocab.txt',binary=False)
#5词向量验证
#加载训练好的模型
model = word2vec.Word2Vec.load("test_01.model")  #加载训练好的语料模型
#计算两个句子间的相似度
list1 = ['孙悟空']
list2 = ['唐僧', '西天', '取经']
print(model.most_similar(list1))

# 计算两个词的相似度/相关程度
# role1 = ['大圣','悟空','齐天大圣','师兄','老孙','行者','孙行者','孙悟空']
# role2 = ['天蓬','猪悟能','老猪','八戒','猪八戒','呆子']
# role1 = ['天地','万物','一元']
# role2 = ['天地','百岁']
# pairs = [(x,y) for x in role1 for y in role2]
# print(pairs)  #[('天地', '天地'), ('天地', '百岁'), ('万物', '天地'), ('万物', '百岁'), ('一元', '天地'), ('一元', '百岁')]
#
# #pairs = [('观音','猪悟能'),('观音','天蓬'),('观音','八戒'),('呆子','八戒'),('天蓬','嫦娥'),('天蓬','大圣'),('天蓬','卷帘'),('八戒','姐姐')]
# for pair in pairs:
#     print("> [%s]和[%s]的相似度为：" % (pair[0],pair[1]), model.similarity(pair[0], pair[1]))   # 预测相似性
#
# # 计算某个词的相关词列表
# figures = ['如来','西天','观音','老君','师父','老孙','八戒','沙和尚','南天门','王母','天王']
# for figure in figures:
#     print("> 和[%s]最相关的词有：\n" % figure, '\n'.join([x[0].ljust(4,'　')+str(x[1]) for x in model.most_similar(figure, topn=10)


from http import HTTPStatus

import pytest
from crud.crud_questions_services import question_service
from httpx import AsyncClient
from schemas.questions_services import CreateQuestionService

@pytest.mark.anyio
async def test_get_all(client: AsyncClient, get_question_service: CreateQuestionService):
    obj = await question_service.create(get_question_service)
    response = await client.get("/api/v1/questions-services/")
    assert response.status_code == int(HTTPStatus.OK)
    assert obj.id in [album["id"] for album in response.json()]

@pytest.mark.anyio
async def test_get_one(client: AsyncClient, get_question_service: CreateQuestionService):
    obj = await question_service.create(get_question_service)
    response = await client.get(f"/api/v1/questions-services/{obj.id}/")
    assert response.status_code == int(HTTPStatus.OK)
    assert response.json()["id"] == obj.id


import array
import codecs
import datetime
import os

from .errors import DecodingError, CompletionCodeError
from .msgs import constants
from .utils import bcd_search, chunks, py3_array_tobytes
from .fields import FruTypeLengthString

codecs.register(bcd_search)

class Fru(object):
    def __init__(self):
        self.write_length = 16

    def get_fru_inventory_area_info(self, fru_id=0):
        rsp = self.send_message_with_name('GetFruInventoryAreaInfo',
                                          fru_id=fru_id)
        return rsp.area_size

    def write_fru_data(self, data, offset=0, fru_id=0):
        for chunk in chunks(data, self.write_length):
            write_rsp = self.send_message_with_name('WriteFruData',
                                                    fru_id=fru_id,
                                                    offset=offset,
                                                    data=chunk)

            # check if device wrote the same number of bytes sent
            if write_rsp.count_written != len(chunk):
                raise Exception('sent {:} bytes but device wrote {:} bytes'
                                .format(len(chunk), write_rsp.count_written))

            offset += len(chunk)

    def read_fru_data(self, offset=None, count=None, fru_id=0):
        req_size = 32
        data = array.array('B')

        # first check for maximum area size
        if offset is None:
            area_size = self.get_fru_inventory_area_info(fru_id)
            off = 0
        else:
            area_size = offset + count
            off = offset

        while off < area_size:
            if (off + req_size) > area_size:
                req_size = area_size - off

            try:
                rsp = self.send_message_with_name('ReadFruData', fru_id=fru_id,
                                                  offset=off, count=req_size)
            except CompletionCodeError as ex:
                if ex.cc in (constants.CC_CANT_RET_NUM_REQ_BYTES,
                             constants.CC_REQ_DATA_FIELD_EXCEED,
                             constants.CC_PARAM_OUT_OF_RANGE):
                    req_size -= 2
                    if req_size <= 0:
                        raise
                    continue
                else:
                    raise

            data.extend(rsp.data)
            off += rsp.count

        return py3_array_tobytes(data)

    def read_fru_data_full(self, fru_id=0):
        return self.read_fru_data(fru_id=fru_id)

    def get_fru_inventory_header(self, fru_id=0):
        data = self.read_fru_data(offset=0, count=8, fru_id=fru_id)
        return InventoryCommonHeader(data)

    def _read_fru_area(self, offset, fru_id=0):
        # read the area header
        data = self.read_fru_data(offset=offset, count=5, fru_id=fru_id)
        # get the whole area data
        count = data[1] * 8
        return self.read_fru_data(offset=offset, count=count, fru_id=fru_id)

    def get_fru_chassis_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.chassis_info_area_offset,
                                   fru_id=fru_id)
        return InventoryChassisInfoArea(data)

    def get_fru_board_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.board_info_area_offset,
                                   fru_id=fru_id)
        return InventoryBoardInfoArea(data)

    def get_fru_product_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.product_info_area_offset,
                                   fru_id=fru_id)
        return InventoryProductInfoArea(data)

    def get_fru_multirecord_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)

        # we have to determine the length of the area first
        offset = header.multirecord_area_offset
        count = 0

        while True:
            # read the header
            data = self.read_fru_data(offset=offset, count=5)
            end_of_list = bool(data[1] & 0x80)
            length = data[2]
            count += length + 5
            offset += length + 5
            if end_of_list:
                break

        # now read the full area
        offset = header.multirecord_area_offset
        data = self.read_fru_data(offset=offset, count=count)
        return InventoryMultiRecordArea(data)

    def get_fru_inventory(self, fru_id=0):
        """
        Get the full parsed FRU inventory data.
        """
        fru = FruInventory()
        header = self.get_fru_inventory_header(fru_id=fru_id)

        if header.chassis_info_area_offset:
            fru.chassis_info_area = self.get_fru_chassis_area(fru_id=fru_id)

        if header.board_info_area_offset:
            fru.board_info_area = self.get_fru_board_area(fru_id=fru_id)

        if header.product_info_area_offset:
            fru.product_info_area = self.get_fru_product_area(fru_id=fru_id)

        if header.multirecord_area_offset:
            fru.multirecord_area = self.get_fru_multirecord_area(fru_id=fru_id)

        return fru

def get_fru_inventory_from_file(filename):
    try:
        file = open(filename, "rb")
    except IOError:
        print('Error open file "%s"' % filename)

    ################################
    # get file size
    file_size = os.stat(filename).st_size
    file_data = file.read(file_size)
    data = array.array('B', file_data)
    file.close()
    return FruInventory(data)

CUSTOM_FIELD_END = 0xc1

def _decode_custom_fields(data):
    offset = 0
    fields = []
    while data[offset] != CUSTOM_FIELD_END:
        field = FruTypeLengthString(data, offset)
        fields.append(field)
        offset += field.length + 1
    return fields

class FruData(object):
    def __init__(self, data=None):
        if data:
            if isinstance(data, str):
                data = [ord(c) for c in data]
            self.data = data
            if hasattr(self, '_from_data'):
                self._from_data(data)

class InventoryCommonHeader(FruData):
    def _from_data(self, data):
        if len(data) != 8:
            raise DecodingError('InventoryCommonHeader length != 8')
        self.format_version = data[0] & 0x0f
        self.internal_use_area_offset = data[1] * 8 or None
        self.chassis_info_area_offset = data[2] * 8 or None
        self.board_info_area_offset = data[3] * 8 or None
        self.product_info_area_offset = data[4] * 8 or None
        self.multirecord_area_offset = data[5] * 8 or None
        if sum(data) % 256 != 0:
            raise DecodingError('InventoryCommonHeader checksum failed')

class CommonInfoArea(FruData):
    def _from_data(self, data):
        self.format_version = data[0] & 0x0f
        if self.format_version != 1:
            raise DecodingError('unsupported format version (%d)' %
                                self.format_version)
        self.length = data[1] * 8
        if sum(data[:self.length]) % 256 != 0:
            raise DecodingError('checksum failed')

class InventoryChassisInfoArea(CommonInfoArea):
    TYPE_OTHER = 1
    TYPE_UNKNOWN = 2
    TYPE_DESKTOP = 3
    TYPE_LOW_PROFILE_DESKTOP = 4
    TYPE_PIZZA_BOX = 5
    TYPE_MINI_TOWER = 6
    TYPE_TOWER = 7
    TYPE_PORTABLE = 8
    TYPE_LAPTOP = 9
    TYPE_NOTEBOOK = 10
    TYPE_HAND_HELD = 11
    TYPE_DOCKING_STATION = 12
    TYPE_ALL_IN_ONE = 13
    TYPE_SUB_NOTEBOOK = 14
    TYPE_SPACE_SAVING = 15
    TYPE_LUNCH_BOX = 16
    TYPE_MAIN_SERVER_CHASSIS = 17
    TYPE_EXPANSION_CHASSIS = 18
    TYPE_SUB_CHASSIS = 19
    TYPE_BUS_EXPANSION_CHASSIS = 20
    TYPE_PERIPHERAL_CHASSIS = 21
    TYPE_RAID_CHASSIS = 22
    TYPE_RACK_MOUNT_CHASSIS = 23

    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.type = data[2]
        offset = 3
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.custom_chassis_info = _decode_custom_fields(data[offset:])

class InventoryBoardInfoArea(CommonInfoArea):
    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.language_code = data[2]
        minutes = data[5] << 16 | data[4] << 8 | data[3]
        self.mfg_date = (datetime.datetime(1996, 1, 1)
                         + datetime.timedelta(minutes=minutes))
        offset = 6
        self.manufacturer = FruTypeLengthString(data, offset)
        offset += self.manufacturer.length + 1
        self.product_name = FruTypeLengthString(data, offset)
        offset += self.product_name.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.fru_file_id = FruTypeLengthString(data, offset, True)
        offset += self.fru_file_id.length + 1
        self.custom_mfg_info = _decode_custom_fields(data[offset:])

class InventoryProductInfoArea(CommonInfoArea):
    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.language_code = data[2]
        offset = 3
        self.manufacturer = FruTypeLengthString(data, offset)
        offset += self.manufacturer.length + 1
        self.name = FruTypeLengthString(data, offset)
        offset += self.name.length + 1
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.version = FruTypeLengthString(data, offset)
        offset += self.version.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.asset_tag = FruTypeLengthString(data, offset)
        offset += self.asset_tag.length + 1
        self.fru_file_id = FruTypeLengthString(data, offset, True)
        offset += self.fru_file_id.length + 1
        self.custom_mfg_info = list()
        self.custom_mfg_info = _decode_custom_fields(data[offset:])

class FruDataMultiRecord(FruData):
    TYPE_POWER_SUPPLY_INFORMATION = 0
    TYPE_DC_OUTPUT = 1
    TYPE_DC_LOAD = 2
    TYPE_MANAGEMENT_ACCESS_RECORD = 3
    TYPE_BASE_COMPATIBILITY_RECORD = 4
    TYPE_EXTENDED_COMPATIBILITY_RECORD = 5
    TYPE_OEM = list(range(0x0c, 0x100))
    TYPE_OEM_PICMG = 0xc0

    def __str__(self):
        return '%02x: %s' % (self.record_type_id,
                             ' '.join('%02x' % b for b in self.raw))

    def _from_data(self, data):
        if len(data) < 5:
            raise DecodingError('data too short')
        self.record_type_id = data[0]
        self.format_version = data[1] & 0x0f
        self.end_of_list = bool(data[1] & 0x80)
        self.length = data[2]
        if sum(data[:5]) % 256 != 0:
            raise DecodingError('FruDataMultiRecord header checksum failed')
        self.raw = data[5:5+self.length]
        if (sum(self.raw) + data[3]) % 256 != 0:
            raise DecodingError('FruDataMultiRecord record checksum failed')

    @staticmethod
    def create_from_record_id(data):
        if data[0] == FruDataMultiRecord.TYPE_OEM_PICMG:
            return FruPicmgRecord.create_from_record_id(data)
        else:
            return FruDataUnknown(data)

class FruDataUnknown(FruDataMultiRecord):
    """This class is used to indicate undecoded picmg record."""

    pass

class FruPicmgRecord(FruDataMultiRecord):
    PICMG_RECORD_ID_BACKPLANE_PTP_CONNECTIVITY = 0x04
    PICMG_RECORD_ID_ADDRESS_TABLE = 0x10
    PICMG_RECORD_ID_SHELF_POWER_DISTRIBUTION = 0x11
    PICMG_RECORD_ID_SHMC_ACTIVATION_MANAGEMENT = 0x12
    PICMG_RECORD_ID_SHMC_IP_CONNECTION = 0x13
    PICMG_RECORD_ID_BOARD_PTP_CONNECTIVITY = 0x14
    PICMG_RECORD_ID_RADIAL_IPMB0_LINK_MAPPING = 0x15
    PICMG_RECORD_ID_MODULE_CURRENT_REQUIREMENTS = 0x16
    PICMG_RECORD_ID_CARRIER_ACTIVATION_MANAGEMENT = 0x17
    PICMG_RECORD_ID_CARRIER_PTP_CONNECTIVITY = 0x18
    PICMG_RECORD_ID_AMC_PTP_CONNECTIVITY = 0x19
    PICMG_RECORD_ID_CARRIER_INFORMATION = 0x1a
    PICMG_RECORD_ID_MTCA_FRU_INFORMATION_PARTITION = 0x20
    PICMG_RECORD_ID_MTCA_CARRIER_MANAGER_IP_LINK = 0x21
    PICMG_RECORD_ID_MTCA_CARRIER_INFORMATION = 0x22
    PICMG_RECORD_ID_MTCA_SHELF_INFORMATION = 0x23
    PICMG_RECORD_ID_MTCA_SHELF_MANAGER_IP_LINK = 0x24
    PICMG_RECORD_ID_MTCA_CARRIER_POWER_POLICY = 0x25
    PICMG_RECORD_ID_MTCA_CARRIER_ACTIVATION_AND_POWER = 0x26
    PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY = 0x27
    PICMG_RECORD_ID_MTCA_FAN_GEOGRAPHY = 0x28
    PICMG_RECORD_ID_OEM_MODULE_DESCRIPTION = 0x29
    PICMG_RECORD_ID_CARRIER_CLOCK_PTP_CONNECTIVITY = 0x2C
    PICMG_RECORD_ID_CLOCK_CONFIGURATION = 0x2d
    PICMG_RECORD_ID_ZONE_3_INTERFACE_COMPATIBILITY = 0x30
    PICMG_RECORD_ID_CARRIER_BUSED_CONNECTIVITY = 0x31
    PICMG_RECORD_ID_ZONE_3_INTERFACE_DOCUMENTATION = 0x32

    def __init__(self, data):
        FruDataMultiRecord.__init__(self, data)

    @staticmethod
    def create_from_record_id(data):
        picmg_record = FruPicmgRecord(data)
        if picmg_record.picmg_record_type_id ==\
                FruPicmgRecord.PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY:
            return FruPicmgPowerModuleCapabilityRecord(data)

        return FruPicmgRecord(data)

    def _from_data(self, data):
        if len(data) < 10:
            raise DecodingError('data too short')
        data = array.array('B', data)
        FruDataMultiRecord._from_data(self, data)
        self.manufacturer_id = \
            data[5] | data[6] << 8 | data[7] << 16
        self.picmg_record_type_id = data[8]
        self.format_version = data[9]

class FruPicmgPowerModuleCapabilityRecord(FruPicmgRecord):
    def _from_data(self, data):
        if len(data) < 12:
            raise DecodingError('data too short')
        FruPicmgRecord._from_data(self, data)
        maximum_current_output = data[10] | data[11] << 8
        self.maximum_current_output = float(maximum_current_output/10)

class InventoryMultiRecordArea(object):
    def __init__(self, data):
        if data:
            self._from_data(data)

    def _from_data(self, data):
        self.records = list()
        offset = 0
        while True:
            record = FruDataMultiRecord.create_from_record_id(data[offset:])
            self.records.append(record)
            offset += record.length + 5
            if record.end_of_list:
                break

class FruInventory(object):
    def __init__(self, data=None):
        self.chassis_info_area = None
        self.board_info_area = None
        self.product_info_area = None
        self.multirecord_area = None

        if data:
            self._from_data(data)

    def _from_data(self, data):
        self.raw = data
        self.common_header = InventoryCommonHeader(data[:8])

        if self.common_header.chassis_info_area_offset:
            self.chassis_info_area = InventoryChassisInfoArea(
                data[self.common_header.chassis_info_area_offset:])

        if self.common_header.board_info_area_offset:
            self.board_info_area = InventoryBoardInfoArea(
                data[self.common_header.board_info_area_offset:])

        if self.common_header.product_info_area_offset:
            self.product_info_area = InventoryProductInfoArea(
                data[self.common_header.product_info_area_offset:])

        if self.common_header.multirecord_area_offset:
            self.multirecord_area = InventoryMultiRecordArea(
                data[self.common_header.multirecord_area_offset:])


# 导入 List 类型标注
from typing import List

class Solution:
    def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
        # 定义 countLess 函数
        def countLess(val: int) -> int:
            # 初始化 res 和 j
            res, j = 0, len(nums) - 1
            # 使用 for 循环遍历数组
            for i in range(len(nums)):
                # 使用 while 循环减小 j 的值，使得 nums[i] + nums[j] 不超过 val
                while i < j and nums[i] + nums[j] > val:
                    j -= 1
                # 计算符合条件的对的数量，并累加到 res
                res += max(0, j-i)
            # 返回 res
            return res

        # 对 nums 进行排序
        nums.sort()
        # 计算并返回符合条件的对的数量
        return countLess(upper) - countLess(lower - 1)

        """
给定一个大小为 n 的 0 索引整数数组 nums 和两个整数 lower 和 upper，返回公平对的数量。

一对 (i, j) 是公平（fair）的，如果：
    1. 0 <= i < j < n，并且
    2. 下限 <= nums[i] + nums[j] <= 上限

解题思路：
这题要求在给定的整数阵列 nums 中找出所有 "公平的" 数对 (i, j)，其中 nums[i] + nums[j] 要在 [lower, upper] 的范围内。

这个问题可以透过排序和双指针方法来解决。首先，对 nums 阵列进行排序。然后，定义一个函数 countLess(val) 来计算所有数对 (i, j) 的和小于等于 val 的数量。

最后，我们计算 countLess(upper) - countLess(lower - 1)，这样就能得到所有和在 [lower, upper] 范围内的数对的数量。

时间复杂度: 排序的时间复杂度是 O(n log n)，countLess 函数中的两个循环的时间复杂度为 O(n)。所以总的时间复杂度是 O(n log n + n) = O(n log n)。
空间复杂度: 我们只用了常数的额外空间，所以空间复杂度是 O(1)。
        """


import re
import json
import shutil
from pathlib import Path

def copy_resource(src, dst, error_msg):
    dst.mkdir(parents=True, exist_ok=True)
    if src.exists():
        shutil.copytree(src, dst, dirs_exist_ok=True)
    else:
        print(error_msg)

def check_file(file_path, missing_on_mac_os=None):
    """Check existence of a file."""
    if not file_path.is_file():
        print(f"{file_path} does not exist")
        if missing_on_mac_os is not None:
            if file_path.stem in missing_on_mac_os:
                return
        exit(1)

def get_missing_on_mac_os():
    with open("../CMakeLists.txt", "r", encoding="utf-8") as fi:
        root_cmake_text = fi.read()

    mt = re.findall(r"if\(NOT APPLE\)(.*?)endif\(\)",
                    root_cmake_text,
                    flags=re.MULTILINE | re.DOTALL)
    return re.findall(r"add_subdirectory\((.+?)\)", mt[0])

def create_archive_from_github_actions_artifact():
    with open("manual.json", "r", encoding="utf-8") as fi:
        manual_dict = json.load(fi)

    pack_dir = Path("pack")
    pack_dir.mkdir(exist_ok=True)

    # For manual packaging.
    for zip_file in Path().glob("*.zip"):
        shutil.unpack_archive(zip_file, pack_dir, format="zip")

    # For GitHub Actions.
    for artifact_dir in Path().glob("vst_*"):
        if not artifact_dir.is_dir():
            continue
        shutil.copytree(artifact_dir, pack_dir, dirs_exist_ok=True)

    for dsym in pack_dir.glob("*.dSYM"):
        shutil.rmtree(dsym)

    missing_on_mac_os = get_missing_on_mac_os()

    for vst3_dir in pack_dir.glob("*.vst3"):
        plugin_name = vst3_dir.stem

        manual_name = (plugin_name
                       if not plugin_name in manual_dict else manual_dict[plugin_name])

        # # Do not make package if a plugin doesn't have manual.
        # if not Path(f"../docs/manual/{manual_name}").exists():
        #     print(f"Skipping {plugin_name}: manual not found")
        #     continue

        copy_resource(
            Path(f"../docs/manual/{manual_name}"),
            vst3_dir / Path("Contents/Resources/Documentation"),
            f"{plugin_name} manual was not found",
        )
        copy_resource(
            Path("../License"),
            vst3_dir / Path("Contents/Resources/License"),
            "License directory was not found",
        )

        # Ensuring that no binary is missing.
        check_file(vst3_dir / Path(f"Contents/x86_64-win/{plugin_name}.vst3"))
        check_file(vst3_dir / Path(f"Contents/x86_64-linux/{plugin_name}.so"))
        check_file(vst3_dir / Path(f"Contents/MacOS/{plugin_name}"), missing_on_mac_os)

        packed_path_str = shutil.make_archive(
            str(vst3_dir.parent / Path(f"{plugin_name}")),
            "zip",
            pack_dir,
            vst3_dir.name,
        )
        packed_path = Path(packed_path_str)

def add_version_to_archive_name():
    re_major_version = re.compile(r"^#define MAJOR_VERSION_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)
    re_minor_version = re.compile(r"^#define SUB_VERSION_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)
    re_patch_version = re.compile(r"^#define RELEASE_NUMBER_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)

    current = list(Path("pack").glob("*.zip"))

    for path in current:
        version_hpp = Path("../") / Path(path.stem) / Path("source/version.hpp")
        if not version_hpp.exists():
            print(f"{version_hpp} was not found")
            continue

        with open(version_hpp, "r", encoding="utf-8") as fi:
            text = fi.read()

        major = re_major_version.search(text).groups()[0]
        minor = re_minor_version.search(text).groups()[0]
        patch = re_patch_version.search(text).groups()[0]

        new_path = path.parent / Path(f"{path.stem}_{major}.{minor}.{patch}.zip")
        if new_path.exists():
            print(f"Error: {new_path} already exists.")
            exit()
        path.rename(new_path)

if __name__ == "__main__":
    create_archive_from_github_actions_artifact()
    add_version_to_archive_name()