from parse import * # pip install parse
import pprint
import xml.etree.ElementTree as ET
import sys

###########################################################################
# Helper Functions

def convertInterfaceToBoolDict(root):
    alphabet = {}
    keyLength = 0 # This will determine the length of the key that we will use to capture the dictionary
    for alphabetItem in root.iter("Interface"):
        for child in alphabetItem:
            if child.get("Type") != "bool":
                print("Support for boolean interfaces only!")
                assert(child.get("Type") == "bool")
            if child.get("Constant") == "false":
                print("Added ", child.get("Name"))
                keyLength += 1
                alphabet[child.get("Name")] = None

    return alphabet, keyLength

def parse_validateNoBrackets(conditionStr):
    if conditionStr.__contains__("(") or conditionStr.__contains__(")"):
        print("Condition string provided has brackets CHECK!")
        return False
    else:
        return True

def parse_isOR(conditionStr):
    assert(parse_validateNoBrackets(conditionStr))
    if parse("{}or{}", conditionStr) is None:
        return False
    else:
        return True

def parse_isAND(conditionStr):
    assert(parse_validateNoBrackets(conditionStr))
    if parse("{}and{}", conditionStr) is None:
        return False
    else:
        return True

def areAnyNone(unwound):
    for anyK in unwound:
        any = unwound[anyK]
        for k in any:
            if any[k] is None:
                return True
    return False

def getKey(alphabetOption):
    key = ""
    for k in alphabetOption:
        if alphabetOption[k] == True:
            key += "1"
        elif alphabetOption[k] == False:
            key += "0"
        else:
            key += "2"
    return key

def unwindConditions(conditions):
    # print('Unwinding')
    # print('Unwinding ', conditions)
    unwound = {}
    # print("At start are any more to unwind??", areAnyNone(conditions))
    if not areAnyNone(conditions):
        for conditionKey in conditions:
            unwound[conditionKey] = conditions[conditionKey]
    for conditionKey in conditions:
        condition = conditions[conditionKey]
        for k in condition:
            if condition[k] is None:
                trueOption = condition.copy()
                trueOption[k] = True
                falseOption = condition.copy()
                falseOption[k] = False
                unwound[getKey(trueOption)] = trueOption
                unwound[getKey(falseOption)] = falseOption
    # print("Any more to unwind??", areAnyNone(unwound))
    while areAnyNone(unwound) == True:
        unwound = unwindConditions(unwound)
    # print("Unwound to", unwound)
    return unwound

def pad(number, width):
    b = '{0:b}'.format(number)
    # Pad with 0s as required to meet length
    toPad = width - len(b)
    b = "0" * toPad + b
    return b

def getAllConditions(alphabet):
    # Get list of boolean combinations
    keys = alphabet.keys()
    width = len(keys)

    highest = pow(2, width)

    conditions = []

    for i in range(0, highest):
        conditions.append(pad(i, width))

    # Take each bool combo and turn into dict
    newConditions = {}
    for condition in conditions:
        newCondition = {}
        i = 0
        for key in keys:
            newCondition[key] = condition[i]
            i += 1
        newConditions[condition] = newCondition

    return newConditions

def addIfNotPresent(existing, new):
    notPresent = []
    for n in new:
        for e in existing:
            if n == e:
                break
        notPresent.append(n)
    existing = existing + notPresent
    return existing

def parse_singleSignal(signalString):
    if signalString[0] == "!":
        return {"signal":str(signalString[1:]).upper(),"value": False}
    else:
        return {"signal":str(signalString).upper(),"value": True}

def isClockCondition(conditionString):
    # In non-valued enforcement, we can assume any condition like <= < > >=
    if ("<" in conditionString) or ("<=" in conditionString) or (">" in conditionString) or (">=" in conditionString):
        return True
    else:
        return False

def isSingleSignal(conditionString, alphabetTemplate):
    if conditionString[0] == "!":
        conditionString = conditionString[1:]

    for option in alphabetTemplate:
        print(conditionString, option, alphabetTemplate[option])
        if conditionString == option:
            return True
    return False

def getCharacterRepeated(count, char):
    repeated = ""
    for number in range(0, count) : repeated = repeated + str(char)
    return repeated

def getIntersection(first, second):
    intersection = {}
    for f in first:
        # if f in second:
        for s in second:
            if f == s:
                # print("Found a match")
                intersection[f] = second[f]
        # else:
            # print("Found NO match", first[f])
    # print("First: ", first)
    # print("Second: ", second)
    # print("Intersection: ", intersection)
    return intersection

def removeClockConditions(conditions, alphabetTemplate):
    withoutClockConditions = {}
    for condition in conditions:
        # print(condition,conditions[condition])
        conditionValue = {}
        for value in conditions[condition]:
            if value in alphabetTemplate:
                conditionValue[value] = conditions[condition][value]
        # print(condition[0:len(alphabetTemplate)], conditionValue)
        withoutClockConditions[condition[0:len(alphabetTemplate)]] = conditionValue
    return withoutClockConditions

def removeClockConditionKeys(conditions, alphabetTemplate):
    assert(False)
    withoutClockConditions = {}
    for condition in conditions:
        # print('hi2', condition, conditions)#[condition], len(alphabetTemplate))
        # conditionValue = {}
        # for value in conditions[condition]:
        #     if value in alphabetTemplate:
        #         conditionValue[value] = conditions[condition][value]
        # print(condition[0:len(alphabetTemplate)], conditionValue)
        withoutClockConditions[condition[0:len(alphabetTemplate)]] = conditions[condition]
    return withoutClockConditions

def stripClockConditionsFromKey(key, alphabetKeyLength):
    # print("alphabetKeyLength:", alphabetKeyLength, "long, Key is", len(key), "long")
    return key[0:alphabetKeyLength]

def convertKeyToBools(key, alphabetTemplate, allowNone=False):
    dictCondition = {}
    alphabet = list(alphabetTemplate.keys())
    for i in range(0, len(alphabet)):
        if key[i] == "1":
            dictCondition[alphabet[i]] = True
        elif key[i] == "0":
            dictCondition[alphabet[i]] = False
        else:
            if allowNone:
                dictCondition[alphabet[i]] = None
            else:
                assert(False)
    return dictCondition

def convertConditionListToDictOfBools(listOfConditions, alphabetTemplate):
    dictOfConditionSets = {}
    for conditionSet in listOfConditions:
        label = ""
        for key in alphabetTemplate.keys():
            if conditionSet[key] == True:
                label += "1"
            elif conditionSet[key] == False:
                label += "0"
            elif conditionSet[key] is None:
                label += "2"
            else:
                assert(False)

        dictOfConditionSets[label] = conditionSet

    # dictOfConditionSets = unwindConditions(dictOfConditionSets)

    return [dictOfConditionSets, None]

    # print(alphabetTemplate)
    print(conditionString)

    # Remove spaces
    a = conditionString.replace(" ", "")
    # print("Original", a)

    # Count number of brackets
    left = a.count("(")
    right = a.count(")")
    assert(left == right)

    # If even count of brackets, there is a missing set of brackets on outer most (true always?)
    if (left % 2 == 0):
        # print("Even;", left)
        count = 1
    else:
        # print("Odd;", left)
        count = 0

    # Remove topmost brackets
    b = parse("({})", a)
    if b is not None:
        while True:
            # Keep going till all top brackets gone
            if parse("({})", b[0]) is not None:
                # print("Part:", b[0])
                b = parse("({})", b[0])
                count += 1
            else:
                break

        # print("Top brackets removed:", count, b[0])
    else:
        b=[]
        # print("No brackets to remove..?", a)
        b.append(a)

    if count > 0:
        # Separate into LHS, condition and RHS
        # Example: !AandB)or(AandB
        # Becomes: <Result ('!AandB', 'or', 'AandB') {}>
        formatString = "{}" + getCharacterRepeated(count, ")") + "{}" + getCharacterRepeated(count, "(") + "{}"
        # print(formatString)
        topCondition = parse(formatString, b[0])

        # print(topCondition)
        # assert (topCondition is not None)
        if (topCondition is None):
            print("You need to do something Mr Alex")

        # TODO: Recursively find all transitions - keep going till you have ONLY ANDS in a list/table

        LHS = topCondition[0]
        RHS = topCondition[2]

        # print("LHS:", LHS, "RHS:", RHS)
        # L = parse_noBracketsCondition(LHS, alphabetTemplate)
        L, clkL = convertConditionToDictOfBools("("+LHS+")", alphabetTemplate)
        # R = parse_noBracketsCondition(RHS, alphabetTemplate)
        R, clkR = convertConditionToDictOfBools("("+RHS+")", alphabetTemplate)

        # Condition is either "AND" or "OR"
        # print("top condition: ", topCondition)

        # Check if either is clock condition
        if isClockCondition(topCondition[0]):
            # print(topCondition[0], "is clock condition")
            topCondition = {**R}
            clk = {**L}
        elif isClockCondition(topCondition[2]):
            # print(topCondition[2], "is clock condition")
            topCondition = {**L}
            clk = {**R}
        else:
            # Neither is sole clock condition, so check how we need to combine
            condition = topCondition[1].lower()
            if (condition == "or"):
                # OR means APPEND sets of conditions for transition to violation
                print("OR")
                topCondition = {**L, **R}
            elif (condition == "and"):
                # AND means INTERSECTION of sets of conditions for transition to violation
                print("AND")
                topCondition = getIntersection(L, R)

            clk = {}
    else:
        print(b, b[0])
        topCondition, clk = parse_noBracketsCondition(b[0], alphabetTemplate)

    # print("Returning: ", topCondition, "and clk", clk)
    return topCondition, clk

def convertConditionToDictOfBools(conditionString, alphabetTemplate):
    import stringConditionParser

    listOfConditions = stringConditionParser.parseConditionString(conditionString, alphabetTemplate)

    return convertConditionListToDictOfBools(listOfConditions, alphabetTemplate)

def getAcceptableTransitions(violationConditions, allConditions):
    violationConditionsNoClocks = violationConditions #removeClockConditionKeys(violationConditions, alphabetTemplate)
    # print("with clocks:", violationConditions)
    # print("without clocks:", violationConditionsNoClocks)
    acceptableTransitions = {}
    allConditions = allConditions.copy()
    for condition in allConditions: # TODO: Come up with a way to compare while ignoring any clock conditions?
        if condition in violationConditionsNoClocks:
            pass
        else:
            acceptableTransitions[condition] = allConditions[condition]

    # print("Acceptable Transitions (", len(acceptableTransitions), ") -", acceptableTransitions)
    print("Acceptable Transitions (", len(acceptableTransitions), ")")
    print("Violating Transitions (", len(violationConditions), ")")
    print("All Conditions (", len(allConditions), ")")
    # print("Violating Transitions (", len(violationConditions), ") -", violationConditions)
    assert(len(acceptableTransitions) + len(violationConditions) == len(allConditions))
    return acceptableTransitions

# Provided two binary numbers (as STRINGS)
# This function will calculate the number of bits difference between the two
def calculateDistanceBetween(condition1, condition2):
    assert(len(condition1) == len(condition2))
    # assert(type(condition1) == type.String)
    distance = 0
    for i in range(0, len(condition1)):
        # print(i, condition1[i], condition2[i], condition1[i] == condition2[i])
        if (condition1[i] != condition2[i]):
            distance += 1
    return (distance)

def convertBinaryStringToTextCondition(binaryString, alphabetTemplate):
    # print(binaryString)
    i = 0
    condition = []
    for k in alphabetTemplate:
        if int(binaryString[i]) == 1:
            condition.append(k)
        else:
            condition.append("!"+k)

        # print(k, binaryString[i], condition)
        i += 1

    textCondition = "(" + condition[0]
    i = 0
    for i in range(1, len(condition)):
        textCondition += " and " + condition[i]
    textCondition += ")"

    return textCondition

def convertBinaryRecoveryStringToTextListRecovery(recoveryString, alphabetTemplate):
    recoveryList = []

    i = 0
    for a in alphabetTemplate:
        recoveryList.append({
            "VarName": a,
            "Value": recoveryString[i]
        })
        i += 1

    return recoveryList

def writeNewXML_two(root, input_filename, output_filename, policies, alphabetTemplate, list_intersections, references, individualRecoveryKeys):
    print("======================================")
    print(" WRITING XML FILE")
    print("======================================")
    from bs4 import BeautifulSoup

    # Reading data from the xml file
    with open(input_filename, 'r') as f:
        data = f.read()

    # Passing the data of the xml
    # file to the xml parser of
    # beautifulsoup
    bs_data = BeautifulSoup(data, features='xml')

    for policyTag in bs_data.find_all("Policy"):
        policy = policyTag.attrs["Name"]
        # location = tag.find("Source").text
        for tag in policyTag.find_all("PTransition"):
            location = tag.find("Source").text

            # Change the value of RecoveryReference to match the references list
            recoveries = tag.find_all("RecoveryReference")
            for recovery in recoveries:
                recovery.string = str(references[policy][location])
                # NOTE: Could add something here to add in individualRecoveryKeys[policy][location] to the xml for easier compiling

    # TODO: LUT with policies variable
    topEnfFnTag = bs_data.find("EnforcedFunction")
    selectLUTTag = bs_data.new_tag("SelectLUT")
    for row in list_intersections:
        rowTag = bs_data.new_tag("Row")

        recoveryTag = bs_data.new_tag("Recovery")
        recoveryTag.append(row["randEdit"]["key"])
        recoveryKeyTag = bs_data.new_tag("RecoveryKey")
        # recoveryKeyTag.append(row["recoveryKey"])
        recoveryKeyTag.append(row["recoveryKey"])

        for policy in policies:
            pRefTag = bs_data.new_tag("PolicyRef", Policy=str(policy), RecoveryReference=str(references[policy][row[policy]]), RecoveryReferenceKey=str(individualRecoveryKeys[policy][row[policy]]))
            rowTag.append(pRefTag)

        for signal in row["randEdit"]["signals"].keys():
            sigName = str(signal)
            sigValue = str(row["randEdit"]["signals"][sigName])

            if sigValue != "None":
                pRecoverTag = bs_data.new_tag("Recover")
                pSig = bs_data.new_tag("Signal")
                pSig.append(sigName)
                pVal = bs_data.new_tag("Value")
                pVal.append(sigValue)
                pRecoverTag.append(pSig)
                pRecoverTag.append(pVal)
                rowTag.append(pRecoverTag)

        rowTag.append(recoveryTag)
        rowTag.append(recoveryKeyTag)
        selectLUTTag.append(rowTag)

    topEnfFnTag.append(selectLUTTag)

    # Output the contents of the
    # modified xml file
    with open(output_filename, "w") as f2:
        # f2.write(str(bs_data.prettify()))
        f2.write(str(bs_data))
        f2.close()

###########################################################################

def main(dir, file):
    print("======================================")
    print(" READING & PARSING EXISTING XML FILE")
    print("======================================")

    # Passing the path of the
    # xml document to enable the
    # parsing process
    input_filename = "example/"+dir+"/"+file+".xml"
    output_filename = "example/"+dir+"/"+file+"_modified.xml"
    # tree = ET.parse('example/abc5/abc5.xml')
    tree = ET.parse(input_filename)

    # getting the parent tag of
    # the xml document
    originalXMLRoot = tree.getroot()

    # printing the root (parent) tag
    # of the xml document, along with
    # its memory location
    print("Enforced Function: ", originalXMLRoot.attrib.get("Name"))

    alphabetTemplate, alphabetKeyLength = convertInterfaceToBoolDict(originalXMLRoot)

    # root.tag
    # root.attrib
    # for child in root:
    #     print(child.tag, child.attrib)
    #     for childchild in child:
    #         print("\t", childchild.tag, childchild.attrib)

    print("==========================================")
    print(" DETERMINE ALL POSSIBLE CONDITIONS")
    print("==========================================")
    print(" - This may take a moment")
    allConditions = getAllConditions(alphabetTemplate.copy())
    print(" - Unique combinations of I/O: ", len(allConditions))

    print("==========================================")
    print(" COLLECTING ALL VIOLATING TRANSITIONS")
    print("==========================================")

    # Find each policies violating transitions
    policies = {}
    table_acceptingTransitions = {}
    table_violatingTransitions = {}
    for policy in originalXMLRoot.iter("Policy"):

        allViolationTransitions = []
        policyViolationCount = 0
        locations = []
        for transition in policy.iter('PTransition'):
            # if (transition.find('Recover')):
            if (transition.find('Destination').text == "violation"):
                # Recovery Statement / PTransition -> Violating

                violatingConditionString = transition.find("Condition").text
                violatingCondition, _ = convertConditionToDictOfBools(violatingConditionString, alphabetTemplate)

                pName = policy.attrib.get("Name")
                location = transition.find("Source").text
                condition = {
                    "string": violatingConditionString,
                    "bool": violatingCondition
                }

                if pName not in table_violatingTransitions.keys():
                    table_violatingTransitions[pName] = {}

                if location not in table_violatingTransitions[pName]:
                    table_violatingTransitions[pName][location] = []

                table_violatingTransitions[pName][location].append(condition)

                break

                # print(policy.attrib.get("Name"), " ", transition.find("Source").text, " to ", transition.find("Destination").text, " on ", transition.find("Condition").text, ". Recovers with ", child.find("VarName").text, child.find("Value").text)
                violationConditions, _ = convertConditionToDictOfBools(transition.find("Condition").text, alphabetTemplate)
                # print(policy.attrib.get("Name"), " ", transition.find("Source").text, " to ", transition.find("Destination").text, " on ", transition.find("Condition").text, ". Recovers with ", child.find("VarName").text, child.find("Value").text)
                # print("Violation Conditions: ", violationConditions)
                acceptable = getAcceptableTransitions(violationConditions, allConditions)
                location = transition.find("Source").text

                for violatingCondition in violationConditions:
                    # Put each violating signal set into table, [policy, reference, location, A, B, C, acceptable resolutions]
                    policyViolationCount += 1 # TODO: Review renaming this, not always a violating trans
                    allViolationTransitions.append({
                        "policy":policy.attrib.get("Name"),
                        "violationRef":policyViolationCount,
                        "location":location,
                        "violatingConditionString":transition.find("Condition").text,
                        "violatingCondition":stripClockConditionsFromKey(violatingCondition, alphabetKeyLength),
                        "acceptableConditions":acceptable
                    })

                if location not in locations:
                    locations.append(location)
                    policyViolationCount += 1 # TODO: Review renaming this
                    allViolationTransitions.append({
                        "policy":policy.attrib.get("Name"),
                        "violationRef":policyViolationCount,
                        "location":location,
                        "violatingConditionString":"NONE",
                        "violatingCondition":"NONE",
                        "acceptableConditions":acceptable
                    })
            else:
                # Normal Transition Statement / PTransition -> Accepting
                acceptConditionString = transition.find("Condition").text
                acceptCondition, _ = convertConditionToDictOfBools(acceptConditionString, alphabetTemplate)

                pName = policy.attrib.get("Name")
                location = transition.find("Source").text
                condition = {
                    "string": acceptConditionString,
                    "bool": acceptCondition
                }

                if pName not in table_acceptingTransitions.keys():
                    table_acceptingTransitions[pName] = {}

                if location not in table_acceptingTransitions[pName]:
                    table_acceptingTransitions[pName][location] = []

                table_acceptingTransitions[pName][location].append(condition)

        policies[policy.attrib.get("Name")] = allViolationTransitions

    # Add non-violation for each location in each policy
    # (because there is still some set of acceptable I/O for each policy+location,
    # and we need to capture this to ensure edit action doesnt inadvertantly violate)
    def getUniqueLocations(policy):
        locations = []
        for violation in policy:
            if violation["location"] not in locations:
                locations.append(violation["location"])
        return locations

    def addRecovery(recoveries, transitionInfo, recovery):
        recoveries[transitionInfo["policy"]+"-"+transitionInfo["location"]+"-"+transitionInfo["violatingCondition"]] = {
            "policy":transitionInfo["policy"],
            "location":transitionInfo["location"],
            "violationRef":transitionInfo["violationRef"],
            "violatingConditionString":transitionInfo["violatingConditionString"],
            "violatingCondition":transitionInfo["violatingCondition"],
            "recovery":recovery
        }
        return

    print("==========================================")
    print(" CREATING VIOLATION REF TABLE")
    print("==========================================")

    def getNumberLocations(policy):
        return len(getUniqueLocations(policy))

    # Create template to be used as rows (each policy should have a column, which will hold the violation reference)
    rowTemplate = {}
    for policy in policies:
        rowTemplate[policy] = 1

    numberRowsExpected = 1
    # recoveryKeyLength = {} NOTE: Determined later
    for policy in policies:
        # numberLocations = getNumberLocations(policies[policy])
        numberRowsExpected = numberRowsExpected * (len(policies[policy]))
        # recoveryKeyLength[policy] = len('{0:b}'.format(len(policies[policy])))  NOTE: Determined later

    print("Expected Recovery Rows:", numberRowsExpected)

    rowsExample = []
    rowsExample.append(rowTemplate)
    for policy in policies:
        rowCount = len(rowsExample)
        for i in range(rowCount):
            for violation in policies[policy]:
                if violation["violationRef"] > 1: # Added check here to remove don't cares
                    row = rowsExample[i].copy()
                    row[policy] = violation["violationRef"]
                    rowsExample.append(row)

    # assert(len(rowsExample) == numberRowsExpected)

    # List of dictionaries with each policy and violation refs
    import pprint
    # pprint.pprint(rowsExample)

    print("=============================================")
    print(" PRE-CRUNCHING EDITS FOR VIOLATION REF COMBO")
    print("=============================================")

    def convertTableRow_policy_location_to_boolCondition(row_policy_location_condition):
        condition = {}
        for cdtn in row_policy_location_condition:
            condition.update(cdtn["bool"])
        return condition

    def appendViolatingTransitionsToList(combinations, violatingPolicyLocations):
        newCombinations = []
        for combination in combinations:
            newCombinations.append(combination)
        return newCombinations

    def appendPolicyLocationsToList(combinations, policyLocations):
        newCombinations = []
        for combination in combinations:
            policy = policyLocations[0]
            locations = policyLocations[1]
            if policy not in combination.keys():
                for location in locations:
                    combination[policy] = location
                    newCombinations.append(combination.copy())
            else:
                newCombinations.append(combination)

        return newCombinations

    # Make a nice list of policies, with a list inside of each location
    # policies_and_locations = [ [ policy 1 name, [policy location 1, policy location 2, .. ]] ]
    print(" - Getting acceptable actions")
    policies_and_locations = []
    policies = list(table_acceptingTransitions.keys())
    for policy in policies:
        locations = list(table_acceptingTransitions[policy].keys())
        policies_and_locations.append([policy, locations])

    # TODO: Add non-violating for each

    # Now, for some fun..
    # So we need precompute the intersection of acceptable actions for each location within each policy
    #
    # What?
    #
    # At any time, each policy is in any one location, and there is a set of acceptable actions in that policy
    # At the same time, EVERY other policy is in any one location, also with a set of acceptable actions
    #
    # In order to precompute edits, we need to determine the intersection of each possible set of locations
    # [Policy1 Locations] X [Policy 2 Locations] X [Policy 3 Locations] and so on
    #
    # Yes it is exponential. So maybe we won't precompute the intersection, but knowing the list of these combinations will be handy.. I think!
    combinations = []
    firstPolicy = policies_and_locations[0]
    for location in firstPolicy[1]:
        combinations.append({firstPolicy[0]: location})
    for policy in policies_and_locations:
        combinations = appendPolicyLocationsToList(combinations, policy)

    def unionDictTransitions(list):
        start = {}
        for i in list:
            start = {**start, **i["bool"]}
        return start

    def intersectionDictTransitions(one, two, alphabetTemplate):
        oneKeys = []
        for item in one:
            # oneKeys.append(list(item["bool"].keys())[0])
            # oneKeys.append(item["bool"].keys())
            oneKeys = oneKeys + list(item["bool"].keys())
        twoKeys = []
        for item in two:
            twoKeys = twoKeys + list(item["bool"].keys())
            # twoKeys.append(list(item["bool"].keys())[0])

        intersection = []
        # for each key in one
        # for oneKey in oneKeys:
        #     # if key is in two
        #     if oneKey in twoKeys:
        #         # add to intersection
        #         intersection[oneKey] = convertKeyToBools(oneKey, alphabetTemplate, allowNone=True) #one[oneKey]

        # If intersection is none, then we need to be more thoughtful
        # intersectionFound = False
        # Specifically comparing for 2s, which are nones- and therefore we dont mind what they are
        for oneKey in oneKeys:
            for twoKey in twoKeys:
                match = True
                for i in range(0, len(oneKey)):
                    # If 0 in onekey, then accept 0 / 2 in twokey
                    if (oneKey[i] == "0"):
                        if (twoKey[i] != "0") and (twoKey[i] != "2"):
                            # Key doesn't match
                            match = False
                            break
                    # If 1 in onekey, then accept 1 / 2 in twokey
                    elif (oneKey[i] == "1"):
                        if (twoKey[i] != "1") and (twoKey[i] != "2"):
                            # Key doesn't match
                            match = False
                            break

                    # If 2 in onekey, then accept any in twokey
                    elif (oneKey[i] == "2"):
                        continue

                if match:
                    jointKey = ""
                    for i in range(0, len(oneKey)):
                        if (oneKey[i] == "2"):
                            jointKey += twoKey[i]
                        elif (twoKey[i] == "2"):
                            jointKey += oneKey[i]
                        else:
                            jointKey += oneKey[i]
                    intersection.append(
                        {"bool":
                         {jointKey: convertKeyToBools(jointKey, alphabetTemplate, allowNone=True)}
                         })
                    # print("Match", oneKey, twoKey, jointKey)
                # else:
                    # print("No-Match", oneKey, twoKey)

                # for oAK in oneAgnosticKey:
                #     if oAK in twoAgnosticKey:
                #         intersection[oAK] = convertKeyToBools(oAK, alphabetTemplate)
                        # intersectionFound = True
                        # break

        return intersection

    print(" - Getting intersection of acceptable actions")
    # For every combination of locations
    list_intersections = []
    # for combination in combinations:
    #     policies = list(combination.keys())
    #     firstPolicy = policies[0]
    #     firstLocation = combination[firstPolicy]
    #     # Union of acceptable for the first policy
    #     acceptableTransitions = unionDictTransitions(table_acceptingTransitions[firstPolicy][firstLocation])

    #     # Then for each other policy
    #     for next in policies:
    #         # nextPolicy = next[0]
    #         nextPolicy = next
    #         nextLocation = combination[nextPolicy]
    #         if nextPolicy != firstPolicy:
    #             # Get union of acceptable
    #             someNewAcceptableTransitions = unionDictTransitions(table_acceptingTransitions[nextPolicy][nextLocation])
    #             # Get intersection
    #             acceptableTransitions = intersectionDictTransitions(acceptableTransitions, someNewAcceptableTransitions, alphabetTemplate)

    #     import random
    #     numAccTrans = len(acceptableTransitions)
    #     assert(numAccTrans > 0)
    #     if numAccTrans > 1:
    #         randInt = random.randrange(len(acceptableTransitions)-1)
    #     else:
    #         randInt = 0

    #     randKey = list(acceptableTransitions.keys())[randInt]
    #     # Now we have the intersection, add it to the list
    #     list_intersections.append({
    #         **combination,
    #         "intersection":acceptableTransitions,
    #         "randEdit":{"key":randKey, "signals":acceptableTransitions[randKey]}
    #     })

    print(" - For each violation")
    for combination in combinations:
        # Combination holds a location for each policy
        # In this combination we can have one or more violating transitions
        # TODO: We need to solve each one of these
        first = True
        accepting = {}
        for policy in policies:
            location = combination[policy]
            # print(policy, location, "violating transitions:", len(table_violatingTransitions[policy][location]), "condition[0]", table_violatingTransitions[policy][location][0]["string"])
            # print("accepting:", table_acceptingTransitions[policy][location][0]['bool'])
            if first:
                accepting = table_acceptingTransitions[policy][location]
                first = False
            else:
                accepting = intersectionDictTransitions(accepting, table_acceptingTransitions[policy][location], alphabetTemplate)
        # print(" - Combination ", combination, "has resolutions:")
        # pprint.pprint(accepting)

        import random
        numAccTrans = len(accepting)
        assert(numAccTrans > 0)
        if numAccTrans > 1:
            randInt = random.randrange(0, len(accepting)) # may need len -1
        else:
            randInt = 0

        print("\t - Found " + str(numAccTrans) + " accepting solutions. Picked index " + str(randInt))
        # randKey = list(accepting.keys())[randInt]
        # randKey = accepting[randInt]
        randKey = list(accepting[randInt]["bool"].keys())[0]
        randValues = accepting[randInt]["bool"][randKey]
        # Now we have the intersection, add it to the list
        list_intersections.append({
            **combination,
            "intersection":accepting,
            "randEdit":{"key":randKey, "signals":randValues}
        })

    # Quick fix to add recovery references to the list of intersections
    print(" - Add recovery references to the list of intersections")
    references = {}
    recoveryKeyLength = {}
    for p_and_l in policies_and_locations:
        ref = 0
        policy = p_and_l[0]
        if policy not in references.keys():
            references[policy] = {}
        for location in p_and_l[1]:
            references[policy] = {**references[policy], location: ref}
            ref += 1
        recoveryKeyLength[policy] = len('{0:b}'.format(ref))

    # Get binary recoveryKeys
    # Stored in the "list_intersections" list1 under key "recoveryKey" for each row
    print(" - Add binary recovery keys")
    individualRecoveryKeys = {} # This one holds individual keys, this might be helpful on the compiler side
    for intersection in list_intersections:
        recoveryKey = ""
        for policy in policies:
            b = '{0:b}'.format(references[policy][intersection[policy]])
            # Pad with 0s as required to meet length
            toPad = recoveryKeyLength[policy] - len(b)
            b = "0" * toPad + b
            recoveryKey += b

            if policy not in individualRecoveryKeys.keys():
                individualRecoveryKeys[policy] = {}
            if intersection[policy] not in individualRecoveryKeys[policy].keys():
                individualRecoveryKeys[policy][intersection[policy]] = {}
            individualRecoveryKeys[policy][intersection[policy]] = b
            # individualRecoveryKeys[policy][intersection[policy]]["binary"] = "TODO"

        intersection["recoveryKey"]= recoveryKey

    writeNewXML_two(originalXMLRoot, input_filename, output_filename, policies, alphabetTemplate, list_intersections, references, individualRecoveryKeys)

    return

    # Now iterate through this list, pulling each set of acceptable from policies object
    rowNumber = 0
    lastPrinted = 100
    for row in rowsExample:
        # print(row)
        totalRows = len(rowsExample)
        rowNumber += 1
        # print(rowNumber / totalRows * 100, totalRows, rowNumber)
        if (int(rowNumber / totalRows * 100)) % 10 == 0:
            if (lastPrinted != (int(rowNumber / totalRows * 100))):
                print(int(rowNumber / totalRows * 100), "%\t", rowNumber, "of", totalRows)
                lastPrinted = int(rowNumber / totalRows * 100)

        acceptableSets = []
        for policy in row:
            if row[policy] == 0:
                print("Dont Care - Add things that dont violate the policy.. in this location..?")
            else:
                # print("Add", policy, row[policy]-1)#, policies[policy][row[policy]-1]["acceptableConditions"])
                acceptableSets.append(policies[policy][row[policy]-1]["acceptableConditions"])

        # Do an intersection
        intersection = acceptableSets[0]
        for i in range(1, len(acceptableSets)):
            intersection = getIntersection(intersection, acceptableSets[i])

        # print("Intersection:", end=" ")
        # pprint.pprint(intersection)

        # NOTE: This will fail when intersection is empty set!
        # NOTE: The script currently ONLY supports CAPS LOCK inputs and outputs! A reason you may be here is because of that...!
        assert(len(intersection) > 0)
        # We are expecting this to occur for some examples, just need to handle it gracefully.
        # In some cases this assert will fail when the designer has created unenforceable policies
        # In other cases, the policies will never emit the two violationRef signals at the same time, thus this row/edit/enforcement action doesnt need to exist

        # TODO: Then do a minEdit
        selectedRecovery = intersection[list(intersection.keys())[0]]

        # Get binary recoveryKeys
        recoveryKey = ""
        for policy in row:
            b = '{0:b}'.format(row[policy])
            # Pad with 0s as required to meet length
            toPad = recoveryKeyLength[policy] - len(b)
            b = "0" * toPad + b
            recoveryKey += b
        row["recoveryKey"] = recoveryKey

        row["recovery"] = list(intersection.keys())[0]
        row["recoveryValue"] = intersection[list(intersection.keys())[0]]

    writeNewXML(originalXMLRoot, input_filename, output_filename, policies, alphabetTemplate, rowsExample)

###########################################################################

if __name__ == "__main__":
    if (len(sys.argv) != 3):
        print("ERROR\nExpecting 2 arguments: project directory then project file.")
        print("For the AB example: python rtecomp/main.py AB AB\n")
        assert(len(sys.argv) == 3)
    projectDir = sys.argv[1]
    projectFile = sys.argv[2]

    # import cProfile
    # import re
    # cProfile.run("main(projectDir,projectFile)")

    main(projectDir, projectFile)

###########################################################################


#!/bin/python
import ffmpeg
import os

flist = []
# 拓展名
video_suffix = ['.MP4', '.avi', '.mkv', '.mp4', '.webm']

# 递归所有子目录
for root, dirs, files in os.walk("/mnt/E/迅雷下载", topdown=False):
    for name in files:
        if os.path.splitext(name)[1] in video_suffix:
            info = ffmpeg.probe(os.path.join(root, name))
            try:
                v_bitrate = int(info['format']['bit_rate'])
            except BaseException:
                v_bitrate = 0
            try:
                a_bitrate = int(info['streams'][1]['bit_rate'])
            except BaseException:
                a_bitrate = 0

            flist.append({'name': os.path.join(root, name),
                         'v_bitrate': v_bitrate, 'a_bitrate': a_bitrate})

# 对视频码率排序
print(sorted(flist, key=lambda x: x['v_bitrate']))
# 对音频码率排序
print(sorted(flist, key=lambda x: x['a_bitrate']))


import torch
from dataset import *
from utils import *
from PIL import Image
import models.crnn as crnn
import numpy as np
import torch.optim as optim

use_cuda=True
model_path = './data/crnn.pth'  # 模型权重路径
img_path = './data/demo.png'  # 测试图片路径
alphabet = '0123456789abcdefghijklmnopqrstuvwxyz'
# epsilon = [0, .05, .1, .15, .2, .25, .3]# 设置FGSM攻击参数
epsilon = 0.3

# Define what device we are using
print("CUDA Available: ",torch.cuda.is_available())
device = torch.device("cuda" if (use_cuda and torch.cuda.is_available()) else "cpu")

model = crnn.CRNN(32, 1, len(alphabet) + 1, 256).to(device)  # 创建模型

# 加载预训练模型
print('loading pretrained model from %s' % model_path)
model.load_state_dict(torch.load(model_path))

# 创建转换器，测试阶段用于将ctc生成的路径转换成最终序列，使用英文字典时忽略大小写
converter = strLabelConverter(alphabet, ignore_case=False)

# 图像大小转换器
transformer = resizeNormalize((100, 32))

# FGSM attack
def fgsm_attack(image, epsilon, data_grad):
    # Collect the element-wise sign of the data gradient
    sign_data_grad = data_grad.sign()
    # Create the perturbed image by adjusting each pixel of the input image
    image = image.squeeze(1)

    sign_data_grad = sign_data_grad.resize_([1,32,100])

    sign_data_grad = sign_data_grad.sign()

    perturbed_image = image + epsilon*sign_data_grad

    # Adding clipping to maintain [0,1] range
    perturbed_image = torch.clamp(perturbed_image, 0, 1)

    # Return the perturbed image
    perturbed_image = perturbed_image.unsqueeze(1)

    # print(perturbed_image)
    return perturbed_image

# # 读取并转换图像大小为100 x 32 w x h
image = Image.open(img_path).convert('L')#参数'L'表示将图像转为灰度图
image = transformer(image) # (1, 32, 100)
image = image.view(1, *image.size())  # (b, c, h, w) (1, 1, 32, 100)
image = image.to(device)

model.train()

criterion = torch.nn.CTCLoss()

def test( model, device, epsilon ):

    # Send the data and label to the device
    target = [24, 11, 418, 323, 446, 2, 350, 335, 291, 109] # label
    target = torch.tensor(target)
    data = image
    data, target = data.to(device), target.to(device)
    # data = data.to(device)

    # Set requires_grad attribute of tensor. Important for Attack
    data.requires_grad = True
    # Forward pass the data through the model

    preds = model(data)
    preds = Variable(preds, requires_grad=True)
    # _, preds = preds.max(2)  # 取可能性最大的indecis size (26, 1)

    batch_size = data.size(0)
    target, length = converter.encode(alphabet)  # encode就是上面这个函数
    preds_size = torch.IntTensor([preds.size(0)] * batch_size)

    # If the initial prediction is wrong, dont bother attacking, just move on
    # if preds.item() != target.item():
    #     continue

    # Calculate the loss
    loss = criterion(preds, target, preds_size, length)

    # Zero all existing gradients
    model.zero_grad()

    # Calculate gradients of model in backward pass
    loss.backward()

    # Collect datagrad
    data_grad = preds.grad

    # Call FGSM Attack
    perturbed_data = fgsm_attack(data, epsilon, data_grad)

    # Re-classify the perturbed image
    output = model(perturbed_data)
    _, output = output.max(2)  # 取可能性最大的indecis size (26, 1)
    output = output.transpose(1, 0).contiguous().view(-1)  # 转成以为索引列表
    # 转成字符序列
    output_size = torch.IntTensor([output.size(0)])
    raw_output = converter.decode(output.data, output_size.data, raw=True)
    sim_output = converter.decode(output.data, output_size.data, raw=False)

    return raw_output, sim_output

raw_output, sim_output = test(model, device, epsilon)
print('%-20s => %-20s' % (raw_output, sim_output))


from api import views

from backend import settings

from django.urls import include, path

from drf_yasg import openapi
from drf_yasg.views import get_schema_view

from rest_framework import permissions, routers

router = routers.DefaultRouter()
router.register(r"example", views.ExampleViewSet)
schema_view = get_schema_view(
    openapi.Info(
        title="Example API",
        default_version="v1",
        description="API description",
        contact=openapi.Contact(email="jdesmare@student.42.fr"),
        license=openapi.License(name="BSD License"),
    ),
    public=True,
    permission_classes=(permissions.AllowAny,),
)

app_name = "api"
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [path("", include(router.urls))]

if settings.DEBUG:
    urlpatterns += [
        path(
            "swagger/",
            schema_view.with_ui("swagger", cache_timeout=0),
            name="schema-swagger-ui",
        ),
        path(
            "redoc/", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc"
        ),
    ]


from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework import status

from orders.models import OrderInfo
from alipay import AliPay
import os
from django.conf import settings
from .models import Payment

class PaymentView(APIView):
    """生成支付链接"""
    permission_classes = [IsAuthenticated]

    def get(self, request, order_id):
        user = request.user
        # 校验订单的有效性
        try:
            order_model = OrderInfo.objects.get(
                order_id=order_id, user=user,
                pay_method=OrderInfo.PAY_METHODS_ENUM['ALIPAY'],
                status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])
        except OrderInfo.DoesNotExist:
            return Response({"message": "订单有误"}, status.HTTP_400_BAD_REQUEST)

        # 创建AliPay  SDK中提供的支付对象
        app_private_key_string = open(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys/app_private_key.pem')
        ).read()
        alipay_public_key_string = open(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/alipay_public_key.pem")
        ).read()
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_private_key_string=app_private_key_string,  # 自己的私钥
            alipay_public_key_string=alipay_public_key_string,  # 支付宝的公钥
            sign_type="RSA2",  # 加密方式
            debug=settings.ALIPAY_DEBUG,
            app_notify_url=None,  # 默认回调的URL
        )
        # 调用SDK的方法得到支付链接后面的查询参数
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(order_model.total_amount),  # 支付总金额  它不认识Decimal
            subject="荣芊商城 ---- %s" % order_id,
            return_url='http://127.0.0.1:8080/pay_success.html',
            notify_url=" "  # 异步回调地址   就算不用也要加上
        )
        print(order_string)
        # 拼接好支付链接
        alipay_url = settings.ALIPAY_URL + "?" + order_string

        # 响应
        return Response({"alipay_url": alipay_url})

class PaymentStatusView(APIView):

    def put(self, request):
        # 获取前端以查询字符串方式传入的数据
        queryDict = request.query_params
        # 将queryDict类型转换成字典（要将中间的sign 从里面移除，然后进行验证）
        data = queryDict.dict()
        # 将sign这个数据从字典中移除 pop
        sign = data.pop('sign')

        # 创建AliPay  SDK中提供的支付对象
        app_private_key_string = open(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys/app_private_key.pem')
        ).read()
        alipay_public_key_string = open(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), "keys/alipay_public_key.pem")
        ).read()
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_private_key_string=app_private_key_string,  # 自己的私钥
            alipay_public_key_string=alipay_public_key_string,  # 支付宝的公钥
            sign_type="RSA2",  # 加密方式
            debug=settings.ALIPAY_DEBUG,
            app_notify_url=None,  # 默认回调的URL
        )
        if alipay.verify(data, sign):
            """校验成功"""
            order_id = data.get("out_trade_no")  # 荣芊订单编号
            trade_no = data.get("trade_no")  # 支付宝流水号
            Payment.objects.create(
                order_id=order_id,
                trade_id=trade_no,
            )
            try:
                new_orderinto = OrderInfo.objects.get(
                    order_id=order_id,
                    user=request.user,
                    pay_method=OrderInfo.PAY_METHODS_ENUM['ALIPAY'],
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID']
                )
                new_orderinto.status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                new_orderinto.save()
                # 完成
                return Response({"trade_id": trade_no})
            except OrderInfo.DoesNotExist:
                return Response({"message": "订单有误"}, status.HTTP_400_BAD_REQUEST)
        else:
            return Response({"message": "非法请求"}, status=status.HTTP_403_FORBIDDEN)


# src/tests/functional/test_users

# list of HTTP status codes: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

import json

import pytest

from src.api.users.models import User

# POST route
def test_add_user(test_app, test_database):
    client = test_app.test_client()
    resp = client.post(
        "/users",
        data=json.dumps({"username": "dataandgis", "email": "dataandgis@gmail.com"}),
        content_type="application/json",
    )
    data = json.loads(resp.data.decode())
    assert resp.status_code == 201
    assert "dataandgis@gmail.com was added!" in data["message"]

def test_add_user_invalid_json(test_app, test_database):
    client = test_app.test_client()
    resp = client.post(
        "/users",
        data=json.dumps({}),
        content_type="application/json",
    )
    data = json.loads(resp.data.decode())
    assert resp.status_code == 400
    assert "Input payload validation failed" in data["message"]

def test_add_user_invalid_json_keys(test_app, test_database):
    client = test_app.test_client()
    resp = client.post(
        "/users",
        data=json.dumps({"email": "john@gmail.com"}),
        content_type="application/json",
    )
    data = json.loads(resp.data.decode())
    assert resp.status_code == 400
    assert "Input payload validation failed" in data["message"]

def test_add_user_duplicate_email(test_app, test_database):
    client = test_app.test_client()
    client.post(
        "/users",
        data=json.dumps({"username": "dataandgis", "email": "dataandgis@gmail.com"}),
        content_type="application/json",
    )
    resp = client.post(
        "/users",
        data=json.dumps({"username": "dataandgis", "email": "dataandgis@gmail.com"}),
        content_type="application/json",
    )
    data = json.loads(resp.data.decode())
    assert resp.status_code == 400
    assert "Sorry. That email already exists." in data["message"]

# GET route
def test_single_user(test_app, test_database, add_user):
    user = add_user("Sir Ed", "sired@everest.com")
    client = test_app.test_client()
    resp = client.get(f"/users/{user.id}")
    data = json.loads(resp.data.decode())
    assert resp.status_code == 200
    assert "Sir Ed" in data["username"]
    assert "sired@everest.com" in data["email"]

def test_single_user_incorrect_id(test_app, test_database):
    client = test_app.test_client()
    resp = client.get("/users/999")
    data = json.loads(resp.data.decode())
    assert resp.status_code == 404
    assert "User 999 does not exist" in data["message"]

def test_all_users(test_app, test_database, add_user):
    # clear the database to ensure the test runs in isolation(removes users added in previous tests).
    test_database.session.query(User).delete()
    add_user("Bert", "bert@seasamestreet.com")
    add_user("Ernie", "ernie@seasamestreet.com")
    client = test_app.test_client()
    resp = client.get("/users")
    data = json.loads(resp.data.decode())
    assert len(data) == 2
    assert resp.status_code == 200
    assert "Bert" in data[0]["username"]
    assert "Ernie" in data[1]["username"]
    assert "bert@seasamestreet.com" in data[0]["email"]
    assert "ernie@seasamestreet.com" in data[1]["email"]

# DELETE Route
def test_remove_user(test_app, test_database, add_user):
    test_database.session.query(User).delete()  # clear database
    user = add_user("user-to-be-removed", "remove-me@seasame.com")
    client = test_app.test_client()
    resp_one = client.get("/users")
    data = json.loads(resp_one.data.decode())
    assert resp_one.status_code == 200
    assert len(data) == 1

    resp_two = client.delete(f"/users/{user.id}")
    data = json.loads(resp_two.data.decode())
    assert resp_two.status_code == 200
    assert "remove-me@seasame.com was removed!" in data["message"]

    resp_three = client.get("/users")
    data = json.loads(resp_three.data.decode())
    assert resp_three.status_code == 200
    assert len(data) == 0

def test_remove_user_incorrect_id(test_app, test_database):
    client = test_app.test_client()
    resp = client.delete("/users/999")
    data = json.loads(resp.data.decode())
    assert resp.status_code == 404
    assert "User 999 does not exist" in data["message"]

# PUT route
def test_update_user(test_app, test_database, add_user):
    user = add_user("user-to-be updated", "update-me@seasame.com")
    client = test_app.test_client()
    resp_one = client.put(
        f"/users/{user.id}",
        data=json.dumps({"username": "me", "email": "me@seasame.com"}),
        content_type="application/json",
    )
    data = json.loads(resp_one.data.decode())
    assert resp_one.status_code == 200
    assert f"{user.id} was updated!" in data["message"]

    resp_two = client.get(f"/users/{user.id}")
    data = json.loads(resp_two.data.decode())
    assert resp_two.status_code == 200
    assert "me" in data["username"]
    assert "me@seasame.com" in data["email"]

@pytest.mark.parametrize(
    "user_id, payload, status_code, message",
    [
        [1, {}, 400, "Input payload validation failed"],
        [1, {"email": "me@seasame.com"}, 400, "Input payload validation failed"],
        [
            999,
            {"username": "shane", "email": "dataandgis@seasame.com"},
            404,
            "User 999 does not exist",
        ],
    ],
)
def test_update_user_invalid(
    test_app, test_database, user_id, payload, status_code, message
):
    client = test_app.test_client()
    resp = client.put(
        f"/users/{user_id}", data=json.dumps(payload), content_type="application/json"
    )
    data = json.loads(resp.data.decode())
    assert resp.status_code == status_code
    assert message in data["message"]

# sudo docker-compose exec api python -m pytest "src/tests"
# sudo docker-compose exec api python -m pytest "src/tests" --lf  (run tests that last failed)


import sys, ply.lex

reserved = {
    'define': 'DEFINE',
    'begin': 'BEGIN',
    'end': 'END',
    'each': 'EACH',
    'select': 'SELECT'
 }

tokens = ( 'LARROW', 'RARROW', 'LPAREN', 'RPAREN', 'LSQUARE', 'RSQUARE', 'COMMA',
            'DOT', 'PIPE', 'DOUBLEPLUS', 'DOUBLEMULT', 'DOUBLEDOT', 'COLON',
            'EQ', 'NOTEQ', 'LT', 'LTEQ', 'GT', 'GTEQ', 'PLUS', 'MINUS', 'MULT',
            'DIV', 'MOD', 'NUMBER_LITERAL', 'STRING_LITERAL', 'varIDENT',
            'constIDENT', 'tupleIDENT', 'funcIDENT', 'WHITESPACE',
            'NEWLINE', 'COMMENT', 'RES') + tuple(reserved.values())

t_LARROW = r'<-'
t_RARROW = r'->'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LSQUARE = r'\['
t_RSQUARE = r'\]'
t_COMMA = r','
t_DOT = r'\.'
t_PIPE = r'\|'
t_DOUBLEPLUS = r'\+\+'
t_DOUBLEMULT = r'\*\*'
t_DOUBLEDOT = r'\.\.'
t_COLON = r':'
t_EQ = r'='
t_NOTEQ = r'!='
t_LT = r'<'
t_LTEQ = r'<='
t_GT = r'>'
t_GTEQ = r'>='
t_PLUS  = r'\+'
t_MINUS = r'-'
t_MULT = r'\*'
t_DIV = r'/'
t_MOD = r'%'

t_constIDENT = r'[A-Z]+'
t_funcIDENT = r'[A-Z][a-z0-9_]+'
t_ignore = ' \t\r'

def not_reserved(func):
    '''
    Decorator, that checks, whether matched string is within
    the list of reserved words. In case of a match, changes the type of
    token to the appropriate reserved value.
    @:param regex-function
    @:return function with ether original or edited regex
    '''

    is_reserved = False

    def wrapper(t):
        if t.value in reserved:
            nonlocal is_reserved
            is_reserved = True
            t.type = reserved[t.value]
        return t

    if is_reserved:
        # arbitrary regex that matched all the reserved words declared in specification
        wrapper.__doc__ = r'[a-z]+'
    else:
        wrapper.__doc__ = func.__doc__

    return wrapper

def t_STRING_LITERAL(t):
    r'\"([^\"]*)\"'
    t.value = t.value.strip('"')
    return t

def t_tupleIDENT(t):
    r'<[a-z]+>'
    t.value = t.value.strip('<>')
    return t

def t_NUMBER_LITERAL(t):
    r'\d+'
    t.value = int(t.value)
    return t

def t_NEWLINE(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

# a string that matches this regex can also be a reserved word,
# therefore marked by the decorator
@not_reserved
def t_varIDENT(t):
    r'[a-z]\w+'
    return t

'''
def t_RES(t):
    r'[a-z]+'
    if t.value in reserved:
        t.type = reserved[t.value]
    return t
'''

#########################################################
# Comments related stuff

states = (
    ('comment', 'exclusive'),
)

def t_comment(t):
    r'\{'
    t.lexer.comment_start = t.lexer.lexpos  # Record the starting position
    t.lexer.level = 1  # Initial brace level
    t.lexer.begin('comment')

def t_comment_lbrace(t):
    r'\{'
    t.lexer.level += 1

def t_comment_rbrace(t):
    r'\}'
    t.lexer.level -= 1

    if t.lexer.level == 0:
        t.lexer.begin('INITIAL')

def t_comment_NEWLINE(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

def t_comment_else(t):
    r'[^\n{}]+'
    pass

t_comment_ignore = ' \t\r'

def t_comment_error(t):
    raise Exception("Illegal character '{}' at line {}".format(
        t.value[0], t.lexer.lineno ) )

def t_comment_eof(t):
    if t.lexer.lexstate == 'comment':
        raise Exception("Unexpexted end of the file. Check the count of brackets")
    return None

#########################################################

def t_error(t):
    raise Exception("Illegal character '{}' at line {}".format(
        t.value[0], t.lexer.lineno ) )

# define lexer in module level so it can be used after
# importing this module:
lexer = ply.lex.lex()

# if this module/file is the first one started (the main module)
# then run:

def main():
    import argparse, codecs
    parser = argparse.ArgumentParser()
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--who', action='store_true', help='name to print')
    group.add_argument('-f', '--file', help='filename to process')

    ns = parser.parse_args()

    if ns.who:
        # identify who wrote this
        print('276190, Magomed Udratov')

    elif ns.file is None:
        # user didn't provide input filename
        parser.print_help()
    else:
        # using codecs to make sure we process unicode
        with codecs.open(ns.file, 'r', encoding='utf-8') as INFILE:
            # blindly read all to memory (what if that is a 42Gb file?)
            # likely I am too lazy to write test files that big
            data = INFILE.read()

        lexer.input(data)

        while True:
            token = lexer.token()
            if token is None:
                break
            print(token)

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import django_extensions.db.fields
import django.utils.timezone
from django.conf import settings

class Migration(migrations.Migration):

    dependencies = [
        ('tag', '0001_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Reply',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('created', django_extensions.db.fields.CreationDateTimeField(editable=False, blank=True, default=django.utils.timezone.now)),
                ('updated', django_extensions.db.fields.ModificationDateTimeField(editable=False, blank=True, default=django.utils.timezone.now)),
                ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='replies')),
            ],
        ),
        migrations.CreateModel(
            name='Topic',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('title', models.CharField(max_length=50)),
                ('slug', django_extensions.db.fields.AutoSlugField(editable=False, blank=True, populate_from='title')),
                ('content', models.TextField(blank=True)),
                ('created', django_extensions.db.fields.CreationDateTimeField(editable=False, blank=True, default=django.utils.timezone.now)),
                ('updated', django_extensions.db.fields.ModificationDateTimeField(editable=False, blank=True, default=django.utils.timezone.now)),
                ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='topics')),
                ('tags', models.ManyToManyField(to='tag.Tag', related_name='topics')),
            ],
        ),
        migrations.AddField(
            model_name='reply',
            name='topic',
            field=models.ForeignKey(to='topic.Topic', related_name='replies'),
        ),
    ]


import torch
import torch.nn as nn

import torch.optim as optim

import torchvision
import torchvision.transforms as transforms
import torchvision.models.resnet as resnet
from torch.utils.data import DataLoader
import numpy as np
import time

from HDF5Dataset import HDF5Dataset

device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)

torch.manual_seed(777)
if device == 'cuda':
    torch.cuda.manual_seed_all(777)

# 폴더 트리 형식으로 저장되어 있는경우에 사용
transform = transforms.Compose([
    transforms.Grayscale(num_output_channels=1),
    transforms.ToTensor()
])
train_data = torchvision.datasets.ImageFolder(root='./data/Eiric/TrainType5/train_data', transform=transform)
train_loader = DataLoader(dataset=train_data, batch_size=16, shuffle=True)

transform = transforms.Compose([
    transforms.Grayscale(num_output_channels=1),
    transforms.ToTensor()
])
test_data = torchvision.datasets.ImageFolder(root='./data/Eiric/TrainType5/test_data', transform=transform)
test_loader = DataLoader(dataset=test_data, batch_size=16, shuffle=True)

# # HDF5 형식으로 되어있는 경우에 사용
# dataset = HDF5Dataset('./data/Eiric/TrainType4/TrainType4.h5', 'train_data')
# train_loader = DataLoader(dataset=dataset, batch_size=128, shuffle=True)

# dataset = HDF5Dataset('./data/Eiric/TrainType4/TrainType4.h5', 'test_data')
# test_loader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)

# for data in train_loader:
#     img, label = data
#     print(img.shape)
#     break

# 이미지 사이즈 확인하는 검토(굳이 없어도 됨)
dataiter = iter(train_loader)
images, labels = dataiter.next()
labels = labels.type('torch.LongTensor') # HDF5를 사용하여 가져올 경우에 "nll_loss_forward_reduce_cuda_kernel_2d_index" not implemented for 'Int' 에러가 발생하는데 이를 해결하기 위한 수정
# print(images, labels)
print(labels.dtype)

# ResNet 정의 시작
# ResNet에 필요한 연산 따로 정의하지 않아 라이브러리에서 불러옴
def conv3x3(in_planes, out_planes, stride=1):
    """3x3 convolution with padding"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                     padding=1, bias=False)

def conv1x1(in_planes, out_planes, stride=1):
    """1x1 convolution"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)

class BasicBlock(nn.Module):
    expansion = 1
    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(BasicBlock, self).__init__()
        self.conv1 = conv3x3(inplanes, planes, stride)
        self.bn1 = nn.BatchNorm2d(planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(planes, planes)
        self.bn2 = nn.BatchNorm2d(planes)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x
        out = self.conv1(x) # 3x3 stride = 2
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out) # 3x3 stride = 1
        out = self.bn2(out)
        if self.downsample is not None:
            identity = self.downsample(x)
        out += identity
        out = self.relu(out)
        return out

class Bottleneck(nn.Module):
    expansion = 4
    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(Bottleneck, self).__init__()
        self.conv1 = conv1x1(inplanes, planes) #conv1x1(64,64)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = conv3x3(planes, planes, stride)#conv3x3(64,64)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = conv1x1(planes, planes * self.expansion) #conv1x1(64,256)
        self.bn3 = nn.BatchNorm2d(planes * self.expansion)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x
        out = self.conv1(x) # 1x1 stride = 1
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out) # 3x3 stride = stride
        out = self.bn2(out)
        out = self.relu(out)
        out = self.conv3(out) # 1x1 stride = 1
        out = self.bn3(out)
        if self.downsample is not None:
            identity = self.downsample(x)
        out += identity
        out = self.relu(out)
        return out

class ResNet(nn.Module):
    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False):
        super(ResNet, self).__init__()
        self.inplanes = 16
        # 채널 개수에 따라서 수정되는 부분
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1, bias=False)
        # self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(16)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        self.layer1 = self._make_layer(block, 16, layers[0], stride=1)
        self.layer2 = self._make_layer(block, 32, layers[1], stride=1)
        self.layer3 = self._make_layer(block, 64, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 128, layers[3], stride=2)

        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(128 * block.expansion, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

        # Zero-initialize the last BN in each residual branch,
        # so that the residual branch starts with zeros, and each residual block behaves like an identity.
        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
        if zero_init_residual:
            for m in self.modules():
                if isinstance(m, Bottleneck):
                    nn.init.constant_(m.bn3.weight, 0)
                elif isinstance(m, BasicBlock):
                    nn.init.constant_(m.bn2.weight, 0)

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                conv1x1(self.inplanes, planes * block.expansion, stride),
                nn.BatchNorm2d(planes * block.expansion),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample))
        self.inplanes = planes * block.expansion
        for _ in range(1, blocks):
            layers.append(block(self.inplanes, planes))

        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        # x.shape =[1, 64, 128,128]
        x = self.bn1(x)
        x = self.relu(x)
        # x = self.maxpool(x)

        x = self.layer1(x)
        # x.shape =[1, 128, 32,32]
        x = self.layer2(x)
        # x.shape =[1, 256, 32,32]
        x = self.layer3(x)
        # x.shape =[1, 512, 16,16]
        x = self.layer4(x)
        # x.shape =[1, 1024, 8,8]

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)

        return x

# net의 계층의 수
netLayer = 152

# # resnet50
# resnetN = ResNet(resnet.Bottleneck, [3, 4, 6, 3], 722, True).to(device)

# resnet152
resnetN = ResNet(resnet.Bottleneck, [3, 8, 36, 3], 722, True).to(device)
# print(resnetN)

# resnet152 pretrained
# resnetN에서 Pretrained를 가져올때 사용(CUDA가 적용되지 않을수 있으므로)
# resnetN = resnet152(pretrained=True)
# num_classes = 722
# num_ftrs = resnetN.fc.in_features
# resnetN.fc = nn.Linear(num_ftrs, num_classes)
# resnetN.to("cuda:0")
# print(resnetN)

# 가중치 시각화 (#%%를 최상단에 입력하면 모듈을 설치하고 실행됨)
# for w in resnetN.parameters():
#     w = w.data.cpu()
#     print(w.shape)
#     break
# # normalize weights
# min_w = torch.min(w)
# w1 = (-1/(2 * min_w)) * w + 0.5
# # make grid to display it
# grid_size = len(w1)
# x_grid = [w1[i] for i in range(grid_size)]
# x_grid = torchvision.utils.make_grid(x_grid, nrow=8, padding=1)
# plt.imshow(x_grid.permute(1, 2, 0))

# 손실 알고리즘 정의 및 옵티마이저 정의(원래는 SGD 였으나 Adam이 더 잘 되는듯하여 변경함)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(resnetN.parameters())
# optimizer = torch.optim.SGD(resnetN.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-5)
lr_sche = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)

# 정확도 체크 해주는 함수(모델의 저장도 해줌)
def acc_check(net, test_set, epoch, save=1):
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_set:
            images, labels = data
            images = images.to(device)
            labels = labels.to(device)
            outputs = net(images)

            _, predicted = torch.max(outputs.data, 1)

            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    acc = (100 * correct / total)
    print('Accuracy of the test images: %d %%' % acc)
    if save:
        torch.save(net.state_dict(), "./model/Eiric_TrainType5/ResNet{}_Eiric_epoch_{}_acc_{}.pth".format(netLayer, epoch, int(acc)))
    return acc

print(len(train_loader))

# Train 시작
epochs = 40
for epoch in range(epochs):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(train_loader, 0):
        # get the inputs
        inputs, labels = data
        inputs = inputs.to(device)
        labels = labels.type('torch.LongTensor') # HDF5를 사용하여 가져올 경우에 "nll_loss_forward_reduce_cuda_kernel_2d_index" not implemented for 'Int' 에러가 발생하는데 이를 해결하기 위한 수정
        labels = labels.to(device)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = resnetN(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 50 == 0:  # print every 5 mini-batches
            print('[%d, %5d, %d%%] loss: %.3f' %
                  (epoch, i + 1, 100 * (i + 1) / len(train_loader), running_loss / 5))
            running_loss = 0.0
    lr_sche.step()
    if epoch % 10 == 0:
        acc = acc_check(resnetN, test_loader, epoch, save=1)
    else:
        acc = acc_check(resnetN, test_loader, epoch, save=0)
acc = acc_check(resnetN, test_loader, epochs, save=1)

print('Finished Training')


import pandas as pd
from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, GridSearchCV
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.preprocessing import StandardScaler

from tools import score

sns.set()

def write_to_file(st):
    File_Object = open("output.csv", "a")
    File_Object.write(st + "\n")
    print(st)
    File_Object.close()

dataframe = pd.read_csv("train.csv", header=None)
dataframe = dataframe.sample(frac=1).reset_index(drop=True)
dataset = dataframe.values
X = dataset[:, 0:10].astype(float)
Y = dataset[:, 10]

X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.20)

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
'''
# AdaBoost
clf = AdaBoostClassifier(n_estimators=4, algorithm='SAMME')
clf.fit(X_train, y_train)

from sklearn.ensemble import GradientBoostingClassifier

loss = ['deviance']
learning_rate = [0.15, 0.1, 0.05, 0.01, 0.005, 0.001]
n_estimators = [100, 250, 500, 750, 1000, 1250, 1500, 1750]
max_depth = [2, 3, 4, 5, 6, 7]

param_grid = {'max_features': [2, 3, 4, 5, 6, 7], 'subsample': [0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1]}

import time

grid = GridSearchCV(estimator=GradientBoostingClassifier(n_estimators=1000, max_depth=7, loss='deviance',
                                                         learning_rate=0.01, min_samples_split=4, min_samples_leaf=5)
                    , scoring='f1_weighted', param_grid=param_grid, cv=3,
                    n_jobs=-1)

start_time = time.time()
grid_result = grid.fit(X_train, y_train)
# Summarize results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
print("Execution time: " + str((time.time() - start_time)) + ' ms')
'''
clf = GradientBoostingClassifier(n_estimators=1000, max_depth=7, loss='deviance', learning_rate=0.01)
clf.fit(X_train, y_train)

labels = clf.predict(X_test)
categories = [1, 2, 3, 4, 5]

mat = confusion_matrix(y_test, labels)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
            xticklabels=categories, yticklabels=categories)
plt.xlabel('true label')
plt.ylabel('predicted label')

plt.show()

accuracy = score(y_test, labels)
print(accuracy)

dataframe = pd.read_csv("test.csv", header=None)
dataset = dataframe.values
tests = dataset[:, 0:10].astype(float)
sc = StandardScaler()

X_tests = sc.fit_transform(tests)
x_ids = dataset[:, 10]

test_values_x = clf.predict(X_tests)
write_to_file("ID,DEFCON_Level")

for x in range(0, len(test_values_x)):
    write_to_file(str(int(x_ids[x])) + "," + str(int(test_values_x[x])))


from flask import Flask,jsonify,request
from model.User import User
app = Flask(__name__)

@app.route('/users/<int:userid>', methods=['GET'])
def getUser(userid):
    try:
        results=User.getUser(userid)

        #print(results)
        message={"users":results}
        return jsonify(message),200
    except Exception as err:
        message={"message":"Error!!"}
        return jsonify(message),500

@app.route('/users') #define the api route
def getAllUsers():
    try:
        results=User.getAllUsers()

        message={"users":results}
        return jsonify(message)
    except Exception as err:
        message={"message":"Error!!"}
        return jsonify(message),500

@app.route('/users', methods=['POST'])
def insertUsers():
    try:
        userJSON=request.json
        #print(userJSON)
        count=User.insertUser(userJSON['username'],userJSON['email'],userJSON['role'],userJSON['password'])
        output={"message":str(count)+"records modified"}
        return jsonify(output),201
    except Exception as err:
        message={"message":"Error!!"}
        return jsonify(message),500

@app.route('/users/<int:userid>', methods=['PUT'])
def updateUser(userid):
    jsonBody=request.json
    email =jsonBody['email']
    count=User.updateUser(userid,email)

    if(count>0):
        return '{"message": "User with '+str(userid)+ ' has been successfully updated!"}',200
    else:
        return '{"message": "User with '+str(userid)+ ' does not exist!"}',404

@app.route('/users/<int:userid>', methods=['DELETE'])
def deleteUser(userid):

    count=User.deleteUser(userid)

    if(count>0):
        return '{"message": "User with '+str(userid)+ ' has been successfully deleted!"}',200
    else:
        return '{"message": "User with '+str(userid)+ ' does not exist!"}',404

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


import os
from typing import List, Optional, Sequence, overload

import torch

import rascaline

if os.environ.get("RASCALINE_IMPORT_FOR_SPHINX") is None:
    System = torch.classes.rascaline.System
else:
    # Documentation for the `System` class, only used when loading the code with sphinx
    class System:
        """
        A single system for which we want to run a calculation.

        Contrary to the Python API of rascaline, only this class is supported as input
        to a :py:class:`CalculatorModule`, but any of the supported system class can be
        transformed to this one with :py:func:`systems_to_torch`.
        """

        def __init__(
            self,
            species: torch.Tensor,
            positions: torch.Tensor,
            cell: torch.Tensor,
        ):
            """
            :param species: species of the atoms/particles in this system. This should
                be a 1D array of integer containing different values for different
                system. The species will typically match the atomic element, but does
                not have to.
            :param positions: positions of the atoms/particles in this system. This
                should be a ``len(species) x 3`` 2D array containing the positions of
                each atom.
            :param cell: 3x3 cell matrix for periodic boundary conditions, where each
                row is one of the cell vector. Use a matrix filled with ``0`` for
                non-periodic systems.
            """

        @property
        def species(self) -> torch.Tensor:
            """the species of the atoms/particles in this system"""

        @property
        def positions(self) -> torch.Tensor:
            """the positions of the atoms/particles in this system"""

        @property
        def cell(self) -> torch.Tensor:
            """
            the bounding box for the atoms/particles in this system under periodic
            boundary conditions, or a matrix filled with ``0`` for non-periodic systems
            """

@overload
def systems_to_torch(
    systems: rascaline.systems.IntoSystem,
    positions_requires_grad: Optional[bool] = None,
    cell_requires_grad: Optional[bool] = None,
) -> System:
    pass

@overload
def systems_to_torch(
    systems: Sequence[rascaline.systems.IntoSystem],
    positions_requires_grad: Optional[bool] = None,
    cell_requires_grad: Optional[bool] = None,
) -> List[System]:
    pass

def systems_to_torch(
    systems,
    positions_requires_grad=None,
    cell_requires_grad=None,
) -> List[System]:
    """
    Convert a arbitrary system to rascaline-torch :py:class:`System`, putting all the
    data in :py:class:`torch.Tensor` and making the overall object compatible with
    TorchScript.

    :param system: any system supported by rascaline. If this is an iterable of system,
        this function converts them all and returns a list of converted systems.

    :param positions_requires_grad: The value of ``requires_grad`` on the output
        ``positions``. If :py:obj:`None`` and the positions of the input is already a
        :py:class:`torch.Tensor`, ``requires_grad`` is kept the same. Otherwise it is
        initialized to :py:obj:`False`.

    :param cell_requires_grad: The value of ``requires_grad`` on the output ``cell``. If
        :py:obj:`None` and the positions of the input is already a
        :py:class:`torch.Tensor`, ``requires_grad`` is kept the same. Otherwise it is
        initialized to :py:obj:`False`.
    """

    try:
        return _system_to_torch(systems, positions_requires_grad, cell_requires_grad)
    except TypeError:
        # try iterating over the systems
        return [
            _system_to_torch(system, positions_requires_grad, cell_requires_grad)
            for system in systems
        ]

def _system_to_torch(system, positions_requires_grad, cell_requires_grad):
    if not _is_torch_system(system):
        system = rascaline.systems.wrap_system(system)
        system = System(
            species=torch.tensor(system.species()),
            positions=torch.tensor(system.positions()),
            cell=torch.tensor(system.cell()),
        )

    if positions_requires_grad is not None:
        system.positions.requires_grad_(positions_requires_grad)

    if cell_requires_grad is not None:
        system.cell.requires_grad_(cell_requires_grad)

    return system

def _is_torch_system(system):
    if not isinstance(system, torch.ScriptObject):
        return False

    # we would like to use system._type() here, but it is broken in torch <2.1
    properties = system._properties()
    if len(properties) != 3:
        return False

    if properties[0].name != "species":
        return False

    if properties[1].name != "positions":
        return False

    if properties[2].name != "cell":
        return False

    return True


import tensorflow as tf
import numpy as np
import torch
import torchvision.utils as vutils
from tqdm import tqdm
from tensorflow.examples.tutorials.mnist import input_data
from tensorboardX import SummaryWriter

mnist = input_data.read_data_sets("/tmp/", one_hot=True)

noise_size = 100
total_epoch = 200

def get_noise(batch_size):
    return np.random.normal(0, 1., size=[batch_size, noise_size]).astype(np.float32)

def gan_log_loss(pos, neg, name='gan_log_loss'):
    """
    log loss function for GANs.
    - Generative Adversarial Networks: https://arxiv.org/abs/1406.2661
    """
    with tf.variable_scope(name):
        # generative model G
        gl = tf.reduce_mean(
            tf.nn.sigmoid_cross_entropy_with_logits(
                logits=neg, labels=tf.ones_like(neg)))
        # discriminative model D
        d_loss_pos = tf.reduce_mean(
            tf.nn.sigmoid_cross_entropy_with_logits(
                logits=pos, labels=tf.ones_like(pos)))
        d_loss_neg = tf.reduce_mean(
            tf.nn.sigmoid_cross_entropy_with_logits(
                logits=neg, labels=tf.zeros_like(neg)))
        pos_acc = tf.reduce_mean(tf.sigmoid(pos))
        neg_acc = tf.reduce_mean(tf.sigmoid(neg))
        # loss
        dl = tf.add(.5 * d_loss_pos, .5 * d_loss_neg)
    return gl, dl, pos_acc, neg_acc

def dense_layer(in_tensor, out_size, name, activation=True, batch_norm=True):
    x = tf.layers.dense(in_tensor, out_size, name=name)

    if activation:
        x = tf.nn.leaky_relu(x)

    if batch_norm:
        x = tf.layers.batch_normalization(x, name=name)

    return x

def gen(noise, reuse=False):
    with tf.variable_scope('gen') as scope:
        if reuse:
            scope.reuse_variables()

        layer1 = dense_layer(noise, 256, name='g_layer1')
        layer2 = dense_layer(layer1, 512, name='g_layer2')
        layer3 = dense_layer(layer2, 1024, name='g_layer3')

        result_img = tf.nn.tanh(dense_layer(layer3, 784, activation=False,
                                            batch_norm=False, name='g_layer4'))

    return result_img

def dis(img, reuse=False):
    with tf.variable_scope('gen') as scope:
        if reuse:
            scope.reuse_variables()

        layer1 = tf.nn.leaky_relu(tf.layers.dense(img, 512, name='d_layer1'))
        layer2 = tf.nn.leaky_relu(tf.layers.dense(layer1, 256, name='d_layer2'))
        layer3 = tf.nn.leaky_relu(tf.layers.dense(layer2, 64), name='d_layer3')
        result = tf.layers.dense(layer3, 1, name='d_layer4')

    return result

noise_input = tf.placeholder(tf.float32, [None, noise_size])
real_input = tf.placeholder(tf.float32, [None, 784])

# real img
D_real = dis(real_input, reuse=False)

# fake img
G_img = gen(noise_input, reuse=False)
D_fake = dis(G_img, reuse=True)

g_loss, d_loss, t_acc, f_acc = gan_log_loss(D_real, D_fake)

t_vars = tf.trainable_variables()
d_vars = [var for var in t_vars if 'd_' in var.name]
g_vars = [var for var in t_vars if 'g_' in var.name]

d_optimization = tf.train.AdamOptimizer(learning_rate=0.0002).minimize(d_loss, var_list=d_vars)
g_optimization = tf.train.AdamOptimizer(learning_rate=0.0002).minimize(g_loss, var_list=g_vars)

sample_img = gen(noise_input, reuse=True)
saver = tf.train.Saver()

writer = SummaryWriter()
sess = tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in tqdm(range(total_epoch)):
    for idx in range(60):
        batch_xs, _ = mnist.train.next_batch(100)
        batch_z = get_noise(100)

        # update D
        sess.run(d_optimization, feed_dict={noise_input: batch_z,
                                            real_input: batch_xs})

        # update G
        sess.run(g_optimization, feed_dict={noise_input: batch_z})
        # sess.run(g_optimization, feed_dict={noise_input: batch_z})

        # calc loss
        dis_loss = sess.run(t_acc, feed_dict={real_input: batch_xs,
                                               noise_input: batch_z})
        gen_loss = sess.run(f_acc, feed_dict={noise_input: batch_z})

    writer.add_scalar('data/d_loss', dis_loss, epoch)
    writer.add_scalar('data/g_loss', gen_loss, epoch)

    # sample
    if (epoch + 1) % 10 == 0:
        sample = sess.run(sample_img, feed_dict={noise_input: batch_z})
        re_sample = torch.from_numpy(np.reshape(sample, (100, 1, 28, 28)))
        x = vutils.make_grid(re_sample, normalize=True, scale_each=True)
        writer.add_image('Image{}'.format(epoch), x, epoch)

writer.close()


from opcua import Server
import datetime
from random import randint
import time

file = open("ServerPrinzipAlle82.txt","w")

server = Server()

url = "opc.tcp://192.168.178.53:4840"

server.set_endpoint(url)
print("SUCCESS SERVER CHECKED...SERVER IS LISTING ON:", url)
server.allow_remote_admin(1)

name = "OPCSERVER_PARAMS_PI"
addspace = server.register_namespace(name)

node = server.get_objects_node()

Param = node.add_object(addspace, "Parameters")

Temp = Param.add_variable(addspace, "TemperatureC", "0")
TempF = Param.add_variable(addspace, "TemperatureF", "0")

Time = Param.add_variable(addspace, "Time", 0)

Temp.set_writable()
TempF.set_writable()
Time.set_writable()

server.start()
print("Server started")
nameSpace = server.get_namespace_array()
print("Current Namespace on Server: ", nameSpace[2])
print("-----------------------------------------------")

sec = 0.0
while True:

    TIME = datetime.datetime.now()
    temperature = Temp.get_value()
    Temp.set_value(temperature)
    temperatureF = TempF.get_value()
    TempF.set_value(temperatureF)
    print("Temperature: ",temperature ,"°C", "|",temperatureF, "°F ","TimeStamp ", TIME)
    file.write("{0:.1f}".format(sec) + " " + str(temperature)+"\n")
    sec = sec+0.1

    Time.set_value(TIME)

    time.sleep(0.1)


import unittest
from collections import namedtuple
from day_3 import parse_claims
from day_3 import find_overlapping_square_inches, find_not_overlapping_claim

class TestFabricClaims(unittest.TestCase):
    """Test claims on the special fabric."""

    def test_prase_claims(self):
        Test = namedtuple('Test', ['claims_as_strings', 'expected'])
        Claim = namedtuple('Claim', ['id', 'pos', 'size'])
        tests = [Test(claims_as_strings=["#1 @ 1,3: 4x4",
                                         "#2 @ 3,1: 4x4",
                                         "#3 @ 5,5: 2x2"],
                      expected=[Claim(id=1, pos=(1, 3), size=(4, 4)),
                                Claim(id=2, pos=(3, 1), size=(4, 4)),
                                Claim(id=3, pos=(5, 5), size=(2, 2))])]

        for test in tests:
            result = parse_claims(test.claims_as_strings)
            self.assertEqual(result, test.expected)

    def test_find_overlapping_square_inches(self):
        Test = namedtuple('Test', ['claims', 'expected'])
        tests = [
            Test(expected=4,
                 claims=["#1 @ 1,3: 4x4", "#2 @ 3,1: 4x4", "#3 @ 5,5: 2x2"])]

        for test in tests:
            result = find_overlapping_square_inches(test.claims)
            self.assertEqual(result, test.expected)

    def test_find_not_overlapping_claim(self):
        Test = namedtuple('Test', ['claims', 'expected'])
        tests = [
            Test(expected=3,
                 claims=["#1 @ 1,3: 4x4", "#2 @ 3,1: 4x4", "#3 @ 5,5: 2x2"])]

        for test in tests:
            result = find_not_overlapping_claim(test.claims)
            self.assertEqual(result, test.expected)

if __name__ == '__main__':
    unittest.main()


import torch
from torch.utils.data import DataLoader

from model_p2.vgg16_fcn8 import Vgg16FCN8
from model_p2.sat_image_dataset import SatImageTestDataset, SatImageDataset
from parse_config import create_parser
from utils import load_checkpoint, save_mask
from mean_iou_evaluate import mean_iou_score, read_masks

if __name__ == '__main__':
    # init configs from args
    parser = create_parser()
    configs = parser.parse_args()

    test_dataset = SatImageTestDataset(configs.p2_input_dir)
    test_dataloader = DataLoader(test_dataset, batch_size=configs.batch_size,
                                 shuffle=False)

    ckpt = load_checkpoint(configs.ckpt)

    net = Vgg16FCN8()
    net.load_state_dict(ckpt['net'])
    net.eval()

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    print('Using device:', device)
    net.to(device)

    with torch.no_grad():
        # Validating:
        # val_dataset = SatImageDataset(configs.p2_input_dir)
        # val_dataloader = DataLoader(val_dataset, batch_size=configs.batch_size,
        #                             shuffle=False)
        #
        # for val_data in val_dataloader:
        #     images, labels, img_filenames_prefix = val_data[0].to(device), val_data[1], val_data[2]
        #     outputs = net(images)
        #     predicted = outputs.max(dim=1)[1].data.cpu().numpy()
        #     save_mask('./p2_valid', predicted, img_filenames_prefix)
        #
        # pred = read_masks('./p2_valid')
        # labels = read_masks(configs.p2_input_dir)
        # miou = mean_iou_score(pred, labels)
        # print('Valid mIoU: {:.4f}'
        #       .format(miou))

        # Testing:
        for test_data in test_dataloader:
            images, filenames = test_data[0].to(device), test_data[1]
            outputs = net(images)
            predicted = outputs.max(dim=1)[1].data.cpu().numpy()
            save_mask(configs.p2_output_dir, predicted, filenames, mode='Test')