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

from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
from odoo import fields, models, api, tools, _
from odoo.exceptions import Warning, UserError, ValidationError

class custom_partner(models.Model):
    _inherit = "res.partner"

    @api.multi
    def _draft_invoice_total(self):
        account_invoice_report = self.env['account.invoice.report']
        if not self.ids:
            self.total_draft_invoices = 0.0
            return True

    @api.depends('his_birthdate')
    def _calc_age(self):
        for line in self:
            line.age = self.compute_age_from_dates(line.his_birthdate)

    def compute_age_from_dates(self, customer_dob):
        now=datetime.strptime(fields.Datetime.now()[:10], '%Y-%m-%d')
        if (customer_dob):
            dob=datetime.strptime(customer_dob, '%Y-%m-%d')
            delta =relativedelta (now, dob)
            years_months_days = str(delta.year) + "y " + str(delta.month) + "m " + str(delta.day) + "d"
        else:
            years_months_days = "No Birthdate"
        return years_months_days

    #Custom Fields Definitions
    last_name = fields.Char(string='Last Name')
    first_name = fields.Char(string='First Name')
    middle_name = fields.Char(string='Middle Name')
    is_customer = fields.Boolean(string='Customer')
    gender = fields.Selection([('MALE','male'),('FEMALE','female')], string="Gender")
    civil_status = fields.Selection([('SINGLE','single'),('MARRIED','married'),('SEPARATED','separated'),('DIVORCED','divorced'),('WIDOW','widowed')],string="Civil Status")
    his_birthdate = fields.Date('Birthdate')
    age = fields.Char(compute='_calc_age', string='Age', size=50, readonly=True)
    age_yrs = fields.Integer('Age (Years)')
    nationality = fields.Many2one('ejob.nationality',string='Nationality')
    religion = fields.Many2one('ejob.religion', string='Religion')

    barangay = fields.Many2one('ejob.barangays',string='Barangay')
    city_id = fields.Many2one('ejob.cities',string='City')
    zip_id = fields.Many2one('ejob.zip.ref',string='Zip')

    #credit_plus_draft_inv = fields.Float(compute='_compute_credit_plus_draft_inv', string="Total Credit with Draft Invoices", digits=(12,2))
    #total_draft_invoices = fields.Float(compute='_draft_invoice_total', string="Total Draft Invoices", digits=(14,2))

    total_draft_charges = fields.Float(compute='_draft_charges_total', string="Total Draft Charges", digits=(14,2))
    total_charges_bal = fields.Float(compute='_draft_charges_bal_total', string="Current Balance", digits=(14,2))
    date_last_visit = fields.Datetime('Last Visit',default=lambda self: fields.datetime.now())

    @api.onchange('ref','last_name','first_name','middle_name')
    def customer_name_change(self):
        vals = {}
        if self.customer:
            name = ''
            if self.ref:
                name += '[' + self.ref + '] '
            if self.last_name:
                name += self.last_name + ', '
            if self.first_name:
                name += self.first_name + ' '
            if self.middle_name:
                name += self.middle_name

            vals.update({'name': name.upper()})
        self.update(vals)

    @api.onchange('barangay')
    def customer_barangay_change(self):
        if self.barangay:
            if self.barangay.city_id:
                vals = {'city_id':self.barangay.city_id.id}
                self.update(vals)

    @api.onchange('city_id')
    def customer_city_id_change(self):
        if self.city_id:
            vals = {'city':self.city_id.name}
            self.update(vals)

    @api.onchange('zip_id')
    def customer_zip_id_change(self):
        if self.zip_id:
            vals = {'zip':self.zip_id.name}
            if self.zip_id.city_id:
                vals.update({'city_id':self.zip_id.city_id.id})
            if self.zip_id.state_id:
                vals.update({'state_id':self.zip_id.state_id.id})
            if self.zip_id.country_id:
                vals.update({'country_id':self.zip_id.country_id.id})
            self.update(vals)

    @api.multi
    def gen_id_number(self):
        for rec in self:
            if not rec.ref or rec.ref == '':
                ref = self.env['ir.sequence'].next_by_code('ejob.id.number')
                name = '[' + ref + '] '
                if rec.last_name:
                    name += rec.last_name + ', '
                if rec.first_name:
                    name += rec.first_name + ' '
                if rec.middle_name:
                    name += rec.middle_name
                rec.update({'ref':ref, 'name': name.upper()})

    @api.one
    def _compute_credit_plus_draft_inv(self):
        self.credit_plus_draft_inv = self.credit + self.total_draft_invoices

    @api.multi
    def _draft_charges_total(self):
        if not self.ids:
            self.total_draft_pos_orders = 0.0
            return True

        charges_obj = self.env['e.job.orders']

        #user_currency_id = self.env.user.company_id.currency_id.id
        for partner in self:
            total = 0
            charges = charges_obj.search([('partner_id', '=', partner.id), ('state', '=', 'bill'), ('company_id', '=', self.env.user.company_id.id)])
            for charge in charges:
                total += charge.total_services_fee

            partner.total_draft_charges = total

    @api.multi
    def _draft_charges_bal_total(self):
        if not self.ids:
            self.total_charges_bal = 0.0
            return True

        payments_obj = self.env['ejob.cashier']

        #user_currency_id = self.env.user.company_id.currency_id.id
        for partner in self:
            total = 0
            charges = payments_obj.search([('partner_id', '=', partner.id), ('state', 'in', ('inv','partial')), ('company_id', '=', self.env.user.company_id.id)])
            for charge in charges:
                total += charge.balance

            partner.total_charges_bal = total

    @api.multi
    def manage_charges(self):
        for rec in self:
            partner_id = rec.id
            pricelist = rec.property_product_pricelist
            currency = self.env.user.company_id and self.env.user.company_id.currency_id or False
            #Check if the customer have a current (NEW) Charge
            charge_obj=self.env['e.job.orders']
            new_charges = charge_obj.search([('partner_id','=',partner_id),('state','in',('new','submit'))])
            if new_charges:
                #A NEW Charge Record is already created, get charge_id
                current_charge_id = new_charges[0].id

            else:

                #No NEW charge, create a new Charge Record
                srv_ref = self.env['ir.sequence'].next_by_code('e.job.orders')
                #srv_line_ref = self.env['ir.sequence'].next_by_code('eHC.charge.line.number')
                charge = charge_obj.create({'name': srv_ref, 'partner_id':partner_id, 'jo_date':fields.Datetime.now(), 'pricelist_id':pricelist.id})
                current_charge_id = charge.id

            #Display Charge Form
            imd = self.env['ir.model.data']
            action = imd.xmlid_to_object('ejob_order.action_e_job_orders')
            tree_view_id = imd.xmlid_to_res_id('ejob_order.e_job_order_tree_view')
            form_view_id = imd.xmlid_to_res_id('ejob_order.e_job_order_form_view')

            result = {
                'name': action.name,
                'help': action.help,
                'type': action.type,
                'views': [[form_view_id, 'form'],[tree_view_id, 'tree']],
                'target': action.target,
                #'context': action.context,
                'res_model': action.res_model,
                'res_id': current_charge_id,
            }
            result['domain'] = "[('id','=',%s)]" % current_charge_id
            return result

    @api.multi
    def manage_payments(self):
        for rec in self:
            if rec.total_draft_charges > 0:
                partner_id = rec.id
                orders_obj = self.env['e.job.orders']
                #Check if the customer have a current (NEW) payment record
                payment_obj = self.env['ejob.cashier']
                new_payments = payment_obj.search([('partner_id','=',partner_id),('state','=',('new','inv'))])
                if new_payments:
                    current_payment_id = new_payments[0].id
                    #A NEW payment is already created, let's check for additional charges
                    orders = orders_obj.search([('partner_id', '=', partner_id),('state', '=', 'bill'), ('company_id', '=', self.env.user.company_id.id)])
                    for order in orders:
                        order.payment_id = current_payment_id
                else:
                    orders = orders_obj.search([('partner_id', '=', partner_id), ('state', '=', 'bill'), ('company_id', '=', self.env.user.company_id.id)])
                    if orders:
                        #payment_ref = self.env['ir.sequence'].next_by_code('eAC.payment.id')
                        payment_ref = 'NEW'
                        pricelist_id = rec.property_product_pricelist and rec.property_product_pricelist.id or orders[0].pricelist_id.id
                        payment_vals = {
                            'name': payment_ref,
                            'partner_id': partner_id,
                            'payment_date': fields.Datetime.now(),
                            'pricelist_id': pricelist_id,
                            'payment_type': 'Cash',
                        }
                        payment_id = payment_obj.create(payment_vals)
                        current_payment_id = payment_id.id
                        for order in orders:
                            order.payment_id = current_payment_id

                    else:
                        raise UserError('There are no Charges entered for this customer.')
                    #return {'type': 'ir.actions.act_window_close'}
                #update date last visit
                rec.date_last_visit = fields.datetime.now()
                #Open Payment Entry Form
                imd = self.env['ir.model.data']
                action = imd.xmlid_to_object('ejob_order.action_ejob_cashier')
                form_view_id = imd.xmlid_to_res_id('ejob_order.ejob_soa_form_view')

                result = {
                    'name': action.name,
                    'help': action.help,
                    'type': action.type,
                    'views': [[form_view_id, 'form']],
                    'target': action.target,
                    #'context': action.context,
                    'res_model': action.res_model,
                    'res_id': current_payment_id,
                }
                result['domain'] = "[('id','=',%s)]" % current_payment_id
                return result
            else:
                raise UserError('Payment Record Creation Failed! No job orders entered for this customer.')


# input 문자열
info = input()
# 문자를 담을 리스트
stack = []
# 갯수 체크
cnt = 0
# enumerate 로 index와 value 값을 가져옴
for i,v in enumerate(info):
    # 여는 괄호일 경우
    if v == "(":
        # 스택에 index 값 추가
        stack.append(i)
        # 레이저인지 막대인지 모르지만 갯수 추가
        cnt += 1
    # 닫는 괄호가 나왔을 경우
    else:
        # check 라는 변수에 stack의 제일 뒤값을 뽑아본다.
        check = stack.pop(-1)
        # 만약 뽑은 값의 +1 과 닫는괄호의 인덱스가 같은경우 => () 인 경우라서 레이저다
        if check+1 == i:
            # cnt로 체크해둔 값을 -1 해준 후 그때까지 저장된 스택의 길이를 더해준다.
            cnt -= 1
            cnt += len(stack)
print(cnt)


class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        '''
            方法：贪心算法
            分析：
                if 总油量>=总消耗量，则表示 该车可以跑完全程
                if 当前 加油站的油量gas[i] > 耗油量 cost[i]
                    说明他可以作为 初始加油站 继续往下跑
                else 该加油站非 初始加油站，只能选择下一个
        '''
        # step 1：判空
        n_len = len(gas)
        if n_len<=0:
            return -1

        total_tank = 0      # 总剩余油量
        curr_tank = 0       # 当前油量
        start_station = 0
        for i in range(n_len):
            total_tank = total_tank+(gas[i]-cost[i])
            curr_tank = curr_tank+(gas[i]-cost[i])
            # step 2：当前节点油量不足，不能作为初始节点
            if curr_tank<0:
                curr_tank = 0
                start_station=i+1
        return start_station if total_tank>=0 else -1


#!/usr/bin/env python
"""Truncation beautifier function
This simple function attempts to intelligently truncate a given string
"""
__author__ = 'Kelvin Wong <www.kelvinwong.ca>'
__date__ = '2007-06-22'
__version__ = '0.10'
__license__ = 'LGPL v.2.1 http://www.gnu.org/licenses/lgpl.html'

def trunc(s,min_pos=0,max_pos=75,ellipsis=True):
    """Return a nicely shortened string if over a set upper limit
    (default 75 characters)

    What is nicely shortened? Consider this line from Orwell's 1984...
    0---------1---------2---------3---------4---------5---------6---------7---->
    When we are omnipotent we shall have no more need of science. There will be

    If the limit is set to 70, a hard truncation would result in...
    When we are omnipotent we shall have no more need of science. There wi...

    Truncating to the nearest space might be better...
    When we are omnipotent we shall have no more need of science. There...

    The best truncation would be...
    When we are omnipotent we shall have no more need of science...

    Therefore, the returned string will be, in priority...

    1. If the string is less than the limit, just return the whole string
    2. If the string has a period, return the string from zero to the first
        period from the right
    3. If the string has no period, return the string from zero to the first
        space
    4. If there is no space or period in the range return a hard truncation

    In all cases, the string returned will have ellipsis appended unless
    otherwise specified.

    Parameters:
        s = string to be truncated as a String
        min_pos = minimum character index to return as Integer (returned
                  string will be at least this long - default 0)
        max_pos = maximum character index to return as Integer (returned
                  string will be at most this long - default 75)
        ellipsis = returned string will have an ellipsis appended to it
                   before it is returned if this is set as Boolean
                   (default is True)
    Returns:
        Truncated String
    Throws:
        ValueError exception if min_pos > max_pos, indicating improper
        configuration
    Usage:
    short_string = trunc(some_long_string)
    or
    shorter_string = trunc(some_long_string,max_pos=15,ellipsis=False)
    """
    # Sentinel value -1 returned by String function rfind
    NOT_FOUND = -1
    # Error message for max smaller than min positional error
    ERR_MAXMIN = 'Minimum position cannot be greater than maximum position'

    # If the minimum position value is greater than max, throw an exception
    if max_pos < min_pos:
        raise ValueError(ERR_MAXMIN)
    # Change the ellipsis characters here if you want a true ellipsis
    if ellipsis:
        suffix = '...'
    else:
        suffix = ''
    # Case 1: Return string if it is shorter (or equal to) than the limit
    length = len(s)
    if length <= max_pos:
        return s + suffix
    else:
        # Case 2: Return it to nearest period if possible
        try:
            end = s.rindex('.',min_pos,max_pos)
        except ValueError:
            # Case 3: Return string to nearest space
            end = s.rfind(' ',min_pos,max_pos)
            if end == NOT_FOUND:
                end = max_pos
        return s[0:end] + suffix


from flask import Flask,request
from flask.helpers import make_response
from flask.json import jsonify
import qrcode
import json
from PIL import Image
app = Flask(__name__)
app.config.from_pyfile("settings.py")

baseUrl = "http://10.0.2.2:5000"

@app.route("/home")
def home():
    list = []
    list.append(createPreviewItem(id=1,image="img1.png",title="叫了只鸡",deliver="起送￥10",deliverTime="配送约48分钟",lable="炸物小吃好评榜第2名",sale="月售1532"))
    list.append(createPreviewItem(id=2,image="img2.png",title="东北饺子馆",deliver="起送￥10",deliverTime="配送约53分钟",lable="近30天999+人复购",sale="月售5677"))
    list.append(createPreviewItem(id=3,image="img3.png",title="肥牛烤肉筋",deliver="起送￥12",deliverTime="配送约48分钟",lable="烧烤回头率第1名",sale="月售3078"))

    result = {
        "data":list,
        "msg": "请求成功"

    }
    return make_response(jsonify(result))

@app.route("/detail/<int:id>")
def detail(id):
    result={
        1:{
            "data":{
                "announce":"公告：炸鸡新款来了，肉和蘸料，口味，公司统一生产！",
                "list":[
                    createFood(1,1,"韩式炸鸡","门店销量第1名","月售656 好评度84%","15.95"),
                    createFood(2,1,"双拼口味炸鸡", "门店销量第2名", "月售336 好评度100%", "21.95"),
                    createFood(3,1,"香酥小酥肉", "小酥肉热榜第3名", "月售72 好评度98%", "5"),
                    createFood(1, 1, "韩式炸鸡2", "门店销量第1名", "月售656 好评度84%", "15.95"),
                    createFood(2, 1, "双拼口味炸鸡2", "门店销量第2名", "月售336 好评度100%", "21.95"),
                    createFood(3, 1, "香酥小酥肉2", "小酥肉热榜第3名", "月售72 好评度98%", "5"),
                ]
            }
        },
        2: {
            "data": {
                "announce": "公告：欢迎光临东北饺子馆 我们尽最大努力按照按时送达！",
                "list": [
                    createFood(1,2, "牛肉水饺24个", "门店销量第3名", "月售968 好评度100%", "14.98"),
                    createFood(2,2, "三陷混搭24个", "还行，吃的很饱", "月售402 好评度99%", "13.98"),
                    createFood(3,2, "韭菜鸡蛋水饺", "门店销量第1名", "月售1343 好评度95%", "4.5"),
                ]
            }
        },
        3: {
            "data": {
                "announce": "公告：下午16点到凌晨一点半都可以配送！",
                "list": [
                    createFood(1, 3, "半斤肉筋", "真香，香死了", "月售508 好评度100%", "22"),
                    createFood(2, 3, "翅中", "我室友特别喜欢", "月售355 好评度99%", "7"),
                    createFood(3, 3, "三肉筋+火腿+面筋+饼", "好吃美滋滋", "月售247 好评度95%", "14"),
                ]
            }
        },
    }
    result = result[id]
    return make_response(jsonify(result))
@app.route("/submit",methods=["POST"])
def submit():
    data = json.loads(request.get_data(as_text=True))
    img = qrcode.make(data)
    path = 'static/cart/'+"qr.png"
    img.save(path)
    result = {
        "msg":"上传成功",
        "path":baseUrl+"/"+path
    }
    return make_response(jsonify(result))

def createFood(id,parentId,title,lable,subTitle,price):
    return {
        "image": baseUrl+"/static/detail/"+str(parentId)+"/"+str(id)+".png",
        "name": title,
        "price": price,
        "subTitle": subTitle,
        "lable": lable
    }
def createPreviewItem(id,image,title,deliver,deliverTime,lable,sale):
    return {
        "id":id,
        "image":baseUrl+"/static/preview/"+image,
        "title":title,
        "deliver":deliver,
        "deliverTime":deliverTime,
        "lable":lable,
        "sale":sale,
        "detailUrl":baseUrl+"/detail/"+str(id)
    }


from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect

from . import models, forms

def show_all_posts(request):
    """
    This view will show all of the posts
    """
    my_posts = models.Post.objects.all()
    return render(
        request=request,
        context={
            'my_posts': my_posts,
            'page_title': 'Show all posts'
        },
        template_name='blog/all_posts.html'
    )

@login_required
def create_post(request):
    """
    Creates a post
    """
    form_instance = forms.PostForm()

    if request.method == 'POST':
        form_instance = forms.PostForm(data=request.POST)
        if form_instance.is_valid():
            form_instance.save()
            return redirect('blog:show-all-posts')

    return render(request, 'blog/create_post.html', {
        'form': form_instance,
    })


######################################################
# 8,330: Machine Learning (MiQEF)
# Assignment 3: kNN Algorithm
# Niklas Leander Kampe | 16-611-618
######################################################

# Utility Libraries
import math
import warnings
import numpy as np
import pandas as pd
from sklearn.model_selection import KFold
pd.set_option('display.max_columns', None)
warnings.filterwarnings('ignore')

def accuracy(data):
    n = len(data)
    correct = 0
    for i in range(n):
        if data.iloc[i,0] == data.iloc[i,1]:
            correct += 1
        else:
            continue
    acc = round((correct/n) * 100, 2)
    return acc

def data():
    df = pd.read_csv('Data/diabetes.csv')
    df = df[['Outcome', 'Glucose']]
    df.rename(columns = {'Outcome': 'y', 'Glucose': 'x'}, inplace = True)
    y = df['y']
    X = df['x']
    print("\n############ Raw Data ############\n")
    print(df)
    return y, X, df

class kNN_Algorithm():
    def __init__(self, y, X, df, n_splits):
        self.y = y
        self.X = X
        self.df = df
        self.n_splits = n_splits
    # Function to Split Train/Test Data for Cross-Validation
    def split(self):
        data = self.df
        kf_n = KFold(n_splits = self.n_splits, shuffle = False)
        split = list(kf_n.split(data))
        data_train = []
        data_test = []
        test_indices = {n: "" for n in range(1,len(split)+1)}
        for i in range(0, len(split)):
            train_index = data.iloc[split[i][0]]
            test_index = data.iloc[split[i][1]]
            data_train.append(train_index)
            data_test.append(test_index)
            test_indices[i+1] = str(test_index.index[0]) + "-" + str(test_index.index[-1])
        print("\n############ Test Indices ############\n")
        for i in range(0, len(split)):
            print(f'Split {i+1}: {test_indices[i+1]}')
        return data_train, data_test
    # Utility Function to Sort Values in a Data Frame Ascending
    def sort(self):
        data_train, data_test = self.split()
        for i in range(0, len(data_train)):
            data_train[i].sort_values(by = 'x', axis = 0, inplace = True)
            data_test[i].sort_values(by = 'x', axis = 0, inplace = True)
        return data_train, data_test
    # kNN Classification Algorithm based on Cross-Validation
    def classifier(self):
        data_train, data_test = self.sort()
        k_benchmark = math.floor(np.sqrt(len(data_train[0])))
        if k_benchmark % 2 == 0:
            k_benchmark = k_benchmark - 1
        k_arr = np.arange(3, k_benchmark * 3, 4)
        if k_benchmark not in k_arr:
            k_arr = np.append(k_arr, k_benchmark)
        accuracies_dict = {k: 0 for k in k_arr}
        y_preds = []
        for k in k_arr:
            accuracies = []
            for i in range(0, len(data_train)):
                y_train = data_train[i]['y'].to_numpy()
                X_train = data_train[i]['x'].to_numpy()
                X_test = data_test[i]['x'].to_numpy()
                y_pred = []
                for obs in X_test:
                    closest = min(X_train, key = lambda x: abs(x - obs))
                    closest_index = list(X_train).index(closest)
                    lower_bound = closest_index - math.floor(k/2)
                    upper_bound = closest_index + math.floor(k/2)
                    k_closest = y_train[lower_bound:upper_bound]
                    if np.mean(k_closest) >= 0.5:
                        y_pred.append(1.0)
                    else:
                        y_pred.append(0.0)
                y_preds.append(y_pred)
                data_pred = pd.DataFrame(columns = ['y_pred', 'y', 'x'])
                data_pred['y_pred'] = y_pred
                data_pred['y'] = data_test[i]['y'].to_numpy()
                data_pred['x'] = X_test
                acc = accuracy(data_pred)
                accuracies.append(acc)
            accuracies_dict[k] = round(np.mean(accuracies), 2)
        print("\n############ Classification Accuracies ############\n")
        for k in k_arr:
            print(f"k={k}: {accuracies_dict[k]}%")
        print("\n############ Best Classifier ############\n")
        k_optimal = max(accuracies_dict, key = accuracies_dict.get)
        print(f"Optimal k: {k_optimal}")
        print(f"Optimal Accuracy: {accuracies_dict[k_optimal]}%")
        print("-----")
        print(f"Benchmark k: {k_benchmark}")
        print(f"Behcmark Accuracy: {accuracies_dict[k_benchmark]}%")

if __name__ == '__main__':
    n_splits = 5
    y, X, df = data()
    kNN_Algorithm(y, X, df, n_splits).classifier()

Assignment 3/kNN Algorithm - Niklas Kampe.py


# coding=utf-8
# Author:fan hongtao
# Date:2020-11-22

import codecs
import time

import segment_dic
import segment_hmm
import pos_tag

class eval:

    def __init__(self):
        # 加载分词器和词性标注模型
        self.Segment_dic = segment_dic.segment()
        self.Segment_hmm = segment_hmm.segment()
        self.Pos_tag = pos_tag.pos()

    def accuracy(self, path, mode):
        data = codecs.open(path, 'r', encoding='utf-8')  # 打开测试文件
        start_time = time.time()  # 开始时间
        A = 0
        B = 0
        TP = 0
        # 双向最长匹配的字典分词
        if mode == "bi-ward":
            for line in data.readlines():
                line = line.strip()
                sentence = line.replace(' ', '')
                line = line.split()
                word_list = self.Segment_dic.bi_segment(sentence)
                A += len(line)
                B += len(word_list)
                for word in line:
                    if word in word_list:
                        TP += 1
                        word_list.remove(word)
            P = TP / B
            R = TP / A
            F = 2 * P * R / (P + R)
            end_time = time.time()
            cost = end_time - start_time
            return P, R, F, cost
        # hmm分词
        elif mode == "hmm":
            for line in data.readlines():
                line = line.strip()
                sentence = line.replace(' ', '')
                line = line.split()
                word_list = self.Segment_hmm.hmm_segment(sentence)
                A += len(line)
                B += len(word_list)
                for word in line:
                    if word in word_list:
                        TP += 1
                        word_list.remove(word)
            P = TP / B
            R = TP / A
            F = 2 * P * R / (P + R)
            end_time = time.time()
            cost = end_time - start_time  # 花费的时间
            return P, R, F, cost
        # 词性标注
        elif mode == "pos-tag":
            for line in data.readlines():
                line = line.strip()
                line = line.split()
                if len(line) == 0:
                    continue
                word_list = []
                for word in line:
                    position = word.index('/')
                    word_list.append(word[:position])
                _, tag_list = self.Pos_tag.pos_tag(word_list, need_cut=False)
                A += len(line)
                B += len(word_list)
                for word in line:
                    if word in tag_list:
                        TP += 1
                        tag_list.remove(word)
            P = TP / B
            end_time = time.time()
            cost = end_time - start_time
            return P, cost

    def evaluate(self):
        # 分词测试文件路径
        test_cut = 'data/test_segment.txt'
        PP, RR, FF, COST = self.accuracy(test_cut, "bi-ward")
        print("分词：bi-ward")
        print("精确率：", round(PP, 3), "召回率：", round(RR, 3), "F1：", round(FF, 3), "花费时间：", round(COST, 3))
        PP, RR, FF, COST = self.accuracy(test_cut, "hmm")
        print("分词：hmm")
        print("精确率：", round(PP, 3), "召回率：", round(RR, 3), "F1：", round(FF, 3), "花费时间：", round(COST, 3))
        # 词性标注文件路径
        test_tag = 'data/test_tag.txt'
        PP, COST = self.accuracy(test_tag, "pos-tag")
        print("词性标注：hmm")
        print("准确率：", round(PP, 3), "花费时间：", round(COST, 3))


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

from __future__ import print_function

import os

from formation import AtomicTemplate, Template

OUTPUT_FILE = os.path.join(
    os.path.dirname(os.path.dirname(__file__)),
    "output",
    "004_vpc_in_template.yaml"
)

def main():
    template = Template()
    vpc = AtomicTemplate("VPC", "EC2::VPC")
    template.merge(vpc)
    return template.to_yaml()

if __name__ == "__main__":
    print(main())


"""Support functions to write and read data."""
import os
from enum import Enum
from pathlib import Path
import yaml

from scm.plams import Molecule as PlamsMolecule
from scm.plams.interfaces.adfsuite.ams import AMSResults

from osp.core.cuds import Cuds
from osp.core.namespaces import crystallography, emmo
# from osp.core.utils import pretty_print

class GeometryType(str, Enum):

    XYZ = "xyz"
    MOL = "mol"
    PDB = "pdb"

def read_molecule(filename: str, TS: bool = False, GO_optimized: bool = False,
                  read_from_object: bool = False, geometry_type: GeometryType = None):
    """
    Read geometry from an external file or from PLAMS object.

    Supported formats: xyz, mol and pdb.

    :param filename: Name of the file to be read.

    :param TS: wether the output CUDS object should be a emmo.TransitionStateGeometry or not.

    :param GO_optimized: in case the output be a emmo.OptimizedMolecularGeometry.

    :param read_from_object: Optionally, emmo.MolecularGeometry is retrieved from a
                             PLAMSMolecule object.

    :param return: emmo.MolecularGeometry or emmo.TransitionStateGeometry or
                   emmo.OptimizedMolecularGeometry CUDS object.
    """

    if not read_from_object:
        if not geometry_type:
            geometry_type = assign_geom_type(filename)

        if geometry_type == GeometryType.XYZ:
            return molecule_from_xyz(filename, TS)

        elif geometry_type == GeometryType.MOL:
            return molecule_from_mol(filename, TS)

        elif geometry_type == GeometryType.PDB:
            raise_error(
                file=os.path.basename(__file__),
                function=read_molecule.__name__,
                type="NotImplementedError",
                message="pdb format not implemented yet.",
            )
    else:
        # Read from PLAMS.molecule format.
        return molecule_from_PlamsMolecule(filename, GO_optimized)

def read_lattice(filename: str) -> crystallography.UnitCell:
    """
    Function to read lattice vectors from different file formats.

    Supported formats: xyz, mol and pdb.

    :param filename: Name of the file to be read.

    :param return: crystallography.UnitCell object with added LatticeVectors.
    """

    geometry_type = assign_geom_type(filename)

    if geometry_type == "xyz":
        return lattice_from_xyz(filename)

    elif geometry_type == "mol":
        raise_error(
            file=os.path.basename(__file__),
            function=read_molecule.__name__,
            type="NotImplementedError",
            message="mol format not implemented yet.",
        )

    elif geometry_type == "pdb":
        raise_error(
            file=os.path.basename(__file__),
            function=read_molecule.__name__,
            type="NotImplementedError",
            message="pdb format not implemented yet.",
        )
    return

def assign_geom_type(filename: str) -> str:
    """
    Assign a geometry type format to a entry filename file.

    :param filename: name containing the path and name to file.

    :param return: String with the format of the geometry file.
    """

    path = Path(filename)

    suffix = path.suffix.lower()

    if suffix not in (".xyz", ".mol", ".pdb"):
        raise NameError(f"Unknown geometry format: {suffix}.")

    return suffix.strip(".")

def assign_chemical_name(root_cuds_object: Cuds, labels: list) -> Cuds:
    """
    Assign a ChemicalName to a Molecular Geometry.

    :param root_cuds_object: emmo.Molecule

    :param labels: list with atom labels.

    :param return: same CUDS object with the ChemicalName added.
    """
    counts = []
    labels_no_redundant = []
    label = str()

    for lb in labels:
        counts.append(labels.count(lb))

    for index, lb in enumerate(labels):
        if counts[index] == 1:
            labels[index] = lb
        else:
            labels[index] = lb + str(counts[index])

    # Eliminate redundancy on labels:
    labels_no_redundant = sorted(list(dict.fromkeys(labels)))

    # Get the final molecular label:
    for lb in labels_no_redundant:
        if lb[:3] != "VEC":
            label = label + lb

    chemical_name = emmo.ChemicalName(hasSymbolData=label)
    root_cuds_object.add(chemical_name, rel=emmo.hasSign)

    return

def molecule_from_xyz(filename: str, TS: bool):
    """
    Create emmo.MolecularGeometry or emmo.TransitionStateGeometry from .xyz file.

    It adds single CUDS atom containers with CUDS atom_labels and CUDS positions.

    :param filename: name containing the path and name to file.

    :param TS: option to return emmo.TransitionStateGeometry instead of emmo.MolecularGeometry.

    :param return: emmo.MolecularGeometry containing atoms, labels and position objects.
    """

    if TS:
        transition_state = emmo.TransitionStateGeometry()
    else:
        molecule = emmo.MolecularGeometry()

    labels = []
    coordinates = []
    regions = []
    xyz = open(filename)
    n_atoms = int(xyz.readline())
    _ = xyz.readline()

    # Reading the .xyz file:
    for line in xyz:

        params = line.split()
        label, x, y, z = params[0:4]
        try:
            if params[4]:
                region = params[4].strip()
        except IndexError:
            region = "x=NIL"

        labels.append(label)
        coordinates.append([float(x), float(y), float(z)])
        regions.append(region.split("=")[1])
    xyz.close()
    print("molecule_from_xyz: External", filename, "file has been read.")

    # Creating atom containers and adding them to the root_cuds_object
    # (i.e. MolecularGeometry)
    atoms = []
    for iatom in range(n_atoms):
        atom = emmo.AtomEntity()
        atom_symbol = emmo.ChemicalElement(hasSymbolData=labels[iatom])

        position_vec = emmo.PositionVector()
        coordinate_x = emmo.Real(hasNumericalData=coordinates[iatom][0])
        coordinate_y = emmo.Real(hasNumericalData=coordinates[iatom][1])
        coordinate_z = emmo.Real(hasNumericalData=coordinates[iatom][2])
        position_vec.add(coordinate_x, rel=emmo.hasSpatialFirst)
        position_vec.add(coordinate_y, rel=emmo.hasSpatialNext)
        position_vec.add(coordinate_z, rel=emmo.hasSpatialLast)

        if regions[iatom] == "NIL":
            atom.add(position_vec, atom_symbol, rel=emmo.hasPart)
        else:
            region = emmo.Region(hasSymbolData=regions[iatom].lower())
            atom.add(position_vec, atom_symbol, region, rel=emmo.hasPart)
        if iatom == 0:
            rel = emmo.hasSpatialFirst
        elif iatom == n_atoms:
            rel = emmo.hasSpatialLast
        else:
            rel = emmo.hasSpatialDirectPart
            atoms[iatom-1].add(atom, rel=emmo.hasSpatialNext)
        atoms.append(atom)
        if TS:
            transition_state.add(atom, rel=rel)
        else:
            molecule.add(atom, rel=rel)
    if TS:
        assign_chemical_name(transition_state, labels)
        return transition_state
    else:
        assign_chemical_name(molecule, labels)
        return molecule

def molecule_from_mol(filename: str, TS: bool = False):
    """
    Create emmo.MolecularGeometry from .mol file.

    It adds single CUDS atom containers with CUDS atom_labels and CUDS positions.

    :param filename: name containing the path and name to file.

    :param TS: option to return emmo.TransitionStateGeometry instead of emmo.MolecularGeometry.

    :param return: emmo.MolecularGeometry or emmo.TransitionStateGeometry containing atoms,
                   labels and position objects.

    #TODO, info on the Bonding structure is not read.
    """

    if TS:
        transition_state = emmo.TransitionStateGeometry()
    else:
        molecule = emmo.MolecularGeometry()

    labels = []
    coordinates = []
    with open(filename, "r") as file:
        mol = file.readlines()
        n_atoms = int(mol[3].split()[0])

        # Reading atoms from .mol file:
        for line in mol[4: 4 + n_atoms]:

            params = line.split()
            x, y, z, label = params[0:4]

            labels.append(label)
            coordinates.append([float(x), float(y), float(z)])

    print("molecule_from_mol External", filename, "file has been read.")

    # Creating atom containers and adding them to the root_cuds_object
    # (i.e. MolecularGeometry)
    for iatom in range(n_atoms):
        atom = emmo.AtomEntity()
        atom_symbol = emmo.ChemicalElement(hasSymbolData=labels[iatom])

        position_vec = emmo.PositionVector()
        coordinate_x = emmo.Real(hasNumericalData=coordinates[iatom][0])
        coordinate_y = emmo.Real(hasNumericalData=coordinates[iatom][1])
        coordinate_z = emmo.Real(hasNumericalData=coordinates[iatom][2])
        position_vec.add(coordinate_x, rel=emmo.hasSpatialFirst)
        position_vec.add(coordinate_y, rel=emmo.hasSpatialNext)
        position_vec.add(coordinate_z, rel=emmo.hasSpatialLast)

        atom.add(position_vec, atom_symbol, rel=emmo.hasPart)
        if TS:
            transition_state.add(atom, rel=emmo.hasSpatialPart)
        else:
            molecule.add(atom, rel=emmo.hasSpatialPart)
    if TS:
        assign_chemical_name(transition_state, labels)
        return transition_state
    else:
        assign_chemical_name(molecule, labels)
        return molecule

def molecule_from_PlamsMolecule(syntactic_molecule: PlamsMolecule, GO_optimized: bool):
    """
    Create emmo.MolecularGeometry from a string from a PlamsMolecule.

    It adds single CUDS atom containers with CUDS atom_labels and CUDS positions.

    :param filename: bulk string.

    :param GO_optimized: in case the output be a emmo.OptimizedMolecularGeometry.

    :param return: emmo.MolecularGeometry or emmo.OptimizedMolecularGeometry containing atoms,
                   labels and position objects.
    """
    labels = []

    if GO_optimized:
        optimized_geometry = emmo.OptimizedMolecularGeometry()
    else:
        molecule = emmo.MolecularGeometry()

    # Reading the .xyz file:
    for atom in syntactic_molecule:

        labels.append(atom.symbol)

        semantic_atom = emmo.AtomEntity()

        atom_symbol = emmo.ChemicalElement(hasSymbolData=atom.symbol)
        position_vec = emmo.PositionVector()
        coordinate_x = emmo.Real(hasNumericalData=atom.coords[0])
        coordinate_y = emmo.Real(hasNumericalData=atom.coords[1])
        coordinate_z = emmo.Real(hasNumericalData=atom.coords[2])
        position_vec.add(coordinate_x, rel=emmo.hasSpatialFirst)
        position_vec.add(coordinate_y, rel=emmo.hasSpatialNext)
        position_vec.add(coordinate_z, rel=emmo.hasSpatialLast)
        semantic_atom.add(position_vec, atom_symbol, rel=emmo.hasPart)

        if GO_optimized:
            optimized_geometry.add(semantic_atom, rel=emmo.hasSpatialPart)
        else:
            molecule.add(semantic_atom, rel=emmo.hasSpatialPart)

    if GO_optimized:
        assign_chemical_name(optimized_geometry, labels)
        return optimized_geometry
    else:
        assign_chemical_name(molecule, labels)
        return molecule

def lattice_from_xyz(filename: str) -> crystallography.UnitCell:
    """
    Create a list of emmo.LatticeVectors from .xyz file.

    :param filename: name containing the path and name to file.

    :param return: List of emmo.LatticeVectors.
    """

    lattice = crystallography.UnitCell()
    labels = []
    coordinates = []
    regions = []
    xyz = open(filename, "r")
    n_atoms = int(xyz.readline())
    _ = xyz.readline()
    n_lines = 2  # to account for the second .xyz blank line.

    # Reading the .xyz file:
    for line in xyz:

        params = line.split()
        label, x, y, z = params[0:4]
        try:
            if params[4]:
                region = params[4].strip()
        except IndexError:
            region = "x=NIL"

        labels.append(label)
        coordinates.append([float(x), float(y), float(z)])
        regions.append(region.split("=")[1])
        n_lines += 1
    xyz.close()
    print("lattice_from_xyz: External", filename, "file has been read.")

    n_vectors = n_lines - n_atoms - 2  # n_atoms line + blank line

    # Raise error if no vectors
    if n_vectors == 0:
        raise_error(
            file=os.path.basename(__file__),
            function=lattice_from_xyz.__name__,
            type="NameError",
            message="LatticeVectors not found in .xyz file.",
        )

    for ivector in range(n_vectors):
        lattice_vec = crystallography.LatticeVector()
        coordinate_x = emmo.Real(
            hasNumericalData=coordinates[len(coordinates) - 1 - ivector][0]
        )
        coordinate_y = emmo.Real(
            hasNumericalData=coordinates[len(coordinates) - 1 - ivector][1]
        )
        coordinate_z = emmo.Real(
            hasNumericalData=coordinates[len(coordinates) - 1 - ivector][2]
        )
        lattice_vec.add(coordinate_x, rel=emmo.hasSpatialFirst)
        lattice_vec.add(coordinate_y, rel=emmo.hasSpatialNext)
        lattice_vec.add(coordinate_z, rel=emmo.hasSpatialLast)
        if ivector == 0:
            lattice.add(lattice_vec, rel=emmo.hasSpatialNext)
        if ivector == 1:
            lattice.add(lattice_vec, rel=emmo.hasSpatialFirst)
        if ivector == 2:
            lattice.add(lattice_vec, rel=emmo.hasSpatialLast)
    return lattice

def read_mechanism(
    filename: str, read_from_file: bool = True, cuds=None,
) -> emmo.ChemicalReactionMechanism:
    """
    Create emmo.ChemicalReactionMechanism from a Zacros-formatted .dat file.

    :param filename: name containing the path and name to file.

    :param return: emmo.ChemicalReactionMechanism with all the semantic information.
    """

    mechanism = cuds or emmo.ChemicalReactionMechanism()

    if read_from_file is True:
        dat = open(filename, "r")
    elif read_from_file is False:
        dat = (
            filename.splitlines()
        )  # For cases where the file names contains the full string.

    initial = False
    final = False

    for count, line in enumerate(dat):
        params = line.split()
        if params:
            if params[0] == "reversible_step":
                reaction = emmo.ReversibleReactionEquation()

            if params[0] == "gas_reacs_prods":
                filedir = os.path.dirname(os.path.abspath(__file__))
                dictionary = os.path.join(
                    filedir, "../dictionaries/energies/gas_energies.yaml"
                )
                with open(dictionary, "r") as f:
                    energy_list = yaml.load(f, Loader=yaml.FullLoader)
                    formation_energy_value_from_dic = energy_list["Gas_energies"][
                        params[1]
                    ]
                if float(params[2]) < 0:
                    gas_reactant = emmo.GasReactantSpecies()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                    formation_energy = emmo.FormationEnergy()
                    formation_energy_value = emmo.Real(
                        hasNumericalData=formation_energy_value_from_dic
                    )
                    formation_energy.add(
                        formation_energy_value, rel=emmo.hasQuantityValue
                    )
                    coefficient = emmo.StoichiometricCoefficient()
                    coefficient_value = emmo.Real(hasNumericalData=params[2])
                    coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                    gas_reactant.add(
                        atom_symbol,
                        coefficient,
                        formation_energy,
                        rel=emmo.hasSpatialDirectPart
                    )
                    reaction.add(gas_reactant, rel=emmo.hasSpatialPart)
                if float(params[2]) > 0:
                    gas_reactant = emmo.GasProductSpecies()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                    formation_energy = emmo.FormationEnergy()
                    formation_energy_value = emmo.Real(
                        hasNumericalData=formation_energy_value_from_dic
                    )
                    formation_energy.add(
                        formation_energy_value, rel=emmo.hasQuantityValue
                    )
                    coefficient = emmo.StoichiometricCoefficient()
                    coefficient_value = emmo.Real(hasNumericalData=params[2])
                    coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                    gas_reactant.add(
                        atom_symbol,
                        coefficient,
                        formation_energy,
                        rel=emmo.hasSpatialDirectPart,
                    )
                    reaction.add(gas_reactant, rel=emmo.hasSpatialPart)

            if params[0] == "sites":
                num_of_sites = int(params[1])

            if params[0] == "neighboring":
                if num_of_sites == 2:
                    neighbors = emmo.Neighboring()
                    for i in range(num_of_sites):
                        neighbor_site = emmo.Real(
                            hasNumericalData=params[1].split("-")[i]
                        )
                        if i == 0:
                            neighbors.add(neighbor_site, rel=emmo.hasSpatialFirst)
                        else:
                            neighbors.add(neighbor_site, rel=emmo.hasSpatialNext)
                    reaction.add(neighbors, rel=emmo.hasSpatialPart)

            if params[0] == "initial":
                record = count
                initial = True

            if initial:
                if count == record:
                    continue
                elif count <= record + num_of_sites:
                    reactant = emmo.ChemicalReactionEquationReactant()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                    coefficient = emmo.StoichiometricCoefficient()
                    coefficient_value = emmo.Real(hasNumericalData=params[2])
                    coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                    reactant.add(
                        atom_symbol, coefficient, rel=emmo.hasSpatialDirectPart
                    )
                    reaction.add(reactant, rel=emmo.hasSpatialPart)
                else:
                    initial = False
                    #

            if params[0] == "final":
                record = count
                final = True

            if final:
                if count == record:
                    continue
                elif count <= record + num_of_sites:
                    reactant = emmo.ChemicalReactionEquationProduct()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                    coefficient = emmo.StoichiometricCoefficient()
                    coefficient_value = emmo.Real(hasNumericalData=params[2])
                    coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                    reactant.add(
                        atom_symbol, coefficient, rel=emmo.hasSpatialDirectPart
                    )
                    reaction.add(reactant, rel=emmo.hasSpatialPart)
                else:
                    final = False
                    #

            if params[0] == "site_types":
                site_type = crystallography.Site()
                atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                site_type.add(atom_symbol, rel=emmo.hasSpatialDirectPart)
                reaction.add(site_type, rel=emmo.hasSpatialPart)
                if num_of_sites == 2:
                    site_type = crystallography.Site()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[2])
                    site_type.add(atom_symbol, rel=emmo.hasSpatialDirectPart)
                    reaction.add(site_type, rel=emmo.hasSpatialPart)

            if params[0] == "pre_expon":
                coefficient = emmo.ArrheniusCoefficient()
                coefficient_value = emmo.Real(hasNumericalData=params[1])
                coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                reaction.add(coefficient, rel=emmo.hasSpatialPart)

            if params[0] == "pe_ratio":
                coefficient = emmo.Constant()
                coefficient_value = emmo.Real(hasNumericalData=params[1])
                coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                reaction.add(coefficient, rel=emmo.hasSpatialPart)

            if params[0] == "activ_eng":
                coefficient = emmo.ActivationEnergy()
                coefficient_value = emmo.Real(hasNumericalData=params[1])
                coefficient.add(coefficient_value, rel=emmo.hasQuantityValue)
                reaction.add(coefficient, rel=emmo.hasSpatialPart)

            if params[0] == "end_reversible_step":
                mechanism.add(reaction, rel=emmo.hasPart)

    #    pretty_print(mechanism)

    if read_from_file is True:
        dat.close()

    print("read_mechanism: External", filename, "file has been read.")

    return mechanism

def read_cluster_expansion(filename: str, read_from_file: bool = True, cuds=None) -> list:
    """
    Create a [emmo.ClusterExpansion] list from a Zacros-formatted .dat file.

    :param filename: name containing the path and name to file.

    :param return: list of emmo.ClusterExpansion
    """

    if read_from_file is True:
        dat = open(filename, "r")
    elif read_from_file is False:
        dat = (
            filename.splitlines()
        )  # For cases where the file names contains the full string.

    cluster_list = []
    read_lattice_state = False

    for count, line in enumerate(dat):
        params = line.split()
        if params:

            if params[0] == "cluster":
                cluster = cuds or emmo.ClusterExpansion()

            if params[0] == "sites":
                num_of_sites = int(params[1])

            if params[0] == "neighboring":
                if num_of_sites == 2:
                    neighbors = emmo.Neighboring()
                    for i in range(num_of_sites):
                        neighbor_site = emmo.Real(
                            hasNumericalData=params[1].split("-")[i]
                        )
                        if i == 0:
                            neighbors.add(neighbor_site, rel=emmo.hasSpatialFirst)
                        else:
                            neighbors.add(neighbor_site, rel=emmo.hasSpatialNext)
                    cluster.add(neighbors, rel=emmo.hasSpatialPart)

            if params[0] == "lattice_state":
                record = count
                read_lattice_state = True

            if read_lattice_state:
                if count == record:
                    lattice_state = emmo.LatticeState()
                    continue
                elif count <= record + num_of_sites:
                    adsorbed_species = emmo.AdsorbedSpecies()
                    species_number = emmo.Real(hasNumericalData=params[0])
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])

                    denticity_number = emmo.Real(hasNumericalData=params[2])
                    denticity = emmo.Denticity()
                    denticity.add(denticity_number, rel=emmo.hasQuantityValue)

                    adsorbed_species.add(
                        species_number,
                        atom_symbol,
                        denticity,
                        rel=emmo.hasSpatialDirectPart,
                    )

                    lattice_state.add(adsorbed_species, rel=emmo.hasSpatialDirectPart)
                else:
                    cluster.add(lattice_state, rel=emmo.hasPart)
                    read_lattice_state = False

            if params[0] == "site_types":
                site_type = crystallography.Site()
                atom_symbol = emmo.ChemicalElement(hasSymbolData=params[1])
                site_type.add(atom_symbol, rel=emmo.hasSpatialDirectPart)
                cluster.add(site_type, rel=emmo.hasSpatialPart)
                if num_of_sites == 2:
                    site_type = crystallography.Site()
                    atom_symbol = emmo.ChemicalElement(hasSymbolData=params[2])
                    site_type.add(atom_symbol, rel=emmo.hasSpatialDirectPart)
                    cluster.add(site_type, rel=emmo.hasSpatialPart)

            if params[0] == "cluster_eng":
                cluster_energy = emmo.ClusterEnergy()
                cluster_energy_value = emmo.Real(hasNumericalData=params[1])
                cluster_energy.add(cluster_energy_value, rel=emmo.hasQuantityValue)
                cluster.add(cluster_energy, rel=emmo.hasSpatialPart)

            if params[0] == "end_cluster":
                cluster_list.append(cluster)

    #    for i in cluster_list:
    #        pretty_print(i)

    if read_from_file is True:
        dat.close()

    print("read_cluster_expansion: External", filename, "file has been read.")

    return cluster_list

def print_results(plams_results: AMSResults, result: str):
    """
    Print results of a PLAMS/AMS/ADF calculation.

    :param plams_results: PLAMS result object to be analyzed.

    :param result: String to select what information to print.
    """

    if result == "total_energy":
        total_energy = plams_results.get_energy(unit="eV")
        print("Total electronic energy:", total_energy, "eV")

    if result == "energy_per_go_step":
        print("Total energy per geometry optimization step:")
        nEntries = plams_results.readrkf("History", "nEntries")
        for k in range(nEntries):
            s = "Energy({})".format(k + 1)
            x = plams_results.readrkf("History", s)
            print("Optimization cycle", k + 1, ":", x, "Hartree")
    return

def raise_error(file: str, function: str, type: str, message: str):
    """
    Raise errors according to arguments:

    :param file: Python file where the error occurs.

    :param function: Name of the function calling the error.

    :param type: Error type.

    :param message: String describing the error.
    """

    nl = "\n"

    msg = (
        f"{nl}### ERROR ### {function} function/method"
        f" in {file}:"
        f'{nl}              "{message}"'
    )
    if type == "NameError":
        raise NameError(msg)
    elif type == "ValueError":
        raise ValueError(msg)
    elif type == "NotImplementedError":
        raise NameError(message)

def raise_warning(file: str, function: str, message: str, message2=None):
    """
    Raise warning according to arguments:

    :param file: Python file where the error occurs.

    :param function: Name of the function calling the error.

    :param message: String describing the error.
    """

    nl = "\n"
    if not message2:
        msg = (
            f"{nl}### WARNING! ### {function} function/method"
            f" in {file}:"
            f'{nl}              "{message}"'
        )
    else:
        msg = (
            f"{nl}### WARNING! ### {function} function/method"
            f" in {file}:"
            f'{nl}              "{message}:", {message2}'
        )
    print(msg)
    return


# -*- coding: utf-8 -*-
import re
import os
import traceback

from core.utils import sectionToMap, readlines

def match(filename):
	filename = os.path.basename(filename)
	return filename == 'zabbix_server.conf' or filename == 'zabbix_proxy.conf'

def run(filename):
	tmp    = {'DBHost': 'localhost', 'DBPort': 3306}
	result = []
	wanted = ['DBHost', 'DBName', 'DBUser', 'DBPassword', 'DBPort']

	for line in readlines(filename):
		parts = re.split(r'\s*=\s*', line.strip())
		if parts[0] in wanted:
			tmp[parts[0]] = parts[1]

	if len(tmp) == 5:
		result.append({
			'type': 'credentials',
			'data': tmp
		})
	return result


from tkinter import *
from PIL import ImageTk,Image

root = Tk()
root.title("Learn to code")
root.iconbitmap(r'C:\Users\tomry\GraphicUserInterface\wifi.ico')

# Odkaz: https://www.youtube.com/watch?v=YXPyB4XeYLA&list=PLWKjhJtqVAbnqBxcdjVGgT3uVR10bzTEB&index=2

def open():
    global my_img
    top = Toplevel()
    top.title("My SCND Window")
    top.iconbitmap(r'C:\Users\tomry\GraphicUserInterface\wifi.ico')
    my_img = ImageTk.PhotoImage(Image.open("images/img1.png"))
    my_label = Label(top, image=my_img).pack()
    btn2 = Button(top, text="close window", command=top.destroy).pack()

btn = Button(root, text="open Second window", command=open).pack()

root.mainloop()


import math
from functools import reduce
f = [x.rstrip('\n').split(',') for x in open('buses.txt').readlines()]
times = []
positions = []
total = 0
for y, x in enumerate(f[1]):
    if x != 'x':
        times.append(int(x))
        positions.append(y)
current = 0
for pos in range(1, len(times)):
    done = False
    while not done:
        total = 0
        for y in range(pos+1):
            if (current + positions[y]) % times[y] != 0:
                break
            else:
                total += 1
        if total == pos + 1:
            done = True
        else:
            current += reduce(lambda a,b: a*b // math.gcd(a,b), times[:pos])
print(current)


# Import heapq
from heapq import *

# Function to return the merged sorted array
def mergeKSortedArrays(kArrays):
    # List to store merged elements
    merged = []

    # Initialize minheap
    minheap = []

    # Traverse over arrays
    for i, array in enumerate(kArrays):
        # Check for empty arrays
        if array:
            # Push the first element of every non-empty array in minheap
            heappush(minheap, (array[0], i))

            # Remove the pushed element from the respective list
            kArrays[i] = array[1:]

    # While heap has elements
    while minheap:
        # Get the minimum value from the heap
        element, arrayIdx = heappop(minheap)

        # Add the element to the merged list
        merged.append(element)

        # Check if there are more elements in the array
        if kArrays[arrayIdx]:
            # Push the next element to the minheap
            heappush(minheap, (kArrays[arrayIdx][0], arrayIdx))

            # Remove the pushed element from the respective list
            kArrays[arrayIdx] = kArrays[arrayIdx][1:]

    return merged

# Initialize array of arrays
kArrays = [[1, 3, 5, 7], [2, 4, 6, 8], [0, 9, 10, 11]]

# Print the merged sorted array
print(mergeKSortedArrays(kArrays))


import numpy
def parse(filename):
    image = []
    part = []
    file = open(filename,"r")
    lines = file.readlines()
    for line in lines:
        coord = line.rstrip("\n").split(",")
        if(len(coord) == 1):
            if(len(part) != 0):
                image.append(part)
            part = []
            part.append(convertColor(coord[0]))
        else:
            coord_temp = []
            j = 0
            for val in coord:
                if(j == 0):
                    coord_temp.append(float(val)/100)
                else:
                    coord_temp.append(float(val)*-1/100)
                j = j+1
            coord_temp.append(0)
            part.append(coord_temp)
    image.append(part)
    return image

def convertColor(color):
    hexcolor = []
    hexcolor.append(int(color[1:3],16)/255)
    hexcolor.append(int(color[3:5],16)/255)
    hexcolor.append(int(color[5:7],16)/255)
    return hexcolor

if __name__ == '__main__':
    image = parse("../data/images/regalia_flat.svg")


from django.shortcuts import render, redirect
from . import models
from . import forms
from django.contrib.auth.decorators import permission_required

# Create your views here.

def Product(request, _product_id):
    category_parents = models.Category_parent.objects.order_by("order")
    product = models.Product.objects.get(product_id = _product_id)
    context = {
        "category_parents": category_parents,
        "product": product
    }
    return render(request, "products/Product.html", context)

def Popular(request):
    category_parents = models.Category_parent.objects.order_by("order")
    products = models.Product.objects.order_by("views")[::-1]
    context = {
        "products": products,
        "category_parents": category_parents
    }
    return render(request, "products/PopularProducts.html", context)

@permission_required("is_superuser")
def List(request):
    _get = request.GET
    if ("search" in _get):
        products = models.Product.objects.filter(nombre__contains=_get["search"])
    else:
        products = models.Product.objects
    products = products.order_by("views")[::-1]
    context = {
        "products": products,
    }
    return render(request, "products/List.html", context)

@permission_required("is_superuser")
def Edit(request, _product_id):
    if (request.method == "GET"):
        product = models.Product.objects.get(product_id = _product_id)
        data = {
            "product_id": product.product_id,
            "category_id": product.category_id,
            "nombre": product.nombre,
            "imagen_principal": product.imagen_principal,
            "precio": product.precio,
            "stock": product.stock,
            "description": product.description,
            "specs": product.specs,
            "views": product.views,
            "garantia": product.garantia,
            }
        form = forms.Product(initial=data)
        context = {
            "product": product,
            "form": form
        }
        return render(request, "products/EditProduct.html", context)
    elif (request.method == "POST"):
        _instance = models.Product.objects.get(product_id = _product_id)
        _form = forms.Product(request.POST, request.FILES)

        if (request.POST['action'] == "Update"):
            if (_form.is_valid()):
                if (_form.cleaned_data['imagen_principal']):
                    _instance.imagen_principal = _form.cleaned_data["imagen_principal"]
                _instance.category_id = _form.cleaned_data["category_id"]
                _instance.nombre = _form.cleaned_data["nombre"]
                _instance.precio = _form.cleaned_data["precio"]
                _instance.stock = _form.cleaned_data["stock"]
                _instance.description = _form.cleaned_data["description"]
                _instance.specs = _form.cleaned_data["specs"]
                _instance.garantia = _form.cleaned_data["garantia"]
                _instance.save()
        elif (request.POST['action'] == "Delete"):
            _instance.delete()

        return redirect("products:list")

@permission_required("is_superuser")
def Add(request):
    if (request.method == "GET"):
        data = {
            "product_id": 0,
            "views": 0,
            }
        _form = forms.Product(initial=data)

    elif (request.method == "POST"):
        _instance = models.Product()
        _form = forms.Product(request.POST, request.FILES)

        if (_form.is_valid()):
            if (_form.cleaned_data['imagen_principal']):
                _instance.imagen_principal = _form.cleaned_data["imagen_principal"]
            _instance.category_id = _form.cleaned_data["category_id"]
            _instance.nombre = _form.cleaned_data["nombre"]
            _instance.precio = _form.cleaned_data["precio"]
            _instance.stock = _form.cleaned_data["stock"]
            _instance.description = _form.cleaned_data["description"]
            _instance.specs = _form.cleaned_data["specs"]
            _instance.garantia = _form.cleaned_data["garantia"]
            _instance.save()

            return redirect("products:list")
    context = {
            "form": _form
        }
    return render(request, "products/AddProduct.html", context)


from __future__ import annotations

import logging

from ._apik import validate_api_key
from ._kafka import KafkaProducer

try:
    KAFKA_PRODUCER = KafkaProducer()
except Exception as exc:
    logging.exception(exc)
    KAFKA_PRODUCER = None  # type: ignore

def add_query_ingest_impl(api_key: str, body: bytes) -> bool:
    if not validate_api_key(api_key):
        logging.warning(f"Invalid API Key {api_key}")
        return False
    KAFKA_PRODUCER.enqueue_message(body)
    return True


class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:

        graph = defaultdict(list)
        in_degree = defaultdict(int)

        for edge in prerequisites:
            graph[edge[1]].append(edge[0])
            in_degree[edge[0]] += 1

        que = deque()
        for node in range(numCourses):
            if not in_degree[node]:
                que.append(node)

        path = []
        while que:
            node = que.popleft()
            path.append(node)
            for child in graph[node]:
                in_degree[child] -= 1
                if not in_degree[child]:
                    que.append(child)

        if len(path) == numCourses:
            return path
        return []


from django.test import TestCase

from datasets.models import RADataEntry
from datasets.serializers import RADataEntrySerializer

class RADataRecordSerializerTestCase(TestCase):
    fixtures = ['set.json', 'record.json', 'entry.json', 'member.json']
    serializer_class = RADataEntrySerializer

    @classmethod
    def setUpTestData(cls):
        cls.instance = RADataEntry.objects.get(number=1, record__number=1, record__dataset__number=1)

    def test_serialize(self):
        serializer = RADataEntrySerializer(instance=self.instance)
        print(serializer.data)

    def test_create(self):
        task_data = {
            'dataset_number': 1,
            'record_number': 1,
            # 'member': '39d6a1e6-e500-46c1-a6ed-acfcc6c485f6',
            'key': 'marked',
            'value': {'has_activities': True}
        }
        serializer = self.serializer_class(data=task_data)
        self.assertTrue(serializer.is_valid(raise_exception=True))
        serializer.save()


"""This submodule handles the cli-like utilities such as the parser

"""

import argparse

class RadolanParser(argparse.ArgumentParser):
    def __init__(self):
        super().__init__(
            description="Training U-Net model for segmentation of RADOLAN precipitation images"
        )
        self.add_arguments(self)

    @staticmethod
    def add_arguments(parent_parser, argument_group=False):
        if argument_group:
            parser = parent_parser.add_argument_group("Radolan Parser")
        else:
            parser = parent_parser
        parser.add_argument(
            "--device",
            type=str,
            default="cuda:0",
            help="device for training (default: cuda:0)",
        )
        parser.add_argument(
            "--workers",
            type=int,
            default=4,
            help="number of workers for data loading (default: 4)",
        )
        parser.add_argument(
            "--weights", type=str, default="./weights", help="folder to save weights"
        )
        parser.add_argument(
            "--logs", type=str, default="./logs", help="folder to save logs"
        )
        parser.add_argument(
            "--images", type=str, default="../Radolan", help="root folder with images"
        )
        parser.add_argument(
            "--save",
            type=bool,
            default=False,
            help="Save the Unet at the end of training. Path is RADOLAN_PATH/Models/RUN-TIMESTAMP"
        )
        parser.add_argument(
            "--verbose",
            type=bool,
            default=False,
            help="Verbose setting. Either true or false."
        )
        if argument_group:
            return parent_parser
        else:
            return parser

class DeprecatedRadolanParser(argparse.ArgumentParser):
    def __init__(self):
        super().__init__(
            description="OldArgparseArguments"
        )

        self.add_argument(
            "--batch-size",
            type=int,
            default=6,
            help="input batch size for training (default: 6)",
        )
        self.add_argument(
            "--epochs",
            type=int,
            default=100,
            help="number of epochs to train (default: 100)",
        )
        self.add_argument(
            "--lr",
            type=float,
            default=0.001,
            help="initial learning rate (default: 0.001)",
        )
        self.add_argument(
            "--device",
            type=str,
            default="cuda:0",
            help="device for training (default: cuda:0)",
        )
        self.add_argument(
            "--workers",
            type=int,
            default=4,
            help="number of workers for data loading (default: 4)",
        )
        self.add_argument(
            "--vis-images",
            type=int,
            default=200,
            help="number of visualization images to save in log file (default: 200)",
        )
        self.add_argument(
            "--vis-freq",
            type=int,
            default=10,
            help="frequency of saving images to log file (default: 10)",
        )
        self.add_argument(
            "--weights", type=str, default="./weights", help="folder to save weights"
        )
        self.add_argument(
            "--logs", type=str, default="./logs", help="folder to save logs"
        )
        self.add_argument(
            "--images", type=str, default="../Radolan", help="root folder with images"
        )
        self.add_argument(
            "--image-size",
            type=int,
            default=256,
            help="target input image size (default: 256)",
        )
        self.add_argument(
            "--aug-scale",
            type=int,
            default=0.05,
            help="scale factor range for augmentation (default: 0.05)",
        )
        self.add_argument(
            "--save",
            type=bool,
            default=False,
            help="Save the Unet at the end of training. Path is RADOLAN_PATH/Models/RUN-TIMESTAMP"
        )
        self.add_argument(
            "--cat",
            type=bool,
            default=False,
            help="Whether the skips should be implemented with torch.cat or with a simple sum. "
                 "False (default) means sum."
        )
        self.add_argument(
            "--verbose",
            type=bool,
            default=False,
            help="Verbose setting. Either true or false."
        )
        self.add_argument(
            "--filename",
            type=str,
            default='no_name.h5',
            help='Name for the h5 file.'
        )


from loaders.dataloader_mnist import load_mnist
from models.model_vae import VariationalInference, VariationalAutoencoder
from models.distributions import ReparameterizedDiagonalGaussian

import torch
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
sns.set_style("whitegrid")

### TEST DISTRIBUTION

def test_normal_distribution():
    """a few safety checks for your implementation"""
    N = 1000000
    ones = torch.ones(torch.Size((N,)))
    mu = 1.224 * ones
    sigma = 0.689 * ones
    dist = ReparameterizedDiagonalGaussian(mu, sigma.log())
    z = dist.sample()

    # Expected value E[N(0, 1)] = 0
    expected_z = z.mean()
    diff = (expected_z - mu.mean())**2
    assert diff < 1e-3, f"diff = {diff}, expected_z = {expected_z}"

    # Variance E[z**2 - E[z]**2]
    var_z = (z**2 - expected_z**2).mean()
    diff = (var_z - sigma.pow(2).mean())**2
    assert diff < 1e-3, f"diff = {diff}, var_z = {var_z}"

    # log p(z)
    from torch.distributions import Normal
    base = Normal(loc=mu, scale=sigma)
    diff = ((base.log_prob(z) - dist.log_prob(z))**2).mean()
    assert diff < 1e-3, f"diff = {diff}"

test_normal_distribution()

n_samples = 10000
mu = torch.tensor([[0, 1]])
sigma = torch.tensor([[0.5 , 3]])
ones = torch.ones((1000,2))
p = ReparameterizedDiagonalGaussian(mu=mu*ones, log_sigma=(sigma*ones).log())
samples = p.sample()
data = pd.DataFrame({"x": samples[:, 0], "y": samples[:, 1]})
g = sns.jointplot(
    data=data,
    x="x",y="y",
    kind="hex",
    ratio=10
)
plt.subplots_adjust(top=0.9)
g.fig.suptitle(r"$\mathcal{N}(\mathbf{y} \mid \mu, \sigma)$")
plt.show()

### TEST LOADER
classes = [3, 7]

path_train = "~/Documents/PhD/courses/deep_learning/assignments/7_Unsupervised"
path_test  = "~/Documents/PhD/courses/deep_learning/assignments/7_Unsupervised"

train_loader, test_loader = load_mnist(path_train, path_test, classes)

#plot a few MNIST examples
f, axarr = plt.subplots(4, 16, figsize=(16, 4))

# Load a batch of images into memory
images, labels = next(iter(train_loader))

for i, ax in enumerate(axarr.flat):
    ax.imshow(images[i].view(28, 28), cmap="binary_r")
    ax.axis('off')

plt.suptitle('MNIST handwritten digits')
plt.show()

vi = VariationalInference(beta=1)
latent_features = 2
vae = VariationalAutoencoder(images[0].shape, latent_features)
loss, diagnostics, outputs = vi(vae, images)
print(f"{'loss':6} | mean = {loss:10.3f}, shape: {list(loss.shape)}")
for key, tensor in diagnostics.items():
    print(f"{key:6} | mean = {tensor.mean():10.3f}, shape: {list(tensor.shape)}")


import xml.etree.ElementTree
import xml_share as xshare
import os

class xml_share_repository:
    """
    Stores the information read from xml for easy access.
    """
    xml_shares = []

    def built_up_repository(self, share_file=os.path.dirname(__file__) + '/shares.xml'):
        """
        Fill the repository at start.
        """
        xml_shares_root = xml.etree.ElementTree.parse(share_file).getroot()

        for xml_share_in_file in xml_shares_root.findall('share'):
            xml_share = xshare.xml_share()

            for xml_name_temp in xml_share_in_file.findall('name'):
                if "&" in xml_name_temp:
                    xml_name_temp.replace('&', '&')
                else:
                    xml_share.xml_name = str(xml_name_temp.text)

            for xml_units_temp in xml_share_in_file.findall('units'):
                xml_share.xml_units = str(xml_units_temp.text)

            for xml_buy_price_temp in xml_share_in_file.findall('buyPrice'):
                xml_share.xml_buy_price = str(xml_buy_price_temp.text)

            for xml_buy_date_temp in xml_share_in_file.findall('buyDate'):
                xml_share.xml_buy_date = str(xml_buy_date_temp.text)

            for xml_trailing_stop_date_temp in xml_share_in_file.findall('trailingStopDate'):
                xml_share.xml_trailing_stop_date = str(xml_trailing_stop_date_temp.text)

            for xml_trailing_stop_percentage_temp in xml_share_in_file.findall('trailingStopPercentage'):
                xml_share.xml_trailing_stop_percentage = str(xml_trailing_stop_percentage_temp.text)

            for xml_trailing_stop_absolute_temp in xml_share_in_file.findall('trailingStopAbsolute'):
                xml_share.xml_trailing_stop_absolute = str(xml_trailing_stop_absolute_temp.text)

            for xml_trailing_stop_init_temp in xml_share_in_file.findall('trailingStopInit'):
                xml_share.xml_trailing_stop_init = str(xml_trailing_stop_init_temp.text)

            if len(xml_share_in_file.findall('stopExpiration')) < 1:
                xml_share.xml_stop_expiration = ''

            for xml_stop_expiration_temp in xml_share_in_file.findall('stopExpiration'):
                xml_share.xml_stop_expiration = str(xml_stop_expiration_temp.text)

            positionToInsert = 0

            for entry in self.xml_shares:
                if entry.xml_name < xml_share.xml_name:
                    positionToInsert = positionToInsert + 1
                else:
                    break

            self.xml_shares.insert(positionToInsert, xml_share)


from flask import Flask, render_template, request, redirect
from mysqlconnection import connectToMySQL
app = Flask(__name__)

mysql = connectToMySQL('friendsdb')
@app.route('/')
def index():
    result = mysql.query_db("select * from players")
    return render_template("index.html", entry = result)

if __name__=="__main__":
    app.run(debug=True)


# Se crea un diccionario vacío llamado 'calificaciones'.
calificaciones = {}

# Se actualiza el diccionario 'calificaciones' con dos pares clave-valor.
calificaciones.update({"Laura": 3.7, "Sebastian": 4.5})

# Se crea un nuevo diccionario 'calificaciones' con un par clave-valor.
calificaciones = {
    'nombre': 'Marlon',  # Clave: 'nombre', Valor: 'Marlon'
    'notafinal': 5.0      # Clave: 'notafinal', Valor: 5.0
}

# Creación de un diccionario 'calificaciones' con varios pares clave-valor.
calificaciones = {
    'Marlon': 5.0,
    'Stievn': 5.0,
    'Sebastian': 4.5,
    'Stevan': 2.5
}

# Se itera sobre los elementos del diccionario y se imprime cada par clave-valor.
for i, j in calificaciones.items():
    print(i, j)

# Se imprime "Técnicas por clave" antes de iterar por las claves del diccionario.
print("Técnicas por clave")

# Se itera sobre las claves del diccionario y se imprime cada clave.
for i in calificaciones.keys():
    print(i)

# Se imprime "Iterar por valor" antes de iterar por los valores del diccionario.
print("Iterar por valor")

# Se itera sobre los valores del diccionario y se imprime cada valor.
for j in calificaciones.values():
    print(j)


def app():
    import pandas as pd
    from operator import itemgetter
    import glob
    import streamlit as st

    pd.options.mode.chained_assignment = None
    st.header('Master List of LPI')
    files = glob.glob('*.xlsx')

    appended_data = []
    leagueList = []
    for file in files:
        leagueName = file.split(".xlsx")[0]
        leagueList.append(leagueName)
        df = pd.read_excel(file, sheet_name="Louie Power Index")
        df["League"] = leagueName
        appended_data.append(df)

    dfFINAL = pd.concat(appended_data)
    dfFINAL = dfFINAL.iloc[: , 1:]
    # dfFINAL.index += 1
    df1 = dfFINAL.sort_values(by=['Louie Power Index (LPI)'], ascending=False)

    df3 = df1.reset_index(drop=True).style.background_gradient(subset=['Louie Power Index (LPI)']).apply(lambda x: ["background-color: purple; color: white"
                            if i == leagueList[0]
                            else "" for i in x], axis = 1).apply(lambda x: ["background-color: skyblue" if i == leagueList[1]
                            else "" for i in x], axis = 1).apply(lambda x: ["background-color: goldenrod" if i == leagueList[2]
                            else "" for i in x], axis = 1).apply(lambda x: ["background-color: gray; color: white" if i == leagueList[3]
                            else "" for i in x], axis = 1).apply(lambda x: ["background-color: green; color: white" if i == leagueList[4]
                            else "" for i in x], axis = 1).apply(lambda x: ["background-color: maroon; color: white" if i == leagueList[5]
                            else "" for i in x], axis = 1)
    st.dataframe(df3, height=2150)

app()


import numpy as np
import h5py
import pickle

def get_emb(word, h):

    if word in h:
        return h[word]
    else:
        return h['__UNK__']

path = 'data/semeval16/laptop/text_vocab.vocab'

with open(path, 'r') as f:
    with open('data/semeval16/laptop/text_vector.pkl', 'rb') as pkl_file:
        h = pickle.load(pkl_file)
        print(type(h))
        lines = f.readlines()
        emb = []
        print(len(lines))
        for line in lines:
            i, word = line.strip().split('\t')
            emb.append(get_emb(word, h))
        print(len(emb), len(emb[0]))
        emb = np.asarray(emb)
        print(emb.shape)


import math
import numpy as np
import pandas as pd
import random
import itertools as itr
import os
from pathlib import PurePath
from scipy.sparse import coo_matrix
from scipy.spatial import distance_matrix
import scipy.stats as sts
from sklearn.preprocessing import normalize
import time
import functools
import operator
import collections
import csv

class Cluster():
	"""
		Classe pour le Neural Gas SOM
	"""
	def __init__(self):
		self.data = 0
		self.obj = 0
		self.N = 0
		self.limi = 2
		self.limf = 6
		self.tmax = 0
		self.ei = 0.3
		self.ef = 0.05
		self.li = 30
		self.lf = 0.01

	def accueil(self):
		choix_set = -1
		choix_methode = -1
		condition = 0
		W = 0
		C = 0
		while not choix_methode in [0,1,2]:
			choix_methode = input("Voulez vous utiliser un de vos jeux de données ou bien un préexistant ?\n \
				   0) Votre jeu de données\n \
				   1) Un jeu de données préexistant sans recalculer les poids des Clusters\n \
				   2) Un jeu de données préexistant en recalculant les poids des Clusters \n")
			choix_methode = int(choix_methode)
		if choix_methode in [1,2]:
			while not choix_set in [1,2]:
				choix_set = input("\n\
				   1) Jeu de données 1 sur les comportements d'utilisateur de Reddit \n \
				   2) Jeu de données 2 sur la fréquence de vente de certains produits\n")
				choix_set = int(choix_set)

		if choix_methode == 0:
			path = input("Entrez le chemin vers votre data set, ce doit être un csv ! attention la première colonne disparaît !!\n")
			while not os.path.exists(path):
				path = input("Veuillez rentrer un chemin valide \n")
			self.data = pd.read_csv(path)
			self.obj = 'df'
		elif choix_methode == 1:
			if choix_set == 1:
				with open("reddit_W.csv",newline='') as file:
					rid = csv.reader(file,delimiter=',')
					W = list(rid)
				W = [[float(x) for x in W[i]] for i in range(len(W))]
				C = [[20], [25], [24, 29, 18, 14], [13], [0], [25, 16, 2], [20], [8, 27], [7], [27, 25], [27, 1, 25], [5, 1, 25], [25, 5, 1], [3, 15, 25], [29], [18, 25], [25, 5, 12], [12, 5, 25], [15, 25, 11], [5], [6], [0, 20], [3], [26], [12], [9], [23], [15], [23, 6], []]
				path = 'reddit_raw.csv'
				self.data = pd.read_csv(path)
				self.obj = 'coo'
			else:
				with open("transaction_W.csv",newline='') as file:
					rid = csv.reader(file,delimiter=',')
					W = list(rid)
				W = [[float(x) for x in W[i]] for i in range(len(W))]
				C = [[10, 20, 2, 22], [16], [4, 8, 0, 21], [14, 27], [2, 10], [19, 16, 29], [4, 28, 10, 13, 25], [13, 23], [20, 2, 18], [1, 14, 24, 3, 19], [18, 6], [24, 12, 15, 29], [11, 5, 26], [10, 23], [9], [23, 11, 24, 1], [26, 24, 27, 1], [25, 4, 13], [4, 21, 22, 10], [27], [28, 21, 18], [2, 22, 20], [21, 8, 18], [24, 25, 6, 3], [23, 15, 26], [10, 8, 17], [15, 1, 24], [5, 29], [10, 6, 13], [5, 16, 12]]
				path = 'transaction_raw.csv'
				self.data = pd.read_csv("transaction_raw.csv",usecols=[x for x in range(55,107)])

				self.obj = 'df'
		elif choix_set == 1:
			path = 'reddit_raw.csv'
			self.data = pd.read_csv(path)
			self.obj = 'coo'
		elif choix_set == 2:
			path = 'transaction_raw.csv'
			self.data = pd.read_csv("transaction_raw.csv",usecols=[x for x in range(55,107)])
			self.obj = 'df'

		return(choix_methode,W,C)

	def prétraitement(self):
		d = self.data
		if self.obj == 'df':
			h = pd.DataFrame(columns=[x for x in d.columns if x != d.columns[0]],index=[x for x in d.index])
			for i,j in itr.product(d.index,h.columns):
				h.loc[i,j] = (d.loc[i,j] - d.loc[:,j].mean())/d.loc[:,j].std()

			f = [[x for x in h.iloc[i,:]] for i in range(len(h.index))]
			self.N = 30
			self.tmax = self.N*self.limf*4
			self.data=f
		elif self.obj == 'coo':
			d.sort_values(d.columns[0], axis=0, ascending=True, inplace=True)
			a = pd.factorize(d.iloc[:,0])
			d.iloc[:,0] = [x for x in a[0]]
			d.sort_values(d.columns[1],axis=0,ascending=True,inplace=True)
			b = pd.factorize(d.iloc[:,1])
			d.iloc[:,1] = [x for x in b[0]]

			row = [x for x in d.iloc[:,0]]
			col = [x for x in d.iloc[:,1]]
			row.sort()
			col.sort()
			row = pd.factorize(row)
			col = pd.factorize(col)

			l_row = len(set(d.iloc[:,0]))
			l_col = len(set(d.iloc[:,1]))

			coo = coo_matrix((d.iloc[:,2],(d.iloc[:,0],d.iloc[:,1])),shape=(l_row,l_col)).toarray()
			normalize(coo,axis=1,copy=False)

			self.N = 30
			self.tmax = self.N*self.limf*4
			self.data = coo
		return(self.data)

	def distance(self,v,W):
		dis = distance_matrix(W,[v],p=2,threshold = 1000)
		dis = [(dis[i][0],i) for i in range(len(dis))]
		dis.sort(key=lambda x : x[0], reverse=False)
		return([x for x in dis])

	def som(self):
		un=time.time()
		cycle1 = 0
		"""
			N : le nombre de neurones à mettre
			e : le pas d'apprentissage
			tmax : le nombre d'itération
			lim : le temps maximum sans que deux noeuds soient proche avant la perte de la connexion entre eux
			path : le chemin vers le jeu de données
		"""
		d = self.data

		# Initialisation de l'algorithme
		"""
		if self.obj == 'df':
			W = [[np.random.normal(0,1) for i in range(len(d.columns))] for j in range(self.N)]
		else :
		"""
		W = [[np.random.normal(0,1) for i in range(len(d[0]))] for j in range(self.N)]
		# Ces deux listes prendront l'une le numéro d'un noeud l'autre le temps sans visite
		C = [[] for i in range(self.N)]
		t = [[] for i in range(self.N)]

		for ep in range(self.tmax):
			#Extraction du candidat

			v = [x for x in d[random.randint(0,len(d)-1)]]
			"""
				Calcule des distances et classement du plus proche au plus loin
				Un peu d'explication, dis[i] contient (la distance, le numéro du noeud)
				dis[i][1] contient donc le numéro du noeud, en appelant W[dis[i][1]] on appelle
				le noeud correspondant.
				"i" quant à lui est le classement du noeud car on a trier la liste dans l'ordre déscendant
			"""
			dis = self.distance(v,W)
			d0 = dis[0][1]
			d1 = dis[1][1]
			eta = self.ei * math.pow((self.ef/self.ei),(ep/self.tmax))
			lamb = self.li * math.pow((self.lf/self.li),(ep/self.tmax))
			lim = self.limi * math.pow((self.limf/self.limi),(ep/self.tmax))
			for i in range(len(dis)):
				f = eta*math.exp(-i/lamb)
				W[dis[i][1]] = [W[dis[i][1]][j] + f*(v[j] -W[dis[i][1]][j]) for j in range(len(W[dis[i][1]]))]

			ret = [i for i in range(len(C[d0])) if (t[d0][i]+1 >= lim and C[d0][i] != d1)]

			C[d0] = [C[d0][i] for i in range(len(C[d0])) if not i in ret]
			t[d0] = [t[d0][i] for i in range(len(t[d0])) if not i in ret]
			if d1 in C[d0]:
				t[d0] = [t[d0][i]+1 if C[d0] != d1 else 0 for i in range(len(t[d0]))]
			else:
				C[d0] += [d1]
				t[d0] = [t[d0][i]+1 for i in range(len(t[d0]))] + [0]
			print((time.time()-un)*self.tmax/3600)

		return(W,C)

class MCMC():
	"""
		Classe pour la Markov Chain Monte Carlo
		C : Contient les liens qui ont été établit lors du clusering par neural gas
		W : Contient les poids des neurones du neural gas
		test : Contient l'élément que l'on va tenter de découvrir
		biais :
			Initialement le poid que l'on veut attribuer à l'ensemble des neurones en lien avec un neurone
				Par exemple, si on met 0.8, l'ensemble des neurones liés à un neurones se partagerons 80% des probabilité d'être tirée à partir de ce noed
			Ensuite contient un dataframe contenant la probabilité de transition d'un noeud à un autre
	"""
	def __init__(self,C,W,biais,test,cov):
		self.C = C
		self.cov = cov
		self.W = W
		self.test = test
		self.nb_clust = 0
		self.biais = biais
		self.prior = 0

	def prétraitement(self):

		self.nb_clust = len(self.C)

		C = [set(x) for x in self.C]

		for i in range(len(self.C)):
			for j in self.C[i]:
				C[j].add((x for x in self.C[i]))

		df = pd.DataFrame(columns=[x for x in range(self.nb_clust)],index=[x for x in range(self.nb_clust)])
		for i,j in itr.product(df.index,df.columns):
			l = len(C[i])
			if i == j :
				df.loc[i,j] = 0
			elif j in C[i]:
				df.loc[i,j] = self.biais/l
			else:
				df.loc[i,j] = (1-self.biais)/(self.nb_clust-l)

		tot = sum([sum(df.loc[i:]) for i in df.index])
		self.prior = [sum(df.loc[i:])/tot for i in df.index]
		self.var = [sorted(x)[math.floor(0.75*len(x))] for x in self.cov]
		self.biais = df
		print(self.prior)

	def alpha(self,cand,al_now,now,dim):
		#Donne la vraisemblance des données sachant une loi normale centrée sur chaque
		al_cand = sts.norm.pdf(np.linalg.norm([self.test[i]-self.W[cand][i] for i in dim]),loc=0,scale=self.var[cand])
		#On multiplie par la probabilité à priori et la probabilité de
		al_cand *= self.prior[cand]

		alpha = al_cand*self.biais.iloc[cand,now]/(al_now*self.biais.iloc[now,cand])
		print("alpha = ",alpha)
		return(alpha,al_cand)

	def mh(self,n_iter,init,test,dim=None,testif=None,bias=None):
		if testif == None:
			pass
		else:
			self.test = test

		if dim == None:
			dim = range(len(self.test))
		else:
			dim = dim

		if bias == None:
			pass
		else:
			self.prior[bias[1]] += bias[0]

		out = [0 for x in range(n_iter)]
		accpt = 0

		now = init

		al_now = sts.norm.pdf(np.linalg.norm([self.test[i]-self.W[now][i] for i in dim]),loc=0,scale=self.var[now])
		#al_now = np.prod([sts.norm.pdf(self.test[i],loc=self.W[now][i],scale=1) for i in range(len(self.test))])
		al_now *= self.prior[now]

		for i in range(n_iter):
			cand = random.choices([x for x in range(self.nb_clust)],weights=[x for x in self.biais.iloc[now]])
			cand = cand[0]
			alpha,al_cand = self.alpha(cand,al_now,now,dim)

			u = np.random.uniform(low=0.0,high=1.0)
			if u < alpha:
				now = cand
				al_now = al_cand
				accpt = accpt + 1

			out[i] = now

		return(out,accpt/n_iter,self.test)

	def pvalue(self,entrée,dim):
		tot = len(entrée[0])
		out = [sum([1/tot for j in entrée[i] if j in dim]) for i in range(len(entrée))]
		"""
		out = {j:[1/tot ] for i,j in itr.product(range(len(entrée)),dim)}
		out = [entrée[i][j] for i,j in itr.product(range(len(entrée)),range(len(entrée[0])))]
		tot = len(out)
		out = [1/tot for i in out if i in dim]

		out = sum(out)
		print(out)
		"""
		if dim == None:
			return(out)
		else:
			return(out)
"""
	def permutation(self,a,b,pas,dim):

		echant = [0 for x in range(math.floor(len(a[0])/pas))]
		test = [0 for x in range(len(echant)-1)]
		deb = 0

		for i in range(0,math.floor(len(a[0])/pas)-1):
			j = (i+1)*pas
			deb *= pas
			echant[i] = [a[k][deb:j]+b[k][deb:j] for k in range(len(a))]
			test[i] = [[random.choice(echant[i])[0] for k in range(deb,j)] for l in range(1000)]
			deb = i
		print(test)
		mcval = [self.pvalue(test[i],dim) for i in range(len(test))]
		print(mcval)
		print(len(mcval))
		print(len(mcval[0]))
		mcval = [[mcval[i][j] for i in range(len(mcval))] for j in range(1000)]
		ran = [(random.choice([x for x in range(1000)]),random.choice([x for x in range(1000)])) for u in range(500)]
		print(len(mcval[0]))
		mcval = [[mcval[u[0]][v] - mcval[u[1]][v] for v in range(len(mcval[0]))] for u in ran]
		mcval = [[1 if (sts.wilcoxon(mcval[i][j:j+25],zero_method="pratt")[1] <0.05) else 0 for j in range(0,len(mcval[i]),25)] for i in range(len(mcval))]
		#test = [[1 if (((sts.wilcoxon(test[i][j],zero_method="pratt")[1]/2) <0.05) and sum(test[i][j]) < 0) else 0 for j in range(len(test[i]))] for i in range(len(test))]
		out = [[] for i in range(len(mcval))]

		for i in range(len(mcval)):
			lon = 0
			for j in range(len(mcval[i])):
				if mcval[i][j] == 1:
					lon+=1
				else:
					out[i] += [lon]
					lon = 0
			out[i] += [lon]

		print(len(mcval))
		pval = functools.reduce(operator.concat, out)
		pval = max(pval)
		print(pval)
		return(pval)

"""