#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['Arial']
plt.rcParams['axes.unicode_minus'] = False

def nscf_learning_curves():
    train_logloss = [13.9749, 12.1171, 10.8976, 7.2394, 4.3570, 3.8065, 3.7157, 3.2558, 2.9546, 2.7440, 1.5259,
                     0.9440, 0.9199, 0.8933, 0.8482, 0.7984, 0.7800, 0.7760, 0.7566, 0.7202, 0.7153, 0.7126, 0.7015, 0.6928, 0.6875, 0.6818, 0.6764, 0.6648, 0.6625, 0.6584, 0.6416, 0.6307, 0.6237, 0.6235, 0.6231, 0.6167, 0.6102, 0.6044, 0.5916, 0.5734]
    test_logloss = [15.7243, 13.5615, 11.4896, 8.4220, 5.8326, 4.6092, 4.0900, 3.7464, 3.6078, 3.4541, 2.9277, 2.1484,
                    1.6946, 1.4267, 1.3630, 1.2300, 1.1092, 0.9644, 0.9417, 0.9174, 0.8959, 0.8343, 0.8138, 0.7931,
                    0.7735, 0.7510, 0.7341, 0.7249, 0.7147, 0.6913, 0.6716, 0.6557, 0.6357, 0.6235, 0.6287, 0.6125,
                    0.6066, 0.5824, 0.6006, 0.6106]
    x = np.linspace(1, len(train_logloss), len(train_logloss))
    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.plot(x, train_logloss, marker='o', color="SkyBlue", label="Train Data LogLoss", linewidth=1.5)
    plt.plot(x, test_logloss, marker='^', color="IndianRed", label="Test Data LogLoss", linewidth=1.5)

    plt.xlabel("Epochs", fontsize=6.5, fontweight='bold', labelpad=-5)
    plt.ylabel("LogLoss", fontsize=6.5, fontweight='bold', labelpad=-5)

    plt.legend(loc=0, numpoints=1)
    leg = plt.gca().get_legend()
    ltext = leg.get_texts()
    plt.setp(ltext, fontsize=6, fontweight='bold')

    plt.show()

def nscf_auc_curves():
    x = np.array([1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50])
    train_logloss = np.array([13.9749, 4.3570, 2.7440, 0.8482, 0.7202, 0.6875, 0.6584, 0.6231, 0.6044, 0.5862, 0.5418])
    test_logloss = np.array([15.7243, 5.8326, 3.7541, 1.6620, 0.9174, 0.7735, 0.6913, 0.6287, 0.5824, 0.6307, 0.6744])

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.plot(x, train_logloss, marker='o', color="SkyBlue", label="Train Data LogLoss", linewidth=1.5)
    plt.plot(x, test_logloss, marker='^', color="IndianRed", label="Test Data LogLoss", linewidth=1.5)

    plt.xlabel("Epochs", fontsize=6.5, fontweight='bold', labelpad=-5)
    plt.ylabel("LogLoss", fontsize=6.5, fontweight='bold', labelpad=-5)

    plt.legend(loc=0, numpoints=1)
    leg = plt.gca().get_legend()
    ltext = leg.get_texts()
    plt.setp(ltext, fontsize=6, fontweight='bold')

    plt.show()

def nscf_auc_logloss():
    aucs = [0.6793, 0.6928, 0.7073, 0.6914, 0.7289, 0.7137, 0.6814, 0.6847, 0.6873]
    logs = [0.6245, 0.6018, 0.5947, 0.6106, 0.5824, 0.5871, 0.6239, 0.6223, 0.6152]
    x = np.arange(len(aucs))
    width = 0.35

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.bar(x-width/2, aucs, width, color='SkyBlue', label='AUC')
    plt.bar(x+width/2, logs, width, color='IndianRed', label='LogLoss')

    plt.ylabel("AUC and LogLoss")
    plt.title("NS-based CF AUC and LogLoss")
    xlabels = ['K=3,L=128',
               'K=3,L=300',
               'K=3,L=500',
               'K=4,L=128',
               'K=4,L=300',
               'K=4,L=500',
               'K=5,L=128',
               'K=5,L=300',
               'K=5,L=500']
    plt.xticks(x, xlabels, fontsize=6)
    plt.ylim(0.4, 0.9)
    plt.legend()

    plt.show()

def nscf_n_auc_logloss():
    aucs = [0.6545, 0.6879, 0.6933, 0.7051, 0.7289, 0.7172, 0.7335, 0.7231, 0.7368]
    logs = [0.6429, 0.6218, 0.6073, 0.5946, 0.5824, 0.5836, 0.5817, 0.5826, 0.5819]
    x = np.arange(len(aucs))
    width = 0.35

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.bar(x - width / 2, aucs, width, color='SkyBlue', label='AUC')
    plt.bar(x + width / 2, logs, width, color='IndianRed', label='LogLoss')

    plt.ylabel("AUC and LogLoss")
    plt.title("NS-based CF AUC and LogLoss")
    xlabels = ['N=1*800167',
               'N=2*800167',
               'N=3*800167',
               'N=4*800167',
               'N=5*800167',
               'N=6*800167',
               'N=7*800167',
               'N=8*800167',
               'N=9*800167']
    plt.xticks(x, xlabels, fontsize=6)
    plt.ylim(0.4, 0.9)
    plt.legend()

    plt.show()

def nscf_rmse():
    epochs = [1, 5, 15, 20, 25, 30, 35, 40, 45, 50]
    funksvd_rmses = [1.1462, 1.0471, 0.9826, 0.9445, 0.9326, 0.9218, 0.9102, 0.9017, 0.9014, 0.9013]
    svd_rmses = [1.1227, 1.0328, 0.9681, 0.9228, 0.9183, 0.8974, 0.8827, 0.8824, 0.8820, 0.8819]
    random_nscf_rmses = [1.0236, 1.0130, 0.9425, 0.8944, 0.8743, 0.8728, 0.8794, 0.8771, 0.8767, 0.8757]
    lda_nscf_rmses = [1.0038, 0.9811, 0.9314, 0.8874, 0.8681, 0.8630, 0.8657, 0.8602, 0.8690, 0.8625]
    item2vec_nscf_rmses = [1.0015, 0.9838, 0.9228, 0.8833, 0.8633, 0.8612, 0.8611, 0.8584, 0.8547, 0.8555]
    lfm_nscf_rmses = [0.9017, 0.8936, 0.8765, 0.8691, 0.8516, 0.8488, 0.8444, 0.8430, 0.8459, 0.8465]

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.plot(epochs, funksvd_rmses, marker='o', color="SkyBlue", label="FunkSVD RMSE", linewidth=1.5)
    plt.plot(epochs, svd_rmses, marker='^', color="IndianRed", label="SVD++ RMSE", linewidth=1.5)
    plt.plot(epochs, random_nscf_rmses, marker='*', color="olive", label="Random NS-based CF RMSE", linewidth=1.5)
    plt.plot(epochs, lda_nscf_rmses, marker='s', color="darkcyan", label="LDA NS-based CF RMSE", linewidth=1.5)
    plt.plot(epochs, item2vec_nscf_rmses, marker='+', color="lightslategray", label="Item2Vec Ns-based CF RMSE", linewidth=1.5)
    plt.plot(epochs, lfm_nscf_rmses, marker="d", color="darkmagenta", label="LFM NS-based CF RMSE", linewidth=1.5)

    plt.xlabel("Epochs", fontsize=6.5, fontweight='bold', labelpad=-5)
    plt.ylabel("RMSE", fontsize=6.5, fontweight='bold', labelpad=0)

    plt.legend(loc=0, numpoints=1)
    leg = plt.gca().get_legend()
    ltext = leg.get_texts()
    plt.setp(ltext, fontsize=6, fontweight='bold')

    plt.show()

def nscf_model_auc_logloss():
    aucs = [0.7073, 0.7143, 0.7289, 0.7317, 0.7304, 0.7378]
    logs = [0.6092, 0.5931, 0.5824, 0.5752, 0.5701, 0.5685]

    x = np.arange(len(aucs))
    width = 0.35

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.bar(x - width / 2, aucs, width, color='SkyBlue', label='AUC')
    plt.bar(x + width / 2, logs, width, color='IndianRed', label='LogLoss')

    plt.ylabel("AUC and LogLoss")
    plt.title("NS-based CF AUC and LogLoss")
    xlabels = ['FunkSVD',
               'SVD++',
               'Random NS-based CF',
               'LDA NS based CF',
               'Item2Vec NS-based CF',
               'LFM NS-based CF',]
    plt.xticks(x, xlabels, fontsize=5)
    plt.ylim(0.4, 0.9)
    plt.legend()

    plt.show()

def nscf_d_auc_logloss():
    aucs = [0.7207, 0.7289, 0.7324]
    logs = [0.5938, 0.5824, 0.5751]

    x = np.arange(len(aucs))
    width = 0.35

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.bar(x - width / 2, aucs, width, color='SkyBlue', label='AUC')
    plt.bar(x + width / 2, logs, width, color='IndianRed', label='LogLoss')

    plt.ylabel("AUC and LogLoss")
    plt.title("NS-based CF AUC and LogLoss")
    xlabels = ['ml-100k',
               'ml-1m',
               'ml-10m']
    plt.xticks(x, xlabels, fontsize=8)
    plt.ylim(0.4, 0.9)
    plt.legend()

    plt.show()

def nssd_logloss():
    x = [1, 5, 10, 15, 20, 25, 30]
    train_logloss = [1.53343, 0.58776, 0.02551, 0.02154, 0.01791, 0.01343, 0.01025]
    test_logloss = [1.56235, 0.59634, 0.02593, 0.03697, 0.04703, 0.05191, 0.05879]

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.plot(x, train_logloss, marker='o', color="SkyBlue", label="Train Data LogLoss", linewidth=1.5)
    plt.plot(x, test_logloss, marker='^', color="IndianRed", label="Test Data LogLoss", linewidth=1.5)

    plt.xlabel("Epochs", fontsize=6.5, fontweight='bold', labelpad=5)
    plt.ylabel("LogLoss", fontsize=6.5, fontweight='bold', labelpad=-5)

    plt.ylim(0.01, 0.6)

    plt.legend(loc=0, numpoints=1)
    leg = plt.gca().get_legend()
    ltext = leg.get_texts()
    plt.setp(ltext, fontsize=6, fontweight='bold')

    plt.show()

def nssd_m_aud_logloss():
    aucs = [0.7981, 0.8132, 0.8246]
    logs = [0.4596, 0.4531, 0.4504]

    x = np.arange(len(aucs))
    width = 0.35

    plt.figure(figsize=(6, 3))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.bar(x - width / 2, aucs, width, color='SkyBlue', label='AUC')
    plt.bar(x + width / 2, logs, width, color='IndianRed', label='LogLoss')

    plt.ylabel("AUC and LogLoss")
    plt.title("NS-based Shallow&Deep AUC and LogLoss")
    xlabels = ['Wide&Deep',
               'DeepFM',
               'NS-based Shallow&Deep']
    plt.xticks(x, xlabels, fontsize=8)
    plt.ylim(0.4, 1.1)
    plt.legend()

    plt.show()

def plot_mae():
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    users = [10, 20, 30, 40, 50]
    # old_maes = [0.96, 0.92, 0.87, 0.85, 0.84]
    # new_maes = [0.90, 0.85, 0.82, 0.815, 0.817]
    old_maes = [0.89, 0.86, 0.81, 0.795, 0.785]
    new_maes = [0.82, 0.79, 0.77, 0.755, 0.757]

    plt.figure(figsize=(7, 4))
    plt.grid(linestyle="--")
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.plot(users, old_maes, marker='o', color="SkyBlue", label=u"传统相似用户模型", linewidth=1.5)
    plt.plot(users, new_maes, marker='^', color="IndianRed", label=u"本文相似用户模型", linewidth=1.5)

    plt.xlabel(u"相似近邻数", fontsize=10, fontweight='bold', labelpad=1)
    plt.ylabel("MAE", fontsize=10, fontweight='bold', labelpad=1)

    plt.ylim(0.7, 1)
    plt.xlim(8, 52)

    plt.legend(loc=0, numpoints=1)
    leg = plt.gca().get_legend()
    ltext = leg.get_texts()
    plt.setp(ltext, fontsize=6, fontweight='bold')

    plt.show()

def nscf_epoch_curve():
    x = np.linspace(1, 100, 100)
    train_logloss = [13.9749, ]
    test_logloss = [15.7243, ]

    # plt.figure(figsize=(6, 3))
    # plt.grid(linestyle="--")
    # ax = plt.gca()
    # ax.spines['top'].set_visible(False)
    # ax.spines['right'].set_visible(False)
    #
    # plt.plot(x, train_logloss, marker='o', color="SkyBlue", label="Train Data LogLoss", linewidth=1.5)
    # plt.plot(x, test_logloss, marker='^', color="IndianRed", label="Test Data LogLoss", linewidth=1.5)
    #
    # plt.xlabel("Epochs", fontsize=6.5, fontweight='bold', labelpad=-5)
    # plt.ylabel("LogLoss", fontsize=6.5, fontweight='bold', labelpad=-5)
    #
    # plt.legend(loc=0, numpoints=1)
    # leg = plt.gca().get_legend()
    # ltext = leg.get_texts()
    # plt.setp(ltext, fontsize=6, fontweight='bold')
    #
    # plt.show()

def main():
    # nscf_learning_curves()
    # nscf_auc_logloss()
    # nscf_n_auc_logloss()
    # nscf_rmse()
    # nscf_model_auc_logloss()
    # nscf_d_auc_logloss()
    # nssd_logloss()
    # nssd_m_aud_logloss()
    # plot_mae()
    # nscf_epoch_curve()
    nscf_learning_curves()

if __name__ == "__main__":
    main()
    # import random
    # for i in range(20):
    #     print random.randint(0, 9), random.randint(0, 9)


import json
import sqlite3
from sqlite3 import Error
from datetime import datetime
import glob
import pandas as pd
import itertools

conn = sqlite3.connect('data.db')
c = conn.cursor()

c.execute('DROP TABLE IF EXISTS "posts";')
c.execute('DROP TABLE IF EXISTS "location";')
c.execute('CREATE TABLE posts(id text PRIMARY KEY not null, location_id text, location_slug text, accessibility_caption text, caption text, likes real, comment_count real, hashtags_string text, timestring text)');

json_files = glob.glob('./*.json')
json_xz_files = glob.glob('./*.json.xz')

for filename in itertools.chain(json_files, json_xz_files):
	print(filename)
	if("comments" in filename):
		continue
	df = pd.read_json(filename)
	info = df["node"]
	accessibility_caption = None
	if("accessibility_caption" in info):
		accessibility_caption = info["accessibility_caption"]
	likes = info["edge_media_preview_like"]["count"]
	caption = None
	if(len(info["edge_media_to_caption"]["edges"])>0):
		caption = info["edge_media_to_caption"]["edges"][0]["node"]["text"]
	comment_count = info["edge_media_to_comment"]["count"]
	location_id = None
	location_slug = None
	if(info["location"]):
		location_id = info["location"]["id"]
		location_slug = info["location"]["slug"]
	hashtags_string = None
	if(caption):
		hashtags = [word[1:] for word in caption.split() if word[0] == '#']
		hashtags_string =  ",".join(hashtags)

	time = int(info["taken_at_timestamp"])
	timestring = datetime.utcfromtimestamp(time).strftime('%Y-%m-%d %H:%M:%S')
	post_id = info["id"]

	c.execute('INSERT INTO posts VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', (post_id, location_id, location_slug, accessibility_caption, caption, likes, comment_count, hashtags_string, timestring))

conn.commit()


#!/usr/bin/env python
"""actionVerification.py:
Small script to check if a given host is reachable and/or pre defined services are available.
Services can be defined in the config.py file.

Current return codes:
'OK':           0
'ERROR':        1
'TARGET_ERROR': 50
'NOTSURE':      100

Author: Tomer Siani Nov. 2014

"""

import sys
import time
import nmap
import argparse
import socket

#Import configurations
from config import services as service_ref
from config import return_codes as return_codes

#define parser for arguments
parser = argparse.ArgumentParser(description='Checks activity for given host using nmap. (Currently only supporting IPv4)')
parser.add_argument('-t', default="10.20.4.115", type=str, dest='target', help='target IP/hostname')
parser.add_argument('-p', default='0', type=int, dest='port', help='Port to scan on target')
parser.add_argument('-s', default="", type=str, dest='service', help='Service to scan for on target')
parser.add_argument('-S', action='store_true', help='Scans all target services')
parser.add_argument('-A', action='store_true', help='Agressive scanning')
parser.add_argument('-v', action='store_true', help='verbose output')
parser.add_argument('--debug', action='store_true', help='Debug output')

global v,d
d=False
v=False

try:
    nm = nmap.PortScanner()         # instantiate nmap.PortScanner object
except nmap.PortScannerError:
    print('Nmap not found', sys.exc_info()[0])
    sys.exit(1)
except:
    print("Unexpected error:", sys.exc_info()[0])
    sys.exit(1)

def main(argv=sys.argv):

    args=parser.parse_args()
    global v,d
    v = args.v
    d = args.debug
    target=checkTarget(args.target)
    port = args.port
    service = args.service
    scanArgs=""
    if args.A:
        log("Agressive scan active")
        scanArgs="-A"
    return_value=0

    #If service scan is required print output
    if args.S:
        v = True
        for i in service_ref:
            checkService(target,service_ref[i],scanArgs)
    else:

        #If only the target is defined ping scan
        if port==0 and service=="":
            log("Checking if host is up")
            nm.scan(target,arguments='-sn')
            return_value=isUp(nm[target].state())

        #if port is defined
        if port>0 and service=="":
            return_value=checkPort(target,port,scanArgs)

        #Check if service is regitered in config file
        if service in service_ref:
            log("Checking service {} on port {}".format(service,service_ref[service]))
            return_value   = checkService(target,service_ref[service],scanArgs)

        elif service != "":
            log("Service not registered in config-file")
            return_value   = return_codes['ERROR']
    print("Return value = {}".format(return_value))
    sys.exit(int(return_value))

def log(string):
    if v:
        print(string)

def debugLog(string):
    if d:
        print("---DEBUG: {}".format(string))

def isUp(state):
    if state=="up":
        return return_codes['OK']
    else:
        return return_codes['ERROR']

def checkPort(target,port,scanArgs):
    nm.scan(target,arguments='{} -p {}'.format(scanArgs,port))
    debugLog("Issued nmap command: {}".format(nm.command_line()))
    if nm[target].has_tcp(port):
            #nm[target].tcp(int(port))
            state=nm[target]['tcp'][port]['state']
            log('port : %s\tstate : %s' % (port, state))
            debugLog("State    : {}".format(state))
            debugLog("Scan info: {}".format(nm.scaninfo()))
            debugLog("Protocols: {}".format(nm[target].all_protocols()))
            debugLog(nm.csv())
            if isOpen(nm[target]['tcp'][port]['state']):
                return return_codes['OK']
            else:
                return return_codes['ERROR']
    else:
        return None

def checkService(target,port,scanArgs):
    nm.scan(target,arguments='-sV {} -p {}'.format(scanArgs,port))
    debugLog("Issued nmap command: {}".format(nm.command_line()))
    if nm[target].has_tcp(port):
            state=nm[target]['tcp'][port]['state']
            service=nm[target]['tcp'][port]['product']
            version=nm[target]['tcp'][port]['version']
            debugLog("State    : {}".format(state))
            debugLog("Service  : {}".format(service))
            debugLog("Version  : {}".format(version))
            debugLog("Scan info: {}".format(nm.scaninfo()))
            debugLog("Protocols: {}".format(nm[target].all_protocols()))
            debugLog(nm.csv())
            log('port : %s\tstate : %s' % (port, nm[target]['tcp'][port]['state']))

            #Version detected: service most likely running
            if isOpen(state) and  not version=="":
                log("Service running: {}".format(service))
                log("Version info: {}\n".format(version))
                return return_codes['OK']

            #Version could not be detected
            if isOpen(state) and version=="":
                log("Failed to determine Verion. Port open but service not reachable")
                return return_codes['NOTSURE']
            else:
                return return_codes['ERROR']
    else:
        return return_codes['ERROR']

def isOpen(state):
    if state=="open":
        return 1
    else:
        return 0

#Check if target (hostname/ip)
def checkTarget(target):
    try:
        socket.inet_aton(target)
        return target
    except:
        try:
            log("Target given is not a valit IPv4 ip")
            log("Found host ip:{}".format(socket.gethostbyname_ex(target)))
            return str(socket.gethostbyname(target))
        except:
            print("Could not resolve hostname")
            sys.exit(return_codes['TARGET_ERROR'])

__name__="__main__"
main()


import logging

from django.db.models.signals import pre_save, post_save, post_delete, m2m_changed
from django.dispatch import receiver

from historie.models import Historie
from services.mailer import Mailer
from uzivatel.models import Organizace, Osoba, User
from rest_framework.authtoken.models import Token

logger = logging.getLogger(__name__)

@receiver(post_save, sender=Organizace)
def orgnaizace_save_metadata(sender, instance: Organizace, **kwargs):
    instance.save_metadata()

@receiver(post_save, sender=Osoba)
def osoba_save_metadata(sender, instance: Osoba, **kwargs):
    instance.save_metadata()

@receiver(pre_save, sender=User)
def create_ident_cely(sender, instance, **kwargs):
    """
    Přidelení identu celý pro usera.
    """
    if not kwargs['update_fields'] and instance.id:
        # Save it, so it can be used in post_save
        database_user_query = User.objects.filter(id=instance.id)
        if database_user_query.count() > 0:
            instance.old = database_user_query.first()
        else:
            instance.old = None
    if instance.pk is None:
        instance.model_is_updated = False
        logger.debug("uzivatel.signals.create_ident_cely.running_create_ident_cely_receiver")
        if not instance.ident_cely:
            users = User.objects.all().order_by("-ident_cely")
            if users.count() > 0:
                last_user = users.first()
                dash_index = last_user.ident_cely.rfind("-")
                number = int(last_user.ident_cely[dash_index + 1:]) + 1
                instance.ident_cely = "U-" + "{0}".format(str(number)).zfill(6)
            else:
                instance.ident_cely = "U-000001"
    if len(kwargs["update_fields"]) == 1 and "last_login" in kwargs["update_fields"]:
        instance.suppress_signal = True

@receiver(post_save, sender=User)
def user_post_save_method(sender, instance: User, created: bool, **kwargs):
    if not instance.suppress_signal:
        instance.save_metadata()
    send_deactivation_email(sender, instance, **kwargs)
    send_new_user_email_to_admin(sender, instance, created)
    send_account_confirmed_email(sender, instance, created)
    # Create or change token when user changed.
    try:
        old_token = Token.objects.get(user=instance)
    except Token.DoesNotExist:
        Token.objects.create(user=instance)
    else:
        old_token.delete()
        Token.objects.create(user=instance)

def send_deactivation_email(sender, instance: User, **kwargs):
    """
    Signál pro poslání deaktivačního emailu uživately.
    """
    if not kwargs.get('update_fields') and hasattr(instance, 'old') and instance.old is not None:
        kwargs['update_fields'] = []
        if instance.is_active != instance.old.is_active:
            kwargs['update_fields'].append('is_active')
    if kwargs['update_fields']:
        if 'is_active' in kwargs['update_fields'] and instance.is_active is False:
            Mailer.send_eu03(user=instance)

def send_new_user_email_to_admin(sender, instance: User, created):
    """
    Signál pro zaslání info o nově registrovaném uživately adminovy.
    """
    if created is True and instance.created_from_admin_panel is False:
        Mailer.send_eu04(user=instance)

def send_account_confirmed_email(sender, instance: User, created):
    """
    signál pro zaslání emailu uživately o jeho konfirmaci.
    """
    if created is True and instance.created_from_admin_panel is True:
        Mailer.send_eu02(user=instance)

@receiver(post_delete, sender=User)
def delete_profile(sender, instance, *args, **kwargs):
    """
    Signál pro zaslání emailu uživately o jeho smazání.
    """
    instance: User
    Mailer.send_eu03(user=instance)
    Historie.save_record_deletion_record(record=instance)
    instance.save_metadata(use_celery=False)
    instance.record_deletion()

@receiver(post_delete, sender=Osoba)
def osoba_delete_repository_container(sender, instance: Osoba, **kwargs):
    instance.record_deletion()

@receiver(post_delete, sender=Organizace)
def osoba_delete_repository_container(sender, instance: Organizace, **kwargs):
    instance.record_deletion()


import re
import sys
import struct

# There are both ---<Lexer>--- and ---<Parser>--- sections to this program

if len( sys.argv ) < 3:
    print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0])
    exit(1)

inputFilename = sys.argv[1]
outputFilename = sys.argv[2]

doCOMMENTs = True       # Save XCOMMENTs in the output xsvf file
#doCOMMENTs = False       # Save XCOMMENTs in the output xsvf file

# pick your file encoding
file_encoding = 'ISO-8859-1'
#file_encoding = 'utf-8'

xrepeat = 0             # argument to XREPEAT, gives retry count for masked compares

#-----< Lexer >---------------------------------------------------------------

StateBin = (RESET,IDLE,
    DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE,
    IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16)

# Any integer index into this tuple will be equal to its corresponding StateBin value
StateTxt = ("RESET","IDLE",
    "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE",
    "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE")

(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO,
    XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC,
    XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,
    LCOUNT,LDELAY,LSDR,XTRST) = range(29)

#Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back
# and check a completion status, essentially waiting on a part until it signals that it is done.
# For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST)
# and exit loop when LSDR compares match.
"""
LCOUNT	25;
! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC.
LDELAY	DRPAUSE	5 TCK	1.00E-003 SEC;
! Test for the completed status. Match means pass.
! Loop back to LDELAY line if not match and loop count less than 25.
LSDR  1 TDI  (0)
        TDO  (1);
"""

#XTRST is an opcode Xilinx seemed to have missed and it comes from the SVF TRST statement.

LineNumber = 1

def s_ident(scanner, token): return ("ident", token.upper(), LineNumber)

def s_hex(scanner, token):
    global LineNumber
    LineNumber = LineNumber + token.count('\n')
    token = ''.join(token.split())
    return ("hex", token[1:-1], LineNumber)

def s_int(scanner, token): return ("int", int(token), LineNumber)
def s_float(scanner, token): return ("float", float(token), LineNumber)
#def s_comment(scanner, token): return ("comment", token, LineNumber)
def s_semicolon(scanner, token): return ("semi", token, LineNumber)

def s_nl(scanner,token):
    global LineNumber
    LineNumber = LineNumber + 1
    #print( 'LineNumber=', LineNumber, file=sys.stderr )
    return None

#2.00E-002

scanner = re.Scanner([
    (r"[a-zA-Z]\w*", s_ident),
#    (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float),
    (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float),
    (r"\d+", s_int),
    (r"\(([0-9a-fA-F]|\s)*\)", s_hex),
    (r"(!|//).*$", None),
    (r";", s_semicolon),
    (r"\n",s_nl),
    (r"\s*", None),
    ],
    re.MULTILINE
    )

# open the file using the given encoding
file = open( sys.argv[1], encoding=file_encoding )

# read all svf file input into string "input"
input = file.read()

file.close()

# Lexer:
# create a list of tuples containing (tokenType, tokenValue, LineNumber)
tokens = scanner.scan( input )[0]

input = None    # allow gc to reclaim memory holding file

#for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue )

#-----<parser>-----------------------------------------------------------------

tokVal = tokType = tokLn = None

tup = iter( tokens )

def nextTok():
    """
    Function to read the next token from tup into tokType, tokVal, tokLn (linenumber)
    which are globals.
    """
    global tokType, tokVal, tokLn, tup
    tokType, tokVal, tokLn = tup.__next__()

class ParseError(Exception):
    """A class to hold a parsing error message"""
    def __init__(self, linenumber, token, message):
        self.linenumber = linenumber
        self.token = token
        self.message = message
    def __str__(self):
        global inputFilename
        return "Error in file \'%s\' at line %d near token %s\n %s" % (
                   inputFilename, self.linenumber, repr(self.token), self.message)

class MASKSET(object):
    """
    Class MASKSET holds a set of bit vectors, all of which are related, will all
    have the same length, and are associated with one of the seven shiftOps:
    HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a
    size.
    """
    def __init__(self, name):
        self.empty()
        self.name = name

    def empty(self):
        self.mask = bytearray()
        self.smask = bytearray()
        self.tdi = bytearray()
        self.tdo = bytearray()
        self.size = 0

    def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ):
        """
        Set all the lengths equal in the event some of the masks were
        not seen as part of the last change set.
        """
        if self.size == newSize:
            return

        if newSize == 0:
            self.empty()
            return

        # If an SIR was given without a MASK(), then use a mask of all zeros.
        # this is not consistent with the SVF spec, but it makes sense because
        # it would be odd to be testing an instruction register read out of a
        # tap without giving a mask for it.  Also, lattice seems to agree and is
        # generating SVF files that comply with this philosophy.
        if self.name == 'SIR' and not sawMASK:
            self.mask = bytearray( newSize )

        if newSize != len(self.mask):
            self.mask = bytearray( newSize )
            if self.name == 'SDR':  # leave mask for HIR,HDR,TIR,TDR,SIR zeros
                for i in range( newSize ):
                    self.mask[i] = 1

        if newSize != len(self.tdo):
            self.tdo = bytearray( newSize )

        if newSize != len(self.tdi):
            self.tdi = bytearray( newSize )

        if newSize != len(self.smask):
            self.smask = bytearray( newSize )

        self.size = newSize
#-----</MASKSET>-----

def makeBitArray( hexString, bitCount ):
    """
    Converts a packed sequence of hex ascii characters into a bytearray where
    each element in the array holds exactly one bit. Only "bitCount" bits are
    scanned and these must be the least significant bits in the hex number. That
    is, it is legal to have some unused bits in the must significant hex nibble
    of the input "hexString". The string is scanned starting from the backend,
    then just before returning we reverse the array. This way the append()
    method can be used, which I assume is faster than an insert.
    """
    global tokLn
    a = bytearray()
    length = bitCount
    hexString = list(hexString)
    hexString.reverse()
    #print(hexString)
    for c in hexString:
        if length <= 0:
            break;
        c = int(c, 16)
        for mask in [1,2,4,8]:
            if length <= 0:
                break;
            length = length - 1
            a.append( (c & mask) != 0 )
    if length > 0:
        raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount )
    a.reverse()
    #print(a)
    return a

def makeXSVFbytes( bitarray ):
    """
    Make a bytearray which is contains the XSVF bits which will be written
    directly to disk.  The number of bytes needed is calculated from the size
    of the argument bitarray.
    """
    bitCount = len(bitarray)
    byteCount = (bitCount+7)//8
    ba = bytearray( byteCount )
    firstBit = (bitCount % 8) - 1
    if firstBit == -1:
        firstBit = 7
    bitNdx = 0
    for byteNdx in range(byteCount):
        mask = 1<<firstBit
        byte = 0
        while mask:
            if bitarray[bitNdx]:
                byte |= mask;
            mask = mask >> 1
            bitNdx = bitNdx + 1
        ba[byteNdx] = byte
        firstBit = 7
    return ba

def writeComment( outputFile, shiftOp_linenum, shiftOp ):
    """
    Write an XCOMMENT record to outputFile
    """
    comment = "%s @%d\0" % (shiftOp, shiftOp_linenum)   # \0 is terminating nul
    ba = bytearray(1)
    ba[0] = XCOMMENT
    ba += comment.encode()
    outputFile.write( ba )

def combineBitVectors( trailer, meat, header ):
    """
    Combine the 3 bit vectors comprizing a transmission.  Since the least
    significant bits are sent first, the header is put onto the list last so
    they are sent first from that least significant position.
    """
    ret = bytearray()
    ret.extend( trailer )
    ret.extend( meat )
    ret.extend( header )
    return ret

def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ):
    """
    Write the output for the SVF RUNTEST command.
    run_count - the number of clocks
    min_time - the number of seconds
    tokenTxt - either RUNTEST or LDELAY
    """
    # convert from secs to usecs
    min_time = int( min_time * 1000000)

    # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command.  Check the SVF spec, then
    # read the XSVF command.   They are not the same.  Use an XSVF XWAITSTATE to
    # implement the required behavior of the SVF RUNTEST command.
    if doCOMMENTs:
        writeComment( output, tokLn, tokenTxt )

    if tokenTxt == 'RUNTEST':
        obuf = bytearray(11)
        obuf[0] = XWAITSTATE
        obuf[1] = run_state
        obuf[2] = end_state
        struct.pack_into(">i", obuf, 3, run_count )  # big endian 4 byte int to obuf
        struct.pack_into(">i", obuf, 7, min_time )   # big endian 4 byte int to obuf
        outputFile.write( obuf )
    else:   # == 'LDELAY'
        obuf = bytearray(10)
        obuf[0] = LDELAY
        obuf[1] = run_state
        # LDELAY has no end_state
        struct.pack_into(">i", obuf, 2, run_count )  # big endian 4 byte int to obuf
        struct.pack_into(">i", obuf, 6, min_time )   # big endian 4 byte int to obuf
        outputFile.write( obuf )

output = open( outputFilename, mode='wb' )

hir = MASKSET('HIR')
hdr = MASKSET('HDR')
tir = MASKSET('TIR')
tdr = MASKSET('TDR')
sir = MASKSET('SIR')
sdr = MASKSET('SDR')

expecting_eof = True

# one of the commands that take the shiftParts after the length, the parse
# template for all of these commands is identical
shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR')

# the order must correspond to shiftOps, this holds the MASKSETS.  'LSDR' shares sdr with 'SDR'
shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir )

# what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length
shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK')

# the set of legal states which can trail the RUNTEST command
run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE')

enddr_state_allowed = ('DRPAUSE', 'IDLE')
endir_state_allowed = ('IRPAUSE', 'IDLE')

trst_mode_allowed = ('ON', 'OFF', 'Z', 'ABSENT')

enddr_state = IDLE
endir_state = IDLE

frequency = 	1.00e+006 # HZ;

# change detection for xsdrsize and xtdomask
xsdrsize = -1           # the last one sent, send only on change
xtdomask = bytearray()  # the last one sent, send only on change

# we use a number of single byte writes for the XSVF command below
cmdbuf = bytearray(1)

# Save the XREPEAT setting into the file as first thing.
obuf = bytearray(2)
obuf[0] = XREPEAT
obuf[1] = xrepeat
output.write( obuf )

try:
    while 1:
        expecting_eof = True
        nextTok()
        expecting_eof = False
        # print( tokType, tokVal, tokLn )

        if tokVal in shiftOps:
            shiftOp_linenum = tokLn
            shiftOp = tokVal

            set = shiftSets[shiftOps.index(shiftOp)]

            # set flags false, if we see one later, set that one true later
            sawTDI = sawTDO = sawMASK = sawSMASK = False

            nextTok()
            if tokType != 'int':
                raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) )
            length = tokVal

            nextTok()

            while tokVal != ';':
                if tokVal not in shiftParts:
                    raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'")
                shiftPart = tokVal

                nextTok()

                if tokType != 'hex':
                    raise ParseError( tokLn, tokVal, "Expecting hex bits" )
                bits = makeBitArray( tokVal, length )

                if shiftPart == 'TDI':
                    sawTDI = True
                    set.tdi = bits

                elif shiftPart == 'TDO':
                    sawTDO = True
                    set.tdo = bits

                elif shiftPart == 'MASK':
                    sawMASK = True
                    set.mask = bits

                elif shiftPart == 'SMASK':
                    sawSMASK = True
                    set.smask = bits

                nextTok()

            set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length )

            # process all the gathered parameters and generate outputs here
            if shiftOp == 'SIR':
                if doCOMMENTs:
                    writeComment( output, shiftOp_linenum, 'SIR' )

                tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi )
                if len(tdi) > 255:
                    obuf = bytearray(3)
                    obuf[0] = XSIR2
                    struct.pack_into( ">h", obuf, 1, len(tdi) )
                else:
                    obuf = bytearray(2)
                    obuf[0] = XSIR
                    obuf[1] = len(tdi)
                output.write( obuf )
                obuf = makeXSVFbytes( tdi )
                output.write( obuf )

            elif shiftOp == 'SDR':
                if doCOMMENTs:
                    writeComment( output, shiftOp_linenum, shiftOp )

                if not sawTDO:
                    # pass a zero filled bit vector for the sdr.mask
                    mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask )
                    tdi  = combineBitVectors( tdr.tdi,  sdr.tdi,  hdr.tdi )

                    if xsdrsize != len(tdi):
                        xsdrsize = len(tdi)
                        cmdbuf[0] = XSDRSIZE
                        output.write( cmdbuf )
                        obuf = bytearray(4)
                        struct.pack_into( ">i", obuf, 0, xsdrsize )  # big endian 4 byte int to obuf
                        output.write( obuf )

                    if xtdomask != mask:
                        xtdomask = mask
                        cmdbuf[0] = XTDOMASK
                        output.write( cmdbuf )
                        obuf = makeXSVFbytes( mask )
                        output.write( obuf )

                    cmdbuf[0] = XSDR
                    output.write( cmdbuf )
                    obuf = makeXSVFbytes( tdi )
                    output.write( obuf )

                else:
                    mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask )
                    tdi  = combineBitVectors( tdr.tdi,  sdr.tdi,  hdr.tdi )
                    tdo  = combineBitVectors( tdr.tdo,  sdr.tdo,  hdr.tdo )

                    if xsdrsize != len(tdi):
                        xsdrsize = len(tdi)
                        cmdbuf[0] = XSDRSIZE
                        output.write( cmdbuf )
                        obuf = bytearray(4)
                        struct.pack_into(">i", obuf, 0, xsdrsize )  # big endian 4 byte int to obuf
                        output.write( obuf )

                    if xtdomask != mask:
                        xtdomask = mask
                        cmdbuf[0] = XTDOMASK
                        output.write( cmdbuf )
                        obuf = makeXSVFbytes( mask )
                        output.write( obuf )

                    cmdbuf[0] = XSDRTDO
                    output.write( cmdbuf )
                    obuf = makeXSVFbytes( tdi )
                    output.write( obuf )
                    obuf = makeXSVFbytes( tdo )
                    output.write( obuf )
                    #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) )

            elif shiftOp == 'LSDR':
                if doCOMMENTs:
                    writeComment( output, shiftOp_linenum, shiftOp )

                mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask )
                tdi  = combineBitVectors( tdr.tdi,  sdr.tdi,  hdr.tdi )
                tdo  = combineBitVectors( tdr.tdo,  sdr.tdo,  hdr.tdo )

                if xsdrsize != len(tdi):
                    xsdrsize = len(tdi)
                    cmdbuf[0] = XSDRSIZE
                    output.write( cmdbuf )
                    obuf = bytearray(4)
                    struct.pack_into(">i", obuf, 0, xsdrsize )  # big endian 4 byte int to obuf
                    output.write( obuf )

                if xtdomask != mask:
                    xtdomask = mask
                    cmdbuf[0] = XTDOMASK
                    output.write( cmdbuf )
                    obuf = makeXSVFbytes( mask )
                    output.write( obuf )

                cmdbuf[0] = LSDR
                output.write( cmdbuf )
                obuf = makeXSVFbytes( tdi )
                output.write( obuf )
                obuf = makeXSVFbytes( tdo )
                output.write( obuf )
                #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) )

        elif tokVal == 'RUNTEST' or tokVal == 'LDELAY':
            # e.g. from lattice tools:
            # "RUNTEST	IDLE  	5 TCK	1.00E-003 SEC;"
            saveTok = tokVal
            nextTok()
            min_time = 0
            run_count = 0
            max_time = 600  # ten minutes
            if tokVal in run_state_allowed:
                run_state = StateTxt.index(tokVal)
                end_state = run_state  # bottom of page 17 of SVF spec
                nextTok()
            if tokType != 'int' and tokType != 'float':
                raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]")
            timeval = tokVal;
            nextTok()
            if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK':
                raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)")
            if tokVal == 'TCK' or tokVal == 'SCK':
                run_count = int( timeval )
            else:
                min_time = timeval
            nextTok()
            if tokType == 'int' or tokType == 'float':
                min_time = tokVal
                nextTok()
                if tokVal != 'SEC':
                    raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time")
                nextTok()
            if tokVal == 'MAXIMUM':
                nextTok()
                if tokType != 'int' and tokType != 'float':
                    raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM")
                max_time = tokVal
                nextTok()
                if tokVal != 'SEC':
                    raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time")
                nextTok()
            if tokVal == 'ENDSTATE':
                nextTok()
                if tokVal not in run_state_allowed:
                    raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE")
                end_state = StateTxt.index(tokVal)
                nextTok()
            if tokVal != ';':
                raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....")
            # print( "run_count=", run_count, "min_time=", min_time,
                # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] )
            writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok )

        elif tokVal == 'LCOUNT':
            nextTok()
            if tokType != 'int':
                raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT")
            loopCount = tokVal
            nextTok()
            if tokVal != ';':
                raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count")
            if doCOMMENTs:
                writeComment( output, tokLn, 'LCOUNT' )
            obuf = bytearray(5)
            obuf[0] = LCOUNT
            struct.pack_into(">i", obuf, 1, loopCount )  # big endian 4 byte int to obuf
            output.write( obuf )

        elif tokVal == 'ENDDR':
            nextTok()
            if tokVal not in enddr_state_allowed:
                raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE)")
            enddr_state = StateTxt.index(tokVal)
            nextTok()
            if tokVal != ';':
                raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state")
            if doCOMMENTs:
                writeComment( output, tokLn, 'ENDDR' )
            obuf = bytearray(2)
            obuf[0] = XENDDR
            # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here.
            # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e.
            # boolean argument to XENDDR which only handles two of the 3 intended states.
            obuf[1] = 1 if enddr_state == DRPAUSE else 0
            output.write( obuf )

        elif tokVal == 'ENDIR':
            nextTok()
            if tokVal not in endir_state_allowed:
                raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE)")
            endir_state = StateTxt.index(tokVal)
            nextTok()
            if tokVal != ';':
                raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state")
            if doCOMMENTs:
                writeComment( output, tokLn, 'ENDIR' )
            obuf = bytearray(2)
            obuf[0] = XENDIR
            # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here.
            # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e.
            # boolean argument to XENDDR which only handles two of the 3 intended states.
            obuf[1] = 1 if endir_state == IRPAUSE else 0
            output.write( obuf )

        elif tokVal == 'STATE':
            nextTok()
            ln = tokLn
            while tokVal != ';':
                if tokVal not in StateTxt:
                    raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE")
                stable_state = StateTxt.index( tokVal )

                if doCOMMENTs and ln != -1:
                    writeComment( output, ln, 'STATE' )
                    ln = -1     # save comment only once

                obuf = bytearray(2)
                obuf[0] = XSTATE
                obuf[1] = stable_state
                output.write( obuf )
                nextTok()

        elif tokVal == 'FREQUENCY':
            nextTok()
            if tokVal != ';':
                if tokType != 'int' and tokType != 'float':
                    raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY")
                frequency = tokVal
                nextTok()
                if tokVal != 'HZ':
                    raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles")
                nextTok()
                if tokVal != ';':
                    raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ")

        elif tokVal == 'TRST':
            nextTok()
            if tokVal not in trst_mode_allowed:
                raise ParseError( tokLn, tokVal, "Expecting 'ON|OFF|Z|ABSENT' after TRST")
            trst_mode = tokVal
            nextTok()
            if tokVal != ';':
                raise ParseError( tokLn, tokVal, "Expecting ';' after TRST trst_mode")
            if doCOMMENTs:
                writeComment( output, tokLn, 'TRST %s' % trst_mode )
            obuf = bytearray( 2 )
            obuf[0] = XTRST
            obuf[1] = trst_mode_allowed.index( trst_mode )  # use the index as the binary argument to XTRST opcode
            output.write( obuf )

        else:
            raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal)

except StopIteration:
    if not expecting_eof:
        print( "Unexpected End of File at line ", tokLn )

except ParseError as pe:
    print( "\n", pe )

finally:
    # print( "closing file" )
    cmdbuf[0] = XCOMPLETE
    output.write( cmdbuf )
    output.close()


#!/usr/bin/env python

import tkinter

class MyApp(tkinter.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.pack()

        self.text = tkinter.Text(master)
        self.text.pack()

        self.text.bind("<KeyRelease>", self.textChanged)

    def textChanged(self, event):
        print("Text:", self.text.get("1.0", "end"))

if __name__ == "__main__":
    root = tkinter.Tk()
    app = MyApp(root)
    app.mainloop()


from collections import Counter
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: int
        """
        counter = Counter(s)
        odd = 0
        ans = 0
        for char, cnt in counter.iteritems():
            if cnt % 2 == 0:
                ans += cnt
            else:
                odd = 1
                ans += cnt - 1
        return ans + odd


from urllib.request import urlopen
from bs4 import BeautifulSoup as bs4
'''lnk="https://www.nature.com/articles/s41598-023-28880-x"
url=urlopen(lnk)
soup = bs4(url, 'lxml')
l=[]
str1=''
all_links = soup.findAll("div",attrs={"class":"c-article-section__content","id":"Bib1-content"})
for link in all_links:
    l.append(link)
for i in l:
    str1+=str(i)
with open ("rra_csv.csv","w",encoding="utf-8") as file:
    file.write(str1)'''
str2=''
lnk="rra_csv.csv"
url=open(lnk)
soup= bs4(url,'lxml')
l2=[]
for i in soup.findAll('a'):
    l2.append(i.get("href"))
for i in l2:
    str2+="\n"
    str2+=str(i)
with open ("references.csv","w") as f1:
    f1.write(str2)
f1.close()


__author__ = 'Masato Taruishi'
__copyright__ = 'Copyright (c) 2013, Masato Taruishi <taru0216@gmail.com>'

import doctest
import ips.sandbox
import unittest

class FakeStub:

  Cmds = {
      'lxc-info -n example': 'example',
      'lxc-stop -r -n example': '',
      'lxc-stop -n example': '',
      'lxc-stop -k -n example': '',
      'lxc-start -d -n example': 'started',
      'lxc-destroy -n example': '',
      'grep lxc.network.link /var/lib/lxc/example/config | cut -d"=" -f2':
          'lxcbr0',
      'grep lxc.network.hwaddr /var/lib/lxc/example/config |' +
          ' cut -d" " -f3': '00:11:22:33:44:55',
      'grep "00:11:22:33:44:55" /var/lib/misc/dnsmasq*.leases |' +
          ' cut -d" " -f3': '192.168.1.1',
      '(ping6 -c 1 -I lxcbr0 ff02::1 && ip -6 neigh show) |' +
          ' grep 00:11:22:33:44:55 | cut -d" " -f1':
              'fe80::213:72ff:fedc:7fb4',
      '/sbin/iptables -L PREROUTING -t nat -n': '',
      '/sbin/iptables -I PREROUTING -t nat -p tcp -d 192.168.1.254' +
          ' --dport 1 -jDNAT --to-destination 192.168.1.1': '',
      '/sbin/iptables -I OUTPUT -t nat -p tcp -d 192.168.1.254' +
          ' --dport 1 -jDNAT --to-destination 192.168.1.1': '',
      '/sbin/iptables -I PREROUTING -t nat -p tcp -d 192.168.1.254' +
          ' --dport 2 -jDNAT --to-destination 192.168.1.1': '',
      '/sbin/iptables -I OUTPUT -t nat -p tcp -d 192.168.1.254' +
          ' --dport 2 -jDNAT --to-destination 192.168.1.1': '',
      '/sbin/iptables -I PREROUTING -t nat -p tcp -d 192.168.1.254' +
          ' --dport 3 -jDNAT --to-destination 192.168.1.1': '',
      '/sbin/iptables -I OUTPUT -t nat -p tcp -d 192.168.1.254' +
          ' --dport 3 -jDNAT --to-destination 192.168.1.1': '',
      'update-alternatives --remove ips-sandbox_. /var/lib/lxc/example': '',
      'lxc-info -n example | grep -i state: || true': 'state: RUNNING',
  }

  File = {
      '/var/lib/lxc/example/sandbox.proto': 'sandbox_id: "example"',
      '/var/lib/lxc/example/ports': '1\n2 statusz\n3',
      '/var/lib/lxc/example/config': '',
      '/proc/sys/net/ipv6/conf/lxcbr0/accept_ra': '2',
  }

  URL = {
      'http://192.168.1.1:2/healthz': 'ok',
  }

  def Exists(self, path):
    return self.__class__.File.has_key(path)

  def ReadFile(self, path):
    return self.__class__.File[path]

  def UrlRead(self, url):
    return self.__class__.URL[url]

  def HostAddress(self):
    return '192.168.1.254'

  def ExecCommand(self, cmd):
    return self.__class__.Cmds[cmd]

ips.sandbox.Sandbox._stub = FakeStub()

def suite():
  suite = unittest.TestSuite()
  suite.addTests(doctest.DocTestSuite(ips.sandbox))
  return suite


# This python program captures real-time image of the vegetable using webcam and
# detects the vegetable using OpenCV with a trained dataset
# the program is tranined for 5 different vegetables: Carrot, Bell_pepper, Tomato, Potato, and Broccoli

#import required libraries
import cv2
import numpy as np
import mysql.connector
import calendar
import time
import os

# 'tkinter' is used to create the GUI
from tkinter import * #import all libraries in tkinter
class MyWindow:       #main class
    def __init__(self, win):        # initialize method
        # promt to take user inputs
        self.lbl1=Label(win, text='User Id:')
        self.lbl2=Label(win, text='Weight in lb:')
        self.lbl3=Label(win, text='Message:')
        self.lbl4=Label(win, text='****Press "Space" to capture photo or "Escape" to cancel****')
        # when "Space" is pressed image would be captured, when "Escape" is pressed the widow is cancelled
        self.t1=Entry(bd=3) #Take user input
        self.t2=Entry()
        # create buttons
        self.btn0 = Button(win, text='Sell') #if item being sold
        self.btn1 = Button(win, text='Buy')  #if item being bought
        self.btn2=Button(win, text='Reset')  #if the inputs need to be reset

        #positioning elements
        self.lbl1.place(x=100, y=50)
        self.t1.place(x=200, y=50)
        self.lbl2.place(x=100, y=100)
        self.t2.place(x=200, y=100)
        # if button being pressed, call associated function
        self.b0=Button(win, text='Sell', command=self.sell) #call sell function
        self.b1=Button(win, text='Buy', command=self.buy) #call buy function
        self.b2=Button(win, text='Reset') #call reset function
        self.b2.bind('<Button-1>', self.reset)

        #positioning elements
        self.b0.place(x=100, y=150)
        self.b1.place(x=160, y=150)
        self.b2.place(x=220, y=150)
        self.lbl3.place(x=20, y=220)
        self.lbl4.place(x=30, y=190)

        #creating the message box
        self.t4 = Text(win, x=20, y=250, height=5, width=20,bg='yellow')
        self.t4.grid(row=3,column=2)
        self.t4.place(x=20, y=250,height=220, width=350)
        self.t4.bind("<1>", lambda event: self.t4.focus_set())

    # image capture, detection and database update
    def imgDetection(self):

        #connect with the MySQL database named "py_project"
        mydb = mysql.connector.connect(
          host="localhost",
          user="root",
          password="",
          database="py_project",
        )
        mycursor = mydb.cursor()

        # capture image using webcam
        cam = cv2.VideoCapture(0)
        cv2.namedWindow("Capture image")

        img_counter = 0
        itemName = ''

        while True:
            ret, frame = cam.read()
            if not ret:
                print("failed to grab frame")
                break
            cv2.imshow("Capture image", frame)

            k = cv2.waitKey(1)
            if k%256 == 27:
                # when ESC pressed
                print("Escape hit, closing...")
                break
            elif k%256 == 32:
                # when SPACE pressed, image being captured
                #creating time-stamp to name every images
                gmt = time.gmtime()
                ts = calendar.timegm(gmt)
                img_name = str(ts)+".png"
                # saving the image file in the directory
                path = 'C:/xampp/htdocs/py_project/uploads'
                cv2.imwrite(os.path.join(path, img_name), frame)

                # Image Detection
                # Load Yolo trained dataset
                net = cv2.dnn.readNet("yolov4-obj_best.weights", "yolov4-obj.cfg")
                classes = []
                with open("obj.names", "r") as f:
                    classes = [line.strip() for line in f.readlines()]
                output_layers = net.getUnconnectedOutLayersNames()
                colors = np.random.uniform(0, 255, size=(len(classes), 3))

                # Loading image
                img = cv2.imread(os.path.join(path, img_name))
                img = cv2.resize(img, None, fx=0.4, fy=0.4)
                height, width, channels = img.shape

                # Detecting objects
                blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
                net.setInput(blob)
                outs = net.forward(output_layers)

                # creating rectangle
                class_ids = []
                confidences = []
                boxes = []
                for out in outs:
                    for detection in out:
                        scores = detection[5:]
                        class_id = np.argmax(scores)
                        confidence = scores[class_id]
                        if confidence > 0.5:
                            # Object detected
                            center_x = int(detection[0] * width)
                            center_y = int(detection[1] * height)
                            w = int(detection[2] * width)
                            h = int(detection[3] * height)

                            # Rectangle coordinates
                            x = int(center_x - w / 2)
                            y = int(center_y - h / 2)
                            boxes.append([x, y, w, h])
                            confidences.append(float(confidence))
                            class_ids.append(class_id)

                indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
                font = cv2.FONT_HERSHEY_PLAIN
                for i in range(len(boxes)):
                    if i in indexes:
                        x, y, w, h = boxes[i]
                        label = str(classes[class_ids[i]])
                        color = colors[i]
                        cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
                        cv2.putText(img, label, (x, y + 30), font, 3, color, 3)
                        #detected object name
                        itemName = classes[class_ids[i]]

                        item_name_ck = ""
                        for x in itemName:
                            item_name_ck+= x

                # showing the detected object in the image
                cv2.imshow("Image", img)
                gmt = time.gmtime()
                ts = calendar.timegm(gmt)
                img_name = "detected"+str(ts)+".png"
                #cv2.imwrite(img_name, img)

                path = 'C:/xampp/htdocs/py_project/uploads'
                cv2.imwrite(os.path.join(path, img_name), img)

                cv2.waitKey(0)
                cv2.destroyAllWindows()
                # release the camera
                cam.release()
                cv2.destroyAllWindows()

                # read the item related information from the database
                mycursor.execute("""SELECT * FROM `tbl_item_price` WHERE item_name = '%s'""" % (itemName))
                itemPriceInfo = mycursor.fetchone()

                # use the user inputs
                userId = int(self.t1.get())
                userQty = float(self.t2.get())
                # read customer information from the database
                mycursor.execute("""SELECT * FROM `tbl_customer_accounts` WHERE customer_id = '%s'""" % (userId))
                userAccountInfo = mycursor.fetchone()

                # preparing the message to display
                result = "User Details:" + "\nUser Name: " + str(userAccountInfo[2]) + "\nAddress: " + str(userAccountInfo[4])+"\nBank Name: " + str(userAccountInfo[5])+"\nAccount No: " + str(userAccountInfo[3])+"\nPrevious Account Balance($): " + str(round((userAccountInfo[6]),2))

                # Calculte payable amount
                payAmount = float(itemPriceInfo[2]) * float(userQty)
                #if item being sold
                if self.arg==1:
                    updatedAmount = float(userAccountInfo[6]) + float(payAmount) #variable to update account balance
                    newstock=float(itemPriceInfo[4])+ float(userQty) #variable to update current stock
                    result = result+"\nItem sold!"
                #if item being bought
                if self.arg==0:
                    updatedAmount = float(userAccountInfo[6]) - float(payAmount)
                    newstock=float(itemPriceInfo[4])- float(userQty)
                    result = result+"\nItem bought!"
                # adding more info in the message to display
                result = result+"\n\n"
                result = result +"Your customer Id: " + str(userId) + "\nDetected item: " + str(itemName) + "\nItem Price($): " + str(itemPriceInfo[2]) +" (per lb)"+ "\nWeight(lb): " + str(userQty) + "\nTotal price($): " + str(round((payAmount),4)) + " (item price*weight)"

                # Insert Image information into the database
                sql = "INSERT INTO tbl_image_info (`img_name`, `category`, `up_by`) VALUES (%s, %s, %s)"
                val = (img_name, itemName, userId)
                mycursor.execute(sql, val)
                mydb.commit()

                # update current stock of the item detected
                sql_update = "UPDATE tbl_item_price SET current_stock_in_lb=%s WHERE item_name=%s"
                val =  (newstock, itemName)
                mycursor.execute(sql_update, val)
                mydb.commit()

                # update balance in user account
                sql_update = "UPDATE tbl_customer_accounts SET balance=%s WHERE customer_id=%s"
                val =  (updatedAmount, userId)
                mycursor.execute(sql_update, val)
                mydb.commit()
                mycursor.close ()
                mydb.close()
                result = result + "\nYour Updated Account Balance($): "+ str(round((updatedAmount),2))
                #display message
                self.t4.insert(END, str(result))
                break

    # function to take user input and call the image detection function
    # if Sell is pressed
    def sell(self):
        self.t4.delete(1.0,END) #erases previous info
        num1=int(self.t1.get()) #get the user inputs
        num2=float(self.t2.get())
        self.arg=1 #flag variable for Sell
        self.imgDetection() # calling the imgDetection function

    # if Buy is pressed
    def buy(self):
        self.t4.delete(1.0,END) #erases previous info
        num1=int(self.t1.get()) #get the user inputs
        num2=float(self.t2.get())
        self.arg=0 #flag variable for Buy
        self.imgDetection() # calling the imgDetection function

    # function to erase the user iputs if Reset is pressed
    def reset(self, event):
        self.t4.delete(1.0,END)
        self.t1.delete(0, 'end')
        self.t2.delete(0, 'end')

# creating the window
window=Tk()
mywin=MyWindow(window)
window.title('Automated Vegetable Store')
window.geometry("400x500+10+10")
window.mainloop()


from tkinter import *
from tkinter.messagebox import *
from collections import defaultdict

class Polynome(defaultdict):
    def __init__(self, **kwargs):
        defaultdict.__init__(self, float, **kwargs)

    def fromstring(s):
        poly = Polynome()
        s = s.replace('+',' ')
        ls = s.split()  #розбиваємо на список одночленів
        for m in ls:
            c = m.split('*x**') #виділяємо степінь та коефіцієнт
            power = int(c[1])
            coeff = float(c[0])
            poly[power] = coeff
        return poly

    fromstring = staticmethod(fromstring)

    def add_monom(self, deg, coeff):
        if coeff != 0:
            self[deg] += coeff

    def get_degree(self):
        return max(self)

    def __str__(self):
        monomials = list(self.items())
        if not monomials:
            poly_str = "0.0*x**0"
        else:
            monomials.sort(reverse=True)
            ls = ["{}*x**{}".format(mono[1], mono[0]) for mono in monomials]
            poly_str = ' + '.join(ls)
        return poly_str

    def __call__(self, x):
        return sum([self[k]*x**k for k in self])

    def __add__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = self[k] + other[k]
        return self._delzeroes(p)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = self[k] - other[k]
        return self._delzeroes(p)

    def __rsub__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = other[k] - self[k]
        return self._delzeroes(p)

    def __mul__(self, other):
        p = Polynome()
        for k1 in self:
            for k2 in other:
                p[k1 + k2] += self[k1] * other[k2]
        return self._delzeroes(p)

    def __rmul__(self, other):
        return self.__rmul__(other)

    def deriv(self, n=1):
        p = self
        for i in range(n):
            p = self._deriv(p)
        return self._delzeroes(p)

    def _deriv(self, p):
        pp = Polynome()
        for k in p:
            if k != 0:
                pp[k - 1] = p[k] * k
        return pp

    def _delzeroes(self, p):
        pp = Polynome()
        for k in p:
            if p[k] != 0:
                pp[k] = p[k]
        return pp

    def makewidgets(self):
        self.frame = Frame(self.root)

# if __name__ == '__main__':
#     p1 = Polynome.fromstring('3.7*x**3 + 0.3*x**1 + -1.2*x**0')
#     print('р1 =', p1)
#     p2 = Polynome.fromstring('2.2*x**3 + -1.3*x**2 + 0.2*x**1')
#     print('р2 =', p2)
#     print('Значення p1 у точці x=2:', p1(2))
#     print('Сума p1+p2:', p1 + p2)
#     print('Різниця p1-p2:', p1 - p2)
#     print('Добуток p1*p2:', p1 * p2)
#     p = p1.deriv(2)
#     print('2 похідна р1:', p)

class Calculator:
    def __init__(self, master):
        self.root = master
        self.first = ""
        self.second = ""
        self.result = ""
        self.n = 0
        self._make_widgets()
        self._calculate()

    def _calculate(self):
        pass

    def _make_widgets(self):
        self._frame_top = Frame(self.root)

        self._lbl_n = Label(self._frame_top, text="Enter n:", font="Arial 16")
        self._lbl_n.pack(side = LEFT, padx = 5)
        self._entry_n = Entry(self._frame_top, width=7, justify='center', font="Arial 16", textvariable = self.n)
        self._entry_n.pack(side = RIGHT, padx = 5)
        self._frame_top.pack(side=TOP, fill=Y, expand=NO)
        self._btn_ok = Button(self.root, width=8, justify='center', text='Ok', command=self.ok_handler)
        self._btn_ok.pack(side=BOTTOM, padx=5, pady=5)

    def ok_handler(self, ev=None):
        self.n = int(self._entry_n.get())
        self._lbl_n.pack_forget()
        self._entry_n.pack_forget()
        self._btn_ok.pack_forget()
        if not self._entry_n.get():
            showwarning(message='Enter n!')
            return
        print("n: ", self.n)
        self._input_coefficients()

    def _input_coefficients(self):
        self.first = []
        for i in range(0, self.n + 1):
            self.first.append(self._input_one(i))
        self._frame_first_wrapper = Frame(self._frame_top)
        self._btn_f = Button(self._frame_first_wrapper, width=8, justify='center', text='Ok', command=self.ok_input())
        self._btn_f.pack(side=RIGHT, padx=5, pady=5)
        self._frame_first_wrapper.pack(side=TOP, fill=Y, expand=NO)

    def _input_one(self, i):
        self._frame_first = Frame(self._frame_top)
        self._lbl_first = Label(self._frame_first, text='*x**' + str(i), font="Arial 16")
        self._lbl_first.pack(side=RIGHT, padx=5)
        self._entry_first = Entry(self._frame_first, width=3, justify='center', font="Arial 16", textvariable="")
        self._entry_first.pack(side=LEFT, padx=5)
        self._frame_first.pack(side=LEFT, fill=Y, expand=NO)

    def ok_input(self):
        result = self._entry_first.get()
        if result:
            self._frame_first.pack_forget()
            self._lbl_first.pack_forget()
            self._entry_first.pack_forget()
            self._frame_top.pack_forget()
        return result

def main():
    top = Tk()
    d = Calculator(top)
    mainloop()
    # val = d.get()

if __name__ == '__main__':
    main()


import sys

# Class used for building NFAs, starting from the base cases
class NFA:
    def __init__(self, exp):

        # Build the generic NFA for a variable
        if isinstance(exp, Var):

            self.alphabet = []
            self.alphabet.append(exp.var)

            self.initialState = 0
            self.finalState = 1

            self.states = []
            self.states.append(self.initialState)
            self.states.append(self.finalState)

            self.delta_function = {}
            self.delta_function[(0, exp.var)] = 1

        # Build the generic NFA for concatenation
        if isinstance(exp, Concat):
            nfa1 = exp.expression1
            nfa2 = exp.expression2

            self.alphabet = []
            self.states = []

            # Renumber staes for the second NFA (which will directly connect to the first one)
            nfa2StatesBackup = nfa2.states.copy()

            for i in range(len(nfa2StatesBackup)):
                nfa2StatesBackup[i] = len(nfa1.states) + i

            # Add states for new NFA in order
            for x in nfa1.states:
                self.states.append(x)

            for x in nfa2StatesBackup:
                self.states.append(x)

            # Add the alphabet for the new NFA
            for x in nfa1.alphabet:
                self.alphabet.append(x)

            for x in nfa2.alphabet:
                self.alphabet.append(x)

            # Check for any possible duplicate letters
            self.alphabet = list(dict.fromkeys(self.alphabet))

            # The initial state of the resulting NFA will automatically
            # be the initial state of the first NFA, while the final state
            # will be the final state of the second NFA
            self.initialState = nfa1.initialState
            self.finalState = nfa2StatesBackup[-1]

            # Compute the new delta function
            newNFA2Dict = {}

            count = 1
            for x in nfa2.delta_function:
                newNFA2Dict[(x[0] + len(nfa1.states), x[1])] = nfa2.delta_function[x] + len(nfa1.states)
                count = count + 1

            self.delta_function = {}
            self.delta_function.update(nfa1.delta_function)

            # Add an epsilon transition to unite both NFAs
            self.delta_function[(nfa1.finalState, "epsilon")] = nfa2StatesBackup[0]
            self.delta_function.update(newNFA2Dict)

        # Build the generic NFA for Kleene star
        if isinstance(exp, Star):

            nfa = exp.expression

            self.alphabet = []
            self.states = []

            # For Kleene star, we keep the same alpahbet
            self.alphabet = nfa.alphabet

            nfaStatesBackup = nfa.states.copy()

            # Renumber states for the new NFA
            for i in range(len(nfaStatesBackup)):
                nfaStatesBackup[i] += 1

            # Our input NFA will receive two new states that connect to
            # the initial state of the input NFA, as well as the final state
            self.initialState = nfaStatesBackup[0] - 1
            self.finalState = nfaStatesBackup[-1] + 1
            self.states.append(self.initialState)

            for x in nfaStatesBackup:
                self.states.append(x)

            self.states.append(self.finalState)

            # Compute the new delta function
            newDeltaFunction = {}

            for x in nfa.delta_function:
                newDeltaFunction[(x[0] + 1, x[1])] = nfa.delta_function[x] + 1

            self.delta_function = {}

            # We will add epsilon transitions according to the base case of a star NFA:
            # * One from the new initial state to the previous initial state
            # * One from the new initial state to the new final state
            # * One from the previous final state to the new final state
            # * One from the previous final state to the previous initial state
            self.delta_function[(self.initialState, "epsilon1")] = nfaStatesBackup[0]
            self.delta_function[(self.initialState, "epsilon2")] = self.finalState
            self.delta_function[(nfaStatesBackup[-1], "epsilon3")] = self.finalState
            self.delta_function[(nfaStatesBackup[-1], "epsilon4")] = nfaStatesBackup[0]
            self.delta_function.update(newDeltaFunction)

        # Build the generic NFA for plus
        if isinstance(exp, Plus):

            currentNFA = exp.expression

            # For plus, we just convert the input NFA to one of this form:
            # Plus(NFA) = Concat(NFA, Star(NFA))
            # There is no need to calculate plus as a standalone NFA
            newDFA = NFA(Concat(currentNFA, NFA(Star(currentNFA))))

            self.alphabet = newDFA.alphabet
            self.states = newDFA.states
            self.delta_function = newDFA.delta_function
            self.initialState = newDFA.initialState
            self.finalState = newDFA.finalState

        # Build the generic NFA for union
        if isinstance(exp, Union):
            nfa1 = exp.expression1
            nfa2 = exp.expression2

            self.alphabet = []
            self.states = []
            self.delta_function = {}

            # Compute the alphabet for the new NFA
            for x in nfa1.alphabet:
                self.alphabet.append(x)

            for x in nfa2.alphabet:
                self.alphabet.append(x)

            # Check for any possible duplicate letters
            self.alphabet = list(dict.fromkeys(self.alphabet))

            # Renumber the states of the input NFA according to this rule:

            # * The first input NFA will have its states renumbered by 1
            # (in order to connect seamlessly to the new state)

            # * The second input NFA will have its states renumbered after the first
            # input NFA and the final state will in this way become the second to last
            # state before the new final state
            nfa1StatesBackup = nfa1.states.copy()

            for i in range(len(nfa1StatesBackup)):
                nfa1StatesBackup[i] += 1

            self.initialState = nfa1StatesBackup[0] - 1

            self.states.append(self.initialState)

            for x in nfa1StatesBackup:
                self.states.append(x)

            nfa2StatesBackup = nfa2.states.copy()

            for i in range(len(nfa2StatesBackup)):
                nfa2StatesBackup[i] = len(nfa1.states) + i + 1

            for x in nfa2StatesBackup:
                self.states.append(x)

            self.finalState = nfa2StatesBackup[-1] + 1
            self.states.append(self.finalState)

            # Compute the new delta function of the NFA

            # We will add epsilon transitions according to the base case of am union NFA:
            # * One from the new initial state to the previous initial states of our input NFAS
            # * One from the previous final states of our input NFAs to the new final state
            self.delta_function[(self.initialState, "epsilon1")] = nfa1StatesBackup[0]
            self.delta_function[(self.initialState, "epsilon2")] = nfa2StatesBackup[0]
            self.delta_function[(nfa1StatesBackup[-1], "epsilon1")] = self.finalState
            self.delta_function[(nfa2StatesBackup[-1], "epsilon2")] = self.finalState

            # Compute the rest of the new delta function of the NFA
            newNFA1DeltaFunction = {}

            for x in nfa1.delta_function:
                newNFA1DeltaFunction[(x[0] + 1, x[1])] = nfa1.delta_function[x] + 1

            self.delta_function.update(newNFA1DeltaFunction)

            newNFA2DeltaFunction = {}

            for x in nfa2.delta_function:
                newNFA2DeltaFunction[(x[0] + len(nfa1.states) + 1, x[1])] = nfa2.delta_function[x] + len(nfa1.states) + 1

            self.delta_function.update(newNFA2DeltaFunction)

    def __str__(self):
        return f"alphabet: {self.alphabet} \n" \
               f"states: {self.states} \n" \
               f"initialState: {self.initialState} \n" \
               f"finalState: {self.finalState} \n" \
               f"deltafunction: {self.delta_function}"

# Class used for parsing a generic prenex expresssion into regex form
class Expr:
    def __init__(self, string):
        self.expression = string

# Class used for parsing the prenex form of a variable into regex form
class Var(Expr):
    def __init__(self, string):
        self.var = string

    def __str__(self):
        return self.var

# Class used for parsing the prenex form of Kleene star into regex form
class Star(Expr):
    def __init__(self, string):
        super().__init__(string)

    def __str__(self):
        return f"Star({self.expression})"

# Class used for parsing the prenex form of plus into regex form
class Plus(Expr):
    def __init__(self, string):
        super().__init__(string)

    def __str__(self):
        return f"Plus({self.expression})"

# Class used for parsing the prenex form of concatenation into regex form
class Concat(Expr):
    def __init__(self, string1, string2):
        self.expression1 = string1
        self.expression2 = string2

    def __str__(self):
        return f"Concat({self.expression1}, {self.expression2})"

# Class used for parsing the prenex form of union into regex form
class Union(Expr):
    def __init__(self, string1, string2):
        self.expression1 = string1
        self.expression2 = string2

    def __str__(self):
        return f"Union({self.expression1}, {self.expression2})"

# Function used when parsing prenex to regex form
def checkExpression(expr):

    # If current operator has both of its members filled
    if isinstance(expr, Concat) or isinstance(expr, Union):
        if expr.expression1 != "?" and expr.expression2 != "?":
            return True

        else:
            return False

    # If current operator has its member filled
    if isinstance(expr, Star) or isinstance(expr, Plus):
        if expr.expression != "?":
            return True

        else:
            return False

# Function used for converting the input to a regex
def parse(string):
    stack = []
    alphabet = []

    # Will be used to determine the order in which we build our NFA
    stackOrder = []

    # Append to a stack all the operations that occur in order (important for later)
    while string:

        # If we encounter a new Concat, add it to stack with no members (no members = ?)
        if string.startswith('CONCAT '):
            string = string[len('CONCAT '):]
            stack.append(Concat("?", "?"))

        # If we encounter a new Kleene Star, add it to stack with no members (no members = ?)
        elif string.startswith('STAR '):
            string = string[len('STAR '):]
            stack.append(Star("?"))

        # If we encounter a new Plus, add it to stack with no members (no members = ?)
        elif string.startswith('PLUS '):
            string = string[len('PLUS '):]
            stack.append(Plus("?"))

        # If we encounter a new Union, add it to stack with no members (no members = ?)
        elif string.startswith('UNION '):
            string = string[len('UNION '):]
            stack.append(Union("?", "?"))

        # If we encounter something else, it is a variable
        else:
            alphabet.append(string[0])

            variable = Var(string[0])
            ok = 0
            stack.append(variable)

            # Check if before this variable we had operators, in order to add this variable as a member
            # to one of the operators
            if len(stack) > 1:

                # If we had an Union or a Concat check if we should add the variable
                # as left or right member
                if isinstance(stack[-2], Union) or isinstance(stack[-2], Concat):
                    if stack[-2].expression1 == "?":
                        stack[-2].expression1 = variable

                        # Add variable to the order of steps for building NFA
                        stackOrder.append(stack[-2].expression1)
                        ok = 1

                    elif stack[-2].expression2 == "?":
                        stack[-2].expression2 = variable

                        # Add variable to the order of steps for building NFA
                        stackOrder.append(stack[-2].expression2)
                        ok = 1

                # If we had a Kleene star or a Plus, just check if its available member slot is free
                if isinstance(stack[-2], Star) or isinstance(stack[-2], Plus):

                    if stack[-2].expression == "?":
                        stack[-2].expression = variable

                        # Add variable to the order of steps for building NFA
                        stackOrder.append(stack[-2].expression)
                        ok = 1

            # If we successfully added the variable to an operator, remove it from the stack
            if ok == 1:
                stack.pop()

            # After inserting the current variable, check if an operator has been filled
            # and the member/members are in place (there are no "?" marks around)
            while len(stack) > 1 and checkExpression(stack[-1]) == True:

                # If our filled operator is an Union or a Concat
                if isinstance(stack[-1], Union) or isinstance(stack[-1], Concat):

                    # If the operator before it is a Star or a Plus and hasn't been filled
                    # add current operator to it
                    if isinstance(stack[-2], Star) or isinstance(stack[-2], Plus):
                        stack[-2].expression = stack[-1]

                        # Add operator to the order of steps for building NFA
                        stackOrder.append(stack[-2].expression)
                        stack.pop()
                        if len(stack) == 1:
                            break

                    # If the operator before it is an Union or a Concat and hasn't been filled
                    # add current operator to it
                    if isinstance(stack[-2], Union) or isinstance(stack[-2], Concat):

                        # Check if we should add operator as either left or right member
                        if stack[-2].expression1 == "?":
                            stack[-2].expression1 = stack[-1]

                            # Add operator to the order of steps for building NFA
                            stackOrder.append(stack[-2].expression1)
                            stack.pop()
                            if len(stack) == 1:
                                break

                        else:
                            stack[-2].expression2 = stack[-1]

                            # Add operator to the order of steps for building NFA
                            stackOrder.append(stack[-2].expression2)
                            stack.pop()
                            if len(stack) == 1:
                                break

                # If our filled operator is a Kleene star or a Plus
                if isinstance(stack[-1], Star) or isinstance(stack[-1], Plus):

                    # If the operator before it is a Star or a Plus and hasn't been filled
                    # add current operator to it
                    if isinstance(stack[-2], Star) or isinstance(stack[-2], Plus):
                        stack[-2].expression = stack[-1]

                        # Add operator to the order of steps for building NFA
                        stackOrder.append(stack[-2].expression)
                        stack.pop()
                        if len(stack) == 1:
                            break

                    # If the operator before it is an Union or a Concat and hasn't been filled
                    # add current operator to it
                    if isinstance(stack[-2], Union) or isinstance(stack[-2], Concat):

                        # Check if we should add operator as either left or right member
                        if stack[-2].expression1 == "?":
                            stack[-2].expression1 = stack[-1]

                            # Add operator to the order of steps for building NFA
                            stackOrder.append(stack[-2].expression1)
                            stack.pop()
                            if len(stack) == 1:
                                break

                        else:
                            stack[-2].expression2 = stack[-1]

                            # Add operator to the order of steps for building NFA
                            stackOrder.append(stack[-2].expression2)
                            stack.pop()
                            if len(stack) == 1:
                                break

            # Cut currently parsed element from the main string
            if len(string) > 1:
                string = string[len(variable.var) + 1:]

            else:
                string = ""

    # Now we have the order of steps (or order of NFAs we should build) to reach
    # the fully converted NFA in a stack
    stackOrder.append(stack[0])

    return stackOrder

# Function that receives the stack with the steps required to
# build the full NFA of our regex
def regexToNFA(stackOrder):

    # For each step in the stack we build a NFA that will be used to build
    # the next NFA in the stack and so on, till we get the final NFA of our regex
    currentNFAs = []

    # We will process all steps individually till our stack is empty
    while len(stackOrder) > 0:

        for i in range(len(stackOrder)):

            # If the current step is a variable, build the NFA for it
            if isinstance(stackOrder[i], Var):

                currentNFAs.append(NFA(stackOrder[i]))

                # If our regex is just a letter, that's all we have to do
                if len(stackOrder) == 1:
                    del stackOrder[i]

            # If our current step is concatenation, we build its NFA based on the
            # previously two computed NFAs, which will become its members
            elif isinstance(stackOrder[i], Concat):
                currentNFAs.append(NFA(Concat(currentNFAs[-2], currentNFAs[-1])))

                # After the computation, we no longer need the NFAs for the members
                # (a better NFA has taken their place)
                del currentNFAs[-2]
                del currentNFAs[-2]

                # Also delete all steps from stack from beginning to this one
                # to avoid unwanted results
                stackOrder = stackOrder[i + 1:]
                break

            # If our current step is union, we build its NFA based on the
            # previously two computed NFAs, which will become its members
            elif isinstance(stackOrder[i], Union):
                currentNFAs.append(NFA(Union(currentNFAs[-2], currentNFAs[-1])))

                # After the computation, we no longer need the NFAs for the members
                # (a better NFA has taken their place)
                del currentNFAs[-2]
                del currentNFAs[-2]

                # Also delete all steps from stack from beginning to this one
                # to avoid unwanted results
                stackOrder = stackOrder[i + 1:]
                break

            # If our current step is Kleene star, we build its NFA based on the
            # previously computed NFA, which will become its member
            elif isinstance(stackOrder[i], Star):
                currentNFAs.append(NFA(Star(currentNFAs[-1])))

                # After the computation, we no longer need the NFA for the member
                # (a better NFA has taken its place)
                del currentNFAs[-2]

                # Also delete all steps from stack from beginning to this one
                # to avoid unwanted results
                stackOrder = stackOrder[i + 1:]
                break

            # If our current step is plus, we build its NFA based on the
            # previously computed NFA, which will become its member
            elif isinstance(stackOrder[i], Plus):
                currentNFAs.append(NFA(Plus(currentNFAs[-1])))

                # After the computation, we no longer need the NFA for the member
                # (a better NFA has taken its place)
                del currentNFAs[-2]

                # Also delete all steps from stack from beginning to this one
                # to avoid unwanted results
                stackOrder = stackOrder[i + 1:]
                break

    # At the end, our list of processed NFAs will only contain the final, desirable NFA
    return currentNFAs[0]

# Function used for computing the epsilon closures of our NFA
def getEpsilonClosures(epsilonClosures, myNFA):

    # Add the current state as a member of its epsilon closure
    for x in myNFA.states:
        epsilonClosures[x] = []
        epsilonClosures[x].append(x)

    # Add the epsilon transitions that are directly connected to the current state
    for x in myNFA.states:
        for y in myNFA.delta_function:
            if x == y[0] and y[1].startswith("epsilon"):
                epsilonClosures[x].append(myNFA.delta_function[y])

    # Check if the state at the end of an epsilon transition has further
    # epsilon transitions
    for x in epsilonClosures:

        # If the list of epsilon closures for the current state is greater
        # than one, then for sure it has multiple epsilon transitions
        if len(epsilonClosures[x]) > 1:
            visited = []
            for i in range(len(myNFA.states)):
                visited.append(0)

            # We will keep looking for all epsilon closures for the current state
            searchFurtherClosures = epsilonClosures[x][1:]

            while len(searchFurtherClosures) > 0:

                # If we find additional lists of closures greater than one
                # we continue to search for more epsilon closures
                for i in range(len(searchFurtherClosures)):
                    if len(epsilonClosures[searchFurtherClosures[i]]) > 1:

                        # Add currently found closure to the total of closures of current state
                        epsilonClosures[x] = epsilonClosures[x] + epsilonClosures[searchFurtherClosures[i]]

                        # Mark current closure for this state as visited in case we will reach
                        # a loop later on
                        visited[searchFurtherClosures[i]] = 1
                        epsilonClosures[x] = list(dict.fromkeys(epsilonClosures[x]))

                        # Sort closures so we won't get duplicate states when trying to
                        # build the DFA
                        epsilonClosures[x] = sorted(epsilonClosures[x])
                        checkClosure = epsilonClosures[searchFurtherClosures[i]].copy()
                        checkClosure = checkClosure[1:]
                        nextClosure = []

                        # Only check the closures for the newly found state if they weren't
                        # already visited (to avoid loops)
                        for j in range(len(checkClosure)):
                            if visited[checkClosure[j]] == 1:
                                continue
                            else:
                                nextClosure.append(checkClosure[j])

                        # Keep on finding closures till our stack is empty
                        del searchFurtherClosures[i]
                        searchFurtherClosures = searchFurtherClosures + nextClosure
                        break
                    else:
                        del searchFurtherClosures[i]
                        break

    return epsilonClosures

# Function used for converting one list of epsilon closures
# to a DFA state
def convertListToString(list):

    word = ""
    for x in list:
        word = word + str(x)

    return word

# Function used for reading the inputs
def read_file(filename):
    file = open(filename, "r")
    input_as_strings = file.read()
    file.close()
    return input_as_strings

# Function used for writing final results
def write_file(filename, string):
    file = open(filename, "w")
    file.write(string)
    file.close()

# Main implementation of getting the desired DFA using the functions described above
if __name__ == '__main__':

    # Get required parameters for the checker
    args = sys.argv[1:]
    finput = args[0]
    foutput = args[1]

    # Read prenex form expression
    regular_expr = read_file(finput)

    # Convert it to an oop regex
    operators = parse(regular_expr)

    # Convert that regex to a NFA
    myNFA = regexToNFA(operators)

    # Determine epsilon closures for our NFA
    epsilonClosures = {}
    epsilonClosures = getEpsilonClosures(epsilonClosures, myNFA)

    dfaDelta = {}

    # The order in which we encounter new states will determine
    # how we number the states for our DFA
    dfaIndexes = []
    finalStates = []

    # The initial state of our DFA will be the concatenation
    # of states from the epsilon closure of the initial state of the NFA
    initialState = epsilonClosures[0]
    initialDFAStates = []
    initialDFAStates.append(initialState)

    state = ""
    processed = []

    # Process all possible linking states till all of them have a connection
    # to other states and we no longer have to analyse any of them
    while len(initialDFAStates) > 0:

        # Mark newly found state and add it in order
        # as a new state for our DFA
        for x in initialDFAStates[0]:
            state = state + str(x)

        if state not in dfaIndexes:
            dfaIndexes.append(state)

        state = ""

        # A new DFA state will be built upon the concatenation
        # of multiple NFA states

        # Check if those concatenated states go somewhere else when receiving
        # a letter from our alphabet
        for x in myNFA.alphabet:
            count = 0
            for y in initialDFAStates[0]:

                # If a final state from our NFA is found in the concatenation of states
                # then it means we found a new final state for our DFA
                if y == myNFA.finalState:
                    finalStates.append(convertListToString(initialDFAStates[0]))

                # If we find a path from one of our states when receiving a letter
                # add the connection in the delta function of our DFA
                if (y, x) in myNFA.delta_function:

                    # Check if we hadn't processed this state already (to avoid loops)
                    if epsilonClosures[myNFA.delta_function[(y, x)]] not in processed:
                        initialDFAStates.append(epsilonClosures[myNFA.delta_function[(y, x)]])
                    dfaDelta[(convertListToString(initialDFAStates[0]), x)] = convertListToString(epsilonClosures[myNFA.delta_function[(y, x)]])

                # If we haven't found a path, remember how many states didn't accept that letter
                else:
                    count += 1

            # If all states from our concatenation didn't accept that letter
            # mark this state as a sink one
            if count == len(initialDFAStates[0]):
                dfaDelta[(convertListToString(initialDFAStates[0]), x)] = "sink"

        # Mark recently processed state to avoid duplicate analysis
        processed.append(initialDFAStates[0])

        # Continue to process other remaining states
        initialDFAStates = initialDFAStates[1:]

    # Add all sink to sink transitions to our delta function
    for x in myNFA.alphabet:
        dfaDelta[("sink", x)] = "sink"
    dfaIndexes.append("sink")

    # Get final states for the new DFA
    finalStates = list(dict.fromkeys(finalStates))

    for i in range(len(finalStates)):
        finalStates[i] = dfaIndexes.index(finalStates[i])

    # Renumber states in delta function so that they are in order
    newDFADelta = {}

    for x in dfaDelta:
        newDFADelta[(dfaIndexes.index(x[0]), x[1])] = dfaIndexes.index(dfaDelta[x])

    dfaDelta = newDFADelta

    # Write final results according to ref files
    finalResult = ""
    for x in myNFA.alphabet:
        finalResult = finalResult + x
    finalResult = finalResult + "\n"
    finalResult = finalResult + str(len(dfaIndexes))
    finalResult = finalResult + "\n"
    finalResult = finalResult + str(dfaIndexes.index(dfaIndexes[0]))
    finalResult = finalResult + "\n"
    for i in range(len(finalStates)):
        if i == len(finalStates) - 1:
            finalResult = finalResult + str(finalStates[i]) + "\n"
        else:
            finalResult = finalResult + str(finalStates[i]) + " "

    idx = 0
    for x in dfaDelta:
        if idx == len(dfaDelta) - 1:
            finalResult = finalResult + str(x[0]) + "," + "'" + x[1] + "'" + "," + str(dfaDelta[x])
        else:
            finalResult = finalResult + str(x[0]) + "," + "'" + x[1] + "'" + "," + str(dfaDelta[x]) + "\n"
            idx += 1

    write_file(foutput, finalResult)

3rd Year/Formal Languages and Automata/Project/Phase 2/main.py