from cuwo.types import AttributeSet, AttributeDict
import collections
import sys
import inspect

class InvalidPlayer(Exception):
    pass

class InsufficientRights(Exception):
    pass

def get_player(server, value):
    ret = None
    players = server.players
    try:
        if value.startswith('#'):
            value = int(value[1:])
            return players[value]
        try:
            return players[value]
        except KeyError:
            pass
        value = value.lower()
        for player in players.values():
            name = player.name.lower()
            if name == value:
                return player
            if name.count(value):
                ret = player
    except (KeyError, IndexError, ValueError):
        pass
    if ret is None:
        raise InvalidPlayer()
    return ret

# command decorators/class implementation

class Command:
    def __init__(self, func):
        self.func = func
        self.base = base = get_command_base(func)
        self.name = base.__name__
        self.module = base.__module__
        self.user_types = getattr(base, 'user_types', None)
        self.doc = base.__doc__
        self.__call__ = func

        # parse function object information

        # get min args
        func_info = inspect.getargspec(base)
        self.min_args = len(func_info.args) - 1
        if func_info.varargs:
            self.max_args = None
        else:
            self.max_args = self.min_args
        if func_info.defaults is not None:
            self.min_args -= len(func_info.defaults)

    def __call__(self, *arg, **kw):
        return self.func(*arg, **kw)

    def is_compatible(self, rights):
        if self.user_types is None:
            return True
        return not rights.isdisjoint(self.user_types)

    def get_help(self):
        syntax = self.get_syntax()
        if self.doc is None:
            return syntax
        return "%s\n%s" % (self.doc, syntax)

    def get_syntax(self):
        func_info = inspect.getargspec(self.base)
        has_defaults = func_info.defaults is not None
        if has_defaults:
            defaults_start = len(func_info.args) - len(func_info.defaults)
        arguments = [self.name]
        for i in range(1, len(func_info.args)):
            argument = func_info.args[i]
            if not has_defaults:
                arguments.append(argument)
                continue
            defaults_index = i - defaults_start
            if defaults_index >= 0:
                default = func_info.defaults[defaults_index]
                if default is None:
                    arguments.append('[%s]' % argument)
                else:
                    arguments.append('[%s=%s]' % (argument, default))
                continue
            arguments.append(argument)
        if func_info.varargs is not None:
            arguments.append('[%s]' % func_info.varargs)
        return 'Syntax: /' + ' '.join(arguments)

def get_command_base(func):
    return getattr(func, 'func', func)

def set_command_base(new_func, func):
    new_func.func = func

def command(func, klass=None):
    command = Command(func)
    if klass is None:
        klass = sys.modules[command.module].get_class()
    if klass.commands is None:
        klass.commands = {}
        klass.aliases = {}
    klass.commands[command.name] = command

    base = get_command_base(func)
    for alias in getattr(base, 'aliases', ()):
        klass.aliases[alias] = command.name
    return func

def alias(*aliases):
    """Aliases the command to additional names."""
    def dec(func):
        base = get_command_base(func)
        base.aliases = aliases
        return func
    return dec

def restrict(*user_types):
    """Restricts the command to certain user types."""
    def dec(func):
        def new_func(script, *arg, **kw):
            if script.connection.rights.isdisjoint(user_types):
                raise InsufficientRights()
            return func(script, *arg, **kw)
        base = get_command_base(func)
        base.user_types = user_types
        set_command_base(new_func, base)
        return new_func
    return dec

# decorator to restrict the use of commands to administrators only
admin = restrict('admin')

class ScriptManager:
    """Manages scripts for either a server or connection."""

    def __init__(self):
        self.items = collections.OrderedDict()
        self.cached_calls = {}

    def __getattr__(self, name):
        return self.items[name]

    def __getitem__(self, name):
        return self.items[name]

    def __contains__(self, name):
        return name in self.items

    def add(self, script):
        self.items[script.script_name] = script
        self.cached_calls.clear()

    def remove(self, script):
        del self.items[script.script_name]
        self.cached_calls.clear()

    def unload(self):
        for script in self.items.copy().values():
            script.unload()

    def get(self):
        return self.items.values()

    def call(self, event_name, **kw):
        try:
            handlers = self.cached_calls[event_name]
        except KeyError:
            handlers = []
            for script in self.items.values():
                f = getattr(script, event_name, None)
                if not f:
                    continue
                handlers.append(f)
            self.cached_calls[event_name] = handlers

        event = AttributeDict(kw)
        for handler in handlers:
            ret = handler(event)
            if ret is None:
                continue
            event.result = ret
            break
        else:
            event.result = None
        return event

class BaseScript:
    def call(self, event_name, **kw):
        event = AttributeDict(kw)
        f = getattr(self, event_name, None)
        if f is None:
            return
        event.result = f(event)
        return event

    def on_load(self):
        pass

    def on_unload(self):
        pass

    def unload(self):
        pass

class ConnectionScript(BaseScript):
    def __init__(self, parent, connection):
        self.script_name = parent.script_name

        self.parent = parent
        self.server = parent.server
        self.world = parent.world
        self.loop = connection.loop
        self.connection = connection
        connection.scripts.add(self)
        parent.children.append(self)
        self.on_load()

    def on_disconnect(self, event):
        self.unload()

    def on_command(self, event):
        ret = self.parent.call_command(self, event.command, event.args)
        if ret is None:
            return
        if ret:
            self.connection.send_chat(ret)
        return False

    def get_player(self, name=None):
        if name is None:
            return self.connection
        return get_player(self.server, name)

    def get_commands(self):
        rights = self.connection.rights
        for command in self.server.get_commands():
            if command.is_compatible(rights):
                yield command

    def get_command(self, name):
        command = self.server.get_command(name)
        if not command:
            return
        if not command.is_compatible(self.connection.rights):
            return
        return command

    def unload(self):
        if self.parent is None:
            return
        self.connection.scripts.remove(self)
        self.parent.children.remove(self)
        self.on_unload()
        self.parent = None
        self.connection = None
        self.server = None
        self.world = None

    @property
    def entity(self):
        return self.connection.entity

class ServerScript(BaseScript):
    connection_class = ConnectionScript
    commands = None
    aliases = None

    def __init__(self, server):
        self.script_name = self.__module__.split('.')[1]

        self.server = server
        self.world = server.world
        self.loop = server.loop
        server.scripts.add(self)
        self.children = []
        self.on_load()
        for connection in server.connections:
            self.call('on_existing_connection', connection=connection)

    def on_new_connection(self, event):
        if self.connection_class is None:
            return
        script = self.connection_class(self, event.connection)
        script.call('on_connect')

    def on_existing_connection(self, event):
        if self.connection_class is None:
            return
        self.connection_class(self, event.connection)

    def on_command(self, event):
        return self.call_command(event.user, event.command, event.args)

    def unload(self):
        if self.server is None:
            return
        self.on_unload()
        self.server.scripts.remove(self)
        for script in self.children[:]:
            script.unload()
        self.children = None
        self.server = None
        self.world = None

    def call_command(self, user, command, args):
        if self.commands is None:
            return
        command = command.lower()
        command = self.aliases.get(command, command)
        command = self.commands.get(command, None)
        if not command:
            return
        user.parent = self  # for ScriptInterface

        if len(args) < command.min_args:
            return command.get_syntax()
        if command.max_args is not None and len(args) > command.max_args:
            return command.get_syntax()

        try:
            ret = command(user, *args) or ''
        except InvalidPlayer:
            ret = 'Invalid player specified'
        except InsufficientRights:
            ret = 'Insufficient rights'
        except Exception:
            import traceback
            traceback.print_exc()
            ret = ''
        return ret

class ScriptInterface:
    """
    Used for external script interfaces to emulate a connection for e.g.
    console and IRC commands
    """

    def __init__(self, name, server, *rights):
        self.name = name
        self.rights = AttributeSet(rights)
        self.server = server
        self.connection = self
        self.parent = None  # set by call_command

    def get_player(self, name):
        if name is None:
            raise InvalidPlayer()
        return get_player(self.server, name)

    def get_commands(self):
        return self.server.get_commands()

    def get_command(self, name):
        return self.server.get_command(name)


####################### Import Packages ###################################
import simpy
import pandas as pd
import numpy
from random import randint
from tkinter import *

root = Tk()
root.geometry("400x500")
l0 = Label(root,text='Globale Einstellungen',background='grey', font = "Times")
varPassagieraufkommen = IntVar()
cPassagieraufkommen = Checkbutton(root, text='erhöhtes Passagieraufkommen an einigen Haltestellen',
                                  variable=varPassagieraufkommen)
varVerkehrsaufkommen = IntVar()
cVerkehrsaufkommen = Checkbutton(root, text='erhöhtes Verkehrsaufkommen an einigen Haltestellen',
                                  variable=varVerkehrsaufkommen)
varPufferzeit = IntVar()
cPufferzeit = Checkbutton(root, text='Pufferzeiten für Abbau von Verspätungen nutzen',
                                  variable=varPufferzeit)
l1 = Label(root,text='Verkehrslage',background='grey', font = "Times")
varUnfall = IntVar()
cUnfall = Checkbutton(root, text='Unfall nahe einer Haltestelle',
                      variable=varUnfall)
varBaustelle = IntVar()
cBaustelle = Checkbutton(root, text='Baustelle an bestimmter Haltestelle (hier: HS 29)',
                         variable=varBaustelle)
l2 = Label(root,text='Wetter',background='grey', font = "Times")
varSturm = IntVar()
cSturm = Checkbutton(root, text='An diesem Tag gibt es Sturm.',
                     variable=varSturm)
varRegen = IntVar()
cRegen = Checkbutton(root, text='An diesem Tag regnet es.',
                     variable=varRegen)
l3 = Label(root,text='Specials',background='grey', font = "Times")
varFahrzeugausfall = IntVar()
cFahrzeugausfall = Checkbutton(root, text='Fahrzeug fällt aus (1%)',
                               variable=varFahrzeugausfall)
button = Button(text = "Bestätigen", bg = "green", command = root.destroy)

l0.pack(fill=X, padx='20', pady='5')
cPassagieraufkommen.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
cVerkehrsaufkommen.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
cPufferzeit.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
l1.pack(fill=X, padx='20', pady='5')
cUnfall.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
cBaustelle.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
l2.pack(fill=X, padx='20', pady='5')
cSturm.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
cRegen.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
l3.pack(fill=X, padx='20', pady='5')
cFahrzeugausfall.pack(side='top', fill='x', padx='5', pady='5', anchor = "w")
button.pack(side='bottom', fill='y', padx='5',pady='10')

mainloop()

####################### Daten einlesen ####################################
df = pd.read_csv("/home/chris/PythonProjekte/SemProjekt-1920/tableFinal.txt", sep=";")
####################### Daten transformieren und neue Zeitspalten in Dataframe einfügen (Zeit) ########################
# Umrechnung der Start- & Endzeit in Minuten (für Simulationsuhr)
StartTime = []
count_row = df.shape[0]
for x in range(0, count_row):
    min_time = df.iloc[x, 5].split(":")
    minutes = int(min_time[1]) * 60
    minutes = minutes + int(min_time[2])
    StartTime.append(minutes)
EndTime = []
count_row = df.shape[0]
for x in range(0, count_row):
    min_time = df.iloc[x, 6].split(":")
    minutes = int(min_time[1]) * 60
    minutes = minutes + int(min_time[2])
    EndTime.append(minutes)
df["EndTime"] = EndTime
df["StartTime"] = StartTime

################################ Daten für Simulation erzeugen ##################################
# Gesamtanzahl an Fahrzeugen ermitteln
numberVeh = df["BlockID"].unique()
numberVeh = numberVeh.tolist()  # von Array in Liste formatieren
numberVeh = [elem for elem in numberVeh if elem >= 0]  # -1 entfernen
print("Die Gesamtanzahl von Fahrzeugen beträgt %d." % len(numberVeh))

# DepotID (jedem Fahrzeug die unique DepotID zuordnen)
DepotID = []
counter = 1
for i in range(1, len(numberVeh) + 1):
    for j in range(0, df.shape[0]):
        if df.BlockID[j] == i and counter == i:
            DepotID.append(df.DepotID[j])
            counter += 1
print("Es gibt %d verschiedene Depots." % (len(set(DepotID))))
print("Jedes Fahrzeug wurde einem Depot zugeordnet: %s." % (
        len(DepotID) == len(numberVeh)))

# StartTimes der einzelnen Fahrzeuge in jedem Teilumlauf (in Dictionary gespeichert)
DepotID_plusOne = [0] + DepotID  # DepotIDListe verlängern, damit Schleife mit i funktioniert
startTime_dic = {}
for i in range(1, len(numberVeh) + 1):
    startTimes_Block = []
    for j in range(len(df)):
        if df.BlockID[j] == i:
            if df.FromStopID[j] == DepotID_plusOne[i]:
                startTimes_Block.append(df.StartTime[j])
    startTimes_Block = startTimes_Block + [
        1440]  # Add to every list a 1440 as last element for simulation loop (timeout)
    startTime_dic.update(
        {(
                     i - 1): startTimes_Block})  # i-1 damit Index bei 0 anfängt (wichtig für Schleife (nachträgliche Ãnderung!)

StartTime_dic = startTime_dic

numTU_proF = []
for i in range(0, len(numberVeh)):
    numTU_proF.append(len(StartTime_dic[i]) - 1)
print("Die Fahrzeuge fahren im Schnitt %d Teilumläufe am Tag."
      " Das Maximum ist %d und das Minimum %d." % (sum(numTU_proF) / len(numTU_proF), max(numTU_proF), min(numTU_proF)))

# Listen von Haltestellen (from/to) (Liste mit vielen Listen)
FromStopID = []
ToStopID = []
for i in range(1, len(numberVeh) + 1):
    fromStopID_cache = []
    toStopID_cache = []
    for j in range(0, df.shape[0]):
        if df.BlockID[j] == i:
            fromStopID_one = df.FromStopID
            fromStopID_cache.append(fromStopID_one)
            toStopID_one = df.ToStopID
            toStopID_cache.append(toStopID_one)
    FromStopID.append(fromStopID_cache)
    ToStopID.append(toStopID_cache)

############ab hier Dictionaries erstellen #####################

DriveDuration_dic = {}
FromHS_dic = {}
ToHS_dic = {}
PartStartTime_dic = {}
PartEndTime_dic = {}
ElementID_dic = {}

for i in range(1, len(numberVeh) + 1):
    DifTime = []
    PartDif = []

    FromHS = []
    PartFromHS = []

    ToHS = []
    PartToHS = []

    StartTime = []
    PartStartTime = []

    EndTime = []
    PartEndTime = []

    Umlauf = []
    Teilumlauf = []

    for j in range(0, count_row):
        if df.BlockID[j] == i:

            difTime = df.EndTime[j] - df.StartTime[j]
            fromhs = df.FromStopID[j]
            tohs = df.ToStopID[j]
            stTime = df.StartTime[j]
            eTime = df.EndTime[j]
            elementID = df.ElementType[j]

            if df.ToStopID[j] == DepotID[i - 1]:
                PartDif.append(difTime)
                DifTime.append(PartDif)
                PartDif = []

                PartFromHS.append(fromhs)
                FromHS.append(PartFromHS)
                PartFromHS = []

                PartToHS.append(tohs)
                ToHS.append(PartToHS)
                PartToHS = []

                PartStartTime.append(stTime)
                StartTime.append(PartStartTime)
                PartStartTime = []

                PartEndTime.append(eTime)
                EndTime.append(PartEndTime)
                PartEndTime = []

                Teilumlauf.append(elementID)
                Umlauf.append(Teilumlauf)
                Teilumlauf = []

            else:
                PartDif.append(difTime)
                PartFromHS.append(fromhs)
                PartToHS.append(tohs)
                PartStartTime.append(stTime)
                PartEndTime.append(eTime)
                Teilumlauf.append(elementID)

    DriveDuration_dic.update({i - 1: DifTime})
    FromHS_dic.update({i - 1: FromHS})
    ToHS_dic.update({i - 1: ToHS})
    PartStartTime_dic.update({i - 1: StartTime})
    PartEndTime_dic.update({i - 1: EndTime})
    ElementID_dic.update({i - 1: Umlauf})

###########Funktion um random Haltestellen auszusuchen, an denen Stau entsteht############
##Berechnet Anzahl Haltestellen
numberHS = 0
for i in range(0, count_row):
    if df.FromStopID[i] > numberHS:
        numberHS = df.FromStopID[i]

##Berechnet, welche Haltestellen am meisten frequentiert sind
HScount = []
for j in range(0, numberHS):
    count = 0
    for i in range(0, count_row):
        if df.FromStopID[i] == j:
            count += 1
    HScount.append(count)

##für die Annahme, dass ein Stau eher im Zentrum ist (Annahme, dass Zentrum dort ist, wo eine Haltestelle stark befahren wird)
cumulativeHS = []
cumulative = 0
for j in range(0, len(HScount)):
    cumulative += HScount[j]
    cumulativeHS.append(cumulative)

##Random mit gewichteter Wahrscheinlichkeit 10 Haltestellen, an denen Stau entsteht
Jam = []
for i in range(0, 10):  ##Anzahl an Haltestellen mit Stau
    x = (randint(0, count_row))
    for j in range(0, len(cumulativeHS)):
        if x <= cumulativeHS[j]:
            Jam.append(j)
            break

############################## Funktionen für Objekt Vehicle #############################

# Abfrage: Fahrtzeit über Simulationsdauer
def drive_outOfTime(time, clock):
    doOT = time + clock > 1440
    return doOT

############################ Störgenerator##################################
# Ausmaß = Anteil an Fahrten, die von Störung betroffen sind
# delayonTop = Verspätung, die abhängig von Fahrtzeit on Top auf die Fahrtzeit raufkommt
def globalDisruption(driveduration, time):
    delay = 0
    delayType = ""
    if varPassagieraufkommen.get() == 1: #Passagieraufkommen
        ausmaß = 0.2
        delayonTop = 0.2
        coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
        if (coin == 1):
            delay += int(driveduration * delayonTop)
            delayType += "PA"
    if varVerkehrsaufkommen.get() == 1: #Verkehrsaufkommen
        if fromhs in Jam or tohs in Jam:
            if (time < 390) or (time > 1200): # Schwachverkehrszeiten
                ausmaß = 1
                delayonTop = 0
                coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
                if (coin == 1):
                    delay += int(driveduration * delayonTop)
                    delayType += ", VA(Schwach)"
            if (time > 510 and time < 870) or (time > 1110 and time <= 1200): #Normalverkehrzeiten
                ausmaß = 0.5
                delayonTop = 0.1
                coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
                if (coin == 1):
                    delay += int(driveduration * delayonTop)
                    delayType += ", VA(Normal)"
            if (time >= 390 and time <= 510) or (time >= 870 and time <= 1110): # Hauptverkehrszeiten
                ausmaß = 1
                delayonTop = 0.4
                coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
                if (coin == 1):
                    delay += int(driveduration * delayonTop)
                    delayType += ", VA(Haupt)"
    if varSturm.get() == 1: #Sturm
        ausmaß = 0.8 # Anteil an Fahrten, die von Störung betroffen sind
        delayonTop = 0.6 # Verspätung, die abhängig von Fahrtzeit on Top auf die Fahrtzeit raufkommt
        coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
        if (coin == 1):
            delay += int(driveduration * delayonTop)
            delayType += ", Sturm"
    if varRegen.get() == 1: #Regen
        ausmaß = 0.5
        delayonTop += 0.4
        coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
        if (coin == 1):
            delay += int(driveduration * delayonTop)
            delayType += ", Regen"
    if varFahrzeugausfall.get() == 1:
        ausmaß = 0.01
        delayonTop += 1440
        coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
        if (coin == 1):
            delay += int(driveduration * delayonTop)
            delayType += ", Fahrzeugausfall"
    return delay, delayType #Type der Störung bei Ausgabe angeben (durch Input Checkbox bestimmt)(Funktion immer dieselbe)

BaustelleanbestimmterHS = [29] # Eingabe von Benutzer nutzen
def selectionDisruption(fromhs, tohs, driveduration, time):
    delay = 0
    delayType = ""
    if varBaustelle.get() == 1:
        if fromhs in BaustelleanbestimmterHS or tohs in BaustelleanbestimmterHS:
            ausmaß = 1
            delayonTop = 1
            coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
            if (coin == 1):
                delay += int(driveduration * delayonTop)
                delayType += ", Baustelle"
    if varUnfall.get() == 1:
        ausmaß = 0.05
        delayonTop = 1
        coin = numpy.random.choice(numpy.arange(0, 2), p=[1 - ausmaß, ausmaß])
        if (coin == 1):
            delay += int(driveduration * delayonTop)
            delayType += ", Unfall"
    return delay, delayType  # Type der Störung bei Ausgabe angeben (durch Input Checkbox bestimmt)(Funktion immer dieselbe)

def breaktime(vehID, teilumlaufnummer, fahrtnummer, delayTime):
    if varPufferzeit.get() == 1:
        if ElementID_dic[vehID][teilumlaufnummer][fahrtnummer] == 9:
            DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer] = \
                DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer] - delayTime
            if DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer] < 0:
                delayTime = abs(DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer])
                DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer] = 0
            else:
                delayTime = 0
    return delayTime

############################## Daten für CSV-Datei ###############################
# Header für CSV-Datei
print(
    "vehID Teilumlaufnummer Standort Dep/Arr Uhrzeit(Soll) Uhrzeit(Ist) Fahrtverspätung Gesamtverspätung Verspätungsursache",
    file=open("Eventqueue5.3-Chris.txt", "a"))

########################## Objekt Vehicle #########################################
def vehicle(env, vehID):  # Eigenschaften von jedem Fahrzeug
    while True:
        for teilumlaufnummer in range(0, len(StartTime_dic) - 1):  # Loop der durch die einzelnen Teilumläufe führt
            try:
                if StartTime_dic[vehID][teilumlaufnummer] - env.now >= 0:
                    delayTime = 0
                    yield env.timeout(
                        StartTime_dic[vehID][teilumlaufnummer] - env.now)
                else:
                    yield env.timeout(0)
                    delayTime = env.now - StartTime_dic[vehID][teilumlaufnummer]

                umlaufstatus = 1  # Wenn Startzeit erreicht, Fahrzeug im Umlauf (umlaufstatus = 1)

                while umlaufstatus == 1:  # while Fahrzeug im Umlauf
                    for fahrtnummer in range(0, len(FromHS_dic[vehID][teilumlaufnummer])):

                        if ElementID_dic[vehID][teilumlaufnummer][fahrtnummer] == 9:
                            fahrtstatus = 2
                        else:
                            fahrtstatus = 0  # 0 = Abfahrt / 1 = Ankunft / 2 = Pause

                        delayTime_perDrive = 0  # für PrintAusgabe hier definiert
                        print(vehID + 1, teilumlaufnummer + 1, FromHS_dic[vehID][teilumlaufnummer][fahrtnummer],
                              fahrtstatus, PartStartTime_dic[vehID][teilumlaufnummer][fahrtnummer], env.now,
                              "-", delayTime, "-",
                              file=open("Eventqueue5.3-Chris.txt", "a"))

                        # Verspätung auf Fahrt ermitteln
                        delayType = ""
                        if ElementID_dic[vehID][teilumlaufnummer][fahrtnummer] == 9:
                            delayTime_perDrive = 0
                            delayType = "-"
                        else:
                            delayGlobal, delayTypeGlobal = globalDisruption(DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer],
                                                           env.now)
                            delaySelection, delayTypeSelection = selectionDisruption(
                                                                FromHS_dic[vehID][teilumlaufnummer][fahrtnummer],
                                                                ToHS_dic[vehID][teilumlaufnummer][fahrtnummer],
                                                                DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer],
                                                                env.now)

                            delayTime_perDrive = delayGlobal + delaySelection
                            delayType = delayTypeGlobal + " " + delayTypeSelection

                        # Aufsummieren der Verspätungen im Teilumlauf
                        delayTime += delayTime_perDrive

                        # Abfrage, ob Fahrt auÃerhalb der Simulationszeit liegen würde
                        if drive_outOfTime(
                                DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer], env.now):
                            yield env.timeout(1440)
                            break

                        # Abfrage, ob Pausenzeit & Verspätungszeit anpassen
                        delayTime = breaktime(vehID, teilumlaufnummer, fahrtnummer, delayTime)

                        # Timeout für Fahrtdauer zur nächsten Haltestelle
                        yield (
                            env.timeout(DriveDuration_dic[vehID][teilumlaufnummer][fahrtnummer] + delayTime_perDrive))

                        if ElementID_dic[vehID][teilumlaufnummer][fahrtnummer] == 9:
                            fahrtstatus = 2
                        else:
                            fahrtstatus = 1

                        # Abfrage ob Bus im Depot angekommen
                        if ToHS_dic[vehID][teilumlaufnummer][fahrtnummer] == DepotID[vehID]:
                            print(vehID + 1, teilumlaufnummer + 1, ToHS_dic[vehID][teilumlaufnummer][fahrtnummer],
                                  fahrtstatus, PartEndTime_dic[vehID][teilumlaufnummer][fahrtnummer],
                                  env.now, delayTime_perDrive, delayTime, delayType,
                                  file=open("Eventqueue5.3-Chris.txt", "a"))
                            umlaufstatus = 0
                        else:
                            print(vehID + 1, teilumlaufnummer + 1, ToHS_dic[vehID][teilumlaufnummer][fahrtnummer],
                                  fahrtstatus, PartEndTime_dic[vehID][teilumlaufnummer][fahrtnummer],
                                  env.now, delayTime_perDrive, delayTime, delayType,
                                  file=open("Eventqueue5.3-Chris.txt", "a"))

            except:
                if env.now >= 1440:  # to avoid RunTimeError: GeneratorExit
                    return False
                continue

            ########################## Simulationsumgebung ##############################

env = simpy.Environment()

# Initialisierung von Fahrzeugen
for i in range(0, 1):  # Anzahl von Fahrzeugen = len(numberVeh)
    env.process(vehicle(env, i))  # Inputdaten Eigenschaften Fahrzeugen
# Simulation starten und Laufzeit festlegen
env.run(until=1440)  # Ein Tag simulieren: in Minuten ausdrücken. 24h = 1440min


import requests
import socket
import atexit
import os
global server

user = "User:"
bot = "Bot:"
ENDPOINT = "http://127.0.0.1:5001"
conversation_history = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 12345))
def get_prompt(user_msg):
    return {
        "prompt": f"{user_msg}",
        "use_story": False,
        "use_memory": False,
        "use_authors_note": False,
        "use_world_info": False,
        "max_context_length": 2048,
        "max_length": 80,
        "rep_pen": 1.0,
        "rep_pen_range": 2048,
        "rep_pen_slope": 0.7,
        "temperature": 0.7,
        "tfs": 0.97,
        "top_a": 0.8,
        "top_k": 0,
        "top_p": 0.5,
        "typical": 0.19,
        "sampler_order": [6,0,1,3,4,2,5],
        "singleline": False,
        "sampler_seed": 69420, # Use specific seed for text generation?
        "sampler_full_determinism": False, # Always give same output with same settings?
        "frmttriminc": False, #Trim incomplete sentences
        "frmtrmblln": False, #Remove blank lines
        "stop_sequence": ["\n\n\n\n\n", f"{user}"]
        }
def handle_client(client_socket):
    try:
        client_socket.send(user.encode('utf-8'))
        while True:
            user_message = client_socket.recv(1024).decode('utf-8').strip()

            if len(user_message) < 1:
                bot_response = f"{bot}Please provide a valid input.\n"
            else:
                fullmsg = f"{conversation_history[-1] if conversation_history else ''}{user} {user_message}\n{bot} "
                prompt = get_prompt(fullmsg)
                response = requests.post(f"{ENDPOINT}/api/v1/generate", json=prompt)
                if response.status_code == 200:
                    results = response.json()['results']
                    text = results[0]['text']
                    response_text = text.split('\n')[0].replace("  ", " ")
                    conversation_history.append(f"{fullmsg}{response_text}\n")
                    bot_response = f"{bot} {response_text}\n"
                else:
                    bot_response = f"{bot} Unable to generate a response.\n"
            client_socket.send(bot_response.encode('utf-8'))
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        client_socket.close()
def main():
    os.system(f"clear")
    server.listen(5)
    print("Telnet server started. Listening for connections...")
    try:
        while True:
            client_socket, client_address = server.accept()
            print(f"Connection established with {client_address}")
            handle_client(client_socket)
    except KeyboardInterrupt:
        print("Server shutting down...")
        server.close()
def close_socket():
    server.close()
if __name__ == "__main__":
    atexit.register(close_socket)
    main()


import cv2
import tensorflow as tf
import numpy as np
from tensorflow import keras

facec = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')#replace with better classifer
model = keras.models.load_model('ACCURATEMODEL.hdf5')
font = cv2.FONT_HERSHEY_SIMPLEX

class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(0)

    def __del__(self):
        self.video.release()

    # returns camera frames along with bounding boxes and predictions
    def get_frame(self):
        _, fr = self.video.read()
        faces = facec.detectMultiScale(fr)

        for (x, y, w, h) in faces:
            fc = fr[y:y + h, x:x + w]
            roi = cv2.resize(fc, (224, 224))
            roi = tf.keras.applications.mobilenet.preprocess_input(roi)
            roi = np.expand_dims(roi, 0)
            pred = model.predict(roi)
            p = np.argmax(pred, 1)
            if p == 0:
                state = 'NOT DROWSY'
            if p == 1:
                state = "DROWSY"
            cv2.putText(fr, str(state), (x, y), font, 1, ((0,128,128)), 2)
            cv2.rectangle(fr, (x, y), (x + w, y + h), ((0,255,0)), 2)
        cv2.imshow('Stream', fr)
        cv2.waitKey(1)

vc = VideoCamera()
while True:
    vc.get_frame()


import csv
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_absolute_error, mean_squared_error

if __name__ == '__main__':
    train_data_name = 'train_data_regression.csv'
    test_data_name = 'test_data_regression.csv'
    train_data = np.genfromtxt(train_data_name, delimiter=',')

    feature_data = train_data[:, 1:-1]
    label_data = train_data[:, -1]

    train_features = feature_data[0:-200, :]
    train_labels = label_data[0:-200]
    val_features = feature_data[-200:, :]
    val_labels = label_data[-200:]

    regr = linear_model.LinearRegression()
    regr.fit(feature_data, label_data)
    #regr.fit(train_features, train_labels)
    #pred = regr.predict(val_features)
    #mae = mean_absolute_error(pred, val_labels)

    test_data = np.genfromtxt(test_data_name, delimiter=',')
    test_data = test_data[:, 1:]
    pred = regr.predict(test_data)
    print(pred)
    nums = np.arange(100)
    with open('submit.csv', mode='w') as submit:
        submit_writer = csv.writer(submit, delimiter=',')
        submit_writer.writerow(['', 'Predict'])
        for i in range(100):
            submit_writer.writerow(['%i' % i, '%f' % pred[i]])
        submit_writer.writerow([])


import json
import jsonschema
import random
from schema import schema
from multiprocessing import Process, Pipe
import pandas as pd
from pprint import pprint

def load_input(inp: str) -> dict:
    """The "setup" step for reading and validating input data.
    Input should be provided as JSON string following schema in schema.py

    Args:
        inp (str): JSON data

    Returns:
        dict: Parsed input data
    """
    print("Loading JSON data...")
    data = json.loads(inp)
    validate_input(data)
    print("Input is valid")
    return data

def validate_input(inp: dict) -> None:
    """Validates

    Args:
        inp (dict): JSON converted to dict

    Raises:
        e: raised if input is not matching the schema
    """
    try:
        jsonschema.validate(inp, schema=schema)
    except jsonschema.exceptions.ValidationError as e:
        raise e

def generate_rng_results(data: dict) -> list[dict]:
    """The "map" step, takes the input provided and returns generated results

    Args:
        data (dict): Input data, contains seed for random generator (random_seed),
            number of workers which should perform the task (n_workers), and number of samples
            to collect (n_sims).

    Returns:
        list[dict]: A list of two generated results, first: for each worker separately,
            second: for all workers cumulatively.
    """
    print("Assigning tasks to workers...")
    workers_occupancy = get_evenly_split_workers(data["n_sims"], data["n_workers"])
    results_workers, results_total = run_workers(workers_occupancy, data["random_seed"])
    print("Mapping finished")
    return [results_workers, results_total]

def rand_num_generator(seed: float):
    """Random number generator

    Args:
        seed (float): seed used by generator

    Yields:
        Iterator[float]: randomly generated number, from 0 to 1
    """
    random.seed(seed)
    while True:
        yield random.random()

def run_generator(connection, seed: float, n_sims: int):
    """Performs the simulation for a single worker and sends the results to the adult node

    Args:
        connection: Child of pipe connection for the computation process
        seed (float): seed used by generator
        n_sims (int): number of samples to collect
    """
    gen = rand_num_generator(seed)

    connection.send(pd.Series([next(gen) for _ in range(n_sims)]))
    connection.close()

def get_evenly_split_workers(n_sims: int, n_workers: int) -> list[int]:
    """
    Checks if n_sims is divisible by n_workers. If n_sims % n_workers == 0,
    then each worker can handle the same amount of simulations. If not,
    number of simulations is assigned to workers for the least difference between them.

    Example: n_sims = 11, n_workers = 3
    amount_1 = n_sims//n_workers = 3
    amount_2 = n_sims//n_workers + 1 = 4
    n_sims % n_workers == 2, which is the number of workers with amount_1
    the rest of the list is filled with amount_2
    therefore the resulting split is [4, 4, 3]

    Args:
        n_sims (int): total number of samples to collect
        n_workers (int): total number of workers

    Returns:
        list[int]: amount of samples to collect by each worker
    """
    if n_sims % n_workers == 0:
        worker_sims = [n_sims//n_workers for _ in range(n_workers)]
    else:
        worker_sims = []
        remainder = n_sims % n_workers
        for _ in range(remainder):
            worker_sims.append(n_sims//n_workers + 1)
        for _ in range(n_workers - remainder):
            worker_sims.append(n_sims//n_workers)
    return worker_sims

def run_workers(workers: list[int], seed: float) -> [pd.DataFrame, pd.DataFrame]:
    """Main process for running the computation. Creates separate processes for every worker.
    Every worker uses different seed, but for the same seed in input the results are deterministic.

    Args:
        workers (list[int]): amount of samples to collect by each worker
        seed (float): seed used by generators

    Returns:
        [pd.DataFrame, pd.DataFrame]: A list of two dataframes,
            first: all workers' results split into separate columns named worker_{i},
            second: all workers' results in a single column "Total".
    """
    processes = []
    parent_connections = []
    results, results_collective = pd.DataFrame(), pd.DataFrame()
    for i, worker in enumerate(workers):
        parent_conn, child_conn = Pipe()
        parent_connections.append(parent_conn)

        # increment the seed for each worker by 1, so the results are
        # deterministic, but each worker uses different seed to get different numbers
        process = Process(target=run_generator, args=(child_conn, seed+i, worker))
        processes.append(process)
    # starting, collecting and terminating processes
    for process in processes:
        process.start()
    for i, par_conn in enumerate(parent_connections):
        worker_res = par_conn.recv()
        results[f"worker_{i}"] = worker_res
        results_collective = pd.concat([results_collective, worker_res])
    for process in processes:
        process.join()

    results_collective.columns = ["Total"]

    return results, results_collective

def parse_results(data: dict, results: pd.DataFrame, results_collective: pd.DataFrame) -> str:
    """Save the results of computation into JSON summary in total and for each worker.

    Args:
        data (dict): input data, containing title of the summary and optional threshold field
        results (pd.DataFrame): all workers' results split into separate columns named worker_{i}
        results_collective (pd.DataFrame): all workers' results in a single column "Total"

    Returns:
        str: summary of calculations in JSON
    """
    summary = {"title": data["title"], "statistics": {}}
    stats = summary["statistics"]
    for res in results.columns:
        current_col = res
        stats[current_col] = reduce_col(results, current_col, data.get("threshold", 0))

    stats["Total"] = reduce_col(results_collective, "Total", data.get("threshold", 0))

    return json.dumps(summary)

def reduce_col(df: pd.DataFrame, colname: str, threshold: float) -> dict:
    """Generate statistics for calculations' results

    Args:
        df (pd.DataFrame): dataframe of calculations' results
        colname (str): name of the column to generate statistics for,
            either "worker_{i}" or "Total"
        threshold (float, optional): a limit for counting computed values
            greater or equal to threshold.
    Returns:
        dict: statistics for given column in dataframe
    """
    stats = {}
    stats["numof_samples"] = int(df[colname].count())
    stats["numof_samples_thresh"] = int(df[df[colname]>=threshold][colname].count())
    stats["max_result"] = float(df[colname].max())
    stats["min_result"] = float(df[colname].min())
    stats["median"] = float(df[colname].median())
    stats["count_distinct"] = int(df[colname].nunique())
    stats["sum"] = float(df[colname].sum())

    return stats

def full_computation(inp: str) -> dict:
    """Performs full computation in three steps:
    1. Setup - read input data, preparation.
    2. Map - generate random numbers.
    3. Reduce - provide summary statistics.

    Args:
        inp (str): JSON data

    Returns:
        dict: summar of calulations in JSON
    """
    inp_data = load_input(inp)
    results = generate_rng_results(inp_data)
    # results[0] - results per worker
    # results[1] - results collective
    return parse_results(inp_data, results[0], results[1])


import json
from django.shortcuts import render
from django.views.generic import TemplateView
import django.dispatch
from django.db import IntegrityError
from django.http import JsonResponse

from .websterapi import GetWordDefinition
from users.models import Word, Profile

class HomePageView(TemplateView):
    template_name = 'home.html'

    def request_to_history(self, user, word):
        check = Profile.objects.filter(user_id = user.id, history_id = word.id).exists()
        if not check:
            profile = Profile.objects.create(user_id = user.id, history_id = word.id)
            profile.save()

    def request_to_local_history(self, user, word):
        self.request_to_history(user, word)
        check = Profile.objects.filter(user_id = user.id, local_history_id = word.id).exists()
        if not check:
            profile = Profile.objects.create(user_id = user.id, local_history_id = word.id)
            profile.save()
            return True

    def handle_ajax_request(self, request):
        profile = Profile.objects.filter(user_id = request.user.id).exclude(local_history = None)
        word_list = []
        for entry in profile:
            word_list.append(str(entry.local_history))
        list_data_json = (list(word_list))

        data = {
            'words': list(word_list),
            }
        return JsonResponse(data, safe = False)

    def profile_check(self, request, word):
        word_check = Word.objects.get(word = word.lower())
        check = Profile.objects.filter(user_id = request.user.id, local_history_id = word_check.id).exists()
        return True if check else False

    def get(self, request, *args, **kwargs):
        if request.is_ajax():
            if 'to_local_history' in request.GET:
                word = request.GET.get('to_local_history')
                word_to_local_history = Word.objects.get(word = word.lower())
                if self.request_to_local_history(request.user, word_to_local_history):
                    data = {'word': word.lower()}
                    return JsonResponse(data, safe = False)
            elif 'delete' in request.GET:
                delete_request = request.GET.get('delete')
                delete_word = Word.objects.get(word = delete_request.lower())
                Profile.objects.get(user_id = request.user.id, history_id = delete_word.id).delete()
            else:
                return self.handle_ajax_request(request)
        if 'to_local_history' in request.GET:
            word = request.GET.get('to_local_history')
        else:
            word = request.GET.get('word')
        if word != None and word != '':
            result = GetWordDefinition(word).get_definition()
            if 'Error_links' in result:
                return(render(request, self.template_name, {'Error_links': result['Error_links'], 'search': word.capitalize()}))
            else:

                ### Saving new word to database

                try:
                    word_to_db = Word.objects.create(word = word.lower())
                    word_to_db.save()
                except IntegrityError as e:
                    print(f'Word "{word}" already exisits in db')

                ### Saving word to search history

                if request.user.add_all:
                    word_to_history = Word.objects.get(word = word.lower())
                    self.request_to_history(request.user, word_to_history)

                ### Check if already added

                added = self.profile_check(request, word)

                definition = result[0]
                if len(result) > 1:
                    general_info = result[1]
                else:
                    general_info = None
                return(render(request, self.template_name, {'definition': definition, 'general_info': general_info, 'search': word.capitalize(), 'added': added}))
        else:
            return(render(request, self.template_name))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
.. $Id$
"""

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

from zope import interface

from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary

from nti.schema.field import Bool
from nti.schema.field import List
from nti.schema.field import Text
from nti.schema.field import Choice
from nti.schema.field import Number
from nti.schema.field import Object
from nti.schema.field import HTTPURL
from nti.schema.field import DateTime
from nti.schema.field import TextLine
from nti.schema.field import ValidURI

class IRevClient(interface.Interface):
    """
    Handles Rev order operations.
    """

    def __init__(authorization):
        """
        Args:
            authorization (:obj:`IAuthorization`): The client and user API keys.

        """

    def upload_source_file(source_file_upload):
        """
        Upload an ISourceFileUpload to create a new ISourceFileInput to be used in an order.

        Args:
            source_file_upload (:obj:`ISourceFileUpload`): The source file to upload to be used in an order.

        Returns:
            (:obj:`ISourceFileInput`): The newly uploaded source file to be used in an order.

        Raises:
            UnsupportedContentType: If the content type of the media is not currently supported by Rev system.
            CouldNotRetrieveFile: If Rev could not retrieve the file from the specified location.
            InvalidMultipartRequest: If the multipart request did not contain exactly one file part or was otherwise malformed.
            UnspecifiedFilename: If the filename for the media was not specified explicitly and could not be determined automatically.
            UnspecifiedURL: If the URL for the media was not specified.

        """

    def submit_transcription_order(transcription_order_request):
        """
        Submit a new ITranscriptionOrder given an ITranscriptionOrderRequest.

        Args:
            transcription_order_request (:obj:`ITranscriptionOrderRequest`): The order request for a new transcription order.

        Returns:
            (:obj:`ITranscriptionOrder`): The newly created transcription order.

        Raises:
            MissingInputs: If the order request did not contain any input media.
            InvalidInput: If one of the input media URIs is invalid (e.g. does not identify valid uploaded media).
            MultipleServiceOptionsSpecified: If both transcription options and caption options are included in the request.
                Currently, an order can be made for only one of the two services Rev offers (transcription or caption).
            ServiceTypeNotSpecified: If transcription options for order are not specified.
            ExternalLinkAndURISpecified: If both external link and URI are set for input media.
            InputLocationNotSpecified: If neither external link or URI are set for input media.
            CannotConnectToExternalLink: If Rev cannot connect to external link provided.
            InvalidMediaLength: If input media length is not provided and Rev is unable to calculate it automatically
                or if input media length is not a positive integer.
            ReferenceNumberTooLong: If the reference number provided is longer than 256 characters.
            IneligibleForBalancePayments: If the user on whose behalf the order request was made is not eligible for paying using account balance.
            AccountBalanceLimitExceeded: If the order request specified payment using account balance but doing so would exceed the user's balance limit.
            FieldValidationErrors: If one or more of the fields are in the wrong format.

        """

    def submit_caption_order(caption_order_request):
        """
        Submit a new ICaptionOrder given an ICaptionOrderRequest.

        Args:
            caption_order_request (:obj:`ICaptionOrderRequest`): The order request for a new caption order.

        Returns:
            (:obj:`ICaptionOrder`): The newly created caption order.

        Raises:
            MissingInputs: If the order request did not contain any input media.
            InvalidInput: If one of the input media URIs is invalid (e.g. does not identify valid uploaded media).
            MultipleServiceOptionsSpecified: If both transcription options and caption options are included in the request.
                Currently, an order can be made for only one of the two services Rev offers (transcription or caption).
            ServiceTypeNotSpecified: If caption options for order are not specified.
            ExternalLinkAndURISpecified: If both external link and URI are set for input media.
            InputLocationNotSpecified: If neither external link or URI are set for input media.
            CannotConnectToExternalLink: If Rev cannot connect to external link provided.
            InvalidMediaLength: If input media length is not provided and Rev is unable to calculate it automatically
                or if input media length is not a positive integer.
            InvalidLanguageCode: If one or more of the provided language codes are invalid.
            IncompatibleLanguage: If some of the selected output file formats do not support one or more of the specified languages.
                For example, Scenarist (Scc), MacCaptions (Mcc) and CheetahCap (CAP) are incompatible with languages that use non-Latin alphabets.
            ReferenceNumberTooLong: If the reference number provided is longer than 256 characters.
            IneligibleForBalancePayments: If the user on whose behalf the order request was made is not eligible for paying using account balance.
            AccountBalanceLimitExceeded: If the order request specified payment using account balance but doing so would exceed the user's balance limit.
            FieldValidationErrors: If one or more of the fields are in the wrong format.

        """

    def get_order(ordernum):
        """
        Get the IOrder detailed information for the order with the given order number.

        Args:
            ordernum (str): The order number of the order to retrieve.

        Returns:
            (:obj:`IOrder`): The order details for the order with the given order number.

        Raises:
            NotFound: If the order with the given order number is not found or does not belong to the user.

        """

    def get_orders(pagenum=1, pageSize=25, orderNumber=None, referenceId=None):
        """
        Get the paged list IOrders for user, optionally getting orders with specific order number or reference ID.

        Args:
            pagenum (int, optional): The number of the page of orders to return. Defaults to page 1.
            pageSize (int, optional): The number of orders per page to return. Page size must be between 5 and 100.
                Defaults to 25 orders per page.
            orderNumber (str, optional): The order number of the order to retrieve.
                Must not be specified if clientRef is specified.
                Defaults to returning all orders.
            referenceId (str, optional): The reference ID as used in your application of the order to retrieve.
                Must not be specified if orderNumber is specified.
                Defaults to returning all orders.

        Returns:
            (:obj:`IOrders`): The list of orders for a user returned in a paged manner.
                The returned result will indicate the total number of orders, as well as number of orders per page and
                the number of orders in the requested page, which enables a client to iteratively retrieve all orders for the user if desired.
                The results are ordered in reverse chronological order by placed on date.

                Each order entity in the list contains summary information for the order - it omits comments and attachments.
                To get those, call get_order(ordernum) with the appropriate order number.

        Raises:
            OrderNumberAndReferenceIdSpecified: If both orderNumber and referenceId are specified.

        """

    def cancel_order(ordernum):
        """
        Cancel the IOrder with the given order number.

        Orders can only be cancelled if work on them has not begun yet.

        Args:
            ordernum (str): The order number of the order to be cancelled.

        Returns:
            bool: True if successful, False otherwise.

        Raises:
            NotFound: If the order with the given order number is not found.
            CancelForbidden: If the order cannot be cancelled because work on the order has already begun.

        """

    def get_attachment(attachment_id):
        """
        Get the IAttachment for the given attachment ID.

        Args:
            attachment_id (str): The ID of the attachment to retrieve.

        Returns:
            (:obj:`IAttachment`): The attachment with the given attachment ID.

        Raises:
            NotFound: If the attachment with the given attachment ID is not found.

        """

    def get_attachment_content(attachment_id, file_format):
        """
        Get the IAttachmentContent for the IAttachment with the given ID.

        Use this method to download either finished output file(s)
        (transcripts or captions, depending on the type of order you placed),
        or the source file(s) for an order.

        Args:
            attachment_id (str): The ID of the attachment for which to retrieve its content.
            file_format (str): The requested file format for the attachment content.
                Defaults to Microsoft Word (.docx) for transcripts.
                Defaults to SubRip (.srt) for captions.

        Returns:
            (:obj:`IAttachmentContent`): The content of the attachment with the given ID.

        Raises:
            NotFound: If the attachment with the given attachment ID is not found.
            UnsupportedFileFormat: If none of the requested representations are available for the attachments
                or the file format specified for a source file does not match the original format.

        """

class IClientAPIKey(interface.Interface):
    """
    A secret key specific to each partner that wishes to use the Rev API
    """

    client_API_key = TextLine(title=u'The client API key',
                              description=u"""This is a secret key specific to each partner
                              that wishes to use the Rev API.""",
                              required=True)

class IUserAPIKey(interface.Interface):
    """
    A secret key specific to a Rev user
    """

    user_API_key = TextLine(title=u'The user API key',
                            description=u"""This is a secret key specific to a Rev user,
                            which identifies the user account under whose privileges
                            the requested operation executes.""",
                            required=True)

class IAuthorization(IClientAPIKey, IUserAPIKey):
    """
    Security and authentication keys used to access the Rev API
    """

class ISourceFileUpload(interface.Interface):
    """
    Describes a media source file to be retrieved, uploaded, and used in an order.
    """

    content_type = TextLine(title=u'The content type of the media to be retrieved',
                            description=u"""If not specified, Rev will try to determine the content type
                            from the server response.""",
                            required=False)

    filename = TextLine(title=u'The filename for the media',
                        description=u"""If not specified, Rev will try to determine the filename
                        from the URL.""",
                        required=False)

    url = HTTPURL(title=u'The URL where the media can be retrieved',
                  description=u"""The URL must be publicly accessible.
                  HTTPS URLs are ok as long as the site in question has a valid certificate,""",
                  required=True)

class IInput(interface.Interface):
    """
    An order input file to be captioned or transcribed
    """

class ISourceFileInput(IInput):
    """
    An order input for a source file that has already been uploaded to be used in an order
    """

    audio_length_seconds = Number(title=u'The length of the audio (in seconds, rounded up)',
                                  description=u"""If the URI is for media stored in an S3 bucket,
                                  Rev will try to calculate the audio length automatically.""",
                                  required=False)

    uri = ValidURI(title=u'A URI identifying the uploaded media',
                   required=True)

class IExternalLinkInput(IInput):
    """
    An order input for an external link to a file
    """

    audio_length_seconds = Number(title=u'The length of the audio (in seconds, rounded up)',
                                  description=u"""If external link is a YouTube URL,
                                  audio length is determined automatically.""",
                                  required=False)

    external_link = HTTPURL(title=u'The external link URL',
                            required=True)

class ISpeaker(interface.Interface):
    """
    A speaker
    """

    id = Number(title=u'The ID of the speaker',
                required=True)

    name = TextLine(title=u'The name of the speaker',
                    required=True)

class ISpeakers(interface.Interface):
    """
    The attachment speakers
    """

    speakers = List(value_type=Object(ISpeaker),
                    title=u'A list of speakers',
                    required=True)

MONOLOGUE_ELEMENT_TYPE_TAG = u'tag'
MONOLOGUE_ELEMENT_TYPE_TEXT = u'text'

MONOLOGUE_ELEMENT_TYPE_ITEMS = (MONOLOGUE_ELEMENT_TYPE_TEXT,
                                MONOLOGUE_ELEMENT_TYPE_TAG)

MONOLOGUE_ELEMENT_TYPE_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in MONOLOGUE_ELEMENT_TYPE_ITEMS]
)

class IMonologueElement(interface.Interface):
    """
    Each element of a monologue is either text (transcribed speech)
    or a tag (an annotation), such as inaudible or crosstalk.
    """

    type = Choice(vocabulary=MONOLOGUE_ELEMENT_TYPE_VOCABULARY,
                  title=u'The type of the monologue element',
                  required=True)

    value = Text(title=u'The value of the monologue element',
                 description=u"""For text elements, value contains the text.
                 For tag elements, value contains the annotation type.""",
                 required=True)

    # FIXME: Required for tag elements but not required for text elements
    timestamp = DateTime(title=u'The timestamp',
                         description=u"""Rev uses timestamp format hh:mm:sss,fff
                         where fff represent milliseconds.
                         Text elements may or may not contain a timestamp.
                         Tag elements require a timestamp.""")

class IMonologueElements(interface.Interface):
    """
    Elements of a monologue.
    """

    elements = List(value_type=Object(IMonologueElement),
                    title=u'A list of monologue elements',
                    required=True)

class IMonologue(interface.Interface):
    """
    A monologue (transcribed speech).
    Each monologue corresponds to a run of text from one speaker.
    """

    id = Number(title=u'The ID of the monologue',
                required=True)

    # FIXME: Indicate speaker must be one of the speakers from the attachment content's ISpeakers
    # This speaker ID is the same as the ISpeaker id
    speaker = Number(title=u'The ID of the speaker',
                     required=True)

    # FIXME: Indicate speaker must be one of the speakers from the attachment content's ISpeakers
    # This speaker_name is the same as the ISpeaker name
    speaker_name = TextLine(title=u'The name of the speaker',
                            required=True)

    elements = Object(schema=IMonologueElements,
                      title=u'Elements of the monologue',
                      required=True)

class IMonologues(interface.Interface):
    """
    The attachment monologues (transcribed speech)
    """

    monologues = List(value_type=Object(IMonologue),
                      title=u'A list of monologues',
                      required=True)

class IComment(interface.Interface):
    """
    A comment on an order
    """

    by = TextLine(title=u'The author of the comment',
                  required=True)

    timestamp = DateTime(title=u'The date and time the comment was made. in UTC',
                         required=True)

    text = Text(title=u'The text of the comment',
                required=True)

NOTIFICATION_FINAL_ONLY = u'(the default) A notification is sent only when the order is complete'
NOTIFICATION_DETAILED = u'A notification is sent whenever the order is in a new status or has a new comment'

NOTIFICATION_ITEMS = (NOTIFICATION_DETAILED,
                      NOTIFICATION_FINAL_ONLY)

NOTIFICATION_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in NOTIFICATION_ITEMS]
)

class INotification(interface.Interface):
    """
    Options specified when placing a request for an order
    to enable receiving notifications about the order status
    """

    url = HTTPURL(title=u'The URL where updates will be posted',
                  required=True)

    level = Choice(vocabulary=NOTIFICATION_VOCABULARY,
                   title=u'Specifies which notifications are sent',
                   required=False)

# FIXME? nti.interfaces ILinks, might change into NTILinks (leave for now)
class ILink(interface.Interface):
    """
    Link with URL of the resource for getting attachment content
    """

    # Likely, rel="content"
    rel = TextLine(title=u'The relationship between the current document and the linked document',
                   required=True)

    href = TextLine(title=u'The URL of the link',
                    required=True)

class ILinks(interface.Interface):
    """
    Links with URLs of the resource for getting attachment content
    """

    links = List(value_type=Object(ILink),
                 title=u'A list of links with URLs of the resource for getting attachment content',
                 required=True)

ATTACHMENT_KIND_MEDIA = u'media'
ATTACHMENT_KIND_CAPTION = u'caption'
ATTACHMENT_KIND_TRANSCRIPT = u'transcript'

ATTACHMENT_KIND_ITEMS = (ATTACHMENT_KIND_MEDIA,
                         ATTACHMENT_KIND_TRANSCRIPT,
                         ATTACHMENT_KIND_CAPTION)

ATTACHMENT_KIND_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in ATTACHMENT_KIND_ITEMS]
)

class IAttachment(interface.Interface):
    """
    An attachment

    Attachments are either source files (audio or video for transcriptions orders, videos for caption orders)
    or output files (transcripts or captions, depending on the type of order).
    """

    kind = Choice(vocabulary=ATTACHMENT_KIND_VOCABULARY,
                  title=u'The kind of attachment',
                  required=True)
    # FIXME? "name" is not description, change to "filename?"
    # JSON object uses "name," so leave for now
    name = TextLine(title=u'Filename for the attachment',
                    required=True)

    id = TextLine(title=u'ID for the attachment',
                  required=True)

    # FIXME: Indicate this attribute is only included if kind="transcript"
    audio_length_seconds = Number(title=u'The length (in seconds) of the audio attachment',
                                  required=False)

    links = Object(schema=ILinks,
                   title=u'A list of links with URLs of the resource for getting attachment content',
                   required=True)

class IAttachments(interface.Interface):
    """
    A list of attachments
    """

    attachments = List(value_type=Object(IAttachment),
                       title=u'A list of attachments',
                       required=True)

class IAttachmentContent(interface.Interface):
    """
    The content of the attachment
    """

    speakers = Object(schema=ISpeakers,
                      title=u'The speakers',
                      required=True)

    monologues = Object(schema=IMonologues,
                        title=u'The monologues (transcribed speech)',
                        description=u"""Each monologue corresponds to a run of text from one speaker.""",
                        required=True)

class IOrderRequest(interface.Interface):
    """
    An object providing information for placing an order
    """
    client_ref = TextLine(title=u'A reference number for the order meaningful to the client',
                          required=False)

    notification = Object(schema=INotification,
                          title=u'Enables receiving notifications about the order status',
                          required=False)

#: Completed and Cancelled are the only status values guaranteed not to
#: change in v1 of the API.

ORDER_STATUS_COMPLETED = u'Completed'
ORDER_STATUS_CANCELLED = u'Cancelled'
ORDER_STATUS_CAPTIONING = u'Captioning'
ORDER_STATUS_IN_PROGRESS = u'In Progress'
ORDER_STATUS_TRANSCRIBING = u'Transcribing'

ORDER_STATUS_ITEMS = (ORDER_STATUS_TRANSCRIBING,
                      ORDER_STATUS_CAPTIONING,
                      ORDER_STATUS_IN_PROGRESS,
                      ORDER_STATUS_COMPLETED,
                      ORDER_STATUS_CANCELLED)

ORDER_STATUS_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in ORDER_STATUS_ITEMS]
)

class IOrderDetails(interface.Interface):
    """
    The details of an order
    """

    order_number = TextLine(title=u'Rev assigned order number',
                            required=True)

    client_ref = TextLine(title=u'The client reference order number provided with the order request',
                          required=True)

    # TODO: Rounded to the nearest whole dollar? Convert to cents?
    # Probably fractional, rounded to two decimal places
    # "The price unit in Dollars and it shows default order price" what does default order price mean?
    price = Number(title=u'Total cost of the order (in dollars)',
                   required=True)

    status = Choice(vocabulary=ORDER_STATUS_VOCABULARY,
                    title=u'The status of the order',
                    required=True)

    attachments = List(value_type=Object(IAttachment),
                       title=u'The attachments with the order',
                       required=True)

    comments = List(value_type=Object(IComment),
                    title=u'The comments on the order',
                    required=True)

class IOrder(IOrderRequest, IOrderDetails):
    """
    An order
    """

class IOrders(interface.Interface):
    """
    A list of orders
    """

    orders = List(value_type=Object(IOrder),
                  title=u'A list of orders',
                  required=True)

class ITranscriptionOptions(interface.Interface):
    """
    Information specified when placing a transcription order that
    provides information on what needs to be transcribed and
    sets other transcription options
    """

    # TODO: Indicate inputs must have at least one element
    inputs = List(value_type=Object(IInput),
                  title=u'A list of media to transcribe',
                  required=True)

    # TODO: What is the default value for when this field is not included?
    verbatim = Bool(title=u'Transcribe the provided files verbatim',
                    description=u"""If true, all filler words (i.e. umm, huh) will be included""",
                    required=False)

    # TODO: What is the default value for when this field is not included?
    timestamps = Bool(title=u'Include timestamps',
                      required=False)

class ITranscriptionOrderRequest(IOrderRequest):
    """
    An object providing information for placing a transcription order
    """

    transcription_options = Object(schema=ITranscriptionOptions,
                                   title=u'Transcription options for a transcription order',
                                   description=u"""Provides information on what needs to be transcribed
                                   and allows for any transcription options to be set""",
                                   required=True)

class ICaption(interface.Interface):
    """
    Caption details for a caption order
    including total length of the audio of media attachments for the order
    """

    total_length_seconds = Number(title=u'The total length (in seconds) of the videos included in the caption order',
                                  required=True)

class ICaptionOrderDetails(IOrderDetails):
    """
    The details of a caption order
    """

    caption = Object(schema=ICaption,
                     title=u'Caption details for the caption order',
                     description=u"""Total length (in seconds) of the videos included in the caption order""",
                     required=True)

OUPUT_FILE_FORMAT_DFXP = u'Dfxp'
OUPUT_FILE_FORMAT_SUBRIP = u'SubRip'
OUPUT_FILE_FORMAT_SCENARIST = u'Scc'
OUPUT_FILE_FORMAT_WEB_VTT = u'WebVtt'
OUPUT_FILE_FORMAT_MAC_CAPTION = u'Mcc'
OUPUT_FILE_FORMAT_TIMED_TEXT = u'Ttml'
OUPUT_FILE_FORMAT_TRANSCRIPT = u'Transcript'
OUPUT_FILE_FORMAT_CHEETAH_CAP = u'CheetahCap'
OUPUT_FILE_FORMAT_SPRUCE_SUBTITLE_FILE = u'Stl'
OUPUT_FILE_FORMAT_QUICKTIME_TIMED_TEXT = u'QTtext'
OUPUT_FILE_FORMAT_AVID_DS_SUBTITLE_FILE = u'AvidDs'
OUPUT_FILE_FORMAT_FACEBOOK_READY_SUBRIP = u'FacebookSubRip'

OUPUT_FILE_FORMAT_ITEMS = (OUPUT_FILE_FORMAT_SUBRIP,
                           OUPUT_FILE_FORMAT_SCENARIST,
                           OUPUT_FILE_FORMAT_MAC_CAPTION,
                           OUPUT_FILE_FORMAT_TIMED_TEXT,
                           OUPUT_FILE_FORMAT_QUICKTIME_TIMED_TEXT,
                           OUPUT_FILE_FORMAT_TRANSCRIPT,
                           OUPUT_FILE_FORMAT_WEB_VTT,
                           OUPUT_FILE_FORMAT_DFXP,
                           OUPUT_FILE_FORMAT_CHEETAH_CAP,
                           OUPUT_FILE_FORMAT_SPRUCE_SUBTITLE_FILE,
                           OUPUT_FILE_FORMAT_AVID_DS_SUBTITLE_FILE,
                           OUPUT_FILE_FORMAT_FACEBOOK_READY_SUBRIP)

OUTPUT_FILE_FORMAT_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in OUPUT_FILE_FORMAT_ITEMS]
)

#: Rev also has translators in many other languages with limited capacity.
#: Please contact Rev at support@rev.com with your unique needs.

SUBTITLE_LANGUAGE_DUTCH = u'nl'
SUBTITLE_LANGUAGE_ARABIC = u'ar'
SUBTITLE_LANGUAGE_FRENCH = u'fr'
SUBTITLE_LANGUAGE_GERMAN = u'de'
SUBTITLE_LANGUAGE_ITALIAN = u'it'
SUBTITLE_LANGUAGE_RUSSIAN = u'ru'
SUBTITLE_LANGUAGE_SPANISH = u'es'
SUBTITLE_LANGUAGE_PORTUGUESE_BRAZIL = u'pt-br'
SUBTITLE_LANGUAGE_CHINESE_SIMPLIFIED = u'zh-si'
SUBTITLE_LANGUAGE_CHINESE_TRADITIONAL = u'zh-tr'

SUBTITLE_LANGUAGE_ITEMS = (SUBTITLE_LANGUAGE_ARABIC,
                           SUBTITLE_LANGUAGE_CHINESE_SIMPLIFIED,
                           SUBTITLE_LANGUAGE_CHINESE_TRADITIONAL,
                           SUBTITLE_LANGUAGE_DUTCH,
                           SUBTITLE_LANGUAGE_FRENCH,
                           SUBTITLE_LANGUAGE_GERMAN,
                           SUBTITLE_LANGUAGE_ITALIAN,
                           SUBTITLE_LANGUAGE_PORTUGUESE_BRAZIL,
                           SUBTITLE_LANGUAGE_RUSSIAN,
                           SUBTITLE_LANGUAGE_SPANISH)

SUBTITLE_LANGUAGE_VOCABULARY = SimpleVocabulary(
    [SimpleTerm(_x) for _x in SUBTITLE_LANGUAGE_ITEMS]
)

class ICaptionOptions(interface.Interface):
    """
    Information specified when placing a caption order that
    provides information on what needs to be captioned and
    specifies the desired captions output format
    """

    # TODO: Indicate inputs must have at least one element
    inputs = List(value_type=Object(IInput),
                  title=u'A list of media to caption',
                  required=True)

    subtitle_languages = List(value_type=Choice(vocabulary=SUBTITLE_LANGUAGE_VOCABULARY),
                              title=u'A list of language codes to request foreign language subtitles',
                              required=False)

    output_file_formats = List(value_type=Choice(vocabulary=OUTPUT_FILE_FORMAT_VOCABULARY),
                               title=u'A list of file formats the captions should be optimized for',
                               description=u'By default, we optimize for SubRip',
                               required=False)

class ICaptionOrderRequest(IOrderRequest):
    """
    An object providing information for placing a caption order
    """

    non_standard_tat_guarantee = Bool(title=u'Specify that normal turnaround time is not needed',
                                      description=u"""By default, normal turnaround time (false) is assumed.
                                      Note that this value is used as a guideline only.""",
                                      required=False)

    caption_options = Object(schema=ICaptionOptions,
                             title=u'Caption options for a caption order',
                             description=u"""Provides information on what needs to be captioned
                             and specifies the desired captions output format""",
                             required=True)

class ICaptionOrder(ICaptionOrderRequest, ICaptionOrderDetails, IOrder):
    """
    A caption order
    """

class ITranscription(interface.Interface):
    """
    Transcription details for a transcription order
    including total length of the audio of media attachments for the order
    and additional services
    """

    total_length_seconds = Number(title=u'Total length of the audio (in seconds) of media attachments for an order',
                                  required=True)

    verbatim = Bool(title=u'The transcription is verbatim',
                    description=u"""If true, all filler words (i.e. umm, huh) are included in the transcription""",
                    required=True)

    timestamps = Bool(title=u'Timestamps are included in the transcription',
                      required=True)

class ITranscriptionOrderDetails(IOrderDetails):
    """
    The details of a transcription order
    """

    transcription = Object(schema=ITranscription,
                           title=u'Transcription details for the transcription order',
                           description=u"""Total length of the audio (in seconds) of media attachments for the order
                           and additional services""",
                           required=True)

class ITranscriptionOrder(ITranscriptionOrderRequest, ITranscriptionOrderDetails, IOrder):
    """
    A transcription order
    """


# -*- coding: utf-8 -*-
"""
Created on 10:06 13-11-2020

@author: XY Ding
mail to: dxy_vasp@163.com
python3: band.py
"""
import os, sys
curPath = os.path.abspath(os.path.dirname(__file__))
sys.path.append(curPath)
import numpy as np
from matplotlib import pyplot as plt
import math
import initial

# ******************** band ************************
# get K-PATH form KPOINTS and calculating the kpt
def get_kpt(filename = "KPOINTS"):
    high_kpt_num = 0
    high_kpt_point = []
    kpt = []
    kpath = []
    kpoints = open(filename, 'r').read().splitlines()
    num_kpt_line = int(kpoints[1].split()[0])
    for flag_kpath in range(4, len(kpoints), 3):
        kpt_data1 = list(map(float, kpoints[flag_kpath].split()[0:3]))
        kpt_points_data = kpoints[flag_kpath].split('!')[1].strip()
        if kpt_points_data == "\Gamma":              # transform the gamma character
            kpt_points_data = u"Γ"
        high_kpt_num = high_kpt_num + 1              # get high symmetry point number
        high_kpt_point.append(kpt_points_data)       # get high symmetry points
        kpath.append(kpt_data1[0:3])
    kpt_points_data1 = kpoints[-1].split('!')[1].strip()
    if kpt_points_data1 == "\Gamma":             # transform the gamma character
        kpt_points_data1 = u"Γ"
    high_kpt_point.append(kpt_points_data1)      # get high symmetry points
    kpt_data2 = list(map(float, kpoints[-1].split()[0:3]))
    kpath.append(kpt_data2)                          # get high symmetry path
    high_kpt_num = int(high_kpt_num + 1)                 # get high symmetry point number

    # calculating all the kpoints for the k axis of band
    # 1. transform the high symmetry points to its real coordinates in k space
    k_real = []
    k_middle = []
    k = [0, 0, 0]
    kx = [0, 0, 0]
    ky = [0, 0, 0]
    kz = [0, 0, 0]
    for flag_k in range(0, len(kpath)):
        for flag_d in range(0, 3):
            kx[flag_d] = kpath[flag_k][0] * initial.get_reciprocal()[flag_d]
            ky[flag_d] = kpath[flag_k][1] * initial.get_reciprocal()[flag_d+3]
            kz[flag_d] = kpath[flag_k][2] * initial.get_reciprocal()[flag_d+6]
            k[flag_d] = kx[flag_d] + ky[flag_d] + kz[flag_d]
        k_middle = [k[0], k[1], k[2]]                   # real high symmetry point coordinations
        k_real.append(k_middle)

    # calculating the kpath_length
    length = [0] * len(k_real)
    for cal_k in range(0, len(k_real)):
        if cal_k < len(k_real)-1:
            for i in range(0, 3):
                length[cal_k] = (
                    (k_real[cal_k + 1][0] - k_real[cal_k][0]) ** 2 + (k_real[cal_k + 1][1] - k_real[cal_k][1]) ** 2 + (
                                k_real[cal_k + 1][2] - k_real[cal_k][2]) ** 2) ** (0.5)
        else:
            break

    # get all the kpoints
    num_kpt = (num_kpt_line) * (high_kpt_num-1)
    kpt = []
    kn = 0.0
    lent = 0
    for flag_kpt_hn in range(0, high_kpt_num-1):
        for flag_kpt_pn in range(0, num_kpt_line):
            kn = lent + (length[flag_kpt_hn] / (num_kpt_line -1)) * flag_kpt_pn
            round(float(kn), 6)
            kpt.append(kn)
        lent = lent + length[flag_kpt_hn]
    return int(num_kpt), length, high_kpt_point, kpt

# output klines.dat
def output_klines(filename = "KPOINTS"):
    num_kpt, length, high_kpt_point, kpt = get_kpt(filename)
    len_high_k = 0
    for j in range(0, len(length)):
        length[j] = length[j] + len_high_k
        len_high_k = length[j]
    with open("klines.dat", "w", encoding='utf-8') as kline:
        kline.write("high_kpoints" + "\n")
        kline.write(str("0.").ljust(10, '0') + "  " + str(10) + "\n")
        kline.write(str("0.").ljust(10, '0') + "  " + str(-15) + "\n")
        for l_num in range(0, len(length) - 1):
            kline.write(str(length[l_num])[:10].ljust(10, '0') + "  " + str(-15) + "\n")
            kline.write(str(length[l_num])[:10].ljust(10, '0') + "  " + str(10) + "\n")
            kline.write(str(length[l_num])[:10].ljust(10, '0') + "  " + str(-15) + "\n")
    kline.close()

# get Energy level form Eigenval file
def get_eigenval():
    num_kpt, length, high_kpt_point, kpt = get_kpt()
    fermi = initial.get_fermiLevel()
    eig = []
    eig_up = []
    eig_dw = []
    energy_kpt = []
    energy_kpt_up = []
    energy_kpt_dw = []
#    energy = []
    nbd = initial.get_NBANDS() + 2
    ispin = initial.get_ispin()
    eigenval_lines = open('EIGENVAL', 'r').read().splitlines()
    if ispin == 1:
        for flag_nbd_num in range(0, nbd-2):
            for flag_k_num in range(0, int(num_kpt)+1):
                if flag_k_num < int(num_kpt):
                    flag_orbital = 8 + flag_nbd_num + flag_k_num * nbd
                    eig = float(eigenval_lines[flag_orbital].split()[1]) - fermi
                    round(float(eig), 6)
                    energy_kpt.append(eig)
        return energy_kpt
    elif ispin == 2:
        for flag_nbd_num in range(0, nbd-2):
            for flag_k_num in range(0, int(num_kpt)+1):
                if flag_k_num < int(num_kpt):
                    flag_orbital = 8 + flag_nbd_num + flag_k_num * nbd
                    eig_up = float(eigenval_lines[flag_orbital].split()[1]) - fermi
                    eig_dw = float(eigenval_lines[flag_orbital].split()[2]) - fermi
                    round(float(eig_up), 6)
                    round(float(eig_dw), 6)
                    energy_kpt_up.append(eig_up)
                    energy_kpt_dw.append(eig_dw)
        return energy_kpt_up, energy_kpt_dw
    else:
        return "No Ispin Information Obtained !"

# output band.dat
def output_band():
    output_klines()
    ispin = initial.get_ispin()
    if ispin == 1:
        num_kpt, length, high_kpt_point, kpoints = get_kpt()
        nbd = initial.get_NBANDS()
        kpt = np.transpose(np.array(kpoints))
        # kpt = kpoints.astype(np.float)
        eng = np.array(get_eigenval())
        energy = eng.reshape(nbd, num_kpt)
        # reverse the sequence
        #    rev_kpt = kpt[::-1]
        with open("band.dat", "w", encoding='utf-8') as band:
            band.write("Band Data" + "\n")
            for k_num in range(0, num_kpt):
                band.write(str(kpt[k_num])[:10].ljust(10, ' ') + "  ")
                for flag_nbd in range(0, nbd):
                    band.write(str(energy[flag_nbd][k_num])[:10].ljust(10, ' ') + "  ")
                band.write("\n")
        band.close()
    elif ispin == 2:
        num_kpt, length, high_kpt_point, kpoints = get_kpt()
        nbd = initial.get_NBANDS()
        kpt = np.transpose(np.array(kpoints))
        eng_up, eng_dw = get_eigenval()
        eig_up = np.array(eng_up)
        eig_dw = np.array(eng_dw)
        energy_up = eig_up.reshape(nbd, num_kpt)
        energy_dw = eig_dw.reshape(nbd, num_kpt)
        with open("band_up.dat", "w", encoding='utf-8') as band_up:
            band_up.write("Band Data" + "\n")
            for k_num in range(0, num_kpt):
                band_up.write(str(kpt[k_num])[:10].ljust(10, ' ') + "    ")
                for flag_nbd in range(0, nbd):
                    band_up.write(str(energy_up[flag_nbd][k_num])[:10].ljust(10, ' ') + "    ")
                band_up.write("\n")
        band_up.close()
        with open("band_dw.dat", "w", encoding='utf-8') as band_dw:
            band_dw.write("Band Data" + "\n")
            for k_num in range(0, num_kpt):
                band_dw.write(str(kpt[k_num])[:10].ljust(10, ' ') + "    ")
                for flag_nbd in range(0, nbd):
                    band_dw.write(str(energy_dw[flag_nbd][k_num])[:10].ljust(10, ' ') + "    ")
                band_dw.write("\n")
        band_dw.close()
    else:
        print("No Ispin Information Obtained !")

# plot band
def bandplot(eng_r = [-10, 6, 2], color_noispin = "black", color_ispin = "red"):
    output_band()
    ispin = initial.get_ispin()
    if ispin == 1:
        num_kpt, length, high_kpt_point, kpoints = get_kpt()
        nbd = initial.get_NBANDS()
        banddata = np.loadtxt("band.dat", skiprows=1, dtype=np.float64)
        kpt = banddata[:, 0]
        len_high_k = 0
        for j in range(0, len(length) - 1):
            length[j] = length[j] + len_high_k
            len_high_k = length[j]
        fig, ax = plt.subplots()
        for i in range(1, nbd + 1):
            plt.plot(kpt, banddata[:, i], color=color_noispin)
        plt.xlim(0, max(length))
        x_group_label = []
        x_start = 0
        x_group_label.append(x_start)
        for k in range(0, len(length) - 1):
            x_group_label.append(length[k])
        plt.xticks(x_group_label)
        ax.set_xticklabels(high_kpt_point, rotation=0, fontsize=12, fontname='arial')
        # plt.yticks(eng_r[0], eng_r[1], eng_r[2])
        plt.ylim(eng_r[0], eng_r[1])
        plt.ylabel("E - " + "E$_\mathrm{{F}}$" + " (eV)", fontsize=14, fontname='arial')
        ytick = np.arange(eng_r[0], eng_r[1] + 1, eng_r[2])
        a = int(len(ytick) / 2)
        plt.yticks(np.insert(ytick, a, 0), fontsize=12, )

        ax.axhline(y=0, xmin=0, xmax=1, linestyle='--', linewidth=0.5, color='0.5')
        for i in length[0:-1]:
            ax.axvline(x=i, ymin=0, ymax=1, linestyle='--', linewidth=0.5, color='0.5')
        plt.savefig("band.png", dpi=300)
        plt.show()
    elif ispin == 2:
        num_kpt, length, high_kpt_point, kpoints = get_kpt()
        nbd = initial.get_NBANDS()
        banddata_up = np.loadtxt("band_up.dat", skiprows=1, dtype=np.float64)
        banddata_dw = np.loadtxt("band_dw.dat", skiprows=1, dtype=np.float64)
        kpt = banddata_up[:, 0]
        len_high_k = 0
        for j in range(0, len(length) - 1):
            length[j] = length[j] + len_high_k
            len_high_k = length[j]
        fig, ax = plt.subplots()
        for i in range(1, nbd + 1):
            plt.plot(kpt, banddata_up[:, i], color=color_noispin)
            plt.plot(kpt, banddata_dw[:, i], color=color_ispin)
        plt.xlim(0, max(length))
        ax.legend(("Spin_UP", "Spin_DW"), loc='best')
        x_group_label = []
        x_start = 0
        x_group_label.append(x_start)
        for k in range(0, len(length) - 1):
            x_group_label.append(length[k])
        plt.xticks(x_group_label)
        ax.set_xticklabels(high_kpt_point, rotation=0, fontsize=12, fontname='arial')
        # plt.yticks(eng_r[0], eng_r[1], eng_r[2])
        plt.ylim(eng_r[0], eng_r[1])
        plt.ylabel("E - " + "E$_\mathrm{{F}}$" + " (eV)", fontsize=14, fontname='arial')
        ytick = np.arange(eng_r[0], eng_r[1] + 1, eng_r[2])
        a = int(len(ytick) / 2)
        plt.yticks(np.insert(ytick, a, 0), fontsize=12, )

        ax.axhline(y=0, xmin=0, xmax=1, linestyle='--', linewidth=0.5, color='0.5')
        for i in length[0:-1]:
            ax.axvline(x=i, ymin=0, ymax=1, linestyle='--', linewidth=0.5, color='0.5')
        plt.savefig("band.png", dpi=300)
        plt.show()
    else:
        print("No Ispin Information Obtained !")

# manipulate the fig
def manipulate_bandplot():
    print("    ****************************************************************")
    print("    *This is a code used to plot kinds of band structure,written by*")
    print("    *                          XY Ding                             *")
    print("    ****************************************************************")
    print("\n")
    print("                       (^o^)GOOD LUCK!(^o^)                         ")
    print("\n")
    ispin = initial.get_ispin()
    if ispin == 1:
        print("    *************************** ISPIN is 1 ****************************")
        print("(1) energy range")
        print("(2) color")
        print("(3) Use default setting")
        inint = int(input("Input number:"))
        if inint == 1:
            energy = []
            min_energy = float(input("minimum energy:"))
            max_energy = float(input("maximum energy:"))
            scale_energy = float(input("energy scale:"))
            energy = [min_energy, max_energy, scale_energy]
            print("(1) continue to setting color")
            print("(2) end setting")
            con_end = int(input("Input number:"))
            if con_end == 1:
                color = str(input("which color do you want:"))
                bandplot(energy, color)
            else:
                bandplot(energy, "black")
        elif inint == 2:
            color = str(input("which color do you want:"))
            print("(1) continue to setting energy range")
            print("(2) end setting")
            con_end = int(input("Input number:"))
            if con_end == 1:
                min_energy = float(input("minimum energy:"))
                max_energy = float(input("maximum energy:"))
                scale_energy = float(input("energy scale:"))
                energy = [min_energy, max_energy, scale_energy]
                bandplot(energy, color)
            else:
                bandplot([-10, 6, 2], color)
        else:
            bandplot([-10, 6, 2], "black")
    elif ispin == 2:
        print("    *************************** ISPIN is 2 ****************************")
        print("(1) energy range")
        print("(2) color")
        print("(3) Use default setting")
        inint = int(input("Input number:"))
        if inint == 1:
            energy = []
            min_energy = float(input("minimum energy:"))
            max_energy = float(input("maximum energy:"))
            scale_energy = float(input("energy scale:"))
            energy = [min_energy, max_energy, scale_energy]
            print("(1) continue to setting color")
            print("(2) end setting")
            con_end = int(input("Input number:"))
            if con_end == 1:
                color_up = str(input("color for Spin_UP:"))
                color_dw = str(input("color for Spin_DW:"))
                bandplot(energy, color_up, color_dw)
            else:
                bandplot(energy, "black", "red")
        elif inint == 2:
            color_up = str(input("color for Spin_UP:"))
            color_dw = str(input("color for Spin_DW:"))
            print("(1) continue to setting energy range")
            print("(2) end setting")
            con_end = int(input("Input number:"))
            if con_end == 1:
                min_energy = float(input("minimum energy:"))
                max_energy = float(input("maximum energy:"))
                scale_energy = float(input("energy scale:"))
                energy = [min_energy, max_energy, scale_energy]
                bandplot(energy, color_up, color_dw)
            else:
                bandplot([-10, 6, 2], color_up, color_dw)
        else:
            bandplot([-10, 6, 2], "black", "red")
    else:
        print("    ******************** ISPIN is not 1 or 2!  Good bye ! ********************")

if __name__ == '__main__':
    manipulate_bandplot()