import pandas as pd
import pyinputplus
import datetime
import os
from reports.monthly_reports.controllers.database_controller import get_data

pd.options.mode.chained_assignment = None

"""
This script provides an API to explore stats about NGOs lead shares.
"""

def filter_columns(data: pd.DataFrame):
    """
    Returns a DataFrame only with those columns that are needed to proceed with the Deliveries Analysis.
    Columns accepted:
        - user_id
        - created_at
        - age
        - telephone
        - name
        - given_to

    :param data: (pd.DataFrame) input lead data.
    :return: (pd.DataFrame) only with the columns needed to create the Deliveries Analysis
    """

    required_columns = ['user_id', 'created_at', 'age', 'telephone', 'name', 'given_to']

    return data.loc[:, required_columns]

def general_stats(data: pd.DataFrame, country):
    """
    Returns general stats about the number of leads stored in the database and the number of leads that meet all
    delivery requirements.

    :param data: (pd.DataFrame) input lead data.
    :param country: (str) country to segment on.
    :return: (dict) output metrics
    """

    metrics = ['total_leads',               # Total number of leads
               'total_leads_>30',           # Total number of leads aged 30 years or more
               'total_leads_>30_with_tlf']  # Total number of leads aged 30 years or more that registered a tlf

    if country is not None:
        metrics.append('total_leads_{0}'.format(country))
        metrics.append('total_leads_>30_{0}'.format(country))
        metrics.append('total_leads_>30_with_tlf_{0}'.format(country))

    # Creating dictionary from keys
    metrics_dict = dict.fromkeys(metrics, None)

    more_than_30 = 'age >= 30'
    telephone_registered = 'telephone.notna()'

    metrics_dict['total_leads'] = data['user_id'].nunique()
    metrics_dict['total_leads_>30'] = data.query(more_than_30)['user_id'].nunique()
    metrics_dict['total_leads_>30_with_tlf'] = data.query(more_than_30 + '&'
                                                          + telephone_registered)['user_id'].nunique()

    if country is not None:
        data = data[data['name'] == country]

        metrics_dict['total_leads_{0}'.format(country)] = data['user_id'].nunique()
        metrics_dict['total_leads_>30_{0}'.format(country)] = data.query(more_than_30)['user_id'].nunique()
        metrics_dict['total_leads_>30_with_tlf_{0}'.format(country)] = data.query(
            more_than_30 + '&' + telephone_registered)['user_id'].nunique()

    return metrics_dict

def deliveries_stats(data: pd.DataFrame, year: int, country):
    """
    Returns metrics about the average number of lead deliveries and the times each lead has been shared with an NGO.

    :param data: (pd.DataFrame) input lead data.
    :param year: (int) year for which statistics are to be obtained.
    :param country: (str) country to segment on.
    :return:
    """

    metrics = ['average_deliveries',        # Average number of deliveries
               'average_deliveries_year']   # Average number of deliveries in the selected year

    # Creating dictionary from keys
    metrics_dict = dict.fromkeys(metrics, None)

    # Delivery requirements
    more_than_30 = 'age >= 30'
    telephone_registered = 'telephone.notna()'

    if country is not None:
        data = data[data['name'] == country]

    deliverable_leads = data.query(more_than_30 + '&' + telephone_registered)

    # Creating column 'year'
    deliverable_leads['year'] = pd.DatetimeIndex(deliverable_leads['created_at']).year

    # Getting times each lead has been delivered.
    # Zero delivered leads are also counted
    deliveries = deliverable_leads.loc[deliverable_leads['given_to'].notna()]['user_id'].value_counts().\
        rename_axis('user_id').reset_index(name='times_delivered')
    zero_deliveries = pd.DataFrame(data=deliverable_leads.loc[deliverable_leads['given_to'].isna()]['user_id'],
                                   columns=['user_id']).drop_duplicates().reset_index(drop=True)
    zero_deliveries['times_delivered'] = 0
    deliveries = pd.concat([deliveries, zero_deliveries]).sort_values(by='times_delivered', ascending=False)

    # Getting times each lead has been delivered for those leads created on a certain year.
    # Zero delivered leads are also counted
    deliveries_year = deliverable_leads.loc[deliverable_leads['given_to'].notna()].query('year == @year')['user_id']\
        .value_counts().rename_axis('user_id').reset_index(name='times_delivered')
    zero_deliveries = pd.DataFrame(deliverable_leads.loc[deliverable_leads['given_to'].isna()].query('year == @year')
                                   ['user_id'], columns=['user_id']).drop_duplicates().reset_index(drop=True)
    zero_deliveries['times_delivered'] = 0
    deliveries_year = pd.concat([deliveries_year, zero_deliveries]).sort_values(by='times_delivered', ascending=False)

    # Getting average deliveries stats
    metrics_dict['average_deliveries'] = deliveries['times_delivered'].mean()
    metrics_dict['average_deliveries_year'] = deliveries_year['times_delivered'].mean()

    return deliveries, deliveries_year, metrics_dict

def main():

    month = None
    year = None
    country = None

    # Taking input
    # 1) Monthly data or all available data
    response = pyinputplus.inputMenu(prompt='Do you wish to use monthly data? (Yes/No)\n'
                                            'NOTE: in case you want to use the whole database type \'No\'.\n',
                                     choices=['Yes', 'No'],
                                     numbered=True)

    # 2) Monthly data option
    #   2.1) Ask for a month
    #   2.2) Ask for a year
    if response == 'Yes':
        month = pyinputplus.inputMonth(prompt='Enter the month you wish to obtain the data: ')
        year = pyinputplus.inputInt(prompt='Enter the year you wish to obtain the data '
                                           '(format: yyyy, min: 2014): ',
                                    min=2014,
                                    max=datetime.datetime.now().year)

    data = filter_columns(get_data(month=month, year=year))

    # 3) All available data option
    #   3.1) Ask for a year to get the average number of deliveries
    if year is None:
        year = pyinputplus.inputInt(prompt='Enter the year you wish to get the average number of deliveries '
                                           '(format: yyyy, min: 2014): ',
                                    min=2014,
                                    max=datetime.datetime.now().year)

    # 4) Segment by country or get all countries data
    countries = list(data['name'].dropna().unique())
    countries.insert(0, 'No segment')
    response = pyinputplus.inputMenu(prompt='Choose a country to segment on:\n',
                                     choices=countries,
                                     numbered=True)

    if response != 'No segment':
        country = response

    dict_general_stats = general_stats(data=data, country=country)

    df_deliveries, df_deliveries_year, dict_average_deliveries = deliveries_stats(data=data,
                                                                                year=year,
                                                                                country=country)

    display_menu = 1

    while display_menu:
        # Menu to display the results
        choices = ['Print general statistics.',
                   'Print a deliveries summary.',
                   'Print {0} deliveries summary.'.format(year),
                   'Save as csv file (You will choose the destination folder).']
        response = pyinputplus.inputMenu(prompt='Choose an option:\n',
                                         choices=choices,
                                         numbered=True)

        if response == choices[0]:
            print(dict_general_stats)

        elif response == choices[1]:
            print(df_deliveries)

        elif response == choices[2]:
            print(df_deliveries_year)

        elif response == choices[3]:
            folder = pyinputplus.inputMenu(prompt='Where do you want to store the data?\n',
                                           choices=[r'C:\Users\borja\Desktop',
                                                    r'C:\Users\borja\Desktop\Borja\2. Data\4. Proyectos '
                                                    r'internos\20210408_Analisis_Entregas'],
                                           numbered=True)

            df_deliveries.to_csv(os.path.join(folder, 'all_deliveries.csv'), index=False)
            df_deliveries_year.to_csv(os.path.join(folder, '{0}_deliveries.csv'.format(year)), index=False)

            print('all_deliveries.csv and {0}_deliveries.csv files created in {1}'.format(year, folder))

        response = pyinputplus.inputMenu(prompt='Do you wish to perform any other operation?\n',
                                         choices=['Yes',
                                                  'No'],
                                         numbered=True)

        if response == 'No':
            display_menu = 0

            print('Exiting the program')

if __name__ == "__main__":
    main()


from django.shortcuts import render
from django.http import HttpResponse, HttpRequest, JsonResponse
from rest_framework.serializers import Serializer
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import PatientAccount, PatientsHistory
from .serializers import PatientAccountSerializer, PatientsHistorySerializer
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.generics import CreateAPIView
from rest_framework import generics
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.parsers import JSONParser, ParseError
from rest_framework.decorators import api_view
from django.contrib.auth.hashers import make_password
from django.conf import settings
from datetime import datetime
from django.contrib.auth import get_user_model
from django.core.mail import send_mail
from django.contrib.auth.hashers import make_password, check_password
import jwt
import json
import uuid
import os
import vonage
import random
import math
from dotenv import load_dotenv

load_dotenv()

# Create your views here.
class PatientRegistrationView(CreateAPIView):
    def post(self, request):
        serializer = PatientAccountSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        if serializer.save():
            return Response({
                "message":"successfully Registered"
            })
        return Response(serializer.data)

class PatientsListsView(APIView):
    def get(self, request):
        token = request.COOKIES.get('20mxJAM')
        if not token:
            raise AuthenticationFailed('Unauthenticated')
        try:
            payload = jwt.decode(token, 'secret', algorithm=['HS256'])
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed('Unauthenticated')
        patients = PatientAccount.objects.filter(account_created_hospital_id=payload['hospital_id']).all()
        serializer = PatientAccountSerializer(patients, many=True)
        return JsonResponse(serializer.data, safe=False)

class PatientsView(APIView):
    def get(self, request):
        patients = PatientAccount.objects.all()
        serializer = PatientAccountSerializer(patients, many=True)
        return JsonResponse(serializer.data, safe=False)

class PatientsDataView(APIView):
    def get(self, request):
        aadhar_number = request.GET['aadhar_number']
        user = PatientAccount.objects.filter(aadhar_number=aadhar_number).first()
        serializer = PatientAccountSerializer(user)
        return Response(serializer.data)

class PatientLoginSentOTPView(APIView):
    def post(self,request):
        aadhar_number = request.data['aadhar_number']
        user = PatientAccount.objects.filter(aadhar_number=aadhar_number).first()
        if user is None:
            raise AuthenticationFailed('Registration ID is not Valid')

        serializer = PatientAccountSerializer(user)
        patientData=serializer.data
        mobile=patientData['mobile_no']
        email=patientData['email']
        name=patientData['patient_name']

        digits = [i for i in range(0, 10)]
        generate_otp = ""
        for i in range(5):
            index = math.floor(random.random() * 10)
            generate_otp += str(digits[index])

        client = vonage.Client(key=os.environ.get("VONGAGE_API_KEY"), secret=os.environ.get("VONGAGE_API_SECRET"))
        sms = vonage.Sms(client)
        responseData = sms.send_message(
            {
                "from": "JAM",
                "to": f"91{mobile}",
                "text": f"Hello {name}, Your OTP code is : {generate_otp}",
            }
        )

        if responseData["messages"][0]["status"] == "0":
            print("OTP sent successfully.")

            user.otp_code=generate_otp
            user.save()

            subject = "Your OTP to Login"
            msg = f"Hello {name}, Your OTP code is : {generate_otp}"
            to =email
            res = send_mail(subject, msg, settings.EMAIL_HOST_USER, [to])
            if res:
                print("Mail Send Successfully")

        else:
            print(
                f"Message failed with error: {responseData['messages'][0]['error-text']}")

        response = Response()
        response.data = {
            'message': 'OTP code was succesfully sent to your Email and Mobile, Check it!',
        }
        return response

class PatientLoginVerifyOTPView(APIView):
    def post(self, request):
        aadhar_number = request.data['aadhar_number']
        otp_code = request.data['otp_code']
        user = PatientAccount.objects.filter(aadhar_number=aadhar_number,otp_code=otp_code).first()

        response = Response()

        if user is None:
            response.data = {
                'result': 'Failed',
                'message':'Entered OTP is incorrect'
            }
        else:
            payload = {
                'user_id': user.aadhar_number,
                'exp': 24 * (datetime.today().timestamp()),
                'lat': datetime.today().timestamp()
            }

            token = jwt.encode(payload, 'secret', algorithm='HS256').decode('utf-8')

            response = Response(user)

            response.set_cookie(key='20mxJAM', value=token, httponly=True)

            response.data = {
                'result': 'Success',
                'message':'OTP verified Successfully',
                'user_id': user.aadhar_number,
                'hospital_id': user.account_created_hospital_id,
                'email': user.email,
                'interface': 'Patient',
                'token': token,
                "payload": payload
            }
        return response

class PatientAuthenticateView(APIView):
    def get(self, request):
        token = request.COOKIES.get('20mxJAM')
        if not token:
            raise AuthenticationFailed('Unauthenticated')
        try:
            payload = jwt.decode(token, 'secret', algorithm=['HS256'])
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed('Unauthenticated')
        user = PatientAccount.objects.filter(aadhar_number=payload['user_id']).first()
        serializer = PatientAccountSerializer(user)
        return Response(serializer.data)

class PatientLogoutView(APIView):
    def post(self, request):
        response = Response()
        response.delete_cookie('20mxJAM')
        response.data = {'message': 'success'}
        return response

""" class MobileVerifyView(APIView):
    def put(self, request, *args, **kwargs):
        digits = [i for i in range(0, 10)]
        generate_otp = ""
        for i in range(6):
            index = math.floor(random.random() * 10)
            generate_otp += str(digits[index])

        client = vonage.Client(key="", secret="")
        sms = vonage.Sms(client)
        responseData = sms.send_message(
            {
                "from": "JAM",
                "to": f"91{serializer.validated_data['mobile_no']}",
                "text": f"Hello {serializer.validated_data['patient_name']}, Your OTP code is : {generate_otp}",
            }
        )

        if responseData["messages"][0]["status"] == "0":
            print("Message sent successfully.")
        else:
            print(f"Message failed with error: {responseData['messages'][0]['error-text']}")

class EmailVerifyView(APIView):
     subject = "Verify Your Account"
        msg = f"Hello {serializer.validated_data['patient_name']}, Your OTP code is : {generate_otp}"
        to = serializer.validated_data['email']
        res = send_mail(subject, msg, settings.EMAIL_HOST_USER, [to])
         """

class PatientsPrescriptionView(CreateAPIView):
    def post(self, request):
        serializer = PatientsHistorySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        if serializer.save():
            return Response({
                "message": "Prescription Added successfully"
            })
        return Response(serializer.data)

class PatientsPrescriptionDataView(APIView):
    def get(self, request):
        aadhar_number = request.GET['aadhar_number']
        user = PatientsHistory.objects.filter(aadhar_number=aadhar_number).all()
        serializer = PatientsHistorySerializer(user, many=True)
        return JsonResponse(serializer.data, safe=False)


#to be imported into a python kernel.
import numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import utils
import gym
import warnings
warnings.filterwarnings('ignore')
import argparse
import pickle

parser = argparse.ArgumentParser(description="Play Backgammon")

parser.add_argument('-begin',
                    dest='begin',
                    action='store_true',
                    help='Start the game')
parser.add_argument('-starting_player',
                    dest='colour',
                    type=str,
                    default='X',
                    help='Define which player starts first (Either X or O)')
parser.add_argument('-ai',
                    dest='ai',
                    type=int,
                    default=None,
                    nargs='+',
                    help='Define what you have rolled, so the agent can choose the optimal move')
parser.add_argument('-human',
                    dest='human',
                    default=None,
                    nargs='+',
                    help='Define what move the opponent has done.')
parser.add_argument('-skip',
                    dest='skip',
                    action='store_true',
                    help='Parse if a human player cannot go.')

args = parser.parse_args()

trained_model = torch.load('./model.pth')

player = {0 : 'Red', 1 : 'Black'}
pieces = {0 : 'X', 1 : 'O'}
opp_pieces = {'X' : 0, 'O' : 1}

env = gym.make('gym_backgammon:backgammon-v0')

def save(state, agent_colour, only_agent_colour=False):
    if only_agent_colour == False:
        with open("state.pickle", "wb") as f:
            pickle.dump(state, f)

    with open("agent_colour.pickle", "wb") as f:
        pickle.dump(agent_colour, f)

def load():

    state = pickle.load(open("state.pickle", "rb"))
    agent_colour = pickle.load(open("agent_colour.pickle", "rb"))

    return state, agent_colour

def start_game():

    agent_colour, roll, state = env.reset()

    while opp_pieces[args.colour] != agent_colour:

        agent_colour, roll, state = env.reset()

    print()
    env.render()
    print('{} player to start.'.format(pieces[agent_colour]))

    save_state = env.game.save_state()

    save(save_state, agent_colour)

def ai_move():

    #get back to the current state:
    state, agent_colour = load()
    env.game.restore_state(state)
    env.current_agent = agent_colour

    #load the agent in the environment
    network = torch.load('./model.pth')
    agent = utils.TD_BG_Agent(env, agent_colour, network)

    #sort the roll depending on whos turn it is.
    roll = np.array(args.ai)
    roll = -roll if agent_colour == 1 else roll

    action_set = env.get_valid_actions(tuple(roll))

    if len(action_set) == 0:
        print()
        print('You can not make a move given your roll!')
        print()
        env.render()

        next_agent_colour = env.get_opponent_agent()

        save_state = env.game.save_state()

        save(save_state, next_agent_colour)

    else:
        action = agent.best_action(tuple(-roll))
        next_state, _, terminal, _ = env.step(action)

        if terminal:
            print()
            print('AI has won!')
        else:
            print()
            print('Estimated probability AI is going to win: {}'.format(agent.network(torch.Tensor(next_state))[0]))

        #observe action
        print()
        print('AI chose action: {}'.format(action))
        print()
        env.render()

        next_agent_colour = env.get_opponent_agent()
        print('{} player to move.'.format(pieces[next_agent_colour]))

        save_state = env.game.save_state()

        save(save_state, next_agent_colour)

def human_move():

    '''Play a move'''

    #get back to the current state:
    state, agent_colour = load()
    env.game.restore_state(state)
    env.current_agent = agent_colour

    #play the move that the human chose.
    action = args.human

    #For the case when you want to move pieces from the bar onto the board.
    for i in range(len(action)):
        try:
            action[i] = int(action[i])
        except:
            pass

    action = tuple(map(tuple, np.array(action, dtype=object).reshape(-1,2)))

    try:
        next_state, _, terminal, _ = env.step(action)
    except AssertionError:
        raise ValueError('Action {} is invalid. (You are moving the ({}) pieces.)'.format(action, pieces[agent_colour]))

    print()
    env.render()

    if terminal:
        print('{} player won!'.format(pieces[agent_colour]))
    else:

        next_agent_colour = env.get_opponent_agent()

        print('{} player to move.'.format(pieces[next_agent_colour]))

        save_state = env.game.save_state()

        save(save_state, next_agent_colour)

if __name__ == '__main__':

    if args.begin:
        start_game()
    elif args.ai is not None:
        ai_move()
    elif args.skip:

        state, agent_colour = load()
        env.game.restore_state(state)
        env.current_agent = agent_colour

        next_agent_colour = env.get_opponent_agent()
        print()
        print('{} player has skipped their go.'.format(pieces[agent_colour]))
        print()
        env.render()
        print('{} player to move.'.format(pieces[next_agent_colour]))
        save(state, next_agent_colour, only_agent_colour=True)
    else:
        human_move()


from collections import Counter
from wordcloud import WordCloud as _WordCloud
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords

class WordCloud:

    def __init__(self, filename, numOfWords = 10):
        self.filename = filename
        self.numOfWords = numOfWords
        self.filetext = self.loadFile(filename)
        self.cloud = self.makeCloud(self.filetext.lower())

    def loadFile(self, filename):
        file = open(filename, encoding="utf8")
        return file.read()

    def makeCloud(self, fileText):
        stopwordslist = set(stopwords.words('english'))
        tokenizer = RegexpTokenizer(r'\w+')
        token = tokenizer.tokenize(fileText)
        tokens = [w for w in token if w not in stopwordslist]
        count = Counter(tokens)
        countTF =  Counter({k:float(v)/float(len(fileText)) for k,v in count.items()})
        wordcloud = _WordCloud(background_color='white')
        countNumOfWords = dict(countTF.most_common(self.numOfWords))
        wordcloud.generate_from_frequencies(frequencies=countNumOfWords)
        return wordcloud

    def getCloud(self):
        return self.cloud


from sys import argv, exit
import csv

def main():
    if len(argv) != 3:
        print("Usage: python dna.py data.csv sequence.txt")
        exit(1)

    # argv[0] is the name of program (dna.py)
    db_path = argv[1]
    seq_path = argv[2]

    # load database from file to memory
    with open(db_path, newline='') as csvfile:
        #database = list(DictReader(csvfile))
        database = csv.reader(csvfile)
        for row in database:
            print(row)

    exit(0)

main()


# -*- coding: utf-8 -*-
"""
Created on Wed Mar 11 12:43:34 2015

@author: ryuhei
"""

import os
import natsort

dir_name = 'data'

file_paths = [] # 空のリストを作成する
for file_name in os.listdir(dir_name):
    # os.path.joinを使ってフォルダ名とファイル名を結合している。 今回の場合は、
    # dir_name + "\\" + filename としても結果は同じだが、この方法を使うことが望ましい。
    # この方法なら、もしdir_nameの末尾にバックスラッシュがあったり、Linuxの場合（"\\"ではなく"/"）でもOK。
    file_path = os.path.join(dir_name, file_name)
    file_paths.append(file_path) # リストにファイルパスを追加する

#file_paths.sort() # この方法では思ったようにソートされない
file_paths = natsort.natsorted(file_paths) # 自然順ソート
print(file_paths)

# file_pathsのファイル達から順番に中身を読み出し、textに一文字ずつ追加する
text = ""
for path in file_paths:
    f = open(path, 'r')
    char = f.read()
    text += char
    f.close()

print(text)


from var import tokens, S, dic, predictSet, gramTree, grammarError, vt

def my_to_dict(self, nid=None):
    nid = self.root if (nid is None) else nid
    ntag = self[nid].tag
    tree_dict = {"name": ntag, "children": []}
    if self[nid].expanded:
        queue = [self[i] for i in self[nid].successors(self._identifier)]
        for elem in queue:
            tree_dict["children"].append(
                my_to_dict(self, elem.identifier))
        if len(tree_dict["children"]) == 0:
            tree_dict = {"name": ntag}
        return tree_dict

# 记录token信息
class infoNode:
    def __init__(self, nextBrotherId=-1, tokenInfo=None):
        self.nextBrotherId = nextBrotherId
        self.tokenInfo = tokenInfo

def ll1():
    id = 0  # 用于标志每一个树节点
    info = infoNode()
    gramTree.create_node(tag=S, identifier=id, data=info)
    cur_node = gramTree.get_node(id)
    id += 1

    i = 0
    tokensLen = len(tokens)
    while i < tokensLen:
        token = tokens[i]
        empty_tag = False
        while cur_node.tag != token["lex"] and cur_node.tag != '$':
            if cur_node.tag in vt:
                err = '出现语法错误!错误位置：' + '\n' + 'line:' + token["line"] + '\n' + 'lex:' + token["lex"] + '\n' + 'sem:' + \
                      token["sem"]+ '实际应匹配字符：' + cur_node.tag
                raise grammarError(err)
            branch_tag = False
            empty_tag = False
            for formula in dic[cur_node.tag].split(' | '):
                if token["lex"] in predictSet[cur_node.tag + ' = ' + formula]:
                    branch_tag = True
                    # 创建结点
                    vl = formula.split(' ')
                    cur_id = 0
                    for v in range(len(vl)):
                        if v == 0:  # 更新当前结点
                            cur_id = id
                        nextBrotherId = id + 1 if v != len(vl) - 1 else -1
                        info = infoNode(nextBrotherId=nextBrotherId)
                        gramTree.create_node(tag=vl[v], identifier=id, parent=cur_node.identifier, data=info)
                        id += 1
                    cur_node = gramTree.get_node(cur_id)
                    if cur_node.tag == '$':
                        empty_tag = True
                    break
            if not branch_tag:
                cor_vt = set()
                for formula in dic[cur_node.tag].split(' | '):
                    cor_vt |= predictSet[cur_node.tag + ' = ' + formula]
                err = '出现语法错误!错误位置：' + '\n' + 'line:' + token["line"] + '\n' + 'lex:' + token["lex"] + '\n' + 'sem:' + \
                      token["sem"]+ '实际应匹配字符：' + str(cor_vt)
                raise grammarError(err)
        # 匹配成功
        if not empty_tag:
            i += 1
            cur_node.data.tokenInfo = token
        # token序列前进

        # grammarTree回溯
        root_tag = False
        while cur_node.data.nextBrotherId == -1:
            cur_node = gramTree.parent(cur_node.identifier)
            if cur_node.is_root():
                root_tag = True
                break;
        # 正常情况
        if not root_tag and i < tokensLen:
            cur_node = gramTree.get_node(cur_node.data.nextBrotherId)
        # 异常处理
        if root_tag and i < tokensLen:
            err = '出现语法错误!' + '\n' + '语句多余，多余位置:' + '\n' + 'line:' + tokens[i]["line"] + '\n' + 'lex:' + tokens[i][
                "lex"] + '\n' + 'sem:' + tokens[i]["sem"]
            raise grammarError(err)
        if not root_tag and i == tokensLen:
            err = '出现语法错误!' + '\n' + '程序不完整'
            raise grammarError(err)
    return my_to_dict(gramTree)


#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Wed May 22 18:43:00 2019

@author: ammar
"""
import numpy as np
import pandas as pd
from .data_prep import data_prep
import warnings
warnings.filterwarnings("ignore")

def load_datasets(geno_location,expr_location):
    df_expr = pd.read_table(expr_location)
    df_geno = pd.read_table(geno_location)
    # truncate row names to match genotype data
    df_expr.index = [x.split("-")[0] for x in df_expr.index]

    exprdata = df_expr.values
#    expr_indv = df_expr.index.values
    geno_data = df_geno.values
#    geno_indv = df_geno.index.values

    Zall = geno_data
    Y = exprdata

    C,Znall,Yn = data_prep(Y,Zall)

    return(C,Znall,Yn)


class Transaction:
    # tr for transactions
    # def __init__(self, tr_date, tr_sender, tr_amount, tr_reason, tr_bank, tr_receiver, tr_id):
    def __init__(self, transaction):
        # self.tr_date = tr_date
        # self.tr_sender = tr_sender
        # self.tr_amount = tr_amount
        # self.tr_reason = tr_reason
        # self.tr_bank =  tr_bank
        # self.tr_receiver = tr_receiver
        # self.tr_id = tr_id
        self.transaction = transaction
        self.tr_date = self.get_tr_date()
        self.tr_sender = self.get_tr_sender()
        self.tr_amount = self.get_tr_amount()
        self.tr_reason = self.get_tr_reason()
        self.tr_bank = self.get_tr_bank()
        self.tr_receiver = self.get_tr_receiver()
        self.tr_id = self.get_tr_id()

    def get_tr_date(self):
        return self.transaction.date


""" Methods for PhotosDB to process Syndication info (#1054) """

from __future__ import annotations

from typing import TYPE_CHECKING

from .._constants import _DB_TABLE_NAMES, _PHOTOS_SYNDICATION_MODEL_VERSION
from ..sqlite_utils import sqlite_open_ro

if TYPE_CHECKING:
    from osxphotos.photosdb import PhotosDB

def _process_syndicationinfo(self: PhotosDB):
    """Process syndication information"""

    self._db_syndication_uuid = {}

    if self.photos_version < 7:
        raise NotImplementedError(
            f"syndication info not implemented for this database version: {self.photos_version}"
        )

    if self._model_ver < _PHOTOS_SYNDICATION_MODEL_VERSION:
        return

    _process_syndicationinfo_7(self)

def _process_syndicationinfo_7(photosdb: PhotosDB):
    """Process Syndication info for Photos 8.0 and later

    Args:
        photosdb: an OSXPhotosDB instance
    """

    db = photosdb._tmp_db
    zasset = _DB_TABLE_NAMES[photosdb._photos_ver]["ASSET"]

    (conn, cursor) = sqlite_open_ro(db)

    result = cursor.execute(
        f"""
        SELECT
        {zasset}.ZUUID,
        {zasset}.ZSYNDICATIONSTATE,
        ZADDITIONALASSETATTRIBUTES.ZSYNDICATIONHISTORY,
        ZADDITIONALASSETATTRIBUTES.ZSYNDICATIONIDENTIFIER
        FROM {zasset}
        JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {zasset}.Z_PK
        """
    )

    for row in result:
        uuid = row[0]
        syndication_state = row[1]
        syndication_history = row[2]
        syndication_identifier = row[3]
        photosdb._db_syndication_uuid[uuid] = {
            "syndication_state": syndication_state,
            "syndication_identifier": syndication_identifier,
            "syndication_history": syndication_history,
        }


import numpy as np
import matplotlib.pyplot as plt
from multiprocessing import Pool
import os

cipherFile = open('cipher.txt', 'rt')
cipherFileSplit = []
ciphertext = []
timeTaken = []
Td4 = [
    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
    0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
    0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
    0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
    0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
    0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
    0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
    0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
    0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
    0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
    0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
    0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
]

CACHE_LINE_SIZE = 128  # bytes
Te4_ELEM_SIZE = 4  # bytes

def calcRequests(cipher, key_byte_guess, bytePosition):
    kj = key_byte_guess  # key byte that is being guessed

    cache_line_count = 0

    # number of Te4 table elements in one cache line
    num_elems = int(CACHE_LINE_SIZE / Te4_ELEM_SIZE)

    # size of array = no. of unique cache lines needed for the full table
    #               = no. of elems in Te4 / no. of elems in one cache line
    holder = [0] * int(256/num_elems)

    for i in range(0, 32):
        holder[int(Td4[cipher[i * 16 + bytePosition] ^ kj] / num_elems)] += 1

    for i in holder:
        if i != 0:
            cache_line_count += 1
    return cache_line_count

def main(bytePosition):
    x = [[] for i in range(0,256)]

    for lineNumber, splitLine in enumerate(cipherFileSplit):
        for keyByteGuess in range(0, 256):
            num_requests = calcRequests(
                ciphertext[lineNumber], keyByteGuess, bytePosition)
            x[keyByteGuess].append(num_requests)

    correlationsArr = []
    for keyByteGuess in range(0, 256):
        correlationsArr.append(np.corrcoef(x[keyByteGuess], timeTaken)[0, 1])

    assert(len(correlationsArr) == 256)
    with open(f'byte{bytePosition}/cacheLineSize{CACHE_LINE_SIZE}/corFile.txt', 'wt') as corFile:
        print(correlationsArr, file = corFile)
    plt.plot(correlationsArr)
    plt.savefig(f'byte{bytePosition}/cacheLineSize{CACHE_LINE_SIZE}/correlation-guessedValue-plot.png')

    # now, we are going to perform a scatter plot
    # for the timing vs cache line requests for the
    # guessed key byte with the best correlation coefficent
    # between those two quantities

    bestGuess = np.argmax(correlationsArr)
    plt.clf()
    plt.scatter(x[bestGuess], timeTaken)
    plt.savefig(f'byte{bytePosition}/cacheLineSize{CACHE_LINE_SIZE}/scatter-kernelTime-numCacheLines.png')
    with open(f'byte{bytePosition}/cacheLineSize{CACHE_LINE_SIZE}/bestGuess', 'wt') as bgFile:
        print(bestGuess, file=bgFile)

if __name__ == '__main__':
    for line in cipherFile:
        cipherFileSplit.append(line.strip().split(':'))
    cipherFile.close()

    for splitLine in cipherFileSplit:
        timeTaken.append(int(splitLine[0]))
        ciphertext.append(list(bytes.fromhex(splitLine[2])))

    pool = Pool(os.cpu_count())
    pool.map(main, [i for i in range(0, 16)])


import math

# 2D transformation matrices are represented as tuple (a1,a2,a3,a4,a5,a6)
# which correspond to this transformation matrix:
# a1 a2 a3
# a4 a5 a6
#  0  0  1
# see http://stackoverflow.com/questions/1114257/transform-a-triangle-to-another-triangle

def affineTransformFromMovementOfThreePoints(p1Before, p2Before, p3Before, p1After, p2After, p3After):
    x11 = p1Before[0]
    x12 = p1Before[1]
    x21 = p2Before[0]
    x22 = p2Before[1]
    x31 = p3Before[0]
    x32 = p3Before[1]
    y11 = p1After[0]
    y12 = p1After[1]
    y21 = p2After[0]
    y22 = p2After[1]
    y31 = p3After[0]
    y32 = p3After[1]

    a1 = ((y11 - y21) * (x12 - x32) - (y11 - y31) * (x12 - x22)) / (
            (x11 - x21) * (x12 - x32) - (x11 - x31) * (x12 - x22))
    a2 = ((y11 - y21) * (x11 - x31) - (y11 - y31) * (x11 - x21)) / (
            (x12 - x22) * (x11 - x31) - (x12 - x32) * (x11 - x21))
    a3 = y11 - a1 * x11 - a2 * x12
    a4 = ((y12 - y22) * (x12 - x32) - (y12 - y32) * (x12 - x22)) / (
            (x11 - x21) * (x12 - x32) - (x11 - x31) * (x12 - x22))
    a5 = ((y12 - y22) * (x11 - x31) - (y12 - y32) * (x11 - x21)) / (
            (x12 - x22) * (x11 - x31) - (x12 - x32) * (x11 - x21))
    a6 = y12 - a4 * x11 - a5 * x12

    matrix = (a1, a2, a3,
              a4, a5, a6)
    # third row 0, 0, 1 is skipped

    return matrix

# see best http://stackoverflow.com/tags/affinetransform/info
def getTransformComponents(matrix):
    # Matrix:
    # a b x
    # c d y

    a = matrix[0]
    b = matrix[1]
    x = matrix[2]
    c = matrix[3]
    d = matrix[4]
    y = matrix[5]

    if a * d < 0:
        if a < 0:
            flip = 1
            a = -a
            b = -b
        else:
            flip = 2
            d = -d
            c = -c
    else:
        flip = 0

    rx = math.atan2(-b, a)
    ry = math.atan2(c, d)

    if abs(rx) < abs(ry):
        r = rx
        skew_rx = 0
        skew_ry = ry - rx
        scale_x = math.sqrt(a * a + b * b)
        scale_y = d / (math.cos(r) - math.sin(r) * math.tan(skew_ry))
    else:
        r = ry
        skew_ry = 0
        skew_rx = ry - rx
        scale_y = math.sqrt(d * d + c * c)
        scale_x = a / (math.cos(r) + math.sin(r) * math.tan(skew_rx))

    if 1 == flip:
        scale_x = -scale_x
    if 2 == flip:
        scale_y = -scale_y

    result = {
        'translation': (x, y),
        'rotation': r,
        'shear': (skew_rx, skew_ry),
        'scale': (scale_x, scale_y)
    }

    return result

# ALTERNATIVE
# see also http://stackoverflow.com/questions/4361242/extract-rotation-scale-values-from-2d-transformation-matrix
def getTranslationFromAffineTransformation(matrix):
    return matrix[2], matrix[5]

def getRotationFromAffineTransformation(matrix):
    c = matrix[3]
    d = matrix[4]
    rotation = math.atan(c / d)
    return rotation

def getScaleFromAffineTransformation(matrix):
    a = matrix[0]
    b = matrix[1]
    c = matrix[3]
    d = matrix[4]
    scaleX = math.sqrt(a * a + b * b)
    scaleY = math.sqrt(c * c + d * d)
    if a < 0:
        scaleX = scaleX * -1
    if b < 0:
        scaleY = scaleY * -1

    return scaleX, scaleY


import argparse
import asyncio
import configparser
import errno
import logging
import os
import time
from aiohttp.errors import DisconnectedError
from contextlib import suppress
from logging.handlers import TimedRotatingFileHandler
from websockets.exceptions import InvalidState

import discord
import discord.ext.commands as dec

import commandhandler
import database.bot
import database.common
import helpformatter
import player
import streamserver
import usermanager

# set up a logger
logging.Formatter.converter = time.gmtime
log = logging.getLogger('ddmbot')
log.setLevel(logging.INFO)

# load opus library if needed
if not discord.opus.is_loaded():
    discord.opus.load_opus('opus')

# helper function to take care of named pipe creation
def create_pipe(pipe_path):
    try:
        os.mkfifo(pipe_path, mode=0o600)
    except OSError as e:
        if not e.errno == errno.EEXIST:
            raise

#
# Safe Voice Client to use as an placeholder before voice connection is created
#
_VOICE_CHANNELS = 2
_VOICE_BITRATE = 48000

class DummyVoiceClient:
    def __init__(self):
        self.encoder = discord.opus.Encoder(_VOICE_BITRATE, _VOICE_CHANNELS)

    @staticmethod
    def is_connected():
        return False

    def play_audio(self, data, *, encode=True):
        pass

#
# Main DdmBot class (discord.ext.commands.Bot wrapper)
#
class DdmBot:
    def __init__(self, config_file):
        # read configuration
        self._config = configparser.ConfigParser(default_section='ddmbot')
        self._config.read(config_file)

        # create named pipes (FIFOs)
        create_pipe(self._config['ddmbot']['aac_pipe'])
        create_pipe(self._config['ddmbot']['int_pipe'])
        create_pipe(self._config['ddmbot']['pcm_pipe'])

        # create event loop and a new client (bot)
        self._loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self._loop)
        self._init_lock = asyncio.Lock(loop=self._loop)
        self._voice_lock = asyncio.Lock(loop=self._loop)
        self._initialized = asyncio.Event(loop=self._loop)
        self._client = dec.Bot(loop=self._loop, command_prefix=self._config['ddmbot']['delimiter'],
                               formatter=helpformatter.DdmBotHelpFormatter(),
                               help_attrs={'hidden': True, 'aliases': ['h']}, pm_help=True)

        # register event listeners
        self._client.event(self.on_error)
        self._client.event(self.on_message)
        self._client.event(self.on_ready)
        self._client.event(self.on_voice_state_update)

        # future runtime objects -- initialized to None
        self._database = None
        self._player = None
        self._server = None
        self._stream = None
        self._users = None

        self._command_handler = None

        self._text_channel = None
        self._log_channel = None
        self._voice_channel = None
        self._direct_channel = None

        self._operator_role = None

        self._voice_client = DummyVoiceClient()

        self._bot_task = None
        self._restart = False

    #
    # Methods for setup and cleanup
    #
    def run(self):
        try:
            self._database = database.bot.BotInterface(self._loop, self._config['ddmbot'])
            self._stream = streamserver.StreamServer(self)
            self._player = player.Player(self)
            self._users = usermanager.UserManager(self)
        except:
            self._loop.run_until_complete(self._client.close())
            self._loop.close()
            raise

        try:
            self._loop.run_until_complete(self._player.init())
            self._loop.run_until_complete(self._stream.init())
            self._loop.run_until_complete(self._client.login(self._config['discord']['token']))

            self._bot_task = asyncio.gather(self._database.task_credit_renew(), self._users.task_check_timeouts(),
                                            self._player.task_player_fsm(), self._client.connect(), loop=self._loop)

            try:
                self._loop.run_until_complete(self._bot_task)
            except asyncio.CancelledError:
                pass
            finally:
                self._bot_task.cancel()
                with suppress(asyncio.CancelledError):
                    self._loop.run_until_complete(self._bot_task)

            # determine if we wanna shut down the bot instead of restarting it
            if not self._restart:
                raise KeyboardInterrupt()

        finally:
            self._loop.run_until_complete(self._client.logout())
            self._loop.run_until_complete(self._player.cleanup())
            self._loop.run_until_complete(self._stream.cleanup())

            pending = asyncio.Task.all_tasks()
            for task in pending:
                task.cancel()
                with suppress(asyncio.CancelledError, asyncio.TimeoutError, InvalidState, OSError):
                    self._loop.run_until_complete(task)

            self._loop.close()

    async def shutdown(self):
        await asyncio.sleep(3, loop=self._loop)
        self._bot_task.cancel()

    def restart(self):
        self._restart = True
        return self.shutdown()

    #
    # Event listeners
    #
    async def on_ready(self):
        async with self._init_lock:
            if self._initialized.is_set():
                log.info('DdmBot connection to discord was restored')
                self._loop.create_task(self.connect_voice())
                return

            log.info('DdmBot connected as {0} (ID: {0.id})'.format(self._client.user))
            self._setup_discord_objects()
            self._initialized.set()

        await self.connect_voice()

        # populate initial listeners
        for member in self._voice_channel.voice_members:
            if member == self._client.user:
                continue
            with suppress(database.bot.IgnoredUserError):
                if await self._database.interaction_check(int(member.id)):
                    await self._send_welcome_message(member)
                await self._users.add_listener(int(member.id), direct=False)

        # enable commands by creating a command_handler object
        self._command_handler = commandhandler.CommandHandler(self)
        # at this point, bot should be ready
        log.info('Initialization done')

    async def on_message(self, message):
        # we don't want to process bot's messages at all
        if message.author == self._client.user:
            return
        # author of the message wrote something, which is kinda a proof (s)he is alive
        await self._users.refresh_activity(int(message.author.id))
        # do ignore list pre-check ourselves if this appears to be a command
        if message.content.lstrip().startswith(self._config['ddmbot']['delimiter']):
            with suppress(database.bot.IgnoredUserError):
                if await self._database.interaction_check(int(message.author.id)):
                    await self._send_welcome_message(message.author)
                await self._client.process_commands(message)
        # else if not command, check if the channel is the text_channel, if so, refresh the counter
        elif message.channel == self._text_channel:
            self._player.bump_protection_counter()

    async def on_voice_state_update(self, before, after):
        if before == self._client.user:
            if after.voice.voice_channel != self._voice_channel:
                log.warning('Client was disconnected from the voice channel')
                await self.connect_voice()
            return
        # joining
        if before.voice.voice_channel != self._voice_channel and after.voice.voice_channel == self._voice_channel:
            with suppress(database.bot.IgnoredUserError):
                if await self._database.interaction_check(int(after.id)):
                    await self._send_welcome_message(after)
                await self._users.add_listener(int(after.id), direct=False)

        # leaving
        elif before.voice.voice_channel == self._voice_channel and after.voice.voice_channel != self._voice_channel:
            try:
                await self._users.remove_listener(int(after.id), direct=False)
            except ValueError:
                log.warning('Tried to remove {0} (ID: {0.id}) from listeners but the user was not listed'.format(after))

    @staticmethod
    async def on_error(event, *args, **kwargs):
        raise

    #
    # Interaction methods
    #
    def message(self, message):
        return self._client.send_message(self._text_channel, message)

    def whisper(self, message):
        return self._client.whisper(message)

    def whisper_id(self, user_id, message):
        user = discord.utils.get(self._client.get_all_members(), id=str(user_id))
        if user is None:
            log.error('Cannot whisper user {} -- it\'s not a recognized server member'.format(user_id))
            return
        return self._client.send_message(user, message)

    def log(self, message):
        return self._client.send_message(self._log_channel, message)

    async def connect_voice(self):
        log.info('Connecting to the voice channel')
        if self._voice_lock.locked():
            log.warning('Connecting to the voice channel still in progress')
            return
        async with self._voice_lock:
            if self._client.is_voice_connected(self._server):
                log.warning('Client is still connected to the voice channel')
                return
            tmp = await self._client.join_voice_channel(self._voice_channel)
            tmp.encoder_options(sample_rate=_VOICE_BITRATE, channels=_VOICE_CHANNELS)
            self._voice_client = tmp  # TODO: atomicity provided by GIL
            log.info('Voice channel connection succeeded')

    async def wait_for_initialization(self):
        await self._initialized.wait()

    def is_operator(self, user):
        if not isinstance(user, discord.Member):
            user = self._server.get_member(user.id)
        return self._operator_role in user.roles

    @property
    def config(self):
        return self._config

    @property
    def loop(self):
        return self._loop

    @property
    def client(self):
        return self._client

    @property
    def player(self):
        return self._player

    @property
    def server(self):
        return self._server

    @property
    def stream(self):
        return self._stream

    @property
    def users(self):
        return self._users

    @property
    def voice(self):
        return self._voice_client

    @property
    def direct(self):
        return self._direct_channel

    #
    # Internal helpers
    #

    def _setup_discord_objects(self):
        # check the server count, this bot is meant to be run on a single server
        if not self._client.servers:
            raise RuntimeError('Bot needs a server to run on but is connected to none')
        if len(self._client.servers) > 1:
            raise RuntimeError('Bot is connected to multiple servers, multi-server configuration is not supported')
        # store a server variable for later use
        self._server = next(iter(self._client.servers))

        # locate the configured channels, starting with text_channel
        self._text_channel = self._server.get_channel(self._config['discord']['text_channel'])
        if self._text_channel is None:
            raise RuntimeError('Specified text_channel cannot be found')
        if self._text_channel.type != discord.ChannelType.text:
            raise RuntimeError('Specified text_channel is a wrong type')
        text_permissions = self._text_channel.permissions_for(self._server.me)
        if not text_permissions.send_messages:
            raise RuntimeError('Bot does not have a permission to send messages in the text_channel')
        if not text_permissions.read_messages:
            raise RuntimeError('Bot does not have a permission to read messages in the text_channel')
        if not text_permissions.manage_messages:
            raise RuntimeError('Bot does not have a permission to manage messages in the text_channel')

        # log_channel
        self._log_channel = self._server.get_channel(self._config['discord']['log_channel'])
        if self._log_channel is None:
            raise RuntimeError('Specified log_channel cannot be found')
        if self._log_channel.type != discord.ChannelType.text:
            raise RuntimeError('Specified log_channel is a wrong type')
        if not self._log_channel.permissions_for(self._server.me).send_messages:
            raise RuntimeError('Bot does not have a permission to send messages in the log_channel')

        # voice_channel
        self._voice_channel = self._server.get_channel(self._config['discord']['voice_channel'])
        if self._voice_channel is None:
            raise RuntimeError('Specified voice_channel cannot be found')
        if self._voice_channel.type != discord.ChannelType.voice:
            raise RuntimeError('Specified voice_channel is a wrong type')
        voice_permissions = self._voice_channel.permissions_for(self._server.me)
        if not voice_permissions.connect:
            raise RuntimeError('Bot does not have a permission to connect to the voice channel')
        if not voice_permissions.speak:
            raise RuntimeError('Bot does not have a permission to speak in the voice channel')

        # direct_channel -- optional, for seamless stream switch feature
        if 'direct_channel' in self._config['discord'] and self._config['discord']['direct_channel']:
            self._direct_channel = self._server.get_channel(self._config['discord']['direct_channel'])
            if self._direct_channel is None:
                raise RuntimeError('Specified direct_channel cannot be found')
            if self._direct_channel.type != discord.ChannelType.voice:
                raise RuntimeError('Specified direct_channel is a wrong type')
            if not voice_permissions.move_members:
                raise RuntimeError('Bot does not have a permission to move members, either grant it this permission '
                                   'or disable seamless stream switch feature')

        # look up the operator role
        def get_server_roles():
            for role in self._server.roles:
                yield role

        self._operator_role = discord.utils.get(get_server_roles(), id=self._config['discord']['operator_role'])
        if self._operator_role is None:
            raise RuntimeError('Operator role specified cannot be found')

    def _send_welcome_message(self, user):
        return self._client.send_message(user, self._config['ddmbot']['welcome_message']
                                         .format_map(self._config['ddmbot']))

if __name__ == '__main__':
    # parse arguments
    argument_parser = argparse.ArgumentParser(description='Discord Direct Music Bot (DdmBot)')
    argument_parser.add_argument('-c', '--config-file', nargs=1, default='config.ini')
    argument_parser.add_argument('-l', '--log-file', nargs=1, default='ddmbot.log')
    arguments = argument_parser.parse_args()

    # set up logging
    stderr_logger = logging.StreamHandler()
    stderr_logger.setFormatter(logging.Formatter('{asctime} | {levelname:<8} {message}', '%Y-%m-%d %H:%M:%S',
                                                 style='{'))
    log.addHandler(stderr_logger)
    file_logger = TimedRotatingFileHandler(arguments.log_file, when='midnight', backupCount=3, utc=True)
    file_logger.setFormatter(logging.Formatter('{asctime} | {name:<20} | {levelname:<8} {message}',
                                               '%Y-%m-%d %H:%M:%S', style='{'))
    log.addHandler(file_logger)

    try:
        # now there should be an infinite loop trying to fix everything...
        while True:
            # create a ddmbot instance
            ddmbot = DdmBot(arguments.config_file)
            # without a database there is no point in proceeding
            database.common.initialize(ddmbot.config['ddmbot']['db_file'])

            try:
                ddmbot.run()
            except KeyboardInterrupt:
                raise
            except (discord.ConnectionClosed, discord.GatewayNotFound, discord.HTTPException, DisconnectedError):
                log.exception('DdmBot finished with an exception, retrying in 60 seconds')
                time.sleep(60)
            finally:
                # we should always do this to ensure database consistency
                database.common.close()

    except KeyboardInterrupt:
        log.info('DdmBot terminated')
    except Exception:
        log.critical('DdmBot crashed with an exception', exc_info=True)
        raise


from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
import urllib.request
import time
import json

option = Options()
option.headless = False
driver = webdriver.Firefox(options=option)
driver.implicitly_wait(7)
baseurl = "https://www.google.com/"
keyword = "amitabh bachan"
No_Of_Images = 50

driver.get(f"{baseurl}search?q={keyword}")
time.sleep(3)

link_lst = list(driver.find_elements(By.CSS_SELECTOR,"#pTwnEc.yg51vc div#hdtb-msb.IC1Ck div div.MUFPAc div.hdtb-mitem a"))
link_url = list(map(lambda a: a.get_attribute('href'),link_lst))
link_text = list(map(lambda a: a.get_attribute('text'),link_lst))

image_index = 0
for i in range(0,len(link_text)):
    if link_text[i] == "Images":
        image_index = i
        break

driver.get(f"{link_url[image_index]}")
time.sleep(3)

y = 1080
for i in range(0,10):
    location = f"window.scrollTo(0, {y})"
    driver.execute_script(location)
    y = y + 900
    time.sleep(3)

image_link = list(driver.find_elements(By.CSS_SELECTOR,"#islrg div.islrc div.isv-r.PNCib.MSM1fd.BUooTd a.wXeWr.islib.nfEiy div.bRMDJf.islir img.rg_i.Q4LuWd"))

# download the image
count = 1
for url in image_link:
    #count = count + 1
    if count > No_Of_Images:
        driver.close()
        break
    try:
        url.click()
        time.sleep(3)
        link_url = driver.find_element(By.CSS_SELECTOR,".n3VNCb.KAlRDb").get_attribute('src')
        #print(link_url)
        filename = "images/" + link_url.split('/')[-1]
        urllib.request.urlretrieve(link_url, filename)
        count = count + 1
    except:
        pass


import json
import logging
import urllib.request

SWYFTX_API_BASE="https://api.swyftx.com.au/"
SWYFTX_LATEST_BAR="charts/getLatestBar/"
SWYFTX_BASIC_INFO="markets/info/basic/"

def RequestApi(partial_url):
  url = SWYFTX_API_BASE + partial_url
  try:
    # Need to add browser headers
    req = urllib.request.Request(
        url,
        data=None,
        headers={
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
        }
    )
    openurl = urllib.request.urlopen(req)
    return json.loads(openurl.read().decode('utf-8'))
  except Exception as ex:
    logging.error("Failed to send request to " + url)
    logging.error(ex)
    return None

class SwyftxApi:
  _coin_codes=[]
  _base_asset=""
  _resolution=""
  _side=""
  _errors=0
  def __init__(self, base_asset="AUD", resolution="5m", side="bid"):
    self._base_asset = base_asset
    self._resolution = resolution
    self._side = side
    # populate coin codes to start
    basic_info = RequestApi(SWYFTX_BASIC_INFO)
    if basic_info == None:
      logging.fatal("Failed to retrieve list of coins!")

    for coin_info in basic_info:
      self._coin_codes.append(coin_info["code"])

  def get_side(self):
    return self._side

  def get_resolution(self):
    return self._resolution

  def get_base_asset(self):
    return self._base_asset

  def get_latest_bars(self):
    bars={}
    for code in self._coin_codes:
      logging.info("Getting data for " + code)
      coin_data = RequestApi(SWYFTX_LATEST_BAR + self._base_asset + "/" + code + "/" + self._side + "/?resolution=" + self._resolution)
      if coin_data is None:
        self._errors += 1
        logging.error("Failed to get coin data for " + code)
      else:
        bars[code] = coin_data

    return bars

  def get_error_count(self):
    return self._errors


#!/usr/bin/env python3

#python的循环有两种，一种是for..in循环依次把list或者tuple元素迭代出来
names = ["aaa","dsese","deeeeeee"]
for name in names:
	print(name)

#求和
sum = 0
for x in [1,2,3,4,222,5,4,3,433]:
	sum = sum + x
print("sum = ",sum)

#range函数,可以生成一个整数序列在通过工厂方法list()转换成list
a = list(range(100))
sum = 0
for x in a:
	sum = sum + x
print("Range(100) sum is ",sum)

#python的第二种循环是while，只要条件满足就循环，否则退出循环
sum = 0
n = 99
while n > 0:
	sum = sum + n
	n = n - 2
print("while sum is ",sum)


'''
This problem was asked by Google.

Given an array of elements, return the length of the longest subarray where all its elements are distinct.

For example, given the array [5, 1, 3, 5, 2, 3, 4, 1], return 5 as the longest subarray of distinct elements is [5, 2, 3, 4, 1].
'''

def find_subset(arr):
	sorted_arr = sorted(arr)
	sorted_set = sorted(set(sorted_arr), reverse=True)
	print(len(sorted_set))

find_subset([5,1,3,5,2,3,4,1])


import time
from odoo import models, fields, api, _
import odoo.addons.decimal_precision as dp
from odoo.exceptions import except_orm, ValidationError
from odoo.tools import misc, DEFAULT_SERVER_DATETIME_FORMAT
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
from odoo import http

class MemberShipPolicy(models.Model):
    _name = "member.policy"
    _rec_name = "periods_month"
    _order = "id desc"

    """
    Once the user selects the period,
    select the operation type, either activation or deactivation,
    Set the start and end date, click the preview changes button, if operation type is "Deactivation",
    Note:  the filtered list will be the records whose last subscritpion date falls between start and end date
    Click on the confirm changes button: if the operation type is deactivation, it will check all members that is not
    owning set deactivates them. {setting active fied to False}

    If operation type is Activation: click on the Activation changes button and the system automatically generate
    a bill for the records in the member line.
    """

    periods_month = fields.Selection([
        ('Jan-June 2011', 'Jan-June 2011'),
        ('July-Dec 2011', 'July-Dec 2011'),
        ('Jan-June 2012', 'Jan-June 2012'),
        ('July-Dec 2012', 'July-Dec 2012'),
        ('Jan-June 2013', 'Jan-June 2013'),
        ('July-Dec 2013', 'July-Dec 2013'),
        ('Jan-June 2014', 'Jan-June 2014'),
        ('July-Dec 2014', 'July-Dec 2014'),
        ('Jan-June 2015', 'Jan-June 2015'),
        ('July-Dec 2015', 'July-Dec 2015'),
        ('Jan-June 2016', 'Jan-June 2016'),
        ('July-Dec 2016', 'July-Dec 2016'),
        ('Jan-June 2017', 'Jan-June 2017'),
        ('July-Dec 2017', 'July-Dec 2017'),
        ('Jan-June 2018', 'Jan-June 2018'),
        ('July-Dec 2018', 'July-Dec 2018'),
        ('Jan-June 2019', 'Jan-June 2019'),
        ('July-Dec 2019', 'July-Dec 2019'),
        ('Jan-June 2020', 'Jan-June 2020'),
        ('July-Dec 2020', 'July-Dec 2020'),
        ('Jan-June 2021', 'Jan-June 2021'),
        ('July-Dec 2021', 'July-Dec 2021'),
    ], 'Period', index=True, required=True, readonly=False, copy=False,
                                           track_visibility='always')
    state = fields.Selection([
        ('Draft', 'Draft'),
        ('Deactivation', 'Deactivated'),
        ('Activation', 'Activated'),
        ('Invoiced', 'Invoiced'),
    ], 'state', index=True, readonly=False, default="Draft", copy=False,
                                           track_visibility='always')

    operation_type = fields.Selection([
        ('Activation', 'Activation'),
        ('Deactivation', 'Deactivation'),
    ], 'Operation type', default="Deactivation", index=True, required=True, readonly=False, copy=False,
                                           track_visibility='always')
    date_start = fields.Datetime('Filter From', required="True",
                                 default=lambda *a: (datetime.now() - relativedelta(days=29)).strftime('%Y-%m-%d %H:%M:%S'))
    date_end = fields.Datetime('Filter To', required=True,
                                default=lambda *a: (datetime.now() + relativedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))
    get_member_ids = fields.Many2many("member.app", string='Members')
    policy_member_ids = fields.One2many("member.policy.line", 'policy_line_id',
                                        string='Members Policy')
    active = fields.Boolean('Active', default=True)

    # Button to generate members records based on filter date of last subscription
    # @api.onchange('periods_month', 'date_start', 'date_end')
    def preview_changes(self):
        if (self.periods_month) and (self.date_start):
            if not (self.date_start > self.date_end):
                recs = []
                orders = self.env['member.app'].search([('date_of_last_sub', '>=', self.date_start), ('date_of_last_sub', '<=', self.date_end)])
                if len(orders) > 0:
                    for rec in orders:
                        # if (self.date_start <= rec.date_of_last_sub) and (self.date_end >= rec.date_of_last_sub):# and (rec.periods_month == self.periods_month):
                        recs.append(rec.id)
                        self.write({'get_member_ids': [(4, recs)]})
                        # else:
                        #     raise ValidationError('No record found for the filtered date')
            else:
                raise ValidationError('Start date cannot be greater than end start')
        else:
            raise ValidationError('Please insert Period and start date')

    @api.one
    def confirm_deactivation(self):
        if self.operation_type == "Deactivation":
            if self.get_member_ids:
                orders = self.env['member.app'].search([('date_of_last_sub', '>=', self.date_start), ('date_of_last_sub', '<=', self.date_end)])
                if orders:
                    for rec in orders:
                        # self.get_member_ids:
                        if rec.balance_total < 0:
                            rec.write({'activity': 'act'})
                        else:
                            rec.write({'activity': 'inact', 'date_of_last_sub': fields.Datetime.now()})
                else:
                    raise ValidationError('Start date cannot be greater than end start')
            else:
                raise ValidationError("No record generated")
            self.state = 'Deactivation'
        else:
            raise ValidationError("Please ensure you select Operation Type: Activation")

    @api.multi
    def confirm_activation(self):
        if self.operation_type == "Activation":
            if self.get_member_ids:
                member_list = []
                orders = self.env['member.app'].search([('date_of_last_sub', '>=', self.date_start), ('date_of_last_sub', '<=', self.date_end)])
                for partner in orders:
                    member_list.append((0, 0, {
                        'member_id': partner.id,
                        'activation_date': fields.Datetime.now(),
                        'depend_name': [(6, 0, [rec.id for rec in partner.mapped('depend_name')])]
                        }))
                self.write({'policy_member_ids': member_list})
                if len(self.policy_member_ids) > 0:
                    for each in self.policy_member_ids:
                        if each.member_id.section_line:
                            each.create_generate_invoice()
            else:
                raise ValidationError("No record found")
            self.state = "Activation"
        else:
            raise ValidationError("Please ensure you select Operation Type: Activation")

    @api.multi
    def calculate_bill(self):
        for bill in self.policy_member_ids:
            bill.calculate_bill()
        self.state = "Invoiced"

class MemberShipPolicyLine(models.Model):
    _name = "member.policy.line"
    _order = "id desc"

    policy_line_id = fields.Many2one('member.policy', ondelete="cascade")
    member_id = fields.Many2one(
        'member.app',
        'Member ID',
        required=True,
        domain=[
            ('state',
             '!=',
             'suspension')],
        readonly=False)
    identification = fields.Char('Member ID.', size=6, related="member_id.identification")
    state = fields.Selection([
        ('Draft', 'Draft'),
        ('Generated', 'Generated'),

    ], 'state', index=True, readonly=False, default="Draft", copy=False,
                                           track_visibility='always')
    invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete="cascade", store=True)
    activation_date = fields.Datetime('Subscription Date')
    due_dates = fields.Datetime('Due Date')
    subscription = fields.Many2many(
        'subscription.payment',
        string='Add Sections') #, compute='get_all_packages', store=True)

    depend_name = fields.Many2many(
        'register.spouse.member',
        string="Dependents",store=True) # compute='get_all_packages', store=True)
    email = fields.Char('Email', related="member_id.email")
    section_line = fields.Many2many('section.line', string='Add Sections', compute='get_all_packages')
    package = fields.Many2many(
        'package.model',
        string='Packages',
        readonly=False,
        store=True,)
        # compute='get_all_packages')

    total = fields.Float('Total', default =0, compute="gen_total")
    balance_total = fields.Float('Outstanding', default =0)#, compute="gen_total")

    def button_confirm_member(self):
        self.member_id.date_of_last_sub = fields.Datetime.now()
        self.member_id.subscription_period = self.policy_line_id.periods_month
        self.member_id.activity = "act"
        self.member_id.biostar_status = False
        for dep in self.member_id.depend_name:
            dep.biostar_status = False

    @api.multi
    def see_breakdown_invoice(self):
        search_view_ref = self.env.ref(
            'account.view_account_invoice_filter', False)
        form_view_ref = self.env.ref('account.invoice_form', False)
        tree_view_ref = self.env.ref('account.invoice_tree', False)

        return {
            'domain': [('id', 'in', [self.invoice_id.id])],
            'name': 'Membership Invoices',
            'res_model': 'account.invoice',
            'type': 'ir.actions.act_window',
            #  'views': [(form_view_ref.id, 'form')],
            'views': [(tree_view_ref.id, 'tree'), (form_view_ref.id, 'form')],
            'search_view_id': search_view_ref and search_view_ref.id,
        }

    # @api.one
    # @api.depends("subscription","package", "depend_name")
    # def gen_total(self):
    #     # pass
    #     # self.balance_total += [self.member_id.balance_total
    #     subscription_cost, package_cost, depends_cost= 0,0,0
    #     for rec in self.subscription:
    #         subscription_cost += rec.total_cost
    #     for tec in self.package:
    #         package_cost += tec.package_cost
    #     for yec in self.depend_name:
    #         depends_cost += yec.total
    #     self.total = subscription_cost + package_cost + depends_cost

    @api.one
    @api.depends("section_line")
    def gen_total(self):
        member_line = self.member_id.mapped('section_line').filtered(lambda x: x.sub_payment_id.paytype not in ['main_house'])
        depends = self.member_id.mapped('depend_name')
        depends_total = 0
        for rec in depends:
            depend_line = rec.mapped('section_line').filtered(lambda x: x.sub_payment_id.paytype not in ['main_house'])
            depends_total = sum([amt.amount for amt in depend_line])

        subscription_cost = sum([amt.amount for amt in member_line])
        self.total = subscription_cost + depends_total
        self.balance_total = self.member_id.balance_total

    @api.onchange('member_id')
    def get_all_packages(self):
        """This will filter list of subscription that is not of type levy, entry fee, additional fee"""
        get_package = self.env['member.app'].search(
            [('id', '=', self.member_id.id)], limit=1)

        section_line = self.member_id.mapped('section_line').filtered(lambda x: x.sub_payment_id.paytype not in ['addition', 'entry_fee'])
        if section_line:
            self.section_line = section_line
        self.depend_name = get_package.depend_name

    # @api.one
    # @api.depends('member_id')
    # def get_all_packages(self):
    #     appends = []
    #     appends2 = []
    #     appends3 = []
    #     for ret in self.member_id.package:
    #         appends.append(ret.id)
    #     for rett in self.member_id.subscription:
    #         appends2.append(rett.id)
    #         self.subscription = appends2
    #     for spouse in self.member_id.depend_name:
    #         appends3.append(spouse.id)
    #         for spouse_subs in spouse.spouse_subscription:
    #             appends2.append(spouse_subs.subscription.id)
    #     for r in appends:
    #         self.package = [(4, r)]
    #     for r2 in appends2:
    #         self.subscription = [(4, r2)]
    #     for r3 in appends3:
    #         self.depend_name = [(4, r3)]

    # def create_product(self, name):
    #     product = 0
    #     product = self.env['product.product'].search([('name', '=ilike', name)], limit=1)
    #     product = product.id
    #     if not product:
    #         product = self.env['product.product'].create({
    #             'name': name,
    #         }).id
    #     return product

    # def create_branch(self):
    #     branch_id = 0
    #     branch = self.env['res.branch']
    #     branch_search = branch.search([('name', 'ilike', 'Ikoyi Club Lagos')], limit=1)
    #     if not branch_search:
    #         branch_create = branch.create(
    #             {'name': 'Ikoyi Club Lagos', 'company_id': self.env.user.company_id.id or 1})
    #         branch_id = branch_create.id
    #     else:
    #         branch_id = branch_search.id
    #     return branch_id

    @api.multi
    def create_generate_invoice(self):
        for each_depend in self.depend_name:
            depends = self.mapped('depend_name').filtered(lambda a: a.partner_id.property_account_receivable_id == False or a.partner_id.property_account_payable_id == False)
            if depends:
                for rec in depends:
                    rec.partner_id.property_account_receivable_id = self.env['account.account'].search([('user_type_id', '=', 1)], limit=1).id,
                    rec.partner_id.property_account_payable_id = self.env['account.account'].search([('user_type_id', '=', 2)], limit=1).id,
        memberObj = self.env['member.app'].search([('id', '=', self.member_id.id)])
        memberObj.create_white_member_bill()

        self.invoice_id = memberObj.invoice_id[0].id

        # invoice_list, array = [], []
        # invoice = self.env['account.invoice'].create({
        #         'partner_id': self.member_id.partner_id.id,
        #         #  partner.partner_id.property_account_receivable_id.id,
        #         # property_account_payable_id
        #         'account_id': self.member_id.account_id.id,
        #         'fiscal_position_id': self.member_id.partner_id.property_account_position_id.id,
        #         'branch_id': self.env.user.branch_id.id,
        #     })
        # # self.member_id.date_of_last_sub = fields.Datetime.now()
        # self.member_id.activity = "act"
        # self.member_id.invoice_id = [(4, invoice.id)]
        # if self.member_id.balance_total > 0:
        #     array.append((0, 0, {
        #         # 'product_id': self.create_product(each_subscription.name),
        #         'name': "Outanding Credits",
        #         'price_unit': self.member_id.balance_total,
        #         'invoice_id': invoice.id,
        #         'account_id': self.member_id.account_id.id or self.member_id.partner_id.property_account_payable_id.id,
        #         }))
        # for each_subscription in self.subscription:
        #     array.append((0, 0, {
        #         'product_id': self.create_product(each_subscription.name),
        #         'name': "Bills",
        #         'price_unit': each_subscription.total_cost,
        #         'invoice_id': invoice.id,
        #         'account_id': self.member_id.account_id.id or self.member_id.partner_id.property_account_payable_id.id,
        #         }))

        # for each_depend in self.depend_name:
        #     each_depend.partner_id.property_account_receivable_id=self.env['account.account'].search([('user_type_id', '=', 1)], limit=1).id,
        #     each_depend.partner_id.property_account_payable_id=self.env['account.account'].search([('user_type_id', '=', 2)], limit=1).id,

        #     for rex in each_depend.spouse_subscription:

        #         if each_depend.relationship == "Child":
        #             if rex.subscription.name == "Library (Child) -  Subscription" or rex.subscription.name == "Swimming (Child) - Subscription" or rex.subscription.is_child == True:
        #                 array.append((0, 0, {
        #                     'product_id': self.create_product(rex.subscription.name),
        #                     'name': "Child Bills",
        #                     'price_unit': rex.total_fee,
        #                     'invoice_id': invoice.id,
        #                     'account_id': self.member_id.account_id.id if self.member_id.account_id else self.env['account.account'].search([('user_type_id', '=', 1)], limit=1).id, # or self.member_id.partner_id.property_account_payable_id.id,
        #                     }))
        #         else:
        #             array.append((0, 0, {
        #                     'product_id': self.create_product(rex.subscription.name),
        #                     'name': "Dependent Bills for {}".format(each_depend.partner_id.name),
        #                     'price_unit': rex.total_fee,
        #                     'invoice_id': invoice.id,
        #                     'account_id': self.member_id.account_id.id if self.member_id.account_id else self.env['account.account'].search([('user_type_id', '=', 1)], limit=1).id, # or self.member_id.partner_id.property_account_payable_id.id,
        #                     }))

        # invoice.write({'invoice_line_ids': array})
        # self.invoice_id = invoice.id

    def generate_bill(self, amount, product_name):
        array = []
        values = {
                # 'product_id': self.create_product(product_name),
                'price_unit': amount,
                'name': "Desc: "+product_name,
                'invoice_id': self.invoice_id.id,
                'account_id': self.member_id.partner_id.property_account_payable_id.id,
                }
        array.append((0, 0, values))
        self.invoice_id.write({'invoice_line_ids': array})

    @api.multi
    def calculate_bill(self):
        if self.activation_date or self.invoice_id:
            start = datetime.strptime(self.activation_date, "%Y-%m-%d %H:%M:%S")
            end_date = datetime.strptime(fields.Datetime.now(), "%Y-%m-%d %H:%M:%S")
            duration = end_date - start
            duration = int(duration.days)
            if (duration > 89) and (duration in range(89, 91)):
                if self.invoice_id.state != "paid":
                    self.generate_bill(10000, 'Penalty')
                    self.send_mail_to_member()
                    #raise ValidationError("1")

            elif (duration > 90) and (duration in range(90, 180)): ## Session one
                if self.invoice_id.state != "paid":
                    self.generate_bill(110000, 'New Session Extra Charge')
                    self.send_mail_to_member()

            elif (duration > 180) and (duration in range(180, 360)): ## Session two 1year
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.1) - (10000) # 10% of the total bill - the initial penalty (10000)
                    amount = amount + 100000
                    self.generate_bill(amount, '10% Penalty Fee')
                    self.send_mail_to_member()

            elif (duration > 360) and (duration in range(360, 540)): ## Session three
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.1)
                    amount = amount + 100000
                    self.generate_bill(amount, '10% Penalty Fee - Extra')
                    self.send_mail_to_member()

            elif (duration > 540) and (duration in range(540, 720)):   ## Session four 2year
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.05)
                    amount = amount + 100000
                    self.generate_bill(amount, '5% Penalty Fee - Extra')
                    self.send_mail_to_member()

            elif (duration > 720) and (duration in range(720, 900)):  ## Session five
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.05)  # 5% of the total bill -
                    amount = amount + 100000
                    self.generate_bill(amount, '5% Penalty Fee - Extra')
                    self.send_mail_to_member()

            elif (duration > 900) and (duration in range(720, 1080)): ## Session six 3year
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.05)  # 5% of the total bill -
                    amount = amount + 100000
                    self.generate_bill(amount, '5% Penalty Fee - Extra')
                    self.send_mail_to_member()

            elif (duration > 1080) and (duration in range(1080, 1260)):  ## Session seven
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.05)  # 5% of the total bill -
                    amount = amount + 100000
                    self.generate_bill(amount, '5% Penalty Fee - Extra')
                    self.send_mail_to_member()

            elif (duration > 1260) and (duration in range(720, 1440)): ## Session eight 4year
                total = 0.0
                if self.invoice_id.state != "paid":
                    for rec in self.invoice_id.invoice_line_ids:
                        total += rec.amount_total
                    amount = (total * 0.05)  # 5% of the total bill -
                    amount = amount + 100000
                    self.generate_bill(amount, '5% Penalty Fee - Extra')
                    self.send_mail_to_member()
            else:
                pass
                # self.member_id.active = False
                # self.member_id.activity = False
        else:
            raise ValidationError("Oops! No activation Date set for the record.")

    def popup_notification(self,popup_message):
        view = self.env.ref('sh_message.sh_message_wizard')
        view_id = view and view.id or False
        context = dict(self._context or {})
        context['message'] = popup_message # 'Successful'
        return {'name':'Alert',
                    'type':'ir.actions.act_window',
                    'view_type':'form',
                    'res_model':'sh.message.wizard',
                    'views':[(view.id, 'form')],
                    'view_id':view.id,
                    'target':'new',
                    'context':context,
                }

    @api.multi
    def send_mail_to_member(self, force=False):  #  draft
        email_from = self.env.user.company_id.email
        group_user_id = self.env.ref('member_app.manager_member_ikoyi').id
        # extra = self.env.ref('ikoyi_module.inventory_officer_ikoyi').id
        extra = self.email
        bodyx = "Dear Sir/Madam, </br>We wish to notify that you -ID {} , that your membership subscription is \
        due for payment. An extra Penalty charge have been added to you bill: {} </br> Kindly contact the Ikoyi Club 1968 for any further enquires. \
        </br>Thanks" .format(self.member_id.identification, fields.Datetime.now())
        self.mail_sending(email_from, group_user_id, extra, bodyx)

    # @api.multi
    # def print_receipt_sus(self):
    #     report = self.env["ir.actions.report.xml"].search(
    #         [('report_name', '=', 'member_app.subscription_receipt_template')], limit=1)
    #     if report:
    #         report.write({'report_type': 'qweb-pdf'})
    #     return self.env['report'].get_action(
    #         self.id, 'member_app.subscription_receipt_template')

# #  FUNCTIONS # # # #
    # @api.multi
    # def send_mail_suspend(self, force=False):
    #     email_from = self.env.user.company_id.email
    #     group_user_id = self.env.ref('member_app.manager_member_ikoyi').id
    #     # extra = self.env.ref('ikoyi_module.inventory_officer_ikoyi').id
    #     extra = self.email
    #     bodyx = "Dear Sir/Madam, </br>We wish to notify that the member with ID {} have been Suspended from Ikoyi Club on the date: {} </br>\
    #          Kindly contact the Ikoyi Club 1968 for any further enquires. </br><a href={}> </b>Click <a/> to review. Thanks"\
    #          .format(self.member_id.identification, fields.Datetime.now(), self.get_url(self.id, self._name))
    #     self.mail_sending(email_from, group_user_id, extra, bodyx)

    # def get_url(self, id, model):
    #     base_url = http.request.env['ir.config_parameter'].sudo(
    #     ).get_param('web.base.url')
    #     base_url += '/web# id=%d&view_type=form&model=%s' % (id, model)

    def mail_sending(self, email_from, group_user_id, extra, bodyx):
        from_browse = self.env.user.name
        groups = self.env['res.groups']
        for order in self:
            group_users = groups.search([('id', '=', group_user_id)])
            group_emails = group_users.users
            # followers = []
            email_to = []
            # for group_mail in self.users_followers:
            #     followers.append(group_mail.work_email)
            for gec in group_emails:
                email_to.append(gec.login)
            email_froms = str(from_browse) + " <" + str(email_from) + ">"
            # mail_appends = (', '.join(str(item)for item in followers))
            mail_to = (','.join(str(item2)for item2 in email_to))
            subject = "Membership Suscription Notification"
            mail_data = {
                'email_from': email_froms,
                'subject': subject,
                'email_to': mail_to,
                'reply_to': email_from,
                'body_html': bodyx
            }
            mail_id = order.env['mail.mail'].create(mail_data)
            order.env['mail.mail'].send(mail_id)


import os
import albumentations as albu
import numpy as np
import torch
from PIL import Image
from torch.utils.data import Dataset as BaseDataset
import matplotlib.pyplot as plt

# ---------------------------------------------------------------
### 加载数据

class Dataset(BaseDataset):

    CLASSES = ['_background', 'uterus', 'bladder', 'rectum']

    def __init__(self, images_dir, masks_dir, classes=None, preprocessing=None,):
        self.ids = os.listdir(images_dir)
        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]
        self.masks_fps = [os.path.join(masks_dir, image_id) for image_id in self.ids]

        # convert str names to class values on masks
        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]

        self.preprocessing = preprocessing

    def __getitem__(self, i):

        # read data
        image = np.asarray(Image.open(self.images_fps[i]).resize((320, 320)), dtype=np.int32)
        mask = np.asarray(Image.open(self.masks_fps[i]).resize((320, 320)), dtype=np.int32)

        # 从标签中提取特定的类别 (e.g. cars)
        masks = [(mask == v) for v in self.class_values]
        mask = np.stack(masks, axis=-1).astype('float')

        # 图像预处理应用
        if self.preprocessing:
            sample = self.preprocessing(image=image, mask=mask)
            image, mask = sample['image'], sample['mask']

        return image, mask

    def __len__(self):
        return len(self.ids)

def to_tensor(x, **kwargs):
    return x.transpose(2, 0, 1).astype('float32')

def get_preprocessing(preprocessing_fn):
    # 进行图像预处理操作

    _transform = [
        albu.Lambda(image=preprocessing_fn),
        albu.Lambda(image=to_tensor, mask=to_tensor),
    ]
    return albu.Compose(_transform)

def visualize(**images):

    n = len(images)
    plt.figure(figsize=(16, 5))
    for i, (name, image) in enumerate(images.items()):
        plt.subplot(1, n, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.title(' '.join(name.split('_')).title())
        plt.imshow(image)
    plt.show()

if __name__ == '__main__':
    DATA_DIR = '../Medical_Datasets/'

    # 测试集
    x_test_dir = os.path.join(DATA_DIR, 'test')
    y_test_dir = os.path.join(DATA_DIR, 'testannot')

    CLASSES = ['_background', 'uterus', 'bladder', 'rectum']
    test_dataset = Dataset(x_test_dir, y_test_dir, classes=CLASSES,)

    for i in range(6):
        image = test_dataset[i][0]
        gt_mask = test_dataset[i][1]

        gt_mask = np.asarray(gt_mask).transpose(2, 0, 1)
        gt_mask = torch.tensor(gt_mask)
        gt_mask = torch.max(gt_mask, 0)[1]
        gt_mask = np.asarray(gt_mask)

        visualize(
            image = image,
            ground_truth_mask=gt_mask,
        )