import requests
from actionkit.api.test_data import TEST_DATA
from actionkit.api.base import ActionKitAPI

class AKTransactionAPI(ActionKitAPI):

    def get_transaction_detail(self, transaction_id):
        """
            Get recurring donation info and billing info
        """
        if getattr(self.settings, 'AK_TEST', False):
            transaction = TEST_DATA['transactions'][str(transaction_id)]
            res = self.test_service_get_transaction(transaction)
            return res.data
            return TEST_DATA.get('get_orderrecurring_detail')
        result = self.client.get(
            '%s/rest/v1/transaction/%s' % (
                self.base_url, transaction_id))
        rv = {'res': result}

        if result.status_code == 200:
            json = result.json()
            rv.update(json)
        return rv

    def reverse_transaction(self, transaction_id):
        result = self.client.post(
            '%s/rest/v1/transaction/%s/reverse/' % (self.base_url, transaction_id)
        )
        return {'res': result}
    def test_service_get_transaction(self, transaction):
        r = requests.Response()
        if transaction == None:
            r.transaction = {}
            r.status_code = 404
        else:
            r.status_code = 200
            r.data = transaction
        return r


import apiaudio
apiaudio.api_key = "your-key"  # or define env variable: export apiaudio_key=<your-key>

text = "<<sectionName::welcome>> Hey {{username}}, welcome to my workout app!"
audience = [{"username": "John"}]

# script creation
script = apiaudio.Script().create(
    scriptText=text,
    projectName="workout_app",
    moduleName="welcome",
    scriptName="welcome-message",
)
print(f"Script created: \n {script} \n")

# get the scriptId from the script created.
scriptId = script["scriptId"]

# speech creation
response = apiaudio.Speech().create(
    scriptId=scriptId, voice="Joanna", speed="110", audience=audience
)
print(f"Response from text-to-speech: \n {response} \n")

# mastering process
response = apiaudio.Mastering().create(
    scriptId=scriptId, soundTemplate="heatwave", audience=audience
)
print(f"Response from mastering: \n {response} \n")

# get url of audio tracks generated
url = apiaudio.Mastering().retrieve(scriptId=scriptId, parameters=audience[0])
print(f"url to download the track: \n {url} \n")

# or download
file = apiaudio.Mastering().download(
    scriptId=scriptId, parameters=audience[0], destination="."
)
print(f"file location: \n {file} \n")


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf

import argparse
import cv2
import numpy as np
from glob import glob
import copy

num_classes = 2
img_height, img_width = 128, 128
channel = 3
tf.set_random_seed(0)

def Res152(x, keep_prob, train=True):

    def ResBlock(x, in_f, f_1, out_f, stride=1):
        res_x = tf.layers.conv2d(x, f_1, [1, 1], strides=stride, padding='same', activation=None)
        res_x = tf.layers.batch_normalization(res_x, training=train)
        res_x = tf.nn.relu(res_x)

        res_x = tf.layers.conv2d(res_x, f_1, [3, 3], strides=1, padding='same', activation=None)
        res_x = tf.layers.batch_normalization(res_x, training=train)
        res_x = tf.nn.relu(res_x)

        res_x = tf.layers.conv2d(res_x, out_f, [1, 1], strides=1, padding='same', activation=None)
        res_x = tf.layers.batch_normalization(res_x, training=train)
        res_x = tf.nn.relu(res_x)

        if in_f != out_f:
            x = tf.layers.conv2d(x, out_f, [1, 1], strides=1, padding='same', activation=None)
            x = tf.layers.batch_normalization(x, training=train)
            x = tf.nn.relu(x)

        if stride != 1:
            x = tf.layers.max_pooling2d(x, [2, 2], strides=stride, padding='same')

        x = tf.add(res_x, x)
        x = tf.nn.relu(x)

        return x

    x = tf.layers.conv2d(x, 64, [7, 7], strides=2, padding="same", activation=None)
    x = tf.layers.batch_normalization(x, training=train)
    x = tf.nn.relu(x)

    x = tf.layers.max_pooling2d(x, [3, 3], strides=2, padding='SAME')

    # Res block 2
    x = ResBlock(x, 64, 64, 256)
    x = ResBlock(x, 256, 64, 256)
    x = ResBlock(x, 256, 64, 256)

    # Res block 3
    x = ResBlock(x, 256, 128, 512, stride=2)
    for _ in range(7):
        x = ResBlock(x, 512, 128, 512)

    # Res block 4
    x = ResBlock(x, 512, 256, 1024, stride=2)
    for _ in range(35):
        x = ResBlock(x, 1024, 256, 1024)

    # Res block 5
    x = ResBlock(x, 1024, 512, 2048, stride=2)
    x = ResBlock(x, 2048, 256, 2048)
    x = ResBlock(x, 2048, 256, 2048)

    x = tf.reduce_mean(x, axis=[1, 2])
    x = tf.layers.dense(x, num_classes)

    return x

CLS = ['akahara', 'madara']

# get train data
def data_load(path, hf=False, vf=False, rot=False):
    xs = []
    ts = []
    paths = []

    for dir_path in glob(path + '/*'):
        for path in glob(dir_path + '/*'):
            x = cv2.imread(path)
            x = cv2.resize(x, (img_width, img_height)).astype(np.float32)
            x /= 255.
            x = x[..., ::-1]
            xs.append(x)

            t = [0 for _ in range(num_classes)]
            for i, cls in enumerate(CLS):
                if cls in path:
                    t[i] = 1

            ts.append(t)

            paths.append(path)

            if hf:
                xs.append(x[:, ::-1])
                ts.append(t)
                paths.append(path)

            if vf:
                xs.append(x[::-1])
                ts.append(t)
                paths.append(path)

            if hf and vf:
                xs.append(x[::-1, ::-1])
                ts.append(t)
                paths.append(path)

            if rot != False:
                angle = rot
                scale = 1

                # show
                a_num = 360 // rot
                w_num = np.ceil(np.sqrt(a_num))
                h_num = np.ceil(a_num / w_num)
                count = 1
                #plt.subplot(h_num, w_num, count)
                #plt.axis('off')
                #plt.imshow(x)
                #plt.title("angle=0")

                while angle < 360:
                    _h, _w, _c = x.shape
                    max_side = max(_h, _w)
                    tmp = np.zeros((max_side, max_side, _c))
                    tx = int((max_side - _w) / 2)
                    ty = int((max_side - _h) / 2)
                    tmp[ty: ty+_h, tx: tx+_w] = x.copy()
                    M = cv2.getRotationMatrix2D((max_side/2, max_side/2), angle, scale)
                    _x = cv2.warpAffine(tmp, M, (max_side, max_side))
                    _x = _x[tx:tx+_w, ty:ty+_h]
                    xs.append(_x)
                    ts.append(t)
                    paths.append(path)

                    # show
                    #count += 1
                    #plt.subplot(h_num, w_num, count)
                    #plt.imshow(_x)
                    #plt.axis('off')
                    #plt.title("angle={}".format(angle))

                    angle += rot
                #plt.show()

    xs = np.array(xs, dtype=np.float32)
    ts = np.array(ts, dtype=np.int)

    return xs, ts, paths

# train
def train():
    tf.reset_default_graph()

    # place holder
    X = tf.placeholder(tf.float32, [None, img_height, img_width, channel])
    Y = tf.placeholder(tf.float32, [None, num_classes])
    keep_prob = tf.placeholder(tf.float32)

    logits = Res152(X, keep_pro, train=False)
    preds = tf.nn.softmax(logits)

    #loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(logits=logits, onehot_labels=Y))

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=Y))
    optimizer = tf.train.MomentumOptimizer(learning_rate=0.001, momentum=0.9)
    train = optimizer.minimize(loss)

    correct_pred = tf.equal(tf.argmax(preds, 1), tf.argmax(Y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

    xs, ts, paths = data_load('../Dataset/train/images/', hf=True, vf=True, rot=10)

    # training
    mb = 128
    mbi = 0
    train_ind = np.arange(len(xs))
    np.random.seed(0)
    np.random.shuffle(train_ind)

    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    config.gpu_options.visible_device_list="0"

    with tf.Session(config=config) as sess:
        sess.run(tf.global_variables_initializer())

        for i in range(500):
            if mbi + mb > len(xs):
                mb_ind = copy.copy(train_ind)[mbi:]
                np.random.shuffle(train_ind)
                mb_ind = np.hstack((mb_ind, train_ind[:(mb-(len(xs)-mbi))]))
                mbi = mb - (len(xs) - mbi)
            else:
                mb_ind = train_ind[mbi: mbi+mb]
                mbi += mb

            x = xs[mb_ind]
            t = ts[mb_ind]

            _, acc, los = sess.run([train, accuracy, loss], feed_dict={X: x, Y: t, keep_prob: 0.7})

            if (i + 1) % 10 == 0:
                print("iter >>", i+1, ', loss >>', los / mb, ', accuracy >>', acc)

        saver = tf.train.Saver()
        saver.save(sess, './cnn.ckpt')

# test
def test():
    tf.reset_default_graph()

    X = tf.placeholder(tf.float32, [None, img_height, img_width, 3])
    Y = tf.placeholder(tf.float32, [None, num_classes])
    keep_prob = tf.placeholder(tf.float32)

    logits = Res152(X, keep_prob, train=False)
    out = tf.nn.softmax(logits)

    xs, ts, paths = data_load("../Dataset/test/images/")

    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    config.gpu_options.visible_device_list="0"

    with tf.Session(config=config) as sess:
        saver = tf.train.Saver()
        #saver = tf.train.import_meta_graph("./cnn.ckpt.meta")
        saver.restore(sess, "./cnn.ckpt")

        for i in range(len(paths)):
            x = xs[i]
            t = ts[i]
            path = paths[i]

            x = np.expand_dims(x, axis=0)

            pred = sess.run([out], feed_dict={X:x, keep_prob:1.})[0]
            pred = pred[0]
            #pred = out.eval(feed_dict={X: x, keep_prob: 1.0})[0]

            print("in {}, predicted probabilities >> {}".format(path, pred))

def arg_parse():
    parser = argparse.ArgumentParser(description='CNN implemented with Keras')
    parser.add_argument('--train', dest='train', action='store_true')
    parser.add_argument('--test', dest='test', action='store_true')
    args = parser.parse_args()
    return args

# main
if __name__ == '__main__':
    args = arg_parse()

    if args.train:
        train()
    if args.test:
        test()

    if not (args.train or args.test):
        print("please select train or test flag")
        print("train: python main.py --train")
        print("test:  python main.py --test")
        print("both:  python main.py --train --test")


from module import Singleton

SQL_FETCH = '''SELECT channel_code, type, rate, allow_start, allow_end FROM authentic_info LIMIT 20'''

class DBOperator(Singleton):
    def _get_info(self, cur):
        cur.execute(SQL_FETCH)
        if cur.rowcount > 0:
            return cur.fetchall()
        else:
            return None


# -*- coding: utf-8 -*-
"""
Created on Wed Oct 21 13:42:33 2020

@author: Sami
"""

import pymysql
from app import app
from db_config import mysql
from flask import jsonify
from flask import flash, request

@app.route('/createDress', methods=['POST'])
def create_dress():
    try:
        _json = request.json
        _dress_name = _json['dress_name']
        _dress_size = _json['dress_size']

        sqlQuery = "INSERT INTO dresses(dress_name, dress_size) VALUES(%s, %s)"
        sqlQuery2 = "select id from dresses where dress_name = %s"
        data = (_dress_name, _dress_size,)
        conn = mysql.connect()
        cursor = conn.cursor()
        cursor.execute(sqlQuery, data)
        cursor.execute(sqlQuery2, _dress_name)
        conn.commit()
        idd = cursor.fetchall()
        dress = {'id': idd,
        'dress_name': _dress_name,
        'dress_size': _dress_size,
        'available' : 1}
        res = jsonify({'dress':dress})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/createCustomer', methods=['POST'])
def create_customer():
    try:
        _json = request.json
        _first_name = _json['first_name']
        _last_name = _json['last_name']
        _phone_number = _json['phone_number']
        _size = _json['size']
        _wedding_date = _json['wedding_date']

        sqlQuery = "INSERT INTO customers(first_name, last_name, phone_number, size, wedding_date) VALUES(%s, %s, %s, %s, %s)"
        data = (_first_name, _last_name, _phone_number, _size, _wedding_date,)
        sqlQuery2 = "select max(id) from customers"
        conn = mysql.connect()
        cursor = conn.cursor()
        cursor.execute(sqlQuery, data)
        cursor.execute(sqlQuery2)
        conn.commit()
        idd = cursor.fetchall()
        customer = {'id':idd,
        'first_name': _first_name,
        'last_name': _last_name}
        res = jsonify({'customer': customer})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/createReservation', methods=['POST'])
def create_reservation():
    try:
        _json = request.json
        _customer_id = _json['customer_id']
        _dress_id = _json['dress_id']
        _rent_date = _json['rent_date']

        sqlQuery = "INSERT INTO reservations(customer_id, dress_id, rent_date, return_on) VALUES(%s, %s, %s, %s)"
        sqlQuery2 = "select max(id) from reservations"
        data = (_customer_id, _dress_id, _rent_date, None,)
        conn = mysql.connect()
        cursor = conn.cursor()
        cursor.execute(sqlQuery, data)
        cursor.execute(sqlQuery2)
        conn.commit()
        idd = cursor.fetchall()
        reservation = {
            'id': idd,
            'customer_id': _customer_id,
            'dress_id': _dress_id}
        res = jsonify({'reservation': reservation})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/dresses')
def dresses():
    try:
        conn = mysql.connect()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        cursor.execute("SELECT sharks.id, sharks.dress_name, sharks.dress_size, COALESCE(sharks.available, 0 ) as available \
                        FROM ( \
	                        select dresses.id, dresses.dress_name, dresses.dress_size, \
	                        (max(reservations.return_on) > max(reservations.rent_date) or sum(reservations.id) is null) as available \
	                        from reservations \
	                        right join dresses \
	                        on reservations.dress_id = dresses.id \
	                        group by dresses.id) as sharks")
        rows = cursor.fetchall()
        res = jsonify({'dresses': rows})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/customers')
def customers():
    try:
        conn = mysql.connect()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        cursor.execute("SELECT id, first_name, last_name from customers")
        rows = cursor.fetchall()
        res = jsonify({'customers': rows})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/reservations')
def reservations():
    try:
        conn = mysql.connect()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        cursor.execute("SELECT id, customer_id, dress_id from reservations")
        rows = cursor.fetchall()
        res = jsonify({'reservations': rows})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

@app.route('/return', methods=['POST'])
def update_status():
    try:
        _json = request.json
        _reservation_id = _json['reservation_id']
        _return_on = _json['return_on']

        sql = "update reservations set return_on = %s where id =%s"
        sql2 = "select dress_id from reservations where id = %s"
        data = (_return_on, _reservation_id,)
        conn = mysql.connect()
        cursor = conn.cursor()
        cursor.execute(sql, data)
        cursor.execute(sql2, (_reservation_id,))
        idd = cursor.fetchall()
        conn.commit()
        res = jsonify({'dress_id': idd})
        res.status_code = 200
        return res
    except Exception as e:
        print(e)
    finally:
        cursor.close()
        conn.close()

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


import json
import base64
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

class SSOResult:
    """
    Result dari parse Token, didefinisikan hanya valid,
    sisanya akan dilooping dari JSON.
    """

    def __init__(self, valid):
        self.mapping = {
            "id": "SessionID",
            "nk": "NIK",
            "np": "NIP",
            "nm": "Nama",
            "hp": "HP",
            "em": "Email",
            "tl": "TelegramID",
            "ea": "EmailAlternatif",
            "av": "Avatar",
            "dt": "Datetime"
        }
        self.valid = valid

class SSOClient:

    def __init__(self, jsonpath):
        """
        Base class sso client untuk bahasa python,
        load sso_secure.json saat init.
        """
        try:
            with open(jsonpath) as json_file:
                data = json.load(json_file)
                for key, value in data.items():
                    setattr(self, key, value)

        except Exception as e:
            print("Parse Json File Error : {}".format(str(e)))

    def ParseToken(self, token):
        """
        Main method sso client untuk bahasa python,
        parse token dan result menjadi SSOResult.
        """

        result = SSOResult(valid=False)

        try:
            """
            Token dan privateKey masih dalam format Base64 Url safe,
            decode terlebih dahulu.
            """
            decoded_private_key = base64.urlsafe_b64decode(
                self.base64_rsa_private_key)
            decoded_token = base64.urlsafe_b64decode(token)

            """
            Decrypt OAEP dengan SHA-1,
            dalam bentuk bytes, perlu di decode ke string
            """
            key = RSA.importKey(decoded_private_key)
            cipher = PKCS1_OAEP.new(key)
            message = cipher.decrypt(decoded_token)

            """
            Hasil dikembalikan dalam bentuk SSOResult
            menggunakan looping ke dalam atribut
            """
            jsonParsed = json.loads(message.decode('utf-8'))
            result.valid = True
            for key, value in jsonParsed.items():
                setattr(result, result.mapping[key], value)

            return result

        except Exception as e:
            """
            Default return jika terjadi error
            agar tidak error di sisi client
            """
            print("Error Parse Token : {}".format(str(e)))
            for key, value in result.mapping.items():
                setattr(result, value, "")
            return result


import pandas as pd
import numpy as np
from scipy import spatial
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.cluster import KMeans
import seaborn as sns

#feature vector
fv = np.load('Node_Features_Weekly.npy')
# Size 248 (weeks) x 136 (nodes) x 16 (features)

#past weeks/lags
w = 4

#average behavior
ab = np.zeros((248,136,16))
for t in range (w,248):
    ab[t,:,:] = np.mean(fv[t-w:t,:,:], axis = 0)

#dissimilarity
d = np.zeros((248,136))
#dissimilarity between fv and ab at every time
for i in range(0,136):
    for t in range (w,248):
        d[t,i] = spatial.distance.cosine(fv[t,i,:].reshape(16, 1), ab[t,i,:].reshape(16, 1))
d = np.nan_to_num(d)

#plot dissimilarity value for time (y-axis) and node (x-axis)
plt.figure(figsize = (20, 10))
a = sns.heatmap(d, vmin = 0, vmax = 1, xticklabels = 5, yticklabels = 10)
a.set(title = "Cosine Dissimilarity", xlabel = "Node Number", ylabel = "Week Number")

#k-means clustering of all values in d matrix - for finding thresholds
km = KMeans()
a = km.fit(d[w:,:].reshape(-1,1))

#number of clusters
print(a.n_clusters)
print("")

#center of clusters
print(a.cluster_centers_)

b = a.labels_.reshape(248-w,136)

k_clusters_bins = np.zeros((8,3))
for i in range(0,8):
    k_clusters_bins[i,0] = min(d[w:,:].reshape(-1,1)[a.labels_ == i])
    k_clusters_bins[i,1] = max(d[w:,:].reshape(-1,1)[a.labels_ == i])
    k_clusters_bins[i,2] = len(d[w:,:].reshape(-1,1)[a.labels_ == i])
k_clusters_bins = k_clusters_bins[k_clusters_bins[:, 0].argsort()]

ranges = [''] * 8
for i in range(0,8):
    ranges[i] = str(round(k_clusters_bins[i,0], 2))+"-"+str(round(k_clusters_bins[i,1], 2))
x = np.arange(8)
freq = k_clusters_bins[:,2]

plt.figure(figsize = (15, 5))
plt.bar(x, freq, align = 'center')
plt.xticks(x, ranges)
plt.xlabel('Cosine Dissimilarity')
plt.ylabel('Frequency')
plt.title('w = 12 weeks')
plt.show()

#location of anomalies for all combinations of w and tau
locs = [[] for i in range(4)]

#past weeks/lags
w = [4,6,8,12]
#dissimilarity threshold
tau = 0.07

for i in range(len(w)):
    #average behavior
    ab = np.zeros((248,136,16))
    for t in range (w[i],248):
        ab[t,:,:] = np.mean(fv[t-w[i]:t,:,:], axis = 0)

    #dissimilarity
    d = np.zeros((248,136))
    #dissimilarity between fv and ab at every time
    for n in range(0,136):
        for t in range (w[i],248):
            d[t,n] = spatial.distance.cosine(fv[t,n,:].reshape(16, 1), ab[t,n,:].reshape(16, 1))
            d = np.nan_to_num(d)

    locs[i] = np.argwhere(d >= tau)
    np.savetxt('Location'+str(w[i])+'.csv', locs[i], delimiter=',', fmt='%d')
    print(len(locs[i]))

#length of overlap in detected anomaly positions
print(len(np.array([x for x in set(tuple(x) for x in locs[0]) & set(tuple(x) for x in locs[1]) &\
                         set(tuple(x) for x in locs[2]) & set(tuple(x) for x in locs[3])])))


#calss header
class _CLASSIC():
	def __init__(self,):
		self.name = "CLASSIC"
		self.definitions = [u'a piece of writing, a musical recording, or a film that is well known and of a high standard and lasting value: ', u'the most famous works of literature: ', u'the study of ancient Greek and Roman culture, especially their languages and literature: ', u'a piece of clothing that is always fashionable: ']

		self.parents = []
		self.childen = []
		self.properties = []
		self.jsondata = {}

		self.specie = 'nouns'

	def run(self, obj1 = [], obj2 = []):
		return self.jsondata


#!/usr/bin/python3
# -*- coding:utf8 -*-
import os

def show_generator():
    pass

def show_to_create_a_list():
    l = list([1, 2, 3])
    t = ('a', 1, 2)  # tuple just like a list ,but the elements cannot be modified after initialization
    # print_each_element_in_a_list(l)

    # print('\n')
    # l = list(range(1, 10))
    # l = [x**x for x in range(1,10)]

    l = [m+n for m in 'hhh' for n in 'bbb']

    #　list add ,remove ,insert, delete, basic modify operations
    l.insert(3, 'j')
    l.append('haha')
    l.pop(len(l) - 1)  ##  pop -> : remove operation
    print_each_element_in_a_list(l)

# for current directory : use '.', for parent directory ,use '../',etc
def list_all_file_and_folder_in_current_directory():
    print_each_element_in_a_list([d for d in os.listdir('../../')])

def show_to_create_a_generator():
    pass

def print_each_element_in_a_list(l):
    for i in l:
        print(i)

def show_to_create_a_generator():
    list = [x * x for x in range(1, 5)]
    print_each_element_in_a_list(list)

    # looks every resemble each other [] -> ()
    generator = (x * x for x in range(1, 5))
    print_each_element_in_a_list(generator)

# you can return multiple stuff from a function

# 如果一个函数定义中包含yield关键字，那么这个函数就不再是一个普通函数，而是一个generator
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b  # the right hand is a tuple
        n += 1
    return a, b

## generator is like an object you can pass to next(o), at end it will the Stop Iteration
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield (3)
    print('step 3')
    yield (5)

def iterate_generator(g):
    while True:
        try:
            x = next(g)
            print('g = ',x)
        except StopIteration as e:
            print("Generator return value ",e.value)
            break

iterate_generator(fib(20))


# -*- coding: utf-8 -*-
#
# Copyright (C) 2023 CERN
#
# Invenio-RDM-Records is free software; you can redistribute it and/or modify
# it under the terms of the MIT License; see LICENSE file for more details.

"""MARCXML based Schema for Invenio RDM Records."""

from copy import deepcopy

import bleach
from flask_resources.serializers import BaseSerializerSchema
from invenio_access.permissions import system_identity
from invenio_vocabularies.proxies import current_service as vocabulary_service
from marshmallow import fields, missing, post_dump

from ..schemas import CommonFieldsMixin
from ..ui.schema import current_default_locale
from ..utils import get_vocabulary_props

class MARCXMLSchema(BaseSerializerSchema, CommonFieldsMixin):
    """Schema for records in MARC."""

    doi = fields.Method("get_doi")
    oai = fields.Str(attribute="pids.oai.identifier")
    contributors = fields.Method("get_contributors")
    titles = fields.Method("get_titles")
    creators = fields.Method("get_creators")
    relations = fields.Method("get_relations")
    rights = fields.Method("get_rights")
    dates = fields.Method("get_dates")
    subjects = fields.Method("get_subjects")
    descriptions = fields.Method("get_descriptions")
    publishers = fields.Method("get_publishers")
    types = fields.Method(
        "get_types"
    )  # Corresponds to resource_type in the metadata schema
    # TODO: sources = fields.List(fields.Str(), attribute="metadata.references")
    sources = fields.Constant(
        missing
    )  # Corresponds to references in the metadata schema
    formats = fields.List(fields.Str(), attribute="metadata.formats")
    parent_id = fields.Str(attribute="parent.id")
    community_id = fields.List(fields.Str(), attribute="parent.communities.ids")
    last_updated = fields.Method("last_updated")
    sizes = fields.List(fields.Str(), attribute="metadata.sizes")
    version = fields.Str(attribute="metadata.version")
    funding = fields.Method("get_funding")

    def get_funding(self, obj):
        """Get funding information."""
        if "funding" not in obj["metadata"]:
            return missing

        funders = []
        all_funders = obj["metadata"].get("funding", [])

        for funder in all_funders:
            funder_string = ""

            award = funder.get("award", {})

            identifier = award.get("identifiers", [{}])[0]
            scheme = identifier.get("scheme", "null")
            identifier_value = identifier.get("identifier", "null")

            title = award.get("title", {})
            title = list(title.values())[0] if title else "null"

            number = award.get("number", "null")
            id = funder["funder"]["id"]
            name = funder["funder"].get("name", "null")

            funder_string += f"award_identifiers_scheme={scheme}; "
            funder_string += f"award_identifiers_identifier={identifier_value}; "
            funder_string += f"award_title={title}; "
            funder_string += f"award_number={number}; "
            funder_string += f"funder_id={id}; "
            funder_string += f"funder_name={name}; "
            funders.append(funder_string)

        return funders

    def last_updated(self, obj):
        """Get date last updated."""
        return [obj["updated"]]

    def get_relations(self, obj):
        """Get relations."""
        rels = []

        # Fundings
        # FIXME: Add after UI support is there

        # Alternate identifiers
        for a in obj["metadata"].get("alternate_identifiers", []):
            rels.append(f"{a['scheme']}:{a['identifier']}")

        # Related identifiers
        for a in obj["metadata"].get("related_identifiers", []):
            rels.append(f"{a['scheme']}:{a['identifier']}")

        return rels or missing

    def get_rights(self, obj):
        """Get rights."""
        rights = []
        access_right = obj.get("access", {}).get("status")

        if access_right:
            rights.append(f"info:eu-repo/semantics/{access_right}Access")

        if access_right == "metadata-only":
            access_right = "closed"

        ids = []
        for right in obj["metadata"].get("rights", []):
            _id = right.get("id")
            if _id:
                ids.append(_id)
            else:
                title = right.get("title").get(current_default_locale())
                if title:
                    rights.append(title)

                license_url = right.get("link")
                if license_url:
                    rights.append(license_url)

        if ids:
            vocab_rights = vocabulary_service.read_many(
                system_identity, "licenses", ids
            )
            for right in vocab_rights:
                title = right.get("title").get(current_default_locale())
                if title:
                    rights.append(title)

                license_url = right.get("props").get("url")
                if license_url:
                    rights.append(license_url)

        return rights or missing

    def get_dates(self, obj):
        """Get dates."""
        dates = [obj["metadata"]["publication_date"]]

        access_status = obj.get("access", {}).get("status", {})

        if access_status == "embargoed":
            date = obj["access"]["embargo"]["until"]
            dates.append(f"info:eu-repo/date/embargoEnd/{date}")

        return dates or missing

    def get_descriptions(self, obj):
        """Get descriptions."""
        metadata = obj["metadata"]
        descriptions = []

        description = metadata.get("description")
        if description:
            descriptions.append(description)

        additional_descriptions = metadata.get("additional_descriptions", [])
        for add_desc in additional_descriptions:
            descriptions.append(add_desc["description"])

        descriptions = [
            bleach.clean(
                desc,
                strip=True,
                strip_comments=True,
                tags=[],
                attributes=[],
            )
            for desc in descriptions
        ]

        return descriptions or missing

    def get_subjects(self, obj):
        """Get subjects."""
        metadata = obj["metadata"]
        subjects = []
        subjects.extend(
            (s["subject"] for s in metadata.get("subjects", []) if s.get("subject"))
        )
        return subjects or missing

    def get_types(self, obj):
        """Get resource type."""
        props = get_vocabulary_props(
            "resourcetypes",
            [
                "props.eurepo",
            ],
            obj["metadata"]["resource_type"]["id"],
        )
        t = props.get("eurepo")
        return [t] if t else missing

    # FIXME should this be a processor? that's somehow the post_dump place
    # otherwise we cannot guarantee order
    @post_dump()
    def keys_to_tags(self, data, many, **kwargs):
        """Changes the key name to the corresponding MARCXML tag (number)."""
        # [!] The string in the first array corresponds to the tag[0:4] + ind1[4] + ind2[5]
        # [!] The first string needs to be length *5* (this is to do with the dojson parser)
        # [!] The second string corresponds to the subfield code

        # Example: "creators" : ["100a ", "a"]

        #   <datafield tag="100" ind1="a" ind2=" ">
        #       <subfield code="a">Tarocco, Nicola</subfield>
        #   </datafield>

        # To add support for more tags, use the corresponding codes from here
        # https://scoap3.org/scoap3-repository/marcxml/

        changes = {
            "contributors": ["700a ", "u"],  # Abstract
            "titles": ["245a ", "a"],  # Title
            "creators": ["100a ", "a"],  # First author
            "oai": ["909CO", "o"],  # OAI
            "relations": ["856 2", "a"],  # Related Ressource
            "rights": ["540  ", "a"],  # License
            "dates": [
                "260c ",
                "c",
            ],  # Publication Information - Date of Publication
            "subjects": ["653  ", "a"],  # Keywords
            "descriptions": ["520  ", "a"],  # Abstract
            "publishers": [
                "260b ",
                "a",
            ],  # Publication Information - Publisher Name
            "types": ["901  ", "u"],  # Local Implementation
            "sources": ["246i ", "x"],  # Source
            "coverage": ["510  ", "a"],  # Location
            "formats": ["520 1", "a"],  # Abstract
            "parent_id": ["024 1", "a"],  # ID
            "community_id": ["024 2", "a"],  # ID
            "last_updated": [
                "260ca",
                "c",
            ],  # Publication Information - Date of Publication
            "sizes": ["520 2", "a"],  # Abstract
            "version": ["024 3", "a"],  # ID
            "funding": ["856 1", "a"],  # Related Ressource
        }

        data_copy = deepcopy(data)
        for key in data_copy:
            if key in changes:
                data[changes[key][0]] = {changes[key][1]: data.pop(key)}

        doi = data.pop("doi", None)
        if doi:
            data["024  "] = {"a": doi, "2": "doi"}

        return data


# -*- coding: utf-8 -*-
"""
Created on Fri Nov 29 20:11:58 2019

@author: Administrator
"""

import jieba
import jieba.analyse
import pandas as pd
import numpy as np
import jieba.posseg
import os

jieba.analyse.set_idf_path(r"E:\01工作资料\000 C_group data\C_group_product_name\C组产品主要词语-utf-8.txt")  #常见错误，字典之间的空格要注意，保留一个空格

def ad_tag(path):

    df = pd.read_excel(path)

    df.reset_index(inplace = True)

    filename = path.split('\\')[-1].split('.')[0]

    for i in range(0,len(df)):
        ad_tag = jieba.analyse.extract_tags(df.loc[i,'中文名'],topK = 4,allowPOS=('n','nr','ns'))
        df.loc[i,'ad_tag'] = ''.join(ad_tag)

    #将df中的空值复制为缺失值
    for i in range(0,len(df)):
        if df.loc[i,'ad_tag'] == '':
            df.loc[i,'ad_tag'] = np.nan

    #更改ad_tag在df中的位置
    df_tag = df.ad_tag
    df = df.drop('ad_tag',axis = 1)
    df.insert(7,'ad_tag',df_tag)

    #将缺失值填充前一个值
    df[['中文名','ad_tag']] = df[['中文名','ad_tag']].fillna(method = 'ffill',axis = 1) #此处不可用inplace = true

    #去除ad_tag中字符串×，在亚马逊后台系统并不识别,
    df['ad_tag'] = df['ad_tag'].apply(lambda x:x.replace('×',''))
    #去除空格
    df['ad_tag'] = df['ad_tag'].apply(lambda x:x.replace(' ',''))

    output_path = filename + '_广告标签已分解提取' + '.xlsx'

    #导出格式
    df.to_excel(output_path, index = False)

file_path = input('请输入要分解标签的文件（注意经过处理后VBA脚本处理后）:')
#去除输入路径时带入的双引号
if '"' in file_path:
    file_path = file_path.replace('"','')

f_path = os.path.dirname(file_path)
os.chdir(f_path)

ad_tag(file_path)

print('数据提取成功，路径为:%s'%f_path)

11_广告名称中文标签分解.py


import os
import pydwarf
import raws

smalldir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'smallthingsmod')

# A bit of esoteric code which makes smallraws only be read once
def getsmallraws():
    if 'smallraws' not in globals():
        globals()['smallraws'] = raws.dir(path=smalldir, log=pydwarf.log)
    return smallraws

# Help shapes get mapped to words
shapenamedict = {
    'ELF': 'FOREST',
    'DWARF': 'MOUNTAIN',
    'HUMAN': 'PLAIN',
    'MALE': 'MAN',
    'FEMALE': 'WOMAN',
    'OVERSEER': 'STAND',
    'MESSAGE': 'PAPER',
    'BADLAND': 'SAVAGE',
    'PARTY': 'CELEBRATE',
    'WATERFALL': 'WATER',
    'SKIRMISH': 'WAR',
    'HUNTER': 'BOW',
    'RETREAT': 'DEN',
    'STRONGHOLD': 'FORTRESS',
    'SAVANNA': 'PLAIN'
}

@pydwarf.urist(
    name = 'umiman.smallthings.prefstring',
    version = '1.0.0',
    author = ('Umiman', 'Fieari', 'Sophie Kirschner'),
    description = '''This mod simply just adds to the number of prefstrings for
        everything in the game to a minimum of five each. Prefstrings are the stuff
        that tell your dwarves what to like about a creature. For example, "He likes
        large roaches for their ability to disgust". With this mod, you'll see more
        fleshed out descriptions of the things your dwarves like, as well as more
        varied ones. With five each, it's pretty rare to see the same two twice.
        Hopefully I don't have any repeating prefstrings.

        Originally created by Umiman. Ported to ModBase by Fieari. Ported again to
        PyDwarf by Sophie.''',
    compatibility = (pydwarf.df_0_2x, pydwarf.df_0_3x, pydwarf.df_0_40)
)
def prefstring(dfraws):
    # Get the smallthings ModBase raws, which is where this data will be coming from
    smallraws = getsmallraws()
    if not smallraws: return pydwarf.failure('Failed to read smallthings raws.')

    # Get all creatures
    smallcreatures = smallraws.allobj('CREATURE')
    dfcreaturesdict = dfraws.objdict('CREATURE')

    # Add the new prefstrings
    failedcreatures = 0
    for smallcreature in smallcreatures:
        dfcreature = dfcreaturesdict.get(smallcreature.args[0])
        if not dfcreature:
            pydwarf.log.debug('Found prefstrings for %s but there was no corresponding creature in the DF raws. Skipping.' % smallcreature)
            failedcreatures += 1
        else:
            prefs = smallcreature.alluntil(exact_value='PREFSTRING', args_count=1, until_exact_value='CREATURE')
            dfcreature.add(tokens=raws.token.copy(prefs))
            pydwarf.log.debug('Added %d prefstrings to %s.' % (len(prefs), dfcreature))

    # All done!
    return pydwarf.success('Added prefstrings to %d creatures.' % (len(smallcreatures) - failedcreatures))

@pydwarf.urist(
    name = 'umiman.smallthings.engraving',
    version = '1.0.0',
    author = ('Umiman', 'Fieari', 'Sophie Kirschner'),
    description = '''Has this been done before? While I think it's impossible to change
        any of the inbuilt engraving stuff like, "this is a picture of a dwarf and a
        tentacle demon. The dwarf is embracing the tentacle demon", it is possible to
        edit and add to more basic ones such as "this is a picture of a crescent moon".
        Basically, I added maybe 100 or so new engravings you can potentially see on
        your floors, walls, studded armour, images, and the like. Keep in mind maybe
        one or two metagame just a tad but it's funny! I swear!

        Originally created by Umiman. Ported to ModBase by Fieari. Ported again to
        PyDwarf by Sophie.''',
    compatibility = (pydwarf.df_0_2x, pydwarf.df_0_3x, pydwarf.df_0_40)
)
def engraving(dfraws):
    # Get the smallthings ModBase raws, which is where this data will be coming from
    smallraws = getsmallraws()
    if not smallraws: return pydwarf.failure('Failed to read smallthings raws.')

    # Get existing words and shapes
    dfwordsdict = dfraws.objdict('WORD')
    dfshapesdict = dfraws.objdict('SHAPE')

    # Add a new file for the new shapes
    dfshapesfile = dfraws.addfile(filename='descriptor_shape_umiman')
    dfshapesfile.add('OBJECT:DESCRIPTOR_SHAPE')
    shapesadded = 0

    # Add each shape
    for smallshape in smallraws['descriptor_shape_standard'].all(exact_value='SHAPE'):
        if smallshape.args[0] not in dfshapesdict: # Verify that the shape isn't already in the raws
            pydwarf.log.debug('Adding shape %s...' % smallshape)

            # Get the tokens describing this shape
            smallshapetokens = smallshape.until(exact_value='SHAPE')

            # Shapes in DF's descriptor_shape_standard all have a [WORD:X] token but these do not
            # To compensate, let's do our best to map each shape to a word automatically
            smallshapename = smallshape.get(exact_value='NAME', args_count=2)
            if smallshapename:
                useshapename = smallshapename.args[0].upper()
                if useshapename in shapenamedict: useshapename = shapenamedict[useshapename]
                shapeword = dfwordsdict.get(useshapename)
            else:
                pydwarf.log.error('Found no names for %s.' % shallshape)

            # Actually add the new shape to the raws
            dfshapesfile.add(raws.token.copy(smallshape))
            dfshapesfile.add(raws.token.copy(smallshapetokens))

            # And also add the word, provided one was found
            if shapeword:
                dfshapesfile.add(raws.token(value='WORD', args=(shapeword.args[0],)))
            else:
                pydwarf.log.info('Found no word for %s, named %s.' % (smallshape, smallshapename))

            # And on to the next iteration
            shapesadded += 1

    # All done!
    return pydwarf.success('Added %s new shapes.' % shapesadded)


class Solution:
    def is_bipartite(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: bool
        """
        def dfs(node, color):
            res = True
            for nei in graph[node]:
                if nei not in color:
                    color[nei] = -color[node]
                    if not dfs(nei, color):
                        res = False
                elif color[nei] == color[node]:
                    return False
            return res

        color = {}
        n_nodes = len(graph)
        for node in range(n_nodes):
            if node not in color:
                color[node] = 1
                if not dfs(node, color):
                    return False
        return True


from __future__ import unicode_literals
import frappe
import json
from frappe.model.document import Document
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions

from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt

def process(doc):
	"""
	To be called by task periodically. It checks the subscription and takes appropriate action
	as need be. It calls either of these methods depending the `Subscription` status:
	1. `process_for_active`
	2. `process_for_past_due`
	"""
	if doc.status == 'Active':
		process_for_active(doc)
	# elif doc.status in ['Past Due Date', 'Unpaid']:
	#     process_for_past_due_date(doc)

	# doc.save()

def process_for_active(doc):
	"""
	Called by `process` if the status of the `Subscription` is 'Active'.

	The possible outcomes of this method are:
	1. Generate a new invoice
	2. Change the `Subscription` status to 'Past Due Date'
	3. Change the `Subscription` status to 'Cancelled'
	"""
	if not is_current_invoice_paid(doc) and (is_postpaid_to_invoice(doc) or is_prepaid_to_invoice(doc)):
		generate_invoice(doc)
		if current_invoice_is_past_due(doc):
			doc.status = 'Past Due Date'

	if current_invoice_is_past_due(doc) and getdate(nowdate()) > getdate(doc.current_invoice_end):
		doc.status = 'Past Due Date'

	if doc.cancel_at_period_end and getdate(nowdate()) > getdate(doc.current_invoice_end):
		cancel_subscription_at_period_end(doc)

def is_current_invoice_paid(doc):
	if is_new_subscription(doc):
		return False

	last_invoice = frappe.get_doc('Sales Invoice', doc.invoices[-1].invoice)
	if getdate(last_invoice.posting_date) == getdate(doc.current_invoice_start) and last_invoice.status == 'Paid':
		return True

	return False

def is_postpaid_to_invoice(doc):
	return getdate(nowdate()) > getdate(doc.current_invoice_end) or \
		(getdate(nowdate()) >= getdate(doc.current_invoice_end) and getdate(doc.current_invoice_end) == getdate(doc.current_invoice_start)) and \
		not has_outstanding_invoice(doc)

def is_prepaid_to_invoice(doc):
	if not doc.create_inv:
		return False

	if is_new_subscription(doc):
		return True

	# Check invoice dates and make sure it doesn't have outstanding invoices
	return getdate(nowdate()) >= getdate(doc.current_invoice_start) and not has_outstanding_invoice(doc)

def generate_invoice(doc, prorate=0):
	"""
	Creates a `Sales Invoice` for the `Subscription`, updates `doc.invoices` and
	saves the `Subscription`.
	"""
	invoice = create_invoice(doc,prorate)
	doc.append('invoices', {'invoice': invoice.name})
	# doc.save()

	return invoice

def current_invoice_is_past_due(doc, current_invoice=None):
	"""
	Returns `True` if the current generated invoice is overdue
	"""
	if not current_invoice:
		current_invoice = get_current_invoice(doc)

	if not current_invoice:
		return False
	else:
		return getdate(nowdate()) > getdate(current_invoice.due_date)

def cancel_subscription_at_period_end(doc):
	"""
	Called when `Subscription.cancel_at_period_end` is truthy
	"""
	doc.status = 'Cancelled'
	if not doc.cancelation_date:
		doc.cancelation_date = nowdate()

def is_new_subscription(doc):
	"""
	Returns `True` if `Subscription` has never generated an invoice
	"""
	return len(doc.invoices) == 0

def has_outstanding_invoice(doc):
	"""
	Returns `True` if the most recent invoice for the `Subscription` is not paid
	"""
	current_invoice = get_current_invoice(doc)
	if not current_invoice:
		return False
	else:
		return not is_not_outstanding(current_invoice)

def create_invoice(doc, prorate):
	"""
	Creates a `Sales Invoice`, submits it and returns it
	"""
	invoice = frappe.new_doc('Sales Invoice')
	invoice.set_posting_time = 1
	# invoice.posting_date = doc.current_invoice_start
	invoice.customer = doc.customer
	invoice.subscription=doc.name
	invoice.project=doc.project
	invoice.agreement_start_date=doc.agreement_start_date
	invoice.agreement_end_date=doc.agreement_end_date
	invoice.property_rent=doc.property_rent
	invoice.tenure=doc.agreement_tenure
	# if doc.invoice_date and invoice.posting_date!=doc.invoice_date:
	invoice.posting_date=doc.invoice_date if doc.invoice_date else doc.current_invoice_start
	if doc.invoice_due_days:
		invoice.due_date=add_days(invoice.posting_date,doc.invoice_due_days)
	## Add dimesnions in invoice for subscription:
	accounting_dimensions = get_accounting_dimensions()

	for dimension in accounting_dimensions:
		if doc.get(dimension):
			invoice.update({
				dimension: doc.get(dimension)
			})

	# Subscription is better suited for service items. I won't update `update_stock`
	# for that reason
	items_list = get_items_from_plans(doc,doc.plans, prorate)
	for item in items_list:
		invoice.append('items',	item)

	# Taxes
	if doc.tax_template:
		invoice.taxes_and_charges = doc.tax_template
		invoice.set_taxes()

	# Due date
	invoice.append(
		'payment_schedule',
		{
			'due_date': invoice.due_date,
			'invoice_portion': 100
		}
	)

	# Discounts
	if doc.additional_discount_percentage:
		invoice.additional_discount_percentage = doc.additional_discount_percentage

	if doc.additional_discount_amount:
		invoice.discount_amount = doc.additional_discount_amount

	if doc.additional_discount_percentage or doc.additional_discount_amount:
		discount_on = doc.apply_additional_discount
		invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'

	# Subscription period
	invoice.from_date = doc.current_invoice_start
	invoice.to_date = doc.current_invoice_end

	invoice.flags.ignore_mandatory = True
	invoice.save()
	invoice.submit()

	return invoice

def get_current_invoice(doc):
	"""
	Returns the most recent generated invoice.
	"""
	if len(doc.invoices):
		current = doc.invoices[-1]
		if frappe.db.exists('Sales Invoice', current.invoice):
			doc = frappe.get_doc('Sales Invoice', current.invoice)
			return doc
		else:
			frappe.throw(_('Invoice {0} no longer exists'.format(current.invoice)))

# @staticmethod
def is_not_outstanding(invoice):
	"""
	Return `True` if the given invoice is paid
	"""
	return invoice.status == 'Paid'

def get_items_from_plans(doc, plans, prorate=0):
	"""
	Returns the `Item`s linked to `Subscription Plan`
	"""
	if prorate:
		prorate_factor = get_prorata_factor(doc.current_invoice_end, doc.current_invoice_start)

	items = []
	customer = doc.customer
	for plan in plans:
		item_code = frappe.db.get_value("Subscription Plan", plan.plan, "item")
		if len(plans)<2 and doc.custom_rate>0:
			if not prorate:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': doc.custom_rate})
			else:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': (doc.custom_rate * prorate_factor)})
		elif frappe.db.get_value('Subscription Plan',plan.plan,'price_determination')=='Percentage of Rent':
			from homzhub_customization.homzhub_customization.doctype.sales_invoice import get_plan_rate
			rate,srv_chg=get_plan_rate(doc,plan.plan, plan.qty, customer)
			if not prorate:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': rate,'service_charges_in_per':srv_chg})
			else:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': (rate * prorate_factor)})
		else:
			from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
			if not prorate:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': get_plan_rate(plan.plan, plan.qty, customer)})
			else:
				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': (get_plan_rate(plan.plan, plan.qty, customer) * prorate_factor)})

	return items

def get_prorata_factor(period_end, period_start):
	diff = flt(date_diff(nowdate(), period_start) + 1)
	plan_days = flt(date_diff(period_end, period_start) + 1)
	prorate_factor = diff / plan_days

	return prorate_factor

def validate(doc,method):
	if doc.get('project') and doc.get('invoice_date'):
		expected_date=frappe.db.get_value('Project',doc.get('project'),'expected_start_date')
		if  getdate(expected_date) > getdate(doc.get('invoice_date')):
			frappe.throw("Invoice Date must be equal or greater than project's Expected Start Date")
	if doc.get('customer') and doc.get('project'):
		project=frappe.get_doc('Project',doc.get('project'))
		customer_list=[]
		customer_list.append(project.customer)
		# customer_list.append(project.property_owner)
		for d in project.tenant_list:
			customer_list.append(d.tenant)
		for d in project.owner_list:
			customer_list.append(d.prop_owner)
		if doc.get('customer') not in customer_list:
			frappe.throw("customer in subscription should be equal to owner list/tenant list/customer")
	if doc.get('project'):
		pro_doc=frappe.get_doc('Project',doc.get('project'))
		subscriptions=[]
		for d in pro_doc.get('subscription_plans'):
			subscriptions.append(d.get('subscription'))
		if frappe.db.exists("Subscription", doc.name):
			if doc.name not in subscriptions:
				for d in doc.get('plans'):
					pro_doc.append("subscription_plans", {
					"subscription" : doc.name,
					"subscription_plan" : d.plan
					})
					pro_doc.save()

@frappe.whitelist()
def update_status(doc):
	doc=json.loads(doc)
	doc=frappe.get_doc('Subscription',doc.get('name'))
	doc.status='Cancelled'
	doc.cancelation_date = nowdate()
	doc.save()


import numpy as np
import cv2
from tcp_pickle_stream import listener
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions

listen = listener('192.168.1.3')
model = ResNet50(weights='imagenet')
while(True):

    img = listen.get_frame()
    img = np.expand_dims(img, axis=0)
    img = preprocess_input(img)

    preds = model.predict(img)
    predict_string = decode_predictions(preds, top=3)[0]
    predict_string = ''.join(str(predict_string[0]))

    cv2.putText(img, predict_string, (30, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 255, 255), lineType=cv2.LINE_AA)

    #if package:
        #cap = cv2.VideoCapture(0)
        # Capture frame-by-frame
        #ret, frame = cap.read()

        # Our operations on the frame come here
        #gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # Display the resulting frame
    cv2.imshow('frame', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        listen.close()
        break

# When everything done, release the capture
#cap.release()
cv2.destroyAllWindows()


# partially based on code from http://deeplearning.net/tutorial/
import os
import sys
import numpy
import theano
import theano.tensor as T

from mlp import MLP

class FunctionApproximator(object):
    def __init__(self, n_in=1, n_out=1, n_hidden=10):

        self.n_out = n_out
        self.n_in = n_in
        self.n_hidden = n_hidden

    def train(self, X, Y, learning_rate=0.1, n_epochs=100, report_frequency=10, lambda_l2=0.0):

        self.report_frequency = report_frequency

        # allocate symbolic variables for the data
        x = T.matrix('x')
        y = T.vector('y')

        # put the data in shared memory
        self.shared_x = theano.shared(numpy.asarray(X, dtype=theano.config.floatX))
        self.shared_y = theano.shared(numpy.asarray(Y, dtype=theano.config.floatX))
        rng = numpy.random.RandomState(1234)

        # initialize the mlp
        self.mlp = MLP(rng=rng, input=x, n_in=self.n_in, n_out=self.n_out,
                  n_hidden=self.n_hidden)

        # define the cost function, possibly with regularizing term
        if lambda_l2>0.0:
            cost = self.mlp.cost(y) + lambda_l2*self.mlp.l2
        else:
            cost = self.mlp.cost(y)

        # compute the gradient of cost with respect to theta (stored in params)
        # the resulting gradients will be stored in a list gparams
        gparams = [T.grad(cost, param) for param in self.mlp.params]

        updates = [(param, param - learning_rate * gparam)
            for param, gparam in zip(self.mlp.params, gparams) ]

        # compiling a Theano function `train_model` that returns the cost, but
        # at the same time updates the parameter of the model based on the rules
        # defined in `updates`
        train_model = theano.function(
            inputs=[],
            outputs=cost,
            updates=updates,
            givens={
                x: self.shared_x,
                y: self.shared_y
            }
        )

        #define function that returns model prediction
        self.predict_model = theano.function(
            inputs=[self.mlp.input], outputs=self.mlp.y_pred)

        ###############
        # TRAIN MODEL #
        ###############

        epoch = 0

        while (epoch < n_epochs):
            epoch = epoch + 1
            epoch_cost = train_model()
            if epoch % self.report_frequency == 0:
                print("epoch: %d  cost: %f" % (epoch, epoch_cost))

    def get_y_pred(self, x=None):
        if x is None:
            return self.predict_model(self.shared_x.get_value())
        else:
            return self.predict_model(x)

    def get_weights(self):
        return [self.mlp.params[0].get_value(), self.mlp.params[1].get_value()]


import yaml

class Hostname(yaml.YAMLObject):
    yaml_tag = '!Hostname'

    def __init__(self,infrastructureKey, projectKey, serviceName):
        self.harnessApiVersion = '1.0'
        self.type = 'INFRA_DEFINITION'
        self.cloudProviderType = 'KUBERNETES_CLUSTER'
        self.deploymentType = 'KUBERNETES'
        self.infrastructure = self.infrastructure(infrastructureKey, projectKey, serviceName)

    class infrastructure(yaml.YAMLObject):
        def __init__(self, infrastructureName, projectKey, serviceName):
            self.type = 'DIRECT_KUBERNETES'
            self.cloudProviderName: infrastructureName
            self.namespace = f'uwm-{projectKey}'
            self.releaseName = f'{serviceName}'

    def CreateHostname(infrastructureName, projectKey, serviceName):
        yaml.emitter.Emitter.process_tag = Hostname.noopToRemoveOutput
        return yaml.dump(Hostname(infrastructureName, projectKey, serviceName),sort_keys=False)

    # This is needed to remove output
    def noopToRemoveOutput(self, *args, **kw):
        pass

print(Hostname.CreateHostname('hi','nou','hello'))


# -*-coding:utf-8 -*
#!/usr/bin/python3

import random
import datetime
import time
from subprocess import call
import discord

import settings.ekiller2
import settings.dellog
import utils.perms
import utils.usertools

try:
    call(['mkdir', 'tmp'])
except:
    pass

async def commandHandler(client, message, ekiller):

    try:
        if message.content.startswith("/ekiller") and (not await utils.perms.hasrole(message.author, settings.ekiller.auth)):
            await client.send_message(message.channel, message.author.mention + ", vous n'avez pas la permission d'effectuer cette commande.")
            return
    except:
        if message.content.startswith("/ekiller"):
            await client.send_message(message.channel, message.author.mention + ", Une erreur s'est produite. \n\nPS: les commandes ayant un rapport avec ekiller doivent être effectuées sur le serveur.")
            raise

    if message.content == "/ekiller start":
        await start(client, message, ekiller)

    elif message.content.startswith("/ekiller join"):
        await join(client, message, ekiller)

    elif message.content == "/ekiller quit":
        await quit(client, message, ekiller)

    elif message.content.startswith("/ekiller kick"):
        await kick(client, message, ekiller)

    elif message.content == "/ekiller players":
        await players(client, message, ekiller)

    elif message.content == "/ekiller reset":
        await reset(client, message, ekiller)

    elif message.content == "/ekiller logs":
        await logs(client, message)

    elif message.content == "/ekiller help":
        await help(client, message)

    elif message.content == "/ekiller debug":
        await debug(client, message, ekiller)

async def start(client, message, ekiller):
    await client.delete_message(message)
    game = []
    players = []
    words = []
    for (id, word) in ekiller.buffer:
        member = await utils.usertools.UserByID(client, id)
        players.append(member)
        words.append(word)
    random.shuffle(players)
    players.append(players[0])
    random.shuffle(words)
    for i in range(len(players)-1):
        dic = {"ekiller":str(players[i].id)+'#'+players[i].name, "target":str(players[i+1].id)+'#'+players[i+1].name, "word":words[i]}
        game.append(dic)
        embed = discord.Embed(title="E-KILLER", description="Votre cible est : " + players[i+1].display_name + "\nLe mot est : `" + words[i] + "`\n\nBonne chance à vous.", color=0x0000ff)
        await client.send_message(players[i], embed=embed)
    embed = discord.Embed(title="E-KILLER", description="Liste des joueurs :\n" + str([p.display_name for p in players[:-1]]) + "\n\n Bonne chance à tous !", color=0x0000ff)
    await client.send_message(message.channel, embed=embed)
    with open("tmp/ekillerLog.txt", "a") as ekillerlogfile:
        ekillerlogfile.write(str(datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')) + " [" + "\n")
        for dic in game:
            ekillerlogfile.write(str(dic) + "\n")
        ekillerlogfile.write("]\n\n")

async def join(client, message, ekiller):
    await client.delete_message(message)
    args = message.content.split(' ')
    if len(args) == 3:
        if message.author.id in dict(ekiller.buffer):
            await client.send_message(message.channel, message.author.mention + ", vous faites déjà parti des participants.")
        else:
            ekiller.buffer.append((message.author.id, args[2]))
            await client.send_message(message.channel, message.author.mention + ", vous avez bien été ajouté à la liste des participants.")
    else:
        await client.send_message(message.channel, message.author.mention + ", veuillez préciser un unique mot que vous souhaitez ajouter à la liste : `/ekiller join <word>`")

async def quit(client, message, ekiller):
    await client.delete_message(message)
    if message.author.id in dict(ekiller.buffer):
        ekiller.buffer = [(id,word) for (id,word) in ekiller.buffer if id!=message.author.id]
        await client.send_message(message.channel, message.author.mention + ", vous avez bien été retiré de la liste des participants.")
    else:
        await client.send_message(message.channel, message.author.mention + ", vous ne faites pas parti des participants.")

async def kick(client, message, ekiller):
    await client.delete_message(message)
    args = message.content.split(' ')
    if len(args) == 3:
        ids = args[2].split(',')
        for id in ids:
            member = await utils.usertools.UserByID(client, id)
            if not member:
                await client.send_message(message.channel, message.author.mention + ", le joueur `{0}` n'existe pas.".format(id))
            elif id not in dict(ekiller.buffer):
                await client.send_message(message.channel, message.author.mention + ", le joueur `{0}` ne participe pas.".format(member.display_name))
            else:
                ekiller.buffer = [(idd, word) for (idd, word) in ekiller.buffer if idd != id]
                await client.send_message(message.channel, message.author.mention + ", le joueur `{0}` a bien été retiré.".format(member.display_name))
    else:
        await client.send_message(message.channel, message.author.mention + ", veuillez préciser un unique id ou une liste d'ids séparés par une virgule : `/ekiller kick foo,bar`")

async def players(client, message, ekiller):
    await client.delete_message(message)
    players = []
    for (id, word) in ekiller.buffer:
        member = await utils.usertools.UserByID(client, id)
        players.append(member.display_name)
    await client.send_message(message.channel, "Liste des joueurs :")
    await client.send_message(message.channel, "```PYTHON\n" + str(players) + "\n```")

async def reset(client, message, ekiller):
    await client.delete_message(message)
    ekiller.buffer = []
    await client.send_message(message.channel, message.author.mention + ", le jeu a bien été réinitialisé.")

async def logs(client, message):
    if not (message.author == client.user) and await utils.perms.hasrole(message.author, settings.dellog.logsAuth):
        try:
            await client.delete_message(message)
            await client.send_file(message.author, "tmp/ekillerLog.txt")
        except:
            await client.send_message(message.author, "```FAILED```")

async def help(client, message):
    await client.delete_message(message)
    text = "Liste des commandes :\n\n"
    text += "/ekiller join <word>\nRejoindre la partie et ajouter le mot <word> à la liste de mots\n\n"
    text += "/ekiller quit\nQuitter la partie la partie\n\n"
    text += "/ekiller players\nAfficher la liste des participants\n\n"
    text += "/ekiller start\nLancer la partie\n\n"
    text += "/ekiller help\nAffiche cette aide\n\n"
    embed = discord.Embed(title="E-KILLER", description=text, color=0x0000ff)
    await client.send_message(message.channel, embed=embed)

async def debug(client, message, ekiller):
    await client.delete_message(message)
    await client.send_message(message.channel, message.author.mention + "```PYTHON\n" + str(ekiller.buffer) + "\n```")

class Ekiller:

    def __init__(self):
        self.buffer = []


'''
2020 Mark Shui Hu, QuTech

www.github.com/watermarkhu/oop_surface_code
_____________________________________________

Plotting function for the surface/planar uf-lattice.
A plot_2D object is initialized for a graph_2D graph, which plots onto a 2D axis
A plot_3D object is initialized for a graph_3D graph, which plots onto a 3D axis

Plot_2D object is inherited by Plot_3D object. Both inherit from the plot_graph_lattice objects.
Plot colors, linewidths, alpha and scatter sizes are defined in the plot_graph_lattice.plot_2D object.
Otherwise only minor plotting functions are inherited.
'''

import matplotlib.pyplot as plt
from . import plot_graph_lattice as gp

class plot_2D(gp.plot_2D):
    '''
    2D axis plot for both toric/planar uf-lattices.

    Plots the anyons as a scatter, and qubits as edges. Each graph round can be dynamically plotted to show the size and form of the clusters.

    Inherits from the plot_graph.lattice.plot_2D object. Uses colors and other plotting parameters defined there. Also inherits the following helper methods:

        draw_plot()
        legend_circle()
        draw_line()
    '''

    '''
    #########################################################################
                            Init legend
    '''

    def init_legend(self, x, y, loc="upper right"):
        '''
        Initilizes the legend of the plot.
        The qubits, errors and stabilizers are added.
        Aditional legend items can be inputted through the items paramter
        '''

        self.ax.set_title("{} uf-lattice".format(self.graph.__class__.__name__))

        le_xv = self.legend_circle("X-vertex", mew=0, mfc=self.cX)
        le_zv = self.legend_circle("Z-vertex", mew=0, mfc=self.cZ)
        le_xe = self.legend_circle("X-edge", ls="--", lw=self.linewidth, color=self.cx, marker=None)
        le_ze = self.legend_circle("Z-edge", ls="-", lw=self.linewidth, color=self.cz, marker=None)
        self.ax.legend(
            handles=[le_xv, le_zv, le_xe, le_ze],
            bbox_to_anchor=(x, y),
            loc=loc,
            ncol=1,
    )

        '''
    #########################################################################
                            Initialize plot
    '''

    def init_plot(self, z=0):
        '''
        Initilizes a 2D plot of torc/planar uf-lattice
        '''
        plt.sca(self.ax)
        self.init_axis(0-.2, self.size+.2)
        plt.setp(self.rax, visible=0)

        for qubit in self.graph.Q[z].values():
            if qubit.erasure:
                self.draw_edge(qubit, 0)
                self.draw_edge(qubit, 1)
            else:
                qubit.E[0].pu = None
                qubit.E[1].pu = None

        for stab in self.graph.S[z].values():

            if stab.state:
                self.draw_vertex(stab)
            else:
                stab.pu = None

        self.init_legend(1.25, 0.95)
        self.canvas.draw()
        self.draw_plot()

    def get_edge_data(self, ertype, type, y0, x0):

        if ertype == 1:
            (y1, x1) = (
                (y0, (x0 + 1) % self.size)
                if type == 0
                else ((y0 + 1) % self.size, x0)
            )

            if y0 == self.size - 1:
                y0 = self.size if y0 == 0 else y0
                y1 = self.size if y1 == 0 else y1
            if x0 == self.size - 1:
                x0 = self.size if x0 == 0 else x0
                x1 = self.size if x1 == 0 else x1

            xm, ym = (x0 + x1)/2,  (y0 + y1)/2

        else:
            (y1, x1) = (
                (y0, (x0 - 1) % self.size)
                if type == 1
                else ((y0 - 1) % self.size, x0)
            )

            if y0 == 0:
                y0 = -0.5 if y0 == self.size - 1 else y0 + 0.5
                y1 = -0.5 if y1 == self.size - 1 else y1 + 0.5
            else:
                y0 += 0.5
                y1 += 0.5
            if x0 == 0:
                x0 = -0.5 if x0 == self.size - 1 else x0 + 0.5
                x1 = -0.5 if x1 == self.size - 1 else x1 + 0.5
            else:
                x0 += 0.5
                x1 += 0.5

            xm, ym = (x0 + x1)/2,  (y0 + y1)/2

        return x0, y0, xm, ym, x1, y1

    def draw_edge(self, qubit, ertype):
        '''
        Draw lines of the X-edges of the qubit
        '''
        color, alpha = (self.C1[ertype], 1) if qubit.erasure else (self.cl, self.alpha2)

        (type, y0, x0) = qubit.qID

        x0, y0, xm, ym, x1, y1 = self.get_edge_data(ertype, type, y0, x0)

        up1 = self.draw_line([x0,  xm], [y0,  ym], Z=qubit.z, color=color, lw=self.linewidth, ls=self.LS[ertype-1], alpha=alpha)
        up2 = self.draw_line([xm,  x1], [ym,  y1], Z=qubit.z, color=color, lw=self.linewidth, ls=self.LS[ertype-1], alpha=alpha)
        up1.object = up2.object = qubit.E[ertype]
        qubit.E[ertype].pu = [up1, up2]

    def draw_vertex(self, stab):
        '''
        Draws a circle of the stab object
        '''

        (ertype, y, x) = stab.sID
        if ertype == 1:
            y += 0.5
            x += 0.5

        fc, lw = (self.C2[ertype], self.linewidth) if stab.state else (None ,0)

        stab.pu = plt.scatter(
            x, y,
            s = self.scatter_size,
            facecolor=fc,
            linewidth=lw,
            edgecolor=self.C1[ertype],
            zorder=10,
            picker = self.pick
        )
        stab.pu.object = stab

    """
    #########################################################################
                            main plot functions
    """

    def plot_edge(self, edge, num, color, alpha):

        p_edge = edge.pu[num]
        p_edge.set_color(color)
        p_edge.set_alpha(alpha)
        self.ax.draw_artist(p_edge)

    def plot_removed(self, z=0):
        """
        plots the normal edge color over the edges that have been removed during the formation of the tree structure
        """
        for qubit in self.graph.Q[z].values():
            for edge in [qubit.E[0], qubit.E[1]]:
                if edge.peeled and not edge.matching:
                    self.new_attributes(edge.pu[0], dict(color=self.cl, alpha=self.alpha2))
                    self.new_attributes(edge.pu[1], dict(color=self.cl, alpha=self.alpha2))

    def add_edge(self, edge, vertex):
        '''
        Plots a recently half-grown or fully-grown edge
        '''
        if edge.support == 1:
            if not edge.pu:
                self.draw_edge(edge.qubit, edge.ertype)

            (ye, xe) = edge.qubit.qID[1:3]
            (yv, xv) = vertex.sID[1:3]
            id = 0 if (ye == yv and xe == xv) else 1
            color = self.cx if edge.ertype == edge.edge_type else self.cz
            self.new_attributes(edge.pu[id], dict(color=color, alpha=self.alpha))
            self.new_attributes(edge.pu[1-id], dict(color=self.cl, alpha=self.alpha2))
        elif edge.support == 2:
            color = self.cx if edge.ertype == 0 else self.cz
            self.new_attributes(edge.pu[0], dict(color=color, alpha=1), 1)
            self.new_attributes(edge.pu[1], dict(color=color, alpha=1), 1)
        else:
            self.new_attributes(edge.pu[0], dict(color=self.cw, alpha=0), 1)
            self.new_attributes(edge.pu[1], dict(color=self.cw, alpha=0), 1)

    """
    #########################################################################
                            stepwise plot functions
    """

    def plot_edge_step(self, edge, type):
        """
        plots an edge that is to be removed from the plot
        1.  plots black edge as indication
        2.  plots normal edge color

        """
        if type == "remove":
            c1 = self.cl
            c2 = self.cl
            text = "☒ remove"
            alpha = self.alpha2
        elif type == "confirm":
            c1 = self.cx
            c2 = self.cz
            text = "☑ confirm"
            alpha = 1
        elif type == "peel":
            c1 = self.cl
            c2 = self.cl
            text = "☒ peeling"
            alpha = self.alpha2
        elif type == "match":
            c1 = self.cX
            c2 = self.cZ
            text = "☑ matching"
            alpha = 1

        line = text + " edge " + str(edge)
        self.new_iter(line)

        color = c1 if edge.ertype == 0 else c2
        self.new_attributes(edge.pu[0], dict(color=color, alpha=alpha))
        self.new_attributes(edge.pu[1], dict(color=color, alpha=alpha))

        self.draw_plot()

    def plot_strip_step_anyon(self, stab):
        """
        plot function for the flips of the anyons
        plots the anyon in white (removal) or normal error edge color (addition)
        """
        lw = self.linewidth if stab.state else 0
        if not stab.pu:
            self.draw_vertex(stab)
            self.new_attributes(stab.pu, dict(linewidth=lw, facecolor=[1,1,1,0]))
        else:
            self.new_attributes(stab.pu, dict(linewidth=lw))

class plot_3D(plot_2D, gp.plot_3D):
    '''
    3D axis plot for both toric/planar uf-lattices.

    Plots the anyons as a scatter, and qubits as edges. Each graph round can be dynamically plotted to show the size and form of the clusters.

    Inherits from the plot_graph.lattice.plot_2D object. Uses colors and other plotting parameters defined there. Also inherits the following helper methods:

        draw_plot()
        legend_circle()
        init_axis()
        set_axes_equal()
        draw_line()
        plot_scatter()

    Method resoluation order is defined as:

    plot_3D -> plot_2D -> plot_graph_lattice.plot_3D -> plot_graph_lattice.plot_2D
    '''

    '''
    #########################################################################
                            Initalize plot
    '''
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.alpha2 = 0.01

    def init_plot(self, *args, **kwargs):
        '''
        Initializes 3D plot of toric/planar lattice
        Stabilizers are plotted with Axes3D.line objects
        Qubits are plotted with Axes3D.scatter objects
        '''

        self.init_axis(0, self.size, 1)
        plt.setp(self.rax, visible=0)

        for layer in self.graph.Q.values():
            for qubit in layer.values():
                if qubit.erasure:
                    self.draw_edge(qubit, 0)
                    self.draw_edge(qubit, 1)
                else:
                    qubit.E[0].pu = None
                    qubit.E[1].pu = None

        for layer in self.graph.G.values():
            for bridge in layer.values():
                bridge.E.pu = None

        for Z, layer in self.graph.S.items():
            for stab in layer.values():
                (ertype, y, x) = stab.sID
                X, Y = (x, y) if ertype == 0 else (x+.5, y+.5)
                if stab.state:
                    (stab.pu, _) = self.plot_scatter(X, Y, Z, object=stab, facecolor=self.C2[ertype], edgecolor=self.C1[ertype])
                else:
                    stab.pu = {
                        "pos"       : (X, Y, Z),
                        "edgecolor" : self.C2[ertype],
                        "facecolor" : self.C1[ertype],
                        "object"    : stab
                    }

        self.init_legend(1.05, 0.95)
        self.set_axes_equal()
        self.canvas.draw()
        self.draw_plot()

    def draw_bridge(self, bridge):
        '''
        Draw lines of the vertical edges connecting the layers
        '''
        (ertype, y, x), z = bridge.qID, bridge.z
        if ertype == 1:
            y += 0.5
            x += 0.5

        up1 = self.draw_line([x,  x], [y,  y], Z=[z, z-.5], color=self.cl, lw=self.linewidth, ls=self.LS[ertype], alpha=self.alpha2)
        up2 = self.draw_line([x,  x], [y,  y], Z=[z-.5, z-1], color=self.cl, lw=self.linewidth, ls=self.LS[ertype], alpha=self.alpha2)
        up1.object = up2.object = bridge

        bridge.E.pu = [up1, up2]

    '''
    #########################################################################
                            Plotting functions
    '''
    def plot_removed(self):
        """
        plots the normal edge color over the edges that have been removed during the formation of the tree structure
        """
        for z in self.graph.Q:
            super().plot_removed(z)
        for z in self.graph.G:
            for bridge in self.graph.G[z].values():
                edge = bridge.E
                if edge.peeled and not edge.matching:
                    self.new_attributes(edge.pu[0], dict(color=self.cl, alpha=self.alpha2))
                    self.new_attributes(edge.pu[1], dict(color=self.cl, alpha=self.alpha2))

    def add_edge(self, edge, vertex):
        '''
        Plots a recently half-grown or fully-grown edge
        '''
        if edge.support == 1:
            (ye, xe), ze = edge.qubit.qID[1:3], edge.z
            (yv, xv), zv = vertex.sID[1:3], vertex.z

            color = self.Cx if (edge.ertype == edge.edge_type) else self.Cz
            if edge.edge_type == 0:
                id = 0 if (ye == yv and xe == xv) else 1
            else:
                id = 0 if ze == zv else 1

            if not edge.pu:
                if edge.edge_type == 0:
                    self.draw_edge(edge.qubit, edge.ertype)
                else:
                    self.draw_bridge(edge.qubit)

            self.new_attributes(edge.pu[id], dict(color=color, alpha=self.alpha))
            self.new_attributes(edge.pu[1-id], dict(color=self.cl, alpha=self.alpha2))

        elif edge.support == 2:
            color = self.cx if edge.ertype == 0 else self.cz
            self.new_attributes(edge.pu[0], dict(color=color, alpha=1), 1)
            self.new_attributes(edge.pu[1], dict(color=color, alpha=1), 1)
        else:
            self.new_attributes(edge.pu[0], dict(color=self.cw, alpha=0), 1)
            self.new_attributes(edge.pu[1], dict(color=self.cw, alpha=0), 1)

    # def plot_strip_step_anyon(self, stab):
    #     """
    #     plot function for the flips of the anyons
    #     plots the anyon in white (removal) or normal error edge color (addition)
    #     """
    #     lw = self.linewidth if stab.state else 0

    #     if "key" not in stab.pu:
    #         self.new_attributes(stab.pu, dict(linewidth=lw))
    #     else:
    #         self.new_attributes(stab.pu, dict(edgecolor=self.C1[stab.sID[0]]))

    def plot_strip_step_anyon(self, stab):
        """
        plot function for the flips of the anyons
        plots the anyon in white (removal) or normal error edge color (addition)
        """
        lw = self.linewidth if stab.state else 0
        if "key" not in stab.pu:
            self.new_attributes(stab.pu, dict(linewidth=lw, edgecolor=stab.pu["facecolor"]))
        else:
            self.new_attributes(stab.pu, dict(linewidth=lw, edgecolor=[1,1,1,0]))