import sys
import os
import shutil
import time
import re
import numpy as np

# Define console logs colors
class bcolors:
    HEADER = '\033[95m'
    BLUE = '\033[94m'
    CYAN = '\033[96m'
    GREEN = '\033[92m'
    WARNING = '\033[93m'
    RED = '\033[91m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
    ENDC = '\033[0m'

print(bcolors.HEADER + "This script launch a bunch of trainings of TpgVVCPartDatabase for different database. /!\\ Can only be used in specific conditions." + bcolors.ENDC)

# Create MACRO to execute bash commands adn print it in stdout
def execAndPrintBashCmd(cmd, spaces):
    print(bcolors.BLUE + spaces + cmd + bcolors.ENDC)
    os.system(cmd)

# Define a function to print a time from seconds to human redable format
def printHumanTimeFromSeconds(value, spaces):
    valueD  = (((value/60)/60)/24)
    Days    = int(valueD)
    valueH  = (valueD-Days)*24
    Hours   = int(valueH)
    valueM  = (valueH - Hours)*60
    Minutes = int(valueM)
    valueS  = (valueM - Minutes)*60
    Seconds = int(valueS)
    print(bcolors.CYAN + spaces + str(Days) + " days, " + str(Hours) + "h " + str(Minutes) + "min " + str(Seconds) + "s" + bcolors.ENDC)

# Time the whole script
veryStartTime = time.time()

# Init main arguments
pathExec        = "/home/cleonard/dev/TpgVvcPartDatabase2/"
pathRes         = "/home/cleonard/dev/stage/results/scripts_results/BinaryFeatures/cascade-full/TaillesDif/ult-script3_BalancedDTB/"
pathBalancedDTB = "/media/cleonard/alex/cedric_TPG-VVC/balanced_datasets/"
execName        = "TPGVVCPartDatabase_binaryFeaturesEnv"
seed            = 0

# Init and open recapitulative files
fileRecapBalancedName = pathBalancedDTB + "Balanced_DTB_Composition.txt"
fileRecapAllScoreName = pathRes + "RecapAllScore.txt"

# Store params.json file
print("\n\nCopy trainings parameters \"params.json\" in " + pathRes + "params.json")
shutil.copy(pathExec + "params.json", pathRes)

# Build and compile the executable once
print(bcolors.HEADER + "Build and compile the executable:" + bcolors.ENDC)
execAndPrintBashCmd("/usr/local/bin/cmake " + pathExec + " -DCMAKE_BUILD_TYPE=Release -DTESTING=1", "")
execAndPrintBashCmd("/usr/local/bin/cmake --build " + pathExec + "build/ --target " + execName + " -- -j 38", "")

# Init fileRecapAllScore
with open(fileRecapAllScoreName, "a") as fileRecapAllScore:
    print("Final results are stored in \"" + fileRecapAllScoreName + "\"")
    fileRecapAllScore.write("Final scores of each training:\n")
    fileRecapAllScore.write("DTB Split Score Generation Time\n")

# Define actions name
actionsName      = ["NP", "QT", "BTH", "BTV", "TTH", "TTV"]
remainingActions = ["{1,2,3,4,5}", "{0,2,3,4,5}", "{0,1,3,4,5}", "{0,1,2,4,5}", "{0,1,2,3,5}", "{0,1,2,3,4}"]

# Every dtb size
#size = np.array(["128x128"]) # For test purposes
size = np.array(["128x128", "64x64", "32x32", "16x16", "8x8", "64x32", "32x64", "64x16", "16x64", "32x16", "16x32", "64x8", "8x64", "32x8", "8x32", "16x8", "8x16", "64x4", "4x64", "32x4", "4x32", "16x4", "4x16", "8x4", "4x8"]) # 25 different dtb

# For each dtb, how many CNN features does a single .csv file own ?
nbFeaturesDict = {        "4x8" : 1,    "4x16" : 3,    "4x32" : 7,   "4x64" : 14,
             "8x4" : 1,   "8x8" : 4,   "8x16" : 10,   "8x32" : 22,   "8x64" : 46,
            "16x4" : 3, "16x8" : 10,  "16x16" : 24,  "16x32" : 52, "16x64" : 108,
            "32x4" : 7, "32x8" : 22,  "32x16" : 52, "32x32" : 112, "32x64" : 232,
           "64x4" : 14, "64x8" : 46, "64x16" : 108, "64x32" : 232, "64x64" : 480,
           "128x128" : 1984 }

# For each dtb, which splits are available ?
availableSplitsDict = {            "4x8" : [0, 3],            "4x16" : [0, 3, 5],           "4x32" : [0, 3, 5],           "4x64" : [0, 3, 5],
            "8x4" : [0, 2],     "8x8" : [0, 2, 3],         "8x16" : [0, 2, 3, 5],        "8x32" : [0, 2, 3, 5],        "8x64" : [0, 2, 3, 5],
        "16x4" : [0, 2, 4], "16x8" : [0, 2, 3, 4],  "16x16" : [0, 1, 2, 3, 4, 5],    "16x32" : [0, 2, 3, 4, 5],    "16x64" : [0, 2, 3, 4, 5],
        "32x4" : [0, 2, 4], "32x8" : [0, 2, 3, 4],     "32x16" : [0, 2, 3, 4, 5], "32x32" : [0, 1, 2, 3, 4, 5],    "32x64" : [0, 2, 3, 4, 5],
        "64x4" : [0, 2, 4], "64x8" : [0, 2, 3, 4],     "64x16" : [0, 2, 3, 4, 5],    "64x32" : [0, 2, 3, 4, 5], "64x64" : [0, 1, 2, 3, 4, 5],
        "128x128" : [0, 1] }

trainingNumber = 1

# For every database
for i in range(len(size)):

    # Compute dtb name + result directory name
    dtb = size[i]
    arrivalDir = pathRes + "dtb" + str(i) + "_" + dtb + "/"
    cuHeight = dtb.split("x")[0]
    cuWidth  = dtb.split("x")[1]

    print(bcolors.RED + "\n****************************************************** " + dtb + " ******************************************************" + bcolors.ENDC)

    # Create database specific directory + "all"
    print(bcolors.HEADER + "Create specific database directory and the \"all\" directory" + bcolors.ENDC + bcolors.WARNING)
    os.system("mkdir " + arrivalDir)
    os.system("mkdir " + arrivalDir + "all/")

    # Copy inside params.json
    shutil.copy(pathExec + "params.json", arrivalDir + "all/params.json")

    # Init the recapfile
    resultFile = arrivalDir + "recapScore.log"
    with open(resultFile, "w") as file:
        file.write("Final scores of each training :\n")

    # For each available splits for this dtb: launch one training
    for j in range(len(availableSplitsDict[dtb])):

        # ------- Time this single training -------
        startTime = time.time()

        # ------- Define split, split name, dtb path and results file names -------
        act         = availableSplitsDict[dtb][j]
        actName     = actionsName[act]
        logsFile    = "logs_ent"        + str(j) +"_b" + actName
        confMatFile = "confMat_ent"     + str(j) +"_b" + actName
        fullconfMat = "FullConfMat_ent" + str(j) +"_b" + actName
        dtbPath     = pathBalancedDTB + dtb + "_balanced/"

        # ------- Print which training is starting -------
        print(bcolors.ENDC + bcolors.CYAN + "    --------------- Training N°" + str(trainingNumber) + ": " + actName + " ---------------" + bcolors.ENDC)

        # ------- Get nbDatabaseElements from "Balanced_DTB_Composition.txt" -------
        nbDtbElements = -1
        with open(fileRecapBalancedName, "r") as file:
            for line in file:
                if re.search("^" + dtb + "_balanced", line):
                    print("    Database composition: \"" + bcolors.GREEN + line[:-1] + bcolors.ENDC + "\"")
                    words = line.split(' ')
                    nbDtbElements = int(words[-1][:-1])
                    #print("    Total elements in the database: " + bcolors.GREEN + str(nbDtbElements) + bcolors.ENDC)

        # ------- Start the training -------
        print(bcolors.HEADER + "    Launch training and redirect logs in " + logsFile + ".log:" + bcolors.ENDC)
        execAndPrintBashCmd(pathExec +"build/" + execName +
                               " \"{" + str(act) + "}\"" +
                               " \"" + remainingActions[act] + "\"" +
                               " \"" + str(seed) + "\"" +
                               " \"" + cuHeight  + "\"" +
                               " \"" + cuWidth   + "\"" +
                               " \"" + str(nbFeaturesDict[dtb]) + "\"" +
                               " \"" + str(nbDtbElements) + "\"" +
                               " " + actName +
                               " " + dtbPath + " 1 > " + pathExec + "build/" + logsFile + ".log", "    ")

        # ------- Look for best score and generation in the confusion matrix -------
        print(bcolors.HEADER + "\n    Look for best score and generation in confusion matrix:" + bcolors.ENDC + bcolors.WARNING)
        # Get every scores of the file, sort them
        os.system("cat " + pathExec + "fileClassificationTable.txt | grep -o '[0-9]*\\.[0-9]*$' | sort -n > everyScore.txt")
        # Get last score, after the sort: the higher <=> the best
        os.system("cat everyScore.txt | perl -ne 'print if eof' | grep -o '[0-9]*\\.[0-9]*$' > bestScore.txt")
        os.system("rm everyScore.txt")
        # Get bestScore from temporary file
        bestScore = -1.0
        with open("bestScore.txt", "r") as file:
            for line in file:
                bestScore = float(line)
                #print(bestScore)
        os.system("rm bestScore.txt")
        # Get best generation number from bestScore
        execAndPrintBashCmd("cat " + pathExec + "fileClassificationTable.txt | grep " + str(bestScore) + " | grep -o '^\\s*[0-9]*' | sort -n | perl -ne 'print if eof' | grep -o '[0-9]*$' > genBestScore.txt", "    ")
        genBestScore = -1
        with open("genBestScore.txt", "r") as file:
            for line in file:
                genBestScore = int(line)
                #print(genBestScore)
        os.system("rm genBestScore.txt")

        # ------- Replace . with , (Libre Office Calc usage) -------
        bestScore = str(bestScore).replace(".", ",")

        # ------- Time this training -------
        endTime = int(time.time() - startTime)

        # ------- Store results in the recap file -------
        with open(resultFile, "a") as file:
            results = str(act) + " " + remainingActions[act] + " " + str(endTime) + " " + str(genBestScore) + " " + bestScore + "\n"
            print(bcolors.ENDC + bcolors.GREEN + "    " + results + bcolors.ENDC)
            file.write(results)

        # ------- Store results in the overall recap file -------
        with open(fileRecapAllScoreName, "a") as fileRecapAllScore:
            fileRecapAllScore.write(dtb + "_" + actName + " " + bestScore + " " + str(genBestScore) + " " +  str(endTime) + "\n")

        # ------- Move every results files in pathRes (logs, best stats, etc.) -------
        print(bcolors.HEADER + "    Store results in " + arrivalDir + actName + "/" + bcolors.ENDC + bcolors.WARNING)
        # Create action directory
        os.system("mkdir " + arrivalDir + actName)
        # logs.log
        os.system("mv " + pathExec + "build/" + logsFile + ".log " + arrivalDir + actName + "/" + logsFile + "_" + bestScore + ".log")
        # bestStats
        os.system("mv " + pathExec + "build/out_best_stats.md " + arrivalDir + actName + "/out_best_stats_ent" + str(trainingNumber) + "_b" + actName + "_" + bestScore + ".md")
        # TPG (.dot)
        tpgFileName = arrivalDir + actName + "/out_best_last_ent" + str(trainingNumber) + "_b" + actName + "_" + bestScore + ".dot"
        execAndPrintBashCmd("mv " + pathExec + "build/out_best.dot " + tpgFileName, "    ")
        # Special Policy stats
        os.system("mv " + pathExec + "build/bestPolicyStats.md " + arrivalDir + actName + "/bestPolicyStats_ent" + str(trainingNumber) + "_b" + actName + "_" + bestScore + ".md")
        # Confusion matrix
        os.system("mv " + pathExec + "fileClassificationTable.txt " + arrivalDir + actName + "/" + confMatFile + "_" + bestScore + ".txt")
        # Full Confusion matrix
        os.system("mv " + pathExec + "fullClassifTable.txt " + arrivalDir + actName + "/" + fullconfMat + "_" + bestScore + ".txt")

        # ------- Copy .dot file for all/ directory -------
        #print(bcolors.ENDC + "    Copy .dot file: " + bcolors.BLUE + "mv " + tpgFileName + " " + arrivalDir + "all/" + actName + ".dot" + bcolors.ENDC + bcolors.WARNING)
        shutil.copy(tpgFileName, arrivalDir + "all/" + actName + ".dot")

        # ------- Print training time -------
        print(bcolors.ENDC + "    This training last:")
        printHumanTimeFromSeconds(endTime, "    ")
        print("")

        # ------- Go to next training -------
        trainingNumber += 1

    # ------- Complete all/ directory with the final scores file -------
    print("  Copy recapScore file: " + bcolors.BLUE + "mv " + resultFile + " " + arrivalDir + "all/recapScore.log" + bcolors.ENDC)
    shutil.copy(resultFile, arrivalDir + "all/recapScore.log")

    # Jump one line in overall recap file between databases
    with open(fileRecapAllScoreName, "a") as fileRecapAllScore:
        fileRecapAllScore.write("\n")

# Print total time
print("The script went on for: ")
printHumanTimeFromSeconds(round(time.time() - veryStartTime), "")


from .LLC_gym_forward_walker import LLC_RoboschoolForwardWalker
from .gym_urdf_robot_env import RoboschoolUrdfEnv
from roboschool.scene_abstract import cpp_household
from roboschool.scene_stadium import SinglePlayerStadiumScene
import numpy as np

class NaoLLC(LLC_RoboschoolForwardWalker, RoboschoolUrdfEnv):
    '''
    3-D humanoid robot similar to Nao robot.
    The task is to make the robot follow two steps
    '''
    random_yaw = True
    foot_list = ["r_ankle", "l_ankle"]

    def __init__(self):
        LLC_RoboschoolForwardWalker.__init__(self, power=1)
        RoboschoolUrdfEnv.__init__(self,
            "nao_description/urdf/naoV50_generated_urdf/nao.urdf",
            "torso",
            action_dim = 26, obs_dim = 67*4*4,
            fixed_base = False,
            self_collision = True)

    def create_single_player_scene(self):
        return SinglePlayerStadiumScene(gravity=9.8, timestep=0.033/16, frame_skip=16)   # 8 instead of 4 here

    def alive_bonus(self, z, pitch):
        # This is debug code to fix unwanted self-collisions:
        #for part in self.parts.values():
        #    contact_names = set(x.name for x in part.contact_list())
        #    if contact_names:
        #        print("CONTACT OF '%s' WITH '%s'" % (part.name, ",".join(contact_names)) )

        x,y,z = self.head.pose().xyz()
        # Failure mode: robot doesn't bend knees, tries to walk using hips.
        # We fix that by a bit of reward engineering.
        knees = np.array([j.current_relative_position() for j in [self.jdict["LKneePitch"], self.jdict["RKneePitch"]]], dtype=np.float32).flatten()
        knees_at_limit = np.count_nonzero(np.abs(knees[0::2]) > 0.985)
        return +1 if z > 0.2 else -1 #Editado por Fer original: +6 y z>1.3

    def robot_specific_reset(self):
        LLC_RoboschoolForwardWalker.robot_specific_reset(self)
        self.set_initial_orientation(yaw_center=0, yaw_random_spread=np.pi/3.0)
        self.head = self.parts["Head"]

    random_yaw = False

    def set_initial_orientation(self, yaw_center, yaw_random_spread):
        cpose = cpp_household.Pose()
        if not self.random_yaw:
            yaw = yaw_center
        else:
            yaw = yaw_center + self.np_random.uniform(low=-yaw_random_spread, high=yaw_random_spread)

        cpose.set_xyz(self.start_pos_x, self.start_pos_y, self.start_pos_z + self.initial_z)
        cpose.set_rpy(0, 0, yaw)  # just face random direction, but stay straight otherwise
        self.cpp_robot.set_pose_and_speed(cpose, 0,0,0)
        #self.initial_z = 0.35


import sqlite3
global c, conn

conn = sqlite3.connect('jerbot-neo.db')
conn.row_factory = lambda cursor, row: row[0]
c = conn.cursor()

def try_create_table(table: str, keys: tuple):
    """
    Creates a table if it does not exist.
    :param table: String corresponding to a table in the SQLite database.
    :param keys: Tuple of keys for new table.
    :return: False if table exists or could not be created, True if created
    """
    try:
        c.execute(f'CREATE TABLE {table} {keys}')
        conn.commit()
        return True
    except sqlite3.OperationalError:
        return False

def drop_table(table: str):
    """
    Drops a table from the database.
    :param table: String corresponding to a table in the SQLite database.
    :return: True if table was successfully dropped.
    """
    try:
        c.execute(f'DROP TABLE {table}')
        conn.commit()
        return True
    except sqlite3.OperationalError:
        return False

def insert(table: str, values: tuple):
    """
    Inserts values into a table.
    :param table: String corresponding to a table in the SQLite database.
    :param values: Tuple of values to insert into the table.
    :return: False if data could not be inserted, True if inserted
    """
    c.execute(f'INSERT INTO {table} VALUES {values}')
    conn.commit()

def remove(table:str, exp: str):
    """
    Removes values from a table.
    :param table: String corresponding to a table in the SQLite database.
    :param exp: Expression for deletion.
    """
    c.execute(f'DELETE FROM {table} WHERE {exp}')
    conn.commit()

def query(query: str):
    """
    Queries from the database.
    Dangerous. DO NOT EXPOSE to a user command.
    :param query: String containing the query for the database.
    :return: fetchall() from query
    """
    c.execute(query)
    return c.fetchall()


import os
import pathlib
import shutil
import sys

def create_sub_dirs(project_dir):
    sub_dirs = ["css", "js", "imgs"]
    for sub_dir in sub_dirs:
        sub_path = pathlib.PurePath(project_dir, sub_dir)
        os.mkdir(sub_path)

def generate_files(project_dir, site_starter_path):
    def create_index_html_file():
        index_template_path = pathlib.PurePath(site_starter_path,"index_template.html")
        index_file_path = pathlib.PurePath(project_dir, "index.html")
        shutil.copyfile(index_template_path, index_file_path)

    def create_css_files():
        css_file_path = pathlib.PurePath(project_dir, "css", "styles.css")
        f = open(css_file_path, "w")
        f.close()

    def create_js_file():
        js_file_path = pathlib.PurePath(project_dir, "js", "main.js")
        f = open(js_file_path, "w")
        f.close()

    create_index_html_file()
    create_css_files()
    create_js_file()

def main():
    if len(sys.argv) <= 1:
        print("Site Starter generates a project file with the specified project name in the cwd.")
        print("Usage: python3 path_to_generate.py <project_name>")
    else:
        cwd = os.getcwd()
        site_starter_path = pathlib.PurePath(sys.argv[0]).parent
        project_dir = pathlib.PurePath(cwd, sys.argv[1])
        os.mkdir(project_dir)
        create_sub_dirs(project_dir)
        generate_files(project_dir, site_starter_path)

if __name__ == '__main__': main()


import math

#write a function that will convert base-60 to base-10
def convertSexagesimalToDecimal(tuple):
    degrees = tuple[0]
    arcminutes = tuple[1]
    arcseconds = tuple[2]
    sign = 1 #toggle sign
    if (degrees < 0):
        degrees = -degrees #make degrees positive
        sign = -1 #store the sign for later
    #use change of base formula and include sign in product
    comp = sign * (degrees + (arcminutes/60) + (arcseconds/3600))
    return comp #return the computation

#helper function to convert from base-10 to base-60 for time
def convertDecimalToSexagesimal(decimal):
    sign = 1
    if (decimal < 0): #in the case that the decimal is negative
        sign = -1 #store the sign
        decimal = -decimal #reverse decimal variable (to keep positive)
    degrees = math.trunc(decimal) #whole number is in degrees
    #truncate (remaining x 60) to get arcminutes
    arcminutes = math.trunc((decimal-degrees) * 60)
    #truncate (remaining x 60) to get arcseconds
    arcseconds =  round(((decimal-degrees) * 60 - arcminutes) * 60)
    degrees *= sign #add the initial sign to the degrees portion of tuple

    return (degrees, arcminutes, arcseconds);

#helper function to convert from decimal degrees to radians
def convertToRadians(decimal):
    return (2 * math.pi/360) * decimal

#function to calculate angular separation between stars
def calculateAngularSeparation(ra1, d1, ra2, d2):
    #converting all units to radians
    ra1_decimal = convertSexagesimalToDecimal(ra1)
    ra2_decimal = convertSexagesimalToDecimal(ra2)
    d1_decimal = convertSexagesimalToDecimal(d1)
    d2_decimal = convertSexagesimalToDecimal(d2)
    ra1_radians = convertToRadians(360 * ra1_decimal/24)
    ra2_radians = convertToRadians(360 * ra2_decimal/24)
    d1_radians = convertToRadians(d1_decimal)
    d2_radians = convertToRadians(d2_decimal)

    #apply the Angular Separation Formula & convert from radians to degrees
    theta = (180/math.pi) * math.acos((math.sin(d1_radians)*math.sin(d2_radians) +
            math.cos(d1_radians)*math.cos(d2_radians)*math.cos(ra1_radians-ra2_radians)))
    return convertDecimalToSexagesimal(theta) #convert answer to base 60

#Star Data
altair_ra = (19, 51, 0)
altair_d = (8, 52, 0)
vega_ra = (18, 37, 0)
vega_d = (38, 47, 0)
deneb_ra = (20, 41, 0)
deneb_d = (45, 19, 0)
# Altair and Vega: (34, 12, 48)
print(calculateAngularSeparation(altair_ra, altair_d, vega_ra, vega_d))
# Vega and Deneb: (23, 45, 51)
print(calculateAngularSeparation(vega_ra, vega_d, deneb_ra, deneb_d))
# Altair and Deneb: (38, 0, 35)
print(calculateAngularSeparation(altair_ra, altair_d, deneb_ra, deneb_d))


def toJadenCase(string):
    temp = string.split(' ')
    result = ''
    for palabra in temp:
        avanzando = palabra.capitalize()
        result = result + ' ' + avanzando
    print(result[1:])

# return " ".join(word.capitalize() for word in string.split(' '))

toJadenCase('and send simple email messages')


# coding=utf-8
"""Site model definition.

"""

import logging
import requests
import json

from django.core.exceptions import ValidationError
from django.contrib.gis.db import models
from django.dispatch import receiver
from django.contrib.postgres.fields import JSONField
from django.conf import settings

from bims.models.location_type import LocationType
from bims.utils.get_key import get_key
from bims.models.document_links_mixin import DocumentLinksMixin
from bims.models.search_process import SearchProcess
from bims.enums.geomorphological_zone import GeomorphologicalZoneCategory

LOGGER = logging.getLogger(__name__)

class LocationSite(DocumentLinksMixin):
    """Location Site model."""

    __original_centroid = None
    geocontext_url_format = '{geocontext_url}/api/v1/geocontext/value/' \
                            'collection/{longitude}/{latitude}/' \
                            '{geocontext_collection_key}'

    name = models.CharField(
        max_length=300,
        blank=False,
    )
    site_description = models.CharField(
        max_length=500,
        blank=True,
        default=''
    )
    site_code = models.CharField(
        max_length=100,
        blank=True,
        default=''
    )
    legacy_site_code = models.CharField(
        max_length=100,
        blank=True,
        default=''
    )
    location_type = models.ForeignKey(
        LocationType,
        models.CASCADE,
        null=False,
    )
    refined_geomorphological = models.CharField(
        blank=True,
        null=True,
        max_length=200,
        choices=[(g.value, g.value) for g in GeomorphologicalZoneCategory],
        help_text='Would be used in preference to the one discovered '
                  'in geocontext',
    )
    geometry_point = models.PointField(
        null=True,
        blank=True,
    )
    geometry_line = models.LineStringField(
        null=True,
        blank=True,
    )
    geometry_polygon = models.PolygonField(
        null=True,
        blank=True,
    )
    geometry_multipolygon = models.MultiPolygonField(
        null=True,
        blank=True,
    )
    map_reference = models.CharField(
        null=True,
        blank=True,
        max_length=200
    )
    land_owner_detail = models.TextField(
        null=True,
        blank=True,
    )
    river = models.ForeignKey(
        'sass.River',
        null=True,
        blank=True,
    )

    location_context_document = JSONField(
        verbose_name='Document for location context as JSON.',
        help_text='This document is generated from GeoContext by using '
                  'management command or changing the geometry.',
        null=True,
        blank=True
    )

    location_context = JSONField(
        verbose_name='Formatted location_context_document',
        help_text='This is intended for filtering',
        null=True,
        blank=True
    )

    additional_data = JSONField(
        verbose_name='Additional json data',
        null=True,
        blank=True
    )

    latitude = models.FloatField(
        blank=True,
        help_text='Latitude of location site',
        null=True
    )

    longitude = models.FloatField(
        blank=True,
        help_text='Longitude of location site',
        null=True
    )
    original_geomorphological = models.CharField(
        blank=True,
        null=True,
        max_length=200,
        help_text='Original geomorphological zone from spatial layer'
    )

    creator = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        models.SET_NULL,
        blank=True,
        null=True,
    )

    def location_context_group_values(self, group_name):
        """
        Returns location group data by group name
        :param group_name: string of group name, e.g. geomorphological_group
        :return: dict of group data
        """
        try:
            location_context = json.loads(self.location_context)
        except ValueError:
            return {}
        try:
            return (
                location_context
                ['context_group_values']
                [group_name]
                ['service_registry_values']
            )
        except KeyError:
            return {}

    def get_centroid(self):
        """ Getting centroid of location site """

        if self.geometry_point:
            return self.geometry_point
        else:
            if self.get_geometry():
                return self.get_geometry().centroid
            else:
                return None

    def get_geometry(self):
        """Function to get geometry."""
        geometry = None
        validation_error = ValidationError('Only one geometry allowed.')

        if self.geometry_point:
            if geometry:
                raise validation_error
            geometry = self.geometry_point

        if self.geometry_polygon:
            if geometry:
                raise validation_error
            geometry = self.geometry_polygon

        if self.geometry_multipolygon:
            if geometry:
                raise validation_error
            geometry = self.geometry_multipolygon

        if self.geometry_line:
            if geometry:
                raise validation_error
            geometry = self.geometry_line

        return geometry

    def get_geocontext_group_data(self, group_key):
        LOGGER.debug('get_location_group_data for ' + group_key)
        geocontext_url = get_key('GEOCONTEXT_URL')
        if not geocontext_url:
            message = (
                'Can not update location context document because geocontext '
                'url is None. Please set it.')
            return False, message
        if not self.get_centroid():
            message = (
                'Can not update location context document because centroid is '
                'None. Please set it.')
            return False, message
        longitude = self.get_centroid().x
        latitude = self.get_centroid().y

        geocontext_group_url_format = (
            '{geocontext_url}/api/v1/geocontext/value/group/'
            '{longitude}/{latitude}/{geocontext_group_key}')
        # build url
        url = geocontext_group_url_format.format(
            geocontext_url=geocontext_url,
            longitude=longitude,
            latitude=latitude,
            geocontext_group_key=group_key,
        )
        LOGGER.info('Request url : {}'.format(url))

        r = requests.get(url)
        if r.status_code != 200:
            message = (
                    'Request to url %s got %s [%s], can not update location '
                    'context document.' % (url, r.status_code, r.reason))
            LOGGER.info(message)
            return None

        return json.dumps(r.json())

    def add_context_group(self, group_key):
        old_location_context_string = self.location_context_document
        old_location_context = None
        if old_location_context_string:
            try:
                old_location_context = json.loads(old_location_context_string)
            except (ValueError, TypeError):
                if isinstance(old_location_context_string, dict):
                    old_location_context = old_location_context_string
                else:
                    LOGGER.info('Not a JSON Object')
        new_data = self.get_geocontext_group_data(group_key)
        if not new_data:
            return False, "Error from GeoContext"
        if not old_location_context:
            old_location_context_string = (
                '{"context_group_values":[%s]}' % new_data)
            self.location_context_document = old_location_context_string
            return True, "Group values added to empty document"
        new_context_data = json.loads(new_data)
        key = new_context_data['key']
        data_exists = False
        return_message = ''
        for context_group in old_location_context['context_group_values']:
            if context_group['key'] == key:
                return_message = 'Group value updated'
                data_exists = True
                context_group['service_registry_values'] = (
                    new_context_data['service_registry_values']
                )
        if not data_exists:
            return_message = 'Group values added'
            old_location_context['context_group_values'].append(
                new_context_data
            )
        self.location_context_document = json.dumps(old_location_context)
        return True, return_message

    def clear_location_context_document(self):
        self.location_context_document = ""
        return True, "Document cleared"

    def update_location_context_document(self):
        """Update location context document."""
        LOGGER.debug('update_location_context_document')
        geocontext_url = get_key('GEOCONTEXT_URL')
        geocontext_collection_key = get_key('GEOCONTEXT_COLLECTION_KEY')
        if not geocontext_url:
            message = (
                'Can not update location context document because geocontext '
                'url is None. Please set it.')
            return False, message
        if not geocontext_collection_key:
            message = (
                'Can not update location context document because geocontext '
                'collection key is None. Please set it.')
            return False, message
        if not self.get_centroid():
            message = (
                'Can not update location context document because centroid is '
                'None. Please set it.')
            return False, message
        longitude = self.get_centroid().x
        latitude = self.get_centroid().y

        # build url
        url = self.geocontext_url_format.format(
            geocontext_url=geocontext_url,
            longitude=longitude,
            latitude=latitude,
            geocontext_collection_key=geocontext_collection_key,
        )

        r = requests.get(url)
        if r.status_code != 200:
            message = (
                'Request to url %s got %s [%s], can not update location '
                'context document.' % (url, r.status_code, r.reason))
            return False, message

        self.location_context_document = json.dumps(r.json())
        return True, 'Successfully update location context document.'

    # noinspection PyClassicStyleClass
    class Meta:
        """Meta class for project."""
        app_label = 'bims'

    def __unicode__(self):
        return u'%s' % self.name

    def validate_json_field(self, field):
        max_allowed = 10
        attempt = 0
        is_dictionary = False

        while not is_dictionary and attempt < max_allowed:
            if not field:
                break
            if isinstance(field, dict):
                is_dictionary = True
            else:
                field = json.loads(
                    field
                )
                attempt += 1
        return field

    def save(self, *args, **kwargs):
        lon_lat_changed = False

        self.additional_data = self.validate_json_field(
            self.additional_data
        )
        self.location_context_document = self.validate_json_field(
            self.location_context_document
        )
        self.location_context = self.validate_json_field(
            self.location_context
        )

        """Check if one of geometry is not null."""
        if self.geometry_point or self.geometry_line or \
                self.geometry_polygon or self.geometry_multipolygon:
            # Check if geometry is allowed
            if isinstance(self.get_geometry(),
                          self.location_type.get_allowed_geometry_class()):
                if (
                        self.get_centroid().x != self.__original_longitude or
                        not self.longitude
                ):
                    self.longitude = self.get_centroid().x
                    lon_lat_changed = True
                if (
                        self.get_centroid().y != self.__original_latitude or
                        not self.latitude
                ):
                    self.latitude = self.get_centroid().y
                    lon_lat_changed = True

                # Check if latitude or longitude changed manually
                if (
                        self.latitude != self.__original_latitude or
                        self.longitude != self.__original_longitude
                ):
                    if not lon_lat_changed:
                        self.geometry_point.x = self.longitude
                        self.geometry_point.y = self.latitude
                super(LocationSite, self).save(*args, **kwargs)
                self.__original_centroid = self.get_centroid()
            else:
                raise ValidationError('Geometry is not allowed.')
        else:
            raise ValidationError('At least one geometry need to be filled.')

        if (
                self.__original_refined_geomorphological !=
                self.refined_geomorphological):
            SearchProcess.objects.filter(
                finished=True
            ).delete()

    def __init__(self, *args, **kwargs):
        super(LocationSite, self).__init__(*args, **kwargs)
        self.__original_centroid = self.get_centroid()
        self.__original_refined_geomorphological = (
            self.refined_geomorphological
        )
        self.__original_latitude = self.latitude
        self.__original_longitude = self.longitude

@receiver(models.signals.post_save)
def location_site_post_save_handler(sender, instance, **kwargs):
    """
    Update cluster when location site saved
    """
    from bims.utils.location_context import format_location_context
    if not issubclass(sender, LocationSite):
        return
    format_location_context(instance.id)


import numpy as np
from keras.utils import to_categorical, normalize
from matplotlib import pyplot as plt
from keras.datasets import fashion_mnist
from sklearn.model_selection import train_test_split
from keras.models import Sequential,Input,Model
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import LeakyReLU
from keras.losses import categorical_crossentropy
from keras.optimizers import Adam

(train_x , train_y) , (test_x , test_y) = fashion_mnist.load_data()

print('Shape of training data: ',train_x.shape,train_y.shape)
print('shape of testing data: ',test_x.shape,test_y.shape)

train_x = normalize(train_x, axis=1)
test_x = normalize(test_x, axis=1)
classes = np.unique(train_y)
nclasses = len(classes)
print('No of unique classes: ',nclasses)
print('Output Classes: ',classes)

plt.figure(figsize=[5,5])

plt.subplot(121)
plt.imshow(test_x[1,:,:],cmap='gray')
plt.title('Ground Truth: {}'.format(test_y[1]))

plt.subplot(122)
plt.imshow(test_x[0,:,:],cmap='gray')
plt.title('Ground Truth: {}'.format(test_y[0]))
plt.figure()
plt.show()

train_x = train_x.reshape(-1,28,28,1)
test_x = test_x.reshape(-1,28,28,1)
train_x = train_x.astype('float32')
test_x = test_x.astype('float32')
train_x = train_x / 255
test_x = test_x / 255
print(train_x.shape , test_x.shape)
train_y_one_hot = to_categorical(train_y)
test_y_one_hot = to_categorical(test_y)

print('original label: ', train_y[0])
print('one hot: ', train_y_one_hot[0])

train_x, valid_x, train_label, valid_label = train_test_split(train_x, train_y_one_hot, test_size=0.2, random_state=13)
print(train_x.shape , valid_x.shape, train_label.shape, valid_label.shape)

batch_size = 64
epochs = 20
num_classes = 10

fashion_model = Sequential()
fashion_model.add(Conv2D(32, kernel_size=(3,3), activation='linear', input_shape=(28,28,1), padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D(pool_size=(2,2), padding='same'))
fashion_model.add(Dropout(0.25))
fashion_model.add(Conv2D(128, kernel_size=(3,3), activation='linear', padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D(pool_size=(2,2), padding='same'))
fashion_model.add(Dropout(0.25))
fashion_model.add(Conv2D(128,kernel_size=(3,3), activation='linear', padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D(pool_size=(2,2), padding='same'))
fashion_model.add(Dropout(0.4))
fashion_model.add(Flatten())
fashion_model.add(Dense(128, activation='linear'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(Dropout(0.3))
fashion_model.add(Dense(num_classes, activation='softmax'))

fashion_model.summary()

fashion_model.compile(loss= categorical_crossentropy, optimizer=Adam(), metrics=['accuracy'])

fashion_train = fashion_model.fit(train_x, train_label, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(valid_x,valid_label))

fashion_model.save('fashion_model_dropout_1.h5py')

test_eval = fashion_model.evaluate(test_x,test_y_one_hot,verbose=1)
print('Test Loss, Test Acccuracy',test_eval[0], test_eval[1])
#plt.clf()
accuracy = fashion_train.history['acc']
val_accuracy = fashion_train.history['val_acc']
loss = fashion_train.history['loss']
val_loss = fashion_train.history['val_loss']
epochs = range(len(accuracy))
plt.plot(epochs, accuracy, 'bo', label='Training accuracy')
plt.plot(epochs, val_accuracy, 'b', label='validation accuracy')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.show()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.figure()
plt.show()

predicted_classes = fashion_model.predict(test_x)
predicted_classes = np.argmax(np.round(predicted_classes), axis=1)
print(predicted_classes.shape, test_y.shape)
correct = np.where(predicted_classes==test_y)[0]
print('found correct labels:', len(correct))
# for i, correct in enumerate(correct[:9]):
#     plt.subplot(3,3,i+1)
#     plt.imshow(test_x[correct].reshape(28,28), cmap='gray', interpolation='none')
#     plt.title('predicted {}, class {}'.format(predicted_classes[correct], test_y[correct]))
#     plt.tight_layout()


# -*- encoding: utf-8 -*-
# @File    : files.py
# @Contact : chengcheng@heading.loc
# @Modify Time : 2022/1/6 14:46
# @Author : chengchengy
# @Version : 1.0
# @Description : None

import os

"创建嵌套文件夹"

def create_folders(path):
    if not os.path.exists(path):
        os.makedirs(path)
    return path


from .group import Group
from .node import Node
from .topic import Topic
from .task import Task
from . import errors
from . import element

from networkx.algorithms.dag import descendants
from networkx import DiGraph

class Soup:
    def __init__(self):
        self._elements = set()
        self._root_group = None
        self._worldgraph = None

    def __len__(self):
        # well this is a bit dumb
        return len(list(self._root_group.iter_recursive()))

    def iter_topics(self):
        self._assert_committed()
        for name, elem in self._root_group.iter_recursive():
            if isinstance(elem, Topic):
                yield elem
            elif isinstance(elem, Task) or isinstance(elem, Group):
                # possibly generalize that; pass class as argument
                continue
            else:
                assert False, elem

    def add_element(self, element):
        self._assert_uncommitted()
        if self._worldgraph:
            raise errors.TopicError(f'cannot add {element}: graph already made')
        self._elements.add(element)

    def commit(self):
        if self._root_group is not None:
            return

        self._root_group = Group(title='Root', path=(), docname='')
        self._make_hierarchy()
        self._add_nodes_to_groups()
        assert len(self._elements) == 0
        del self._elements

    @property
    def root(self):
        return self._root_group

    def element_by_path(self, path):
        return self._root_group.element_by_path(path)

    def worldgraph(self):
        self._assert_committed()
        return self._make_worldgraph()

    def subgraph(self, entrypoints):
        '''Given entrypoints, compute a subgraph of the world graph that
        contains the entrypoints and all their descendants.

        entrypoints is an iterable of element paths or elements (can
        be mixed)
        '''

        self._assert_committed()
        world = self._make_worldgraph()

        entrypoint_elems = set()
        for e in entrypoints:
            try:
                element.verify_is_path(e)
            except errors.TopicError:   # not a path; must be element
                entrypoint_elems.add(e)
            else:
                entrypoint_elems.add(self.element_by_path(e))

        topics = set()
        for topic in entrypoint_elems:
            topics.add(topic)
            topics.update(descendants(world, topic))
        return world.subgraph(topics)

    def _make_worldgraph(self):
        if self._worldgraph is not None:
            return self._worldgraph

        self._worldgraph = DiGraph()
        for name, elem in self._root_group.iter_recursive():
            if not isinstance(elem, Node):
                continue
            self._worldgraph.add_node(elem)
            for target_path in elem.dependencies:
                try:
                    target_topic = self.element_by_path(target_path)
                except errors.PathNotFound:
                    raise errors.TopicError(f'{elem.docname} ({elem}): dependency {target_path} not found')
                self._worldgraph.add_edge(elem, target_topic)

        return self._worldgraph

    def _make_hierarchy(self):
        level = 1
        while True:
            all_groups = [g for g in self._elements if isinstance(g, Group)]
            if not all_groups:   # no more groups
                break
            level_groups = [g for g in all_groups if len(g._requested_path) == level]
            for g in level_groups:
                self._root_group.add_element(g)
                self._elements.remove(g)
            level += 1

    def _add_nodes_to_groups(self):
        nodes = [n for n in self._elements if isinstance(n, Node)]
        for n in nodes:
            self._root_group.add_element(n)
            self._elements.remove(n)

    def _assert_committed(self):
        if self._root_group is None:
            raise errors.NotCommitted('soup not committed')

    def _assert_uncommitted(self):
        if self._root_group is not None:
            raise errors.AlreadyCommitted('soup already committed')


"""Runway config file module."""
import logging
import os
import sys
from typing import Any, Dict, List, Optional, Union, Iterator  # pylint: disable=unused-import
import yaml

LOGGER = logging.getLogger('runway')

class ConfigComponent(object):
    """Base class for Runway config components."""

    def get(self, key, default=None):
        # type: (str, Any) -> Any
        """Implement evaluation of get."""
        return getattr(self, key, getattr(self, key.replace('-', '_'), default))

    def __getitem__(self, key):
        # type: (str) -> Any
        """Implement evaluation of self[key]."""
        return getattr(self, key, getattr(self, key.replace('-', '_')))

    def __setitem__(self, key, value):
        # type: (str, Any) -> None
        """Implement evaluation of self[key] for assignment."""
        setattr(self, key, value)

    def __len__(self):
        # type: () -> int
        """Implement the built-in function len()."""
        return len(self.__dict__)

    def __iter__(self):
        # type: () -> Iterator[Any]
        """Return iterator object that can iterate over all attributes."""
        return iter(self.__dict__)

class ModuleDefinition(ConfigComponent):  # pylint: disable=too-many-instance-attributes
    """A module defines the directory to be processed and applicable options.

    It can consist of `CloudFormation`_ (using `Stacker`_),
    `Terraform`_, `Serverless Framework`_, `AWS CDK`_, or `Kubernetes`_.
    It is recommended to place the appropriate extension on each directory
    for identification (but it is not required). See
    :ref:`Repo Structure<repo-structure>` for examples of a module
    directory structure.

    +------------------+-----------------------------------------------+
    | Suffix/Extension | IaC Tool/Framework                            |
    +==================+===============================================+
    | ``.cdk``         | `AWS CDK`_                                    |
    +------------------+-----------------------------------------------+
    | ``.cfn``         | `CloudFormation`_                             |
    +------------------+-----------------------------------------------+
    | ``.sls``         | `Serverless Framework`_                       |
    +------------------+-----------------------------------------------+
    | ``.tf``          | `Terraform`_                                  |
    +------------------+-----------------------------------------------+
    | ``.k8s``         | `Kubernetes`_                                 |
    +------------------+-----------------------------------------------+

    A module is only deployed if there is a corresponding env/config
    present. This can take the form of either a file in the module folder
    or the ``environments`` option being defined. The naming format
    varies per-module type. See
    :ref:`Module Configurations<module-configurations>` for acceptable
    env/config file name formats.

    Modules can be defined as a string or a mapping. The minimum
    requirement for a module is a string that is equal to the name of
    the module directory. Providing a string is the same as providing a
    value for ``path`` in a mapping definition.

    Example:
      .. code-block:: yaml

        deployments:
          - modules:
              - my-module.cfn  # this
              - path: my-module.cfn  # is the same as this

    Using a map to define a module provides the ability to specify
    per-module ``options``, environment values, tags, and even a custom
    class for processing the module. The options that can be used with
    each module vary. For detailed information about module-specific
    options, see :ref:`Module Configurations<module-configurations>`.

    Example:
      .. code-block:: yaml

        deployments:
          - modules:
              - name: my-module
                path: my-module.tf
                environments:
                  dev:
                    image_id: ami-1234
                tags:
                  - app:example
                  - my-tag
                options:
                  terraform_backend_config:
                    region: us-east-1
                  terraform_backend_cfn_outputs:
                    bucket: StackName::OutputName
                    dynamodb_table: StackName::OutputName

    One special map keyword, ``parallel``, indicates a list of child
    modules that will be executed in parallel (simultaneously) if the
    ``CI`` :ref:`environment variable is set<non-interactive-mode>`.

    Example:
      .. code-block:: yaml

        deployments:
          - modules:
            - backend.tf
            - parallel:
              - servicea.cfn  # any normal module option can be used here
              - path: serviceb.cfn
              - path: servicec.cfn
                environments:
                  dev:
                    count: 1
                  prod:
                    count: 3
            - frontend.tf

    (in that ^ example, backend.tf will be deployed, the services will be all
    be deployed simultaneously, followed by frontend.tf)

    """

    def __init__(self,  # pylint: disable=too-many-arguments
                 name,  # type: str
                 path,  # type: str
                 class_path=None,  # type: Optional[str]
                 environments=None,  # type: Optional[Dict[str, Dict[str, Any]]]
                 env_vars=None,  # type: Optional[Dict[str, Dict[str, Any]]]
                 options=None,  # type: Optional[Dict[str, Any]]
                 tags=None,  # type: Optional[Dict[str, str]]
                 child_modules=None  # type: Optional[List[Union[str, Dict[str, Any]]]]
                 # pylint only complains for python2
                 ):  # pylint: disable=bad-continuation
        # type: (...) -> None
        """.. Runway module definition.

        Keyword Args:
            name (str): Name of the module. Used to more easily identify
                where different modules begin/end in the logs.
            path (str): Path to the module relative to the Runway config
                file. This cannot be higher than the Runway config file.
            class_path (Optional[str]): Path to custom Runway module class.
                Also used for static site deployments. See
                :ref:`Module Configurations<module-configurations>` for
                detailed usage.
            environments (Optional[Dict[str, Dict[str, Any]]]): Mapping for
                variables to environment names. When run, the variables
                defined here are merged with those in the
                ``.env``/``.tfenv``/environment config file. If this is
                defined, ``.env`` files can be omitted and the module
                will still be processed.
            env_vars (Optional[Dict[str, Dict[str, Any]]]): A mapping of
                OS environment variable overrides to apply when processing
                modules in the deployment. Can be defined per environment
                or for all environments using ``"*"`` as the environment
                name. Takes precendence over values set at the deployment-
                level.
            options (Optional[Dict[str, Any]]): Module-specific options.
                See :ref:`Module Configurations<module-configurations>`
                for detailed usage.
            tags (Optional[Dict[str, str]]): Module tags used to select
                which modules to process using CLI arguments.
                (``--tag <tag>...``)
            child_modules (Optional[List[Union[str, Dict[str, Any]]]]):
                Child modules that can be executed in parallel

        References:
            - `AWS CDK`_
            - `CloudFormation`_
            - `Serverless Framework`_
            - `Stacker`_
            - `Troposphere`_
            - `Terraform`_
            - `Kubernetes`_
            - :ref:`Module Configurations<module-configurations>` -
              detailed module ``options``
            - :ref:`Repo Structure<repo-structure>` - examples of
              directory structure
            - :ref:`command-deploy`
            - :ref:`command-destroy`
            - :ref:`command-plan`

        """
        self.name = name
        self.path = path
        self.class_path = class_path
        self.environments = environments or {}
        self.env_vars = env_vars or {}
        self.options = options or {}
        self.tags = tags or {}
        self.child_modules = child_modules

    @classmethod
    def from_list(cls, modules):
        """Instantiate ModuleDefinition from a list."""
        results = []
        for mod in modules:
            if isinstance(mod, str):
                results.append(cls(mod, mod, {}))
                continue
            if mod.get('parallel'):
                name = 'parallel_parent'
                child_modules = ModuleDefinition.from_list(mod.pop('parallel'))
                path = '[' + ', '.join([x.path for x in child_modules]) + ']'
                if mod:
                    LOGGER.warning(
                        'Invalid keys found in parallel module config have been ignored: %s',
                        ', '.join(mod.keys())
                    )
            else:
                name = mod.pop('name', mod['path'])
                child_modules = None
                path = mod.pop('path')
            results.append(cls(name,
                               path,
                               class_path=mod.pop('class_path', None),
                               environments=mod.pop('environments', {}),
                               env_vars=mod.pop('env_vars', {}),
                               options=mod.pop('options', {}),
                               tags=mod.pop('tags', {}),
                               child_modules=child_modules))
            if mod:
                LOGGER.warning(
                    'Invalid keys found in module %s have been ignored: %s',
                    name, ', '.join(mod.keys())
                )
        return results

class DeploymentDefinition(ConfigComponent):  # pylint: disable=too-many-instance-attributes
    """A deployment defines modules and options that affect the modules.

    Deployments are processed during a ``deploy``/``destroy``/``plan``
    action. If the processing of one deployment fails, the action will
    end.

    During a ``deploy``/``destroy`` action, the user has the option to
    select which deployment will run unless the ``CI`` environment
    variable is set, the ``--tag <tag>...`` cli option was provided, or
    only one deployment is defined.

    Example:
      .. code-block:: yaml

        deployments:
          - modules:  # minimum requirements for a deployment
              # "./" can alternatively be used for the module name to indicate
              # the current directory
              - my-module.cfn
            regions:
              - us-east-1
          - name: detailed-deployment  # optional
            modules:
              - path: my-other-modules.cfn
            regions:
              - us-east-1
            account_id:  # optional
              dev: 0000
              prod: 1111
            assume_role:  # optional
              dev: arn:aws:iam::0000:role/role-name
              prod: arn:aws:iam::1111:role/role-name
            environments:  # optional
              dev:
                region: us-east-1
                image_id: ami-abc123
            env_vars:  # optional environment variable overrides
              dev:
                AWS_PROFILE: foo
                APP_PATH:  # a list will be treated as components of a path on disk
                  - myapp.tf
                  - foo
              prod:
                AWS_PROFILE: bar
                APP_PATH:
                  - myapp.tf
                  - foo
              "*":  # applied to all environments
                ANOTHER_VAR: foo

    """

    def __init__(self, deployment):
        # type: (Dict[str, Any]) -> None
        """.. Runway deployment definition.

        Keyword Args:
            account_alias (Optional[Dict[str, str]]): A mapping of
                ``$environment: $alias`` that, if provided, is used to
                verify the currently assumed role or credentials.
            account_id (Optional[Dict[str, Union[str, int]]]): A mapping
                of ``$environment: $id`` that, if provided, is used to
                verify the currently assumed role or credentials.
            assume_role (Optional[Dict[str, Union[str, Dict[str, str]]]]):
                A mapping of ``$environment: $role`` or
                ``$environment: {arn: $role, duration: $int}`` to assume
                a role when processing a deployment. ``arn: $role`` can
                be used to apply the same role to all environment.
                ``post_deploy_env_revert: true`` can also be provided to
                revert credentials after processing.
            environments (Optional[Dict[str, Dict[str, Any]]]): Mapping for
                variables to environment names. When run, the variables
                defined here are merged with those in the
                ``.env``/``.tfenv``/environment config file and
                environments section of each module.
            env_vars (Optional[Dict[str, Dict[str, Any]]]): A mapping of
                OS environment variable overrides to apply when processing
                modules in the deployment. Can be defined per environment
                or for all environments using ``"*"`` as the environment
                name.
            modules (Optional[List[Dict[str, Any]]]): A list of modules
                to be processed in the order they are defined.
            module_options (Optional[Dict[str, Any]]): Options that are
                shared among all modules in the deployment.
            name (str): Name of the deployment. Used to more easily
                identify where different deployments begin/end in the logs.
            regions (List[str]): AWS region names where modules will be
                deployed/destroyed. Can optionally define as a map with
                ``parallel`` as the key and a list of regions as the value.
                See **parallel_regions** for more info.
            parallel_regions: Can be defined in place of ``regions.parallel[]``.
                This will cause all modules in the deployment to be executed
                in all provided regions in parallel (at the same time).
                Only takes effect when the ``CI`` environment variable is set,
                enabling non-interactive mode, as prompts will not be able
                to be presented. If ``CI`` is not set, the regions will be
                processed one at a time. This can be used in tandom with
                **parallel modules**. ``assume_role.post_deploy_env_revert``
                will always be ``true`` when run in parallel.

        References:
            - :class:`module<runway.config.ModuleDefinition>`
            - :ref:`command-deploy`
            - :ref:`command-destroy`
            - :ref:`command-plan`

        """
        self.account_alias = deployment.pop(
            'account_alias', deployment.pop('account-alias', {})
        )  # type: Optional[Dict[str, str]]
        self.account_id = deployment.pop(
            'account_id', deployment.pop('account-id', {})
        )  # type: Optional[Dict[str, Union[str, int]]]
        self.assume_role = deployment.pop(
            'assume_role', deployment.pop('assume-role', {})
        )  # type: Optional[Dict[str, Union[str, Dict[str, str]]]]
        self.environments = deployment.pop(
            'environments', {}
        )  # type: Optional[Dict[str, Dict[str, Any]]]
        self.env_vars = deployment.pop(
            'env_vars', deployment.pop('env-vars', {})
        )  # type: Optional[Dict[str, Dict[str, Any]]]
        if deployment.pop('current_dir', False):
            # Deprecated in 1.0 (late 2019). Retain for at least a major version.
            LOGGER.warning('DEPRECATION WARNING: The "current_dir" option has '
                           'been deprecated in favor of a "./" module '
                           'definition. Please update your config.')
            modules = ['.' + os.sep]
        else:
            if not deployment.get('modules'):
                LOGGER.error('No modules have been defined in your Runway '
                             'deployment.')
                sys.exit(1)
            modules = deployment.pop('modules')
        self.modules = ModuleDefinition.from_list(
            modules
        )  # type: List[ModuleDefinition]
        self.module_options = deployment.pop(
            'module_options', deployment.pop('module-options', {})
        )  # type: Optional(Dict[str, Any])
        self.name = deployment.pop('name')  # type: str
        self.regions = deployment.pop(
            'regions', []
        )  # type: Union[List[str], Dict[str, List[str]]]

        if self.regions and deployment.get('parallel_regions'):
            LOGGER.error('Found "regions" and "parallel_regions" in '
                         'deployment "%s"; only one can be defined',
                         self.name)
            sys.exit(1)
        if isinstance(self.regions, dict) and self.regions.get('parallel'):
            self.parallel_regions = self.regions.pop('parallel')
            self.regions = []
        else:
            self.parallel_regions = deployment.pop('parallel_regions', [])

        if deployment:
            LOGGER.warning(
                'Invalid keys found in deployment %s have been ignored: %s',
                self.name, ', '.join(deployment.keys())
            )

    @classmethod
    def from_list(cls, deployments):
        """Instantiate DeploymentDefinitions from a list."""
        results = []
        for i, deployment in enumerate(deployments):
            if not deployment.get('name'):
                deployment['name'] = 'deployment_{}'.format(str(i + 1))
            results.append(cls(deployment))
        return results

class TestDefinition(ConfigComponent):
    """Tests can be defined as part of the Runway config file.

    This is to remove the need for complex Makefiles or scripts to initiate
    test runners. Simply define all tests for a project in the Runway
    config file and use the ``runway test`` :ref:`command<command-test>`
    to execute them.

    Example:
      .. code-block:: yaml

        tests:
          - name: my-test
            type: script
            required: false
            args:
              commands:
                - echo "Hello World!"

    """

    def __init__(self,
                 name,  # type: str
                 test_type,  # type: str
                 args=None,  # type: Optional[Dict[str, Any]]
                 required=True  # type: bool
                 # pylint only complains for python2
                 ):  # pylint: disable=bad-continuation
        # type: (...) -> None
        """.. Runway test definitions.

        Keyword Args:
            name (str): Name of the test. Used to more easily identify
                where different tests begin/end in the logs.
            type (str): The type of test to run. See
                :ref:`Build-in Test Types<built-in-test-types>`
                for supported test types.
            args (Optional[Dict[str, Any]]): Arguments to be passed to
                the test. Supported arguments vary by test type. See
                :ref:`Build-in Test Types<built-in-test-types>` for the
                list of arguments supported by each test type.
            required (bool):  If false, testing will continue if the test
                fails. *(default: true)*

        References:
            - :ref:`Build-in Test Types<built-in-test-types>` - Supported
              test types and their
              arguments
            - :ref:`test command<command-test>`

        """
        self.name = name
        self.type = test_type
        self.args = args or {}
        self.required = required

    @classmethod
    def from_list(cls, tests):
        # type: (List[Dict[str, Any]]) -> List[TestDefinition]
        """Instantiate TestDefinitions from a list."""
        results = []

        for index, test in enumerate(tests):
            name = test.pop('name', 'test_{}'.format(index + 1))
            results.append(cls(name, test.pop('type'),
                               test.pop('args', {}),
                               test.pop('required', False)))

            if test:
                LOGGER.warning(
                    'Invalid keys found in test %s have been ignored: %s',
                    name, ', '.join(test.keys())
                )
        return results

class Config(ConfigComponent):
    """The Runway config file is where all options are defined.

    It contains definitions for deployments, tests, and some global
    options that impact core functionality.

    The Runway config file can have two possible names, ``runway.yml``
    or ``runway.yaml``. It must be stored at the root of the directory
    containing all modules to be deployed.

    Example:
        .. code-block:: yaml

            ---
            # See full syntax at https://github.com/onicagroup/runway
            ignore_git_branch: true
            tests:
              - name: example
                type: script
                args:
                  commands:
                    - echo "Hello world"
            deployments:
              - modules:
                  - path: my-modules.cfn
                regions:
                  - us-east-1

    """

    accepted_names = ['runway.yml', 'runway.yaml']

    def __init__(self,
                 deployments,  # type: List[Dict[str, Any]]
                 tests=None,  # type: List[Dict[str, Any]]
                 ignore_git_branch=False  # type: bool
                 # pylint only complains for python2
                 ):  # pylint: disable=bad-continuation
        # type: (...) -> None
        """.. Top-level Runway config file.

        Keyword Args:
            deployments (List[Dict[str, Any]]): A list of
                :class:`deployments<runway.config.DeploymentDefinition>`
                that are processed in the order they are defined.
            tests (Optional[List[Dict[str, Any]]]): A list of
                :class:`tests<runway.config.TestDefinition>` that are
                processed in the order they are defined.
            ignore_git_branch (bool): Disable git branch lookup when
                using environment folders, non-git VCS, or defining the
                ``DEPLOY_ENVIRONMENT`` environment variable before
                execution. Note that defining ``DEPLOY_ENVIRONMENT``
                will automatically ignore the git branch.

        References:
            - :class:`deployment<runway.config.DeploymentDefinition>`
            - :class:`test<runway.config.TestDefinition>`

        """
        self.deployments = DeploymentDefinition.from_list(deployments)
        self.tests = TestDefinition.from_list(tests)
        self.ignore_git_branch = ignore_git_branch

    @classmethod
    def load_from_file(cls, config_path):
        # type: (str) -> Config
        """Load config file into a Config object."""
        if not os.path.isfile(config_path):
            LOGGER.error("Runway config file was not found (looking for "
                         "%s)",
                         config_path)
            sys.exit(1)
        with open(config_path) as data_file:
            config_file = yaml.safe_load(data_file)
            result = Config(config_file.pop('deployments'),
                            config_file.pop('tests', []),
                            config_file.pop('ignore_git_branch',
                                            config_file.pop(
                                                'ignore-git-branch',
                                                False)))

            if config_file:
                LOGGER.warning(
                    'Invalid keys found in runway file have been ignored: %s',
                    ', '.join(config_file.keys())
                )
            return result

    @classmethod
    def find_config_file(cls, config_dir=None):
        # type: (Optional[str]) -> str
        """Find the Runway config file."""
        if not config_dir:
            config_dir = os.getcwd()

        for name in cls.accepted_names:
            conf_path = os.path.join(config_dir, name)
            if os.path.isfile(conf_path):
                return conf_path

        LOGGER.error('Runway config file was not found. Looking for one '
                     'of %s in %s', str(cls.accepted_names), config_dir)
        sys.exit(1)


#!/usr/bin/env python

def read_file():
    import tkFileDialog
    import numpy as np
    # Declaration

    adjacencyList = {}
    edgeCost = {}
    #
    inputFilename = tkFileDialog.askopenfilename(initialdir = "/home/sena/VT-robot-motion-planning-course/F2018-HW/HW2/problem1_inputfiles",
                                    title = "Select file",filetypes = (("Text files","*.txt"),("all files","*.*")))
    inputFile = open(inputFilename,"r")
    inputFileContent = inputFile.readlines()
    #print(len(inputFileContent))
    totNumVert = int(inputFileContent[0])
    startVert = int(inputFileContent[1])
    goalVert = int(inputFileContent[2])
    for counter in range(3,len(inputFileContent)):
        curr = inputFileContent[counter].split()
        if int(curr[0]) not in adjacencyList:
            adjacencyList[int(curr[0])] = []
        adjacencyList[int(curr[0])].append(int(curr[1]))
        edgeCost[tuple([int(curr[0]),int(curr[1])])] = float(curr[2])

    return totNumVert, startVert, goalVert, adjacencyList, edgeCost


# # 创建列表的两种方式
# list1 =[]
# list2 =list ()
#
# # 每两个元素之间以，隔开
# list1 = ['hello world',[[]],1, 3.14 ,True,]
#
#
# list1 =['outMan', '小李子','诺兰','皮克斯']
# # 获取列表里面索引为0的元素
# print(list1[0])
# # IndexError: list index out of range
# # 索引错误：列表索引超出范围
# # print(list1[5])
# # 如果 ：左右两边都不写值，表示获取所有元素
# print(list1[:])
# # ：左边表示指定搜索引开始
# # ：右边表示到指定索引结束（不包括该位置）
# print(list1[1:1])
# # 值1：开始的位置
# # 值2：结束的位置
# # 值3：隔几个元素
# print(list1[1::2])
# # 倒叙
# print(list1[::-1])
#
# # ----------------------------------------insert 插入-----------------------------------------
# list1 = [1,2,3,4,5,6,7]
# # insert 会指定出入的位置
# list1.insert(2,'hello')
# print(list1)
# # append  追加的内容默认放在列表的队尾
# list1.append('world')
# print(list1)
# # extend  扩展
# list1.extend('张三')
# print(list1)
#
# # list1 = [1,2,3]
# # list2 = ['a','b''d','c']
# # list1.append(list2)
# # append 追加内容  [1, 2, 3, ['a', 'bd', 'c']]
# # 不管追加的事什么样的类型的内容
# # 都会讲者快内容当做一个整体
# # 放入到被添加的列表中
# # -------------------------
# # extend 扩展   [1, 2, 3, 'a', 'bd', 'c']
# # 将扩展对象的每一个元素
# # 分别添加到被扩展对象中
# # list1.extend(list2)
# print(list1)
#
# # 晚自习作业三：代码实现extend 将任意容器里面的所有元素放入到另外一个容器当中
# list1 = ['a','s','d','f','d','s','a']
# # 将最后一个元素弹出
# list1.pop()
# print(list1)
#
# # list1.pop(2)
# # print(list1)
# # 删除所有符合指定要求的这些元素中
# # 索引最小的这个  ['a', 's', 'f', 'd', 's']
# list1.remove('d')
# print(list1)
# # 查看列表当中有没有指定的元素
# if 'b'in list1 :
#     print('存在')
# else:
#     print('不存在')
#
# list1 = ['a','b','c','d']
# # reversed 相反的   ['d', 'c', 'b', 'a']
# list1.reverse()
# print(list1)
# # 获取列表里面指定的元素的索引
# result = list1.index('a')
# print(result)
#
# # sort  排序  [0, 2, 3, 4, 5, 7, 8]
# #reverse 倒排序  [8, 7, 5, 4, 3, 2, 0]
# list1 = [5,3,8,4,0,2,7]
# list1.sort()
# list1.reverse()
# print(list1)
# # 获取列表的长度
# print(len(list1))

a = {"var1": {"key6", "data2"}, "var2":{"key2", "data1"}, "var3": {"dataw", "333", "bbss"}}

for k in a:
    if k == 'var3':
        print(k)
    b = a[k]
    for c in b:
        if c == '333':
            print(c)

def count(a):
    a = a
    b = {}
    c = len(a)
    i = 0
    while i < c:
        if a[i] in b:
            b[a[i]] += 1
        else:
            b[a[i]] = 1
        i += 1
    for a in b.items():
        print(a)

count("aasdxzs123123sdf")


'''## Question 2:
Define a class named `ItemInfo` with the following description:

`item_code`(Item Code), `item`(item name), `price`(Price of each item), `qty`(quantity in stock), `discount`(Discount percentage on the item), `net_price`(Price after discount)

**Methods :**
*	A member method `calculate_discount()` to calculate discount as per the following rules:
*	If `qty <= 10` —> discount is `0`
*	If `qty (11 to 20 inclusive)` —> discount is `15`
*	If `qty >= 20` —> discount is `20`
*	A constructor init method to assign the initial values for `item_code` to `0` and `price`, `qty`, `net_price` and `discount` to `null`
*	A function called `buy()` to allow user to enter values for `item_code`, `item`, `price`, `qty`. Then call function `calculate_discount()` to calculate the `discount` and `net_price`(price * qty - discount).
*	A function `show_all()` or similar name to allow user to view the content of all the data members.

'''

class ItemInfo:

    def __init__(self, item_code = 0, item = None, price = None, qty = None, discount = None, net_price= None ):
        self.item_code = item_code
        self.item = item
        self.price = price
        self.qty = qty
        self.discount = discount
        self.net_price = net_price
    def calculate_discount(self):
        if self.qty <= 10:
            self.discount = 0
        elif 20>=self.qty >= 10:
            self.discount = 15
        elif self.qty >= 20:
            self.discount = 20
        return self.discount
    def buy(self):
        self.item_code=input("item code: ")
        self.item = input("item: ")
        self.price = int(input("price: "))
        self.qty = float(input("qty: "))
        self.calculate_discount()
        self.net_price = self.price * self.qty - self.discount

    def show_all(self):
        return print(f"item code:{self.item_code} \n item: {self.item} \n price: {self.price} \n qty: {self.qty } \n discount:{self.discount} \n net price:{self.net_price} ")
shirt = ItemInfo()
shirt.buy()
shirt.show_all()


import os
import unittest
from deta import Deta, send_email
from timeit import timeit

try:
    from dotenv import load_dotenv

    load_dotenv()
except:
    pass

"""class TestSendEmail(unittest.TestCase):
    def setUp(self):
        self.deta = Deta()

    def test_function(self):
        self.assertIsNone(
            send_email("mustafa@deta.sh", "Hello from test", "this is a test!")
        )

    def test_method(self):
        self.assertIsNone(
            self.deta.send_email(
                "mustafa@deta.sh", "Hello from test", "this is a test!"
            )
        )"""

class TestBaseMethods(unittest.TestCase):
    def setUp(self):
        key = os.getenv("DETA_SDK_TEST_PROJECT_KEY")
        name = os.getenv("DETA_SDK_TEST_BASE_NAME")
        self.assertIsNotNone(key)
        self.assertIsNotNone(name)
        deta = Deta(key)
        self.db = deta.Base(str(name))
        self.item1 = {"key": "existing1", "value": "test"}
        self.item2 = {"key": "existing2", "value": 7}
        self.item3 = {"key": "existing3", "value": 44}
        self.item4 = {"key": "existing4", "value": {"name": "patrick"}}
        self.item5 = {"key": "%@#//#!#)#$_", "value": 0, "list": ["a"]}
        self.db.put_many([self.item1, self.item2, self.item3, self.item4, self.item5])

    def tearDown(self):
        all_items = next(self.db.fetch())
        for item in all_items:
            self.db.delete(item["key"])
        self.db.client.close()

    def test_put(self):
        item = {"msg": "hello"}
        resp = {"key": "one", "msg": "hello"}
        self.assertEqual(self.db.put(item, "one"), resp)
        self.assertEqual(self.db.put(item, "one"), resp)
        self.assertEqual({"msg": "hello"}, item)
        self.assertEqual(set(self.db.put("Hello").keys()), set(["key", "value"]))
        self.assertEqual(set(self.db.put(1).keys()), set(["key", "value"]))
        self.assertEqual(set(self.db.put(True).keys()), set(["key", "value"]))
        self.assertEqual(set(self.db.put(False).keys()), set(["key", "value"]))
        self.assertEqual(set(self.db.put(3.14159265359).keys()), set(["key", "value"]))

    @unittest.expectedFailure
    def test_put_fail(self):
        self.db.put({"msg": "hello"}, 1)
        self.db.put({"msg": "hello", "key": True})

    def test_put_many(self):
        self.assertEqual(len(self.db.put_many([1, 2, 3])["processed"]["items"]), 3)
        ok = self.db.put_many([{"msg": "hello"}, {"msg2": "hi"}])["processed"]["items"]
        self.assertEqual(len(ok), 2)

    @unittest.expectedFailure
    def test_put_many_fail(self):
        self.db.put_many([{"name": "joe", "key": "ok"}, {"name": "mo", "key": 7}])

    @unittest.expectedFailure
    def test_put_many_fail_limit(self):
        self.db.put_many([i for i in range(26)])

    def test_insert(self):
        item = {"msg": "hello"}
        self.assertEqual(set(self.db.insert(item).keys()), set(["key", "msg"]))
        self.assertEqual({"msg": "hello"}, item)

    @unittest.expectedFailure
    def test_insert_fail(self):
        self.db.insert(self.item1)

    def test_get(self):
        self.assertEqual(self.db.get(self.item1["key"]), self.item1)
        self.assertIsNone(self.db.get("key_does_not_exist"))

    def test_delete(self):
        self.assertIsNone(self.db.delete(self.item1["key"]))
        self.assertIsNone(self.db.delete("key_does_not_exist"))

    def test_fetch(self):
        res1 = next(self.db.fetch({"value": "test"}))
        res2 = next(self.db.fetch({"valuexyz": "test_none_existing_value"}))
        res3 = next(self.db.fetch(buffer=3))
        res4 = list(self.db.fetch(buffer=1, pages=4))
        res5 = next(self.db.fetch({"value.name": self.item4["value"]["name"]}))
        res6 = next(self.db.fetch({"value?gte": 7}))
        res7 = next(self.db.fetch([{"value?gt": 6}, {"value?lt": 50}]))
        self.assertTrue(len(res1) > 0)
        self.assertTrue(len(res2) == 0)
        self.assertTrue(len(res3) == 3)
        self.assertTrue(len(res4) == 4)
        self.assertTrue(len(res5) > 0)
        self.assertTrue(len(res6) == 2)
        self.assertTrue(len(res7) == 3)

    def test_update(self):
        self.assertIsNone(self.db.update({"value.name": "spongebob"}, "existing4"))
        expectedItem = {"key": "existing4", "value": {"name": "spongebob"}}
        self.assertEqual(self.db.get("existing4"), expectedItem)

        self.assertIsNone(
            self.db.update({"value.name": self.db.util.trim(), "value.age": 32}, "existing4")
        )
        expectedItem = {"key": "existing4", "value": {"age": 32}}
        self.assertEqual(self.db.get("existing4"), expectedItem)

        self.assertIsNone(
            self.db.update(
                {
                    "list": self.db.util.append(["b", "c"]),
                    "value": self.db.util.increment(),
                },
                "%@#//#!#)#$_",
            )
        )

        self.assertIsNone(
            self.db.update(
                {"list": self.db.util.prepend("x"), "value": self.db.util.increment(2)},
                "%@#//#!#)#$_",
            )
        )
        expectedItem = {"key": "%@#//#!#)#$_", "list": ["x", "a", "b", "c"], "value": 3}
        self.assertEqual(self.db.get("%@#//#!#)#$_"), expectedItem)

        # key does not exist
        self.assertRaises(Exception, self.db.update, {"value": "test"}, "doesNotExist")
        # deleting a key
        self.assertRaises(
            Exception,
            self.db.update,
            {"value": "test", "key": self.db.util.trim()},
            "existing4",
        )
        # updating a key
        self.assertRaises(Exception, self.db.update, {"key": "test"}, "existing4")
        # upper hierarchy does not exist
        self.assertRaises(Exception, self.db.update, {"profile.age": 32}, "existing4")
        # no attributes specified
        self.assertRaises(Exception, self.db.update, {}, "existing4")

        # appending to a key
        self.assertRaises(
            Exception,
            self.db.update,
            {"key": self.db.util.append("test")},
            "%@#//#!#)#$_",
        )

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


#calss header
class _WHOOSH():
	def __init__(self,):
		self.name = "WHOOSH"
		self.definitions = [u'a soft sound made by something moving fast through the air or like that made when air is pushed out of something: ', u'a sudden fast movement of a liquid or air: ']

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

		self.specie = 'nouns'

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


from flask import Flask, abort, request
import json
from kafka import KafkaProducer
import configparser

app = Flask(__name__)
config = configparser.ConfigParser();
config.read('config.ini')
producer = KafkaProducer(bootstrap_servers=config['KAFKA']['bootstrap_servers'])

@app.route('/api', methods=['POST'])
def foo():
    if not request.json:
        abort(400)
    producer.send(config['KAFKA']['topic'], bytes(str(request.get_data()).encode()))
    return ('', 200)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80, debug=True)


from acounts import Bd
con = Bd()
class Batepapo:
    def __init__(self):
        self.conversas = list
    def menu(self):
        print('\n\n')
        print('Bate papo')
        print('1 - Nova conversa')
        print('2 - Ver todas as conversas')
        print('3 - Nova menssagem')
        print('x - Sair')
        opca = input('Digite a opção: ')

        if opca == '1':
           mensagem.nova_conversa(None)
        if opca == '2':
            for x in self.conversas():
                print(x)
        if opca == '3':
            mensagem.nova_msg(None)
        return (opca)
class Conversa:
    def __init__(self):
        self.menssagens = list

class mensagem:
    def __init__(self):
        self.texto = str

    def nova_conversa(self):
        destino = input('Digite o nome do destinatario: ')
        for x in con.contas:
            if x.nome == destino:
                txt = self.texto
                new_con = Conversa()
                new_con.menssagens.append(txt)
    def nova_msg(self):#passar a lista de conversas como argumento
        destino = input('Digite o nome do outro prosador: ')
        new_ms = mensagem()
        for x in self.conversas:
            if x.nome == destino:
                for y in x:
                    print(y)
                new_ms.texto = input('Digite a menssagem: ')
                x.append(new_ms.texto)