import pandas as pd  # for data manipulation
from django.conf import settings
from pathlib import Path

import numpy as np
from sklearn import svm, metrics, datasets
from sklearn.utils import Bunch
from sklearn.model_selection import GridSearchCV, train_test_split

from skimage.io import imread
from skimage.transform import resize
import skimage

def load_image_files(container_path, dimension=(104, 104)):
    image_dir = Path(container_path)
    folders = [directory for directory in image_dir.iterdir() if directory.is_dir()]
    categories = [fo.name for fo in folders]
    descr = "A Rice Disease detection using Machine Learning"
    images = []
    flat_data = []
    target = []
    for i, direc in enumerate(folders):
        for file in direc.iterdir():
            img = skimage.io.imread(file)
            img_resized = resize(img, dimension, anti_aliasing=True, mode='reflect')
            flat_data.append(img_resized.flatten())
            images.append(img_resized)
            target.append(i)

    flat_data = np.array(flat_data)
    target = np.array(target)
    images = np.array(images)
    return Bunch(data=flat_data,
                 target=target,
                 target_names=categories,
                 images=images,
                 DESCR=descr)

path = settings.MEDIA_ROOT + "//" + "rice_leaf_diseases"
image_dataset = load_image_files(path)  # Load here dataset
print(image_dataset.target_names)

X_train, X_test, y_train, y_test = train_test_split(image_dataset.data, image_dataset.target, test_size=0.3,
                                                    random_state=109)
param_grid = [
    {'C': [1, 10, 100, 1000], 'kernel': ['linear']},
    {'C': [1, 10, 100, 1000], 'gammatt': [0.001, 0.0001], 'kernel': ['rbf']},
]

def process_randomForest():
    from sklearn.ensemble import RandomForestClassifier
    clf = RandomForestClassifier()
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    # import pickle
    # # now you can save it to a file
    # with open(r'rice_pred.pkl', 'wb') as f:
    #     pickle.dump(clf, f)
    print(clf.score(X_test, y_test))
    rf_report = metrics.classification_report(y_test, y_pred,output_dict=True)
    print("Classification report for - \n{}:\n{}\n".format(clf, rf_report))
    return rf_report

def process_decesionTree():
    from sklearn.tree import DecisionTreeClassifier
    clf = DecisionTreeClassifier()
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    print(clf.score(X_test, y_test))
    dt_report = metrics.classification_report(y_test, y_pred,output_dict=True)
    print("Classification report for - \n{}:\n{}\n".format(clf, dt_report))
    return dt_report

def process_naiveBayes():
    from sklearn.naive_bayes import GaussianNB
    clf = GaussianNB()
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    print(clf.score(X_test, y_test))
    nb_report = metrics.classification_report(y_test, y_pred,output_dict=True)
    print("Classification report for - \n{}:\n{}\n".format(clf, nb_report))
    return nb_report

def process_gradientBoosting():
    from sklearn.ensemble import GradientBoostingClassifier
    clf = GradientBoostingClassifier()
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    print(clf.score(X_test, y_test))
    gb_report = metrics.classification_report(y_test, y_pred,output_dict=True)
    print("Classification report for - \n{}:\n{}\n".format(clf, gb_report))
    return gb_report


from tabulate import tabulate
from io import StringIO
import csv
import getopt
import sys
from IPython.display import display, HTML
import pandas as pd
import numpy as np
import webbrowser
import os
import datetime
from pretty_html_table import build_table

def get_table_html(df):

    """
    From https://stackoverflow.com/a/49687866/2007153

    Get a Jupyter like html of pandas dataframe

    """

    styles = [
        #table properties
        dict(selector=" ",
             props=[("margin","0"),
                    ("font-family",'"Helvetica", "Arial", sans-serif'),
                    ("border-collapse", "collapse"),
                    ("border","none"),
                    # ("border", "2px solid #ccf")
                       ]),

        #background shading
        dict(selector="tbody tr:nth-child(even)",
             props=[("background-color", "#fff")]),
        dict(selector="tbody tr:nth-child(odd)",
             props=[("background-color", "#eee")]),

        #cell spacing
        dict(selector="td",
             props=[("padding", ".5em")]),

        #header cell properties
        dict(selector="th",
             props=[("font-size", "100%"),
                    ("text-align", "center")]),

    ]
    return (df.style.set_table_styles(styles)).render()

class FargatePricing():
    def __init__(self):
        ''' No Upfront Costs '''
        self.on_demand_cpu = 0.04048
        self.on_demand_mem = 0.004445
        self.one_year_cpu = 0.032384
        self.one_year_mem = 0.003556
        self.three_year_cpu = 0.022264
        self.three_year_mem = 0.00244475
        self.monthly = 730

class ECS_Service():
    def __init__(self):
        self.service_name = '-'

        self.current_count = 0
        self.new_count = 0

        self.current_cpu = 0
        self.current_mem = 0
        self.new_cpu = 0
        self.new_mem = 0

        self.count_diff = 0
        self.cpu_diff = 0
        self.mem_diff = 0
        self.total_cpu_diff = 0
        self.total_mem_diff = 0

        self.current_mem_total = 0
        self.current_cpu_total = 0
        self.new_mem_total = 0
        self.new_cpu_total = 0

    def calculate_totals(self):
        self.new_mem_total = int(self.new_mem) * int(self.new_count)
        self.new_cpu_total = int(self.new_cpu) * int(self.new_count)
        self.current_cpu_total = int(self.current_cpu) * int(self.current_count)
        self.current_mem_total = int(self.current_mem) * int(self.current_count)

        totals = {
            'new_mem': self.new_mem_total,
            'new_cpu': self.new_cpu_total,
            'current_mem': self.current_mem_total,
            'current_cpu': self.current_cpu_total,
        }

        return totals

    def calculate_diffs(self):
        self.count_diff = int(self.new_count) - int(self.current_count)
        self.cpu_diff = int(self.new_cpu) - int(self.current_cpu)
        self.mem_diff = int(self.new_mem) - int(self.current_mem)
        self.total_cpu_diff = int(self.new_cpu_total) - int(self.current_cpu_total)
        self.total_mem_diff = int(self.new_mem_total) - int(self.current_mem_total)

        diffs = {
            'count': self.count_diff,
            'cpu': self.cpu_diff,
            'mem': self.mem_diff,
            'total_cpu': self.total_cpu_diff,
            'total_mem': self.total_mem_diff,
        }
        return diffs

# def create_dataframe(dataframe, names):
#     df = pd.DataFrame(
#         dataframe, index=list(names),
#         # columns=pd.MultiIndex.from_product([['Decision Tree', 'Regression', 'Random'],['Tumour', 'Non-Tumour']], names=['Model:', 'Predicted:'])
#     )
#     return df

def import_csv(csvfile):
    def header_validation(headers):
        validity = True
        try:
            if header[0] != 'Service Name' or\
               header[1] != 'Current Count' or\
               header[2] != 'New Count' or\
               header[3] != 'Current vCPU Value' or\
               header[4] != 'New vCPU Value' or\
               header[5] != 'Current Memory (in MB)' or\
               header[6] != 'New Memory (in MB)':
                validity = False
        except Exception as e:
            print(e)
            return False
        return validity

    def row_processor(row):
        service_name = row[0]
        current_count = row[1]
        new_count = row[2]
        current_cpu = row[3]
        new_cpu = row[4]
        current_mem = row[5]
        new_mem = row[6]

        e = ECS_Service()
        e.service_name = service_name
        e.current_count = current_count
        e.new_count = new_count
        e.current_cpu = current_cpu
        e.new_cpu = new_cpu
        e.current_mem = current_mem
        e.new_mem = new_mem

        totals = e.calculate_totals()

        e.new_mem_total = totals['new_mem']
        e.new_cpu_total = totals['new_cpu']
        e.current_mem_total = totals['current_mem']
        e.current_cpu_total = totals['current_cpu']

        diffs = e.calculate_diffs()

        e.count_diff = diffs['count']
        e.cpu_diff = diffs['cpu']
        e.mem_diff = diffs['mem']
        e.total_cpu_diff = diffs['total_cpu']
        e.total_mem_diff = diffs['total_mem']

        return e

    with open(csvfile, newline='') as csvfile:
        reader = csv.reader(csvfile, delimiter=',')
        header = next(reader)
        valid_headers = header_validation(header)
        if not valid_headers:
            return False

        rows = []
        for row in reader:
            rows.append(row)

        services = []
        for row in rows:
            service = row_processor(row)
            services.append(service)
        return services

def process_services(services):

    headers = [
        'Current Count',
        'New Count',
        'Count Diff',
        'Current CPU',
        'New CPU',
        'CPU Diff',
        'Current Memory',
        'New Memory',
        'Memory Diff',
        'Current Total CPU',
        'New Total CPU',
        'Current Total Memory',
        'New Total Memory',
        'Total CPU Diff',
        'Total Memory Diff'
    ]

    dataframe = {}
    key_list = list(headers)
    names = []
    changes = []

    for header in headers:
        dataframe[header] = []

    for service in services:

        change = {
            'name': service.service_name,
            'data': [
                service.current_count,
                service.new_count,
                service.count_diff,
                service.current_cpu,
                service.new_cpu,
                service.cpu_diff,
                service.current_mem,
                service.new_mem,
                service.mem_diff,
                service.current_cpu_total,
                service.new_cpu_total,
                service.current_mem_total,
                service.new_mem_total,
                service.total_cpu_diff,
                service.total_mem_diff,
            ]
        }

        changes.append(change)

    for change in changes:
        name = change['name']
        names.append(name)
        for index, data in enumerate(change['data']):
            key = key_list[index]
            dataframe[key].append(data)

    df = pd.DataFrame(
        dataframe, index=list(names),
    )
    return df

def process_pricing(services):

    fargate = FargatePricing()

    headers = [
        'Current Total CPU',
        'Current CPU Price',
        'New Total CPU',
        'New CPU Price',
        'CPU Price Diff',
        'Current Total Memory',
        'Current Mem Price',
        'New Total Memory',
        'New Mem Price',
        'Mem Price Diff',
        'Total Price Diff'
    ]

    dataframe = {}
    key_list = list(headers)
    names = []
    changes = []

    for header in headers:
        dataframe[header] = []

    for service in services:
        current_cpu_price = (service.current_cpu_total / 1024) * (fargate.one_year_cpu * fargate.monthly)
        new_cpu_price = (service.new_cpu_total / 1024) * (fargate.one_year_cpu * fargate.monthly)
        cpu_diff = new_cpu_price - current_cpu_price
        current_mem_price = (service.current_mem_total / 1024) * (fargate.one_year_mem * fargate.monthly)
        new_mem_price = (service.new_mem_total / 1024) * (fargate.one_year_mem * fargate.monthly)
        total_cpu_diff = (service.total_cpu_diff / 1024) * (fargate.one_year_cpu * fargate.monthly)
        total_mem_diff = (service.total_mem_diff / 1024) * (fargate.one_year_mem * fargate.monthly)
        total_price_diff = total_cpu_diff + total_mem_diff

        change = {
            'name': service.service_name,
            'data': [
                service.current_cpu_total,
                current_cpu_price,
                service.new_cpu_total,
                new_cpu_price,
                cpu_diff,
                service.current_mem_total,
                current_mem_price,
                service.new_mem_total,
                new_mem_price,
                total_mem_diff,
                total_price_diff

            ]
        }

        changes.append(change)

    for change in changes:
        name = change['name']
        names.append(name)
        for index, data in enumerate(change['data']):
            key = key_list[index]
            dataframe[key].append(data)

    df = pd.DataFrame(
        dataframe, index=list(names),
    )
    df.loc['Total'] = df.sum()
    df = df.round(2)
    return df

def display_df_html(df):
    df = get_table_html(df)
    filename = 'pandas.html'
    with open(filename, 'w') as f:
        f.write(df)
    file_location = os.path.abspath(f'./%s' % (filename))
    webbrowser.open('file://' + file_location)

def define_service():
    new_cpu = 0
    new_mem = 0
    service_name = input("Set service name: ")
    service_action = input("Do you want to change or remove? (remove/change): ")
    service_action = service_action.strip().lower()
    current_count = int(input("How many tasks are currently running as a baseline: "))
    if service_action in ('r', 'remove'):
        new_count = 0
    else:
        new_count = int(input("Set new service count baseline: "))
        if not new_count:
            new_count = current_count
    current_cpu = int(input("Set current vCPU value: "))
    current_mem = int(input("Set current Memory value: "))
    if service_action in ('change', 'c'):
        service_action = 'change'
        new_cpu = int(input("Set new vCPU value: "))
        new_mem = int(input("Set new Memory value: "))
        # new_count = int(input("Set new service count baseline: "))
        if not new_count:
            new_count = current_count
    if service_action in ('r', 'remove'):
        new_count = 0

    service_definition = {
        'name': service_name,
        'current_count': current_count,
        'new_count': new_count,
        'action': service_action,
        'current_cpu': current_cpu,
        'current_mem': current_mem,
        'new_cpu': new_cpu,
        'new_mem': new_mem
        }
    return service_definition

def manual():
    services = []
    changes = []
    while True:
        service = define_service()
        services.append(service)

        add_more = input("Add another service? (y/n): ")
        add_more = add_more.strip().lower()

        if add_more in ('y', 'yes'):
            continue
        break

    current_total_count = 0
    current_total_cpu_usage = 0
    current_total_mem_usage = 0
    new_total_count = 0
    new_total_cpu_usage = 0
    new_total_mem_usage = 0

    for service in services:
        action = service.get('action')
        current_cpu = service.get('current_cpu')
        current_mem = service.get('current_mem')
        new_cpu = service.get('new_cpu')
        new_mem = service.get('new_mem')
        name = service.get('name')
        current_count = service.get('current_count')
        new_count = service.get('new_count')

        if action == 'change':

            current_cpu_total = current_cpu * current_count
            current_mem_total = current_mem * current_count
            new_cpu_total = new_cpu * new_count
            new_mem_total = new_mem * new_count
            cpu_diff = new_cpu - current_cpu
            mem_diff = new_mem - current_mem

            current_total_count += current_count
            current_total_cpu_usage += current_cpu_total
            current_total_mem_usage += current_mem_total

            new_total_count += new_count
            new_total_cpu_usage += new_cpu_total
            new_total_mem_usage += new_mem_total

            service_cpu_diff = new_cpu_total - current_cpu_total
            service_mem_diff = new_mem_total - current_mem_total
            count_diff = new_count - current_count

            change = {
                'name': name,
                'data': [
                    current_count,
                    new_count,
                    count_diff,
                    current_cpu,
                    new_cpu,
                    cpu_diff,
                    current_mem,
                    new_mem,
                    mem_diff,
                    current_cpu_total,
                    new_cpu_total,
                    current_mem_total,
                    new_mem_total,
                    service_cpu_diff,
                    service_mem_diff,
                ]
            }

            changes.append(change)

    total_cpu_diff = new_total_cpu_usage - current_total_cpu_usage
    total_mem_diff = new_total_mem_usage - current_total_mem_usage
    total_count_diff = new_total_count - current_total_count

    headers = [
        # 'Name',
        'Current Count',
        'New Count',
        'Count Diff',
        'Current CPU',
        'New CPU',
        'CPU Diff',
        'Current Memory',
        'New Memory',
        'Memory Diff',
        'Current Total CPU',
        'New Total CPU',
        'Current Total Memory',
        'New Total Memory',
        'Total CPU Diff',
        'Total Memory Diff'
    ]

    dataframe = {}

    for header in headers:
        dataframe[header] = []

    key_list = list(dataframe)
    names = []

    for change in changes:
        name = change['name']
        names.append(name)
        for index, data in enumerate(change['data']):
            key = key_list[index]
            dataframe[key].append(data)

    df = pd.DataFrame(
        dataframe, index=list(names),
        # columns=pd.MultiIndex.from_product([['Decision Tree', 'Regression', 'Random'],['Tumour', 'Non-Tumour']], names=['Model:', 'Predicted:'])
    )
    df.style
    print(tabulate(df, headers='keys', tablefmt='pretty'))

def run_csv(inputfile):
    services = import_csv(inputfile)
    service_df = process_services(services)
    pricing_df = process_pricing(services)

    print(tabulate(service_df, headers='keys', tablefmt='pretty'))
    print(tabulate(pricing_df, headers='keys', tablefmt='pretty'))

    display_df_html(pricing_df)

def main(argv):

    inputfile = ''
    try:
        opts, args = getopt.getopt(argv, "hmi:", ["ifile="])
    except getopt.GetoptError:
        print('pricing.py -i <csvfile.csv>')
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-h':
            print('pricing -i <file>.csv')
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputfile = arg
            run_csv(inputfile)
        elif opt == '-m':
            manual()

if __name__ == '__main__':
    main(sys.argv[1:])


from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated, IsAdminUser

from .serializers import BookSerializer, LibrarySerializer, BookInfoSerializer
from .models import Book, Library, BookInfo

class BookViewSet(viewsets.ModelViewSet):
    serializer_class = BookSerializer

    def get_queryset(self):
        books = Book.objects.all()

        library = self.request.query_params.get('library')
        title = self.request.query_params.get('title')
        author = self.request.query_params.get('author')
        publisher = self.request.query_params.get('publisher')
        published_year = self.request.query_params.get('year')

        if library:
            books = books.filter(library__name__icontains=library)
        if title:
            books = books.filter(book_info__title__icontains=title)
        if author:
            books = books.filter(book_info__author__icontains=author)
        if publisher:
            books = books.filter(book_info__publisher__icontains=publisher)
        if published_year:
            books = books.filter(book_info__published_year=published_year)

        return books

    def get_permissions(self):
        if self.action == 'list' or self.action == 'retrieve' or self.action == 'update':
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = [IsAdminUser]

        return [permission() for permission in permission_classes]

class LibraryViewSet(viewsets.ModelViewSet):
    queryset = Library.objects.all()
    serializer_class = LibrarySerializer

    def get_permissions(self):
        if self.action == 'list' or self.action == 'retrieve':
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = [IsAdminUser]

        return [permission() for permission in permission_classes]

class BookInfoViewSet(viewsets.ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get_permissions(self):
        if self.action == 'list' or self.action == 'retrieve':
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = [IsAdminUser]

        return [permission() for permission in permission_classes]


import geoip2.webservice
from maxmind_integration import *

class GeoIP(MaxMind):

	def __init__(self):
		MaxMind.__init__(self)
		self.client = geoip2.webservice.Client(self.account_id, self.license_key)

	def lookup_geoip(self, d):
		"""
		Takes a dict D with key IP (as a string) and returns
		a response dictionary.
		"""
		try:
			insight = self.client.insights(d['ip'])
			response = {}

			#Create variables for each instance variable of INSIGHT
			city = insight.city
			continent = insight.continent
			country = insight.country
			location = insight.location
			registered_country = insight.registered_country
			represented_country = insight.represented_country
			subdivisions = insight.subdivisions
			traits = insight.traits

			#Create a dictionary with all CITY information
			response['City'] = {}
			city_d = response['City']

			city_d['Confidence'] = city.confidence
			city_d['Geoname ID'] = city.geoname_id
			city_d['Name'] = city.name

			#Create a dictionary with all CONTINENT information
			response['Continent'] = {}
			continent_d = response['Continent']

			continent_d['Code'] = continent.code
			continent_d['Geoname ID'] = continent.geoname_id
			continent_d['Name'] = continent.name

			#Create a dictionary with all COUNTRY information
			response['Country'] = {}
			country_d = response['Country']

			country_d['Confidence'] = country.confidence
			country_d['Geoname ID'] = country.geoname_id
			country_d['Is in EU?'] = country.is_in_european_union
			country_d['ISO Code'] = country.iso_code
			country_d['Name'] = country.name

			#Create a dictionary with all LOCATION information
			response['Location'] = {}
			location_d = response['Location']

			location_d['Average Income'] = location.average_income
			location_d['67% Confidence Location Radius (km)'] = location.accuracy_radius
			location_d['Latitude'] = location.latitude
			location_d['Longitude'] = location.longitude
			location_d['Metro Code'] = location.metro_code
			location_d['Population Density'] = location.population_density
			location_d['Time Zone'] = location.time_zone

			#Create a dictionary with all ISP REGISTERED COUNTRY information
			response['ISP Registered Country'] = {}
			reg_country_d = response['ISP Registered Country']

			reg_country_d['Confidence'] = registered_country.confidence
			reg_country_d['Geoname ID'] = registered_country.geoname_id
			reg_country_d['Is in EU?'] = registered_country.is_in_european_union
			reg_country_d['ISO Code'] = registered_country.iso_code
			reg_country_d['Name'] = registered_country.name

			#Create a dictionary with all REPRESENTED COUNTRY information
			response['Country Represented by Users of IP Address'] = {}
			rep_country_d = response['Country Represented by Users of IP Address']

			rep_country_d['Confidence'] = represented_country.confidence
			rep_country_d['Geoname ID'] = represented_country.geoname_id
			rep_country_d['Is in EU?'] = represented_country.is_in_european_union
			rep_country_d['ISO Code'] = represented_country.iso_code
			rep_country_d['Name'] = represented_country.name
			rep_country_d['Type'] = represented_country.type

			#Find most specific SUBDIVISION
			subdivision = subdivisions.most_specific

			#Create a dictionary with all MOST SPECIFIC SUBDIVISION information
			response['Most Specific Subdivision'] = {}
			subdivision_d = response['Most Specific Subdivision']

			subdivision_d['Confidence'] = subdivision.confidence
			subdivision_d['Geoname ID'] = subdivision.geoname_id
			subdivision_d['ISO Code'] = subdivision.iso_code
			subdivision_d['Name'] = subdivision.name

			#Create a dictionary with all TRAITS information
			response['Traits'] = {}
			traits_d = response['Traits']

			traits_d['Autonomous System Number'] = traits.autonomous_system_number
			traits_d['Autonomous System Organization'] = traits.autonomous_system_organization
			traits_d['Connection Type'] = traits.connection_type
			traits_d['Domain'] = traits.domain
			traits_d['IP Address'] = traits.ip_address
			traits_d['Is Anonymous?'] = traits.is_anonymous
			traits_d['Is Anonymous VPN?'] = traits.is_anonymous_vpn
			traits_d['Is Hosting Provider?'] = traits.is_hosting_provider
			traits_d['Is Legitimate Proxy?'] = traits.is_legitimate_proxy
			traits_d['Is Public Proxy?'] = traits.is_public_proxy
			traits_d['Is Satellite Provider?'] = traits.is_satellite_provider
			traits_d['Is Tor Exit Node?'] = traits.is_tor_exit_node
			traits_d['ISP'] = traits.isp
			traits_d['Organization'] = traits.organization
			traits_d['User Type'] = traits.user_type

			return response

		except geoip2.errors.AddressNotFoundError:
			return 'The address you were looking up was not found.'

		except geoip2.errors.AuthenticationError:
			return 'There was a problem authenticating the request.'

		except geoip2.errors.GeoIP2Error:
			return 'There was a generic error in GeoIP2.'

		except geoip2.errors.HTTPError:
			return 'There was an error when making your HTTP request.'

		except geoip2.errors.InvalidRequestError:
			return 'The request was invalid.'

		except geoip2.errors.OutOfQueriesError:
			return 'No funds remaining for the service queried.'

		except geoip2.errors.PermissionRequiredError:
			return 'Your account does not have permission to access this service.'


"""Implementation of estimators that select features."""
from typing import List, Optional, Tuple

import dask.dataframe as daskdf
import networkx as nx
import numpy as np
import pandas as pd
import scipy.stats as stats
from py4ai.data.model.ml import PandasDataset
from dask.multiprocessing import get
from psutil import cpu_count
from typeguard import typechecked
from typing_extensions import Literal

from py4ai.analytics.ml.core import Estimator, Numeric
from py4ai.analytics.ml.core.enricher.transformer.discretizer import toMultiLevels
from py4ai.analytics.ml.core.enricher.transformer.selector import FeatureSelector
from py4ai.analytics.ml.eda.general import computeCorrelation, filterColumnsWith

Correlations = Literal["absolute", "positive", "negative"]

class DeleteConstantFeatures(Estimator):
    """Remove features with ratio between standard deviation and mean less than a defined threshold."""

    def __init__(self, threshold: Numeric = 0) -> None:
        """
        Class instance initializer.

        :param threshold: threshold for the standard deviation of features
        """
        self.threshold = threshold

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Select columns to keep and drop.

        :param dataset: Dataset instance with features and labels

        :return: FeatureSelector Transformer
        """
        X = dataset.features
        self.logger.debug("Deleting constant features...")
        to_drop = X.columns[X.std() <= self.threshold]
        to_keep = list(set(X.columns).difference(set(to_drop)))

        self.logger.info(
            "Number of columns dropped by EnhancedDeleteCostantFeatures: %d"
            % len(to_drop)
        )
        self.logger.debug(
            "EnhancedDeleteCostantFeatures dropped columns:\n%s"
            % ("\n".join(sorted(to_drop)))
        )

        return FeatureSelector(to_keep=to_keep, estimator=self)

class FilterOutNans(Estimator):
    """Drop columns with a number of nulls bigger than the selected threshold."""

    def __init__(self, percentage: Numeric = 0.05):
        """
        Class instance initializer.

        :param percentage: minimum percentage of NAs allowed in a column
        """
        self.percentage = percentage

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Select columns to keep and drop.

        :param dataset: Dataset instance with features and labels
        :return: FeatureSelector Transformer
        """
        X = dataset.features
        nans = X.isnull().sum() * 1.0 / X.shape[0]
        to_drop = list(nans[nans > self.percentage].index)
        to_keep = list(set(X.columns).difference(set(to_drop)))

        return FeatureSelector(to_keep=to_keep, estimator=self)

class SelectByCorrelation(Estimator):
    """Select features based on a correlation threshold."""

    _correlation_functions = {
        "absolute": lambda x: np.abs(x),
        "positive": lambda x: x,
        "negative": lambda x: -x,
    }

    def __init__(
        self,
        threshold: Numeric = 0.4,
        correlation: Correlations = "absolute",
        start: Optional[str] = None,
        end: Optional[str] = None,
    ):
        """
        Class instance initializer.

        :param threshold: minimum correlation threshold to select variables
        :param correlation: function to apply to calculate correlation one of "absolute", "positive" or "negative". Default "absolute"
        :param start: start date to apply correlation function
        :param end: end date to apply correlation function
        """
        self.threshold = threshold
        self.start = start
        self.end = end
        self._f = self._correlation_functions[correlation]

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Select columns to keep and drop.

        :param dataset: Dataset instance with features and labels
        :return: FeatureSelector Transformer
        """
        x = dataset.features
        y = dataset.labels

        if type(x) == pd.DataFrame:
            x_ = x[slice(self.start, self.end)].copy()
        else:
            x_ = pd.DataFrame(x)[slice(self.start, self.end)]

        if type(y) == pd.DataFrame:
            y_ = y[slice(self.start, self.end)].copy()
        else:
            y_ = pd.DataFrame(y, index=x.index)[slice(self.start, self.end)]

        correlations = computeCorrelation(x_, y_).applymap(self._f)

        # Max correlations along rows
        maxCorrelations = correlations.max(axis=1)
        self.correlations = maxCorrelations

        to_keep = maxCorrelations[maxCorrelations > self.threshold].index

        # self.logger.info("Number of columns dropped by SelectByCorrelation: %d" % len(to_drop))
        # self.logger.debug("SelectByCorrelation dropped columns:\n%s" % ("\n".join(sorted(to_drop))))

        return FeatureSelector(to_keep=to_keep, estimator=self)

class SelectorFromSubstrings(Estimator):
    """Select columns with given substings in their name."""

    def __init__(self, strlist: List[str]):
        """
        Class instance initializer.

        :param strlist: list of strings
        """
        self.strlist = strlist

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Select columns to keep and drop.

        :param dataset: Dataset instance with features and labels
        :return: FeatureSelector Transformer
        """
        X = dataset.features
        to_keep = filterColumnsWith(X, self.strlist).columns

        # self.logger.info("Number of columns dropped by SelectFromSubstrings: %d" % len(to_drop))
        # self.logger.debug("SelectorFromSubstrings dropped columns:\n%s" % ("\n".join(sorted(to_drop))))

        return FeatureSelector(to_keep=to_keep, estimator=self)

class SelectByKL(Estimator):
    """Select features depending on the Kullback-Leibler divergence.

    Select features depending on the Kullback-Leibler divergence between the distribution of under the two levels of the
    target variable. The ratio is to drop features that to not exhibit particularly different distribution under the two
    levels of the target variables.
    """

    def __init__(
        self, kl_thresh: Numeric = 1.0, y_thresh: Optional[Numeric] = None
    ) -> None:
        """
        Class instance initializer.

        :param kl_thresh: threshold on KL divergence. Drop columns if KL divergence is greater than thresh
        :param y_thresh: threshold to discretize the target variable (in case it is not already discrete)
        """
        self.kl_thresh = kl_thresh
        self.y_thresh = y_thresh
        self.divergences01: Optional[PandasDataset] = None

    @staticmethod
    def _compute_divergences(x: pd.Series, y: pd.Series) -> float:
        """
        Compute KL between x series when y is 0 and when y is 1.

        :param x: feature series
        :param y: target series
        :return: KL divergence
        """
        yvals = np.unique(y)
        points = np.linspace(x.min(), x.max(), max((x.max() - x.min()) * 2, 100))

        if x.std() == 0:  # If the feature is constant, we drop it
            out = 0.0
        elif len(np.unique(x[y == yvals[0]])) == 1:
            # If the feature is constant where the target is not interesting it means that it is not constant where the
            # target is interesting and thus we keep it
            out = np.inf
        elif len(np.unique(x[y == yvals[1]])) == 1:
            # If the feature is constant where the target is interesting it means that it is not constant where the
            # target is not interesting.
            # Thus we check if that value is common where the target is not interesting and, if it is, we drop it.
            if (
                sum(x[y == yvals[0]] == np.unique(x[y == yvals[1]])[0])
                * 1.0
                / len(x[y == yvals[0]])
                > 0.3
            ):
                out = 0.0
            else:
                out = np.inf
        else:
            out = stats.entropy(
                stats.kde.gaussian_kde(x[y == yvals[0]].values.ravel())(points),
                stats.kde.gaussian_kde(x[y == yvals[1]].values.ravel())(points),
            )

        return out

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Select columns to keep and drop.

        :param dataset: Dataset instance with features and labels
        :return: FeatureSelector Transformer
        """
        cleaned = dataset.dropna().intersection()

        if len(cleaned) != len(dataset):
            self.logger.warning(
                f"{type(self)}: Training Set has nan values which has been dropped from the training"
            )

        X, y = cleaned.features, cleaned.labels

        if self.y_thresh is not None:
            y = toMultiLevels(y, self.y_thresh)

        if len(np.unique(y)) == 2:
            dX = daskdf.from_pandas(X.T, npartitions=cpu_count() * 2)
            self.divergences01 = dX.apply(
                (lambda x: self._compute_divergences(x, y)), axis=1
            ).compute(get=get)
            to_drop = list(
                self.divergences01[self.divergences01.values < self.kl_thresh].index
            )
        else:
            to_drop = []
        to_keep = list(set(X.columns).difference(to_drop))

        return FeatureSelector(to_keep=to_keep, estimator=self)

class DeleteDuplicates(Estimator):
    """Keep only the most correlated with the target of a set of highly correlated features."""

    def __init__(
        self,
        threshold: Numeric = 0.9,
        min_threshold: Numeric = 0.8,
        step: Numeric = 0.1,
    ):
        """
        Class instance initializer.

        :param threshold: minimum value to consider features to be deleted
        :param min_threshold: min_threshold for graph correlation
        :param step: step used to increase threshold
        """
        self.threshold = threshold
        self.min_threshold = min_threshold
        self.step = step

    def _most_correlated(self, X: pd.DataFrame, y: pd.DataFrame) -> Tuple[str, float]:
        """
        Calculate the feature with the max correlation.

        :param X: pd.DataFrame with features
        :param y: pd.DataFrame with targets
        :return: tuple with the name of the variable and the value of correlation
        """
        corr = computeCorrelation(X, y).abs().max(axis=1)
        ret = (corr.idxmax(), corr.max())
        if len(corr) > 1:
            self.logger.info(
                f"Keeping \033[1m{ret[0]}\033[0m [{round(ret[1], 2)}] between {', '.join(corr.index)}"
            )
        return ret

    @staticmethod
    def _least_correlated_components(
        corr: pd.DataFrame, cols: List[str]
    ) -> Tuple[float, int]:
        """
        Calculate least correlated features.

        :param corr: corr matrix
        :param cols: columns to include in calculation
        :return: tuple with the name of the variable, the value of correlation and the number of cols considered
        """
        sub_corr = corr[cols].loc[cols].abs().min(axis=1)
        return sub_corr.min(), len(cols)

    def _graph_correlation(self, dataset: PandasDataset) -> PandasDataset:
        """
        Get list with columns to drop based on the thresholds selected.

        :param dataset: input dataset
        :return: new dataset with removed columns
        """
        corrs = computeCorrelation(dataset.features).abs()
        thres = self.threshold
        self.logger.info(f"Initial pruning threshold: {self.threshold}")
        to_keep = dataset.features.columns

        check = False
        ith = 0
        while not check:
            ith += 1
            self.logger.debug("Iteration: %d" % ith)
            # Undirected Graph with edges given by correlations over threshold
            mat = corrs.applymap(lambda x: 1 if x > thres else 0)
            g = nx.Graph(mat.values)
            for icol, col in enumerate(mat.columns):
                g.nodes[icol].update({"name": col})

            # List of couples of least correlated features for each connected component
            minCorrs = [
                self._least_correlated_components(
                    corrs, [g.nodes[x]["name"] for x in group]
                )
                for group in nx.connected_components(g)
            ]

            self.logger.info(
                f"Number of non-singleton connected components: "
                f"{sum(map(lambda x: 1 if x[1] > 1 else 0, minCorrs))}"
            )
            self.logger.info(
                f"Total elements in non-sigleton connected components: "
                f"{sum(map(lambda x: x[1] if x[1] > 1 else 0, minCorrs))}"
            )
            self.logger.info(
                f"Number of connected components with minimal correlation under {self.min_threshold}: "
                f"{len([t for t in minCorrs if t[0] <= self.min_threshold])}"
            )

            # Check that all correlations are above a certain threshold
            check = all(map(lambda x: x[0] > self.min_threshold, minCorrs))
            self.logger.debug("check: " + str(check))

            if not check:
                thres = (1 - self.step) * thres + self.step
                self.logger.info(f"Updating threshold to: {thres}\n")
            else:
                to_keep = [
                    self._most_correlated(
                        dataset.features[[g.nodes[x]["name"] for x in group]],
                        dataset.labels,
                    )[0]
                    for group in nx.connected_components(g)
                ]
                self.logger.debug(f"Number of columns to keep: {len(to_keep)}")

        if set(to_keep) != set(dataset.features.columns):
            return self._graph_correlation(
                dataset.createObject(dataset.features[to_keep], dataset.labels)
            )
        else:
            return dataset

    @typechecked
    def train(self, dataset: PandasDataset) -> FeatureSelector:
        """
        Get the list of columns to drop based on the correlation function selected.

        :param dataset: input data
        :return: feature selector instance
        """
        outdataset = self._graph_correlation(
            DeleteConstantFeatures(threshold=0).train(dataset).transform(dataset)
        )

        self.logger.info(
            f"Number of columns to keep: {len(outdataset.features.columns)}"
        )
        self.logger.debug(
            "Columns to keep:\n%s" % ("\n".join(sorted(outdataset.features.columns)))
        )

        return FeatureSelector(
            to_keep=list(outdataset.features.columns), estimator=self
        )


import numpy as np
import random
import math
from environment import *
import matplotlib.pyplot as plt
import matplotlib.animation as animation

class MountainCar():

	def __init__(self,position,velocity):
		self.position = position
		self.velocity = velocity
		self.action = np.array([0,1,2])

	def bound(self, x, x_min, x_max):
		if x < x_min:
			return x_min
		else:
			return min(x, x_max)

	def move(self, a, x_bound, v_bound):
		v = self.velocity + 0.001*a - 0.0025*(math.cos(3*self.position))
		x = self.position + v
		self.position = self.bound(x, x_bound[0], x_bound[1])
		self.velocity = self.bound(v, v_bound[0], v_bound[1])
		return self.position, self.velocity

	def get_state(self):
		return (self.position, self.velocity)

	def reset(self, x0_min, x0_max):
		self.position = random.uniform(x0_min, x0_max)
		self.velocity = 0

	def render(self,S,file_path='/Users/Miri/RL-Practice/MountainCar/mountain_car.mp4', mode='mp4'):
		fig = plt.figure()
		ax = fig.add_subplot(111, autoscale_on=False, xlim=(-1.2, 0.5), ylim=(-1.1, 1.1))
		ax.grid(False)  # disable the grid
		x_sin = np.linspace(start=-1.2, stop=0.5, num=100)
		y_sin = np.sin(3 * x_sin)
		ax.plot(x_sin, y_sin)  # plot the sine wave
		dot, = ax.plot([], [], 'ro')
		time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)

		def _init():
			dot.set_data([], [])
			time_text.set_text('')
			return dot, time_text

		def animate(i):
			x = S[i]
			y = np.sin(3 * x)
			dot.set_data(x, y)
			time_text.set_text("Time: " + str(np.round(i*0.1, 1)) + "s" + '\n' + "Frame: " + str(i))
			return dot, time_text

		ani = animation.FuncAnimation(fig, animate, frames =np.arange(1,len(S)),
                                      blit=True, init_func=_init, repeat=False)

		writervideo = animation.FFMpegWriter(fps=60)

		ani.save(file_path, writer= writervideo) #,codec='libx264')
		fig.clear()
		plt.close(fig)

def Policy(s,w):
	a = np.argmax((qvalue(s,-1,w), qvalue(s,0,w), qvalue(s,1,w)))
	return a-1


#!/usr/bin/python3
import yaml
import os
import ipaddress
import random
import sys

if len(sys.argv) != 3:
    print('Incorrect usage')
    print('Usage : ./gen_instances.py input.yaml templates.yaml')
    exit()

# Open file all.yml
stream = open('all.yml', 'w')

# Read test specific config file
#test_stream = open('input.yaml', 'r')
test_stream = open(sys.argv[1], 'r')
for x in yaml.load_all(test_stream):
    test_dict = x

# Store test specific variables
test_var_dict = dict(test_dict['test_var'])

# Store machines specific variables
machines_dict = dict(test_dict['machine_info'])
machine_names = machines_dict.keys()
number_of_machines = len(machines_dict.keys())

# Store role info for instances
role_dict = dict(test_dict['role_def'])

# Calculate number of bms
number_of_bms = 0
bms_names = []
bms_ips = []
for machine in machines_dict:
    if machines_dict[machine]['number_of_vms'] == 0:
        number_of_bms = number_of_bms + 1
        bms_names.append(machines_dict[machine]['name'])
        bms_ips.append(machines_dict[machine]['ip'])

# Calculate the number of hypervisors
number_of_hypervisors = 0
hypervisor_names = []
hypervisor_ips = []
for machine in machines_dict:
    if machines_dict[machine]['number_of_vms'] > 0:
        number_of_hypervisors = number_of_hypervisors + 1
        hypervisor_names.append(machines_dict[machine]['name'])
        hypervisor_ips.append(machines_dict[machine]['ip'])

# Calculate the number of instances
number_of_instances = 0
for machine in machines_dict:
    number_of_instances = number_of_instances + machines_dict[machine]['number_of_vms']
number_of_instances = number_of_instances + number_of_bms

# Create the ip list
start_ip = test_var_dict['start_ip']
start_addr = ipaddress.IPv4Address(start_ip)
ip_list = []
for ip in range(1,number_of_instances + 1):
    ip_list.append(str(start_addr+ip))

# Generate unique mac address
mac_addr_list = []
def randomMAC():
        mac = [ 0x00,
                random.randint(0x00, 0xff),
                random.randint(0x00, 0xff),
                random.randint(0x00, 0xff),
                random.randint(0x00, 0xff),
                random.randint(0x00, 0xff) ]
        return ':'.join(map(lambda x: "%02x" % x, mac))

# Read all block templates and store them
#template_stream = open('templates.yaml', 'r')
template_stream = open(sys.argv[2], 'r')
for x in yaml.load_all(template_stream):
    deployment_dict = x['deployment_section']
    servermanager_dict = x['servermanager_section']
    providerconfig_dict = x['providerconfig_section']
    instance_template_dict = x['instances_section']
    host_template_dict = x['hosts_section']
    network_template_dict = host_template_dict['network']
    interfaces_template_dict = network_template_dict['interfaces']
    intf1_template = interfaces_template_dict['intf1']
    intf2_template = interfaces_template_dict['intf2']
    contrail_config_dict =  x['contrail_section']
    kolla_config_dict =   x['kolla_section']
    orchestrator_config_dict =   x['orchestrator_section']
    test_topo_dict =   x['test_topo_section']

# Create the instances block
instances_dict = {}
instances_list_dict = {}
instances_list = []

for machine in machines_dict:
    if machines_dict[machine]['number_of_vms'] > 0:
        for vm_num in range(1,machines_dict[machine]['number_of_vms'] + 1):
            instances_list.append(str(machines_dict[machine]['name'])+'-vm'+str(vm_num))
    else:
        for vm_num in range(1,2):
            #instances_list.append(str(machines_dict[machine]['name'])+'-vm'+str(vm_num))
            instances_list.append(str(machines_dict[machine]['name']))

## create all the instances
vrouter_role = ['vrouter','openstack_compute']
for instance_num in range(0,number_of_instances):
    instances_list_dict[instances_list[instance_num]] = dict(instance_template_dict)
    instances_list_dict[instances_list[instance_num]]['provider'] = 'bms'
    instances_list_dict[instances_list[instance_num]]['ip'] = ip_list[instance_num]
    if instances_list[instance_num] in role_dict.keys():
        instances_list_dict[instances_list[instance_num]]['roles'] = role_dict[instances_list[instance_num]]['roles']
    else:
        instances_list_dict[instances_list[instance_num]]['roles'] = dict.fromkeys(vrouter_role)
    del instances_list_dict[instances_list[instance_num]]['instance_name']
instances_dict = {'instances': instances_list_dict}

hypervisors_list = []
for machine in machines_dict:
    if machines_dict[machine]['number_of_vms'] > 0:
            hypervisors_list.append(machines_dict[machine])

## create hosts per hypervisor
def get_hosts_kvm(hyp_dict,bms_index):
    hosts_list_dict = {}
    instances_per_bms = hyp_dict['number_of_vms']
    for host_num in range(1,instances_per_bms+1):
        hosts_list_dict['host'+str(host_num)] = dict(host_template_dict)
        hosts_list_dict['host'+str(host_num)]['name'] = hyp_dict['name']+'-vm'+str(host_num)
        hosts_list_dict['host'+str(host_num)]['ip'] =  instances_dict['instances'][hyp_dict['name']+'-vm'+str(host_num)]['ip']
        hosts_list_dict['host'+str(host_num)]['ram'] =  1024
        hosts_list_dict['host'+str(host_num)]['vcpus'] = 4
        hosts_list_dict['host'+str(host_num)]['server'] = 'kvm_host'+str(host_num)
        hosts_list_dict['host'+str(host_num)]['network'] = dict(network_template_dict)
        hosts_list_dict['host'+str(host_num)]['network']['interfaces'] = dict(interfaces_template_dict)
        hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf1'] = dict(intf1_template)
        if 'bond_interface_name' in machines_dict[bms_index].keys():
            hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf1']['bridge'] = machines_dict[bms_index]['bond_interface_name']
        else:
            hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf1']['bridge'] = hyp_dict['interface1']
        random_mac = randomMAC()
        mac_addr_list.append(random_mac)
        hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf1']['mac'] = random_mac
        if test_var_dict['multi_interface'] == True:
            hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf2'] = dict(intf2_template)
            hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf2']['bridge'] = hyp_dict['interface2']
            random_mac = randomMAC()
            mac_addr_list.append(random_mac)
            hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf2']['mac'] = random_mac
        else:
            del hosts_list_dict['host'+str(host_num)]['network']['interfaces']['intf2']
    return hosts_list_dict

kvmhost_names = []
for kvm_num in range(1,number_of_hypervisors+1):
    kvmhost_names.append('kvm_host'+str(kvm_num))

hypervisors_list_dict = {}
for kvmhost in kvmhost_names:
    temp = {}
    temp['ip'] = hypervisor_ips.pop(0)
    temp['username'] = "root"
    temp['password'] = "c0ntrail123"
    hyp_dict = hypervisors_list.pop(0)
    for bms in machines_dict:
        if str(machines_dict[bms]['ip']) == str(hyp_dict['ip']):
           bms_index = bms
           break
    temp['vm_config'] = get_hosts_kvm(hyp_dict,bms_index)
    hypervisors_list_dict[kvmhost] = dict(temp)

default_dict = {}
default_dict['image_dest'] = test_var_dict['image_dest']
default_dict['disk_format'] =  test_var_dict['disk_format']
default_dict['vagrant_images'] = test_var_dict['vagrant_images']
default_dict['vagrant_plugin'] =  test_var_dict['vagrant_plugin']
default_dict['vagrant_box'] =  test_var_dict['vagrant_box']
default_dict['vagrant_box_name'] = test_var_dict['vagrant_box_name']

vm_info = {'default': default_dict,
           'hypervisors': hypervisors_list_dict}
vm_info_dict = {'vm_info': vm_info}
bond_info_dict = {'bond_info': machines_dict}

deployment_dict['deployment']['orchestrator'] = test_var_dict['orchestrator']
deployment_dict['deployment']['type']['contrail']['branch'] = test_var_dict['contrail_branch']
deployment_dict['deployment']['type']['contrail']['registry'] = test_var_dict['contrail_registry']
deployment_dict['deployment']['type']['kolla']['branch'] = test_var_dict['kolla_branch']
deployment_dict['deployment']['type']['kolla']['registry'] = test_var_dict['kolla_registry']
deployment_dict['deployment']['sku'] = test_var_dict['sku']
deployment_dict['deployment']['version'] = test_var_dict['version']
deployment_dict['deployment']['os'] = test_var_dict['os']
servermanager_dict['server_manager']['ip'] = test_var_dict['server_manager']
orchestrator_config_dict['orchestrator_configuration']['internal_vip'] = test_var_dict['internal_vip']
orchestrator_config_dict['orchestrator_configuration']['external_vip'] = test_var_dict['external_vip']
kolla_config_dict['kolla_config']['kolla_globals']['kolla_internal_vip_address'] = test_var_dict['internal_vip']
kolla_config_dict['kolla_config']['kolla_globals']['kolla_external_vip_address'] = test_var_dict['external_vip']
kolla_config_dict['kolla_config']['kolla_globals']['contrail_api_interface_address'] = test_var_dict['contrail_api_interface_addr']
kolla_config_dict['kolla_config']['kolla_globals']['docker_registry'] = test_var_dict['contrail_registry']
contrail_config_dict['contrail_configuration']['CONTAINER_REGISTRY'] = test_var_dict['contrail_registry']
contrail_config_dict['contrail_configuration']['CONTRAIL_VERSION'] = test_var_dict['version']
contrail_config_dict['contrail_configuration']['CLOUD_ORCHESTRATOR'] = test_var_dict['orchestrator']
contrail_config_dict['contrail_configuration']['KEYSTONE_AUTH_HOST'] = test_var_dict['keystone_auth_host']
contrail_config_dict['contrail_configuration']['VROUTER_GATEWAY'] = test_var_dict['vrouter_gw']

yaml.dump(deployment_dict,stream,default_flow_style=False)
yaml.dump(servermanager_dict,stream,default_flow_style=False)
yaml.dump(providerconfig_dict,stream,default_flow_style=False)
yaml.dump(contrail_config_dict,stream,default_flow_style=False)
yaml.dump(kolla_config_dict,stream,default_flow_style=False)
yaml.dump(orchestrator_config_dict,stream,default_flow_style=False)
yaml.dump(test_topo_dict,stream,default_flow_style=False)
yaml.dump(instances_dict,stream,default_flow_style=False)
yaml.dump(vm_info_dict,stream,default_flow_style=False)
yaml.dump(bond_info_dict,stream,default_flow_style=False)
if len(mac_addr_list) != len(set(mac_addr_list)):
   print('MAC addr is not uniquely generated')


"""Config flow for Google Photos integration."""
from __future__ import annotations

from collections.abc import Mapping
import logging
from typing import Any, List
import voluptuous as vol

from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError as GoogleApiError

from homeassistant import config_entries
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import config_entry_oauth2_flow

from .api_types import PhotosLibraryService, Album
from .const import (
    DEFAULT_ACCESS,
    DOMAIN,
    CONF_WRITEMETADATA,
    WRITEMETADATA_DEFAULT_OPTION,
    CONF_ALBUM_ID,
    CONF_ALBUM_ID_FAVORITES,
)

class OAuth2FlowHandler(
    config_entry_oauth2_flow.AbstractOAuth2FlowHandler, domain=DOMAIN
):
    """Config flow to handle Google Photos OAuth2 authentication."""

    DOMAIN = DOMAIN
    VERSION = 2

    reauth_entry: ConfigEntry | None = None

    @property
    def logger(self) -> logging.Logger:
        """Return logger."""
        return logging.getLogger(__name__)

    @property
    def extra_authorize_data(self) -> dict[str, Any]:
        """Extra data that needs to be appended to the authorize url."""
        return {
            "scope": " ".join(DEFAULT_ACCESS),
            # Add params to ensure we get back a refresh token
            "access_type": "offline",
            "prompt": "consent",
        }

    async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
        """Perform reauth upon an API authentication error."""
        self.reauth_entry = self.hass.config_entries.async_get_entry(
            self.context["entry_id"]
        )
        return await self.async_step_reauth_confirm()

    async def async_step_reauth_confirm(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Confirm reauth dialog."""
        if user_input is None:
            return self.async_show_form(step_id="reauth_confirm")
        return await self.async_step_user()

    async def async_oauth_create_entry(self, data: dict[str, Any]) -> FlowResult:
        """Create an entry for the flow, or update existing entry."""
        if self.reauth_entry:
            self.hass.config_entries.async_update_entry(self.reauth_entry, data=data)
            await self.hass.config_entries.async_reload(self.reauth_entry.entry_id)
            return self.async_abort(reason="reauth_successful")

        credentials = Credentials(data[CONF_TOKEN][CONF_ACCESS_TOKEN])

        def _get_profile() -> dict[str, Any]:
            """Get profile from inside the executor."""
            lib = build("oauth2", "v2", credentials=credentials)
            userinfo = lib.userinfo().get().execute()  # pylint: disable=no-member
            return userinfo

        def _check_photoslibrary_access() -> PhotosLibraryService:
            lib = build(
                "photoslibrary",
                "v1",
                credentials=credentials,
                static_discovery=False,
            )
            albums = (
                lib.albums().list(pageSize=1).execute()  # pylint: disable=no-member
            )
            return albums

        try:
            (await self.hass.async_add_executor_job(_check_photoslibrary_access))
            email = (await self.hass.async_add_executor_job(_get_profile))["email"]
        except GoogleApiError as ex:
            return self.async_abort(
                reason="access_error", description_placeholders={"reason": ex.reason}
            )

        await self.async_set_unique_id(email)
        self._abort_if_unique_id_configured()

        options = dict()
        options[CONF_ALBUM_ID] = [CONF_ALBUM_ID_FAVORITES]
        return self.async_create_entry(title=email, data=data, options=options)

    @staticmethod
    @callback
    def async_get_options_flow(
        config_entry: config_entries.ConfigEntry,
    ) -> OptionsFlowHandler:
        """Get the options flow for this handler."""
        return OptionsFlowHandler(config_entry)

class OptionsFlowHandler(config_entries.OptionsFlow):
    """Handle a option flow for google photos."""

    def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
        """Initialize options flow."""
        self.config_entry = config_entry

    @property
    def logger(self) -> logging.Logger:
        """Return logger."""
        return logging.getLogger(__name__)

    async def _get_albumselect_schema(self) -> vol.Schema:
        """Return album selection form"""

        credentials = Credentials(self.config_entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN])

        def get_photoslibrary() -> PhotosLibraryService:
            return build(
                "photoslibrary",
                "v1",
                credentials=credentials,
                static_discovery=False,
            )

        def get_albums() -> List[Album]:
            service: PhotosLibraryService = get_photoslibrary()
            albums = service.albums()  # pylint: disable=no-member
            fields = "albums(id,title,mediaItemsCount),nextPageToken"
            request = albums.list(pageSize=50, fields=fields)
            album_list = []
            while request is not None:
                result = request.execute()
                album_list = album_list + result.get("albums", [])
                request = albums.list_next(request, result)

            sharedAlbums = service.sharedAlbums()  # pylint: disable=no-member
            fields = "sharedAlbums(id,title,mediaItemsCount),nextPageToken"
            request = sharedAlbums.list(pageSize=50, fields=fields)
            while request is not None:
                result = request.execute()
                album_list = album_list + result.get("sharedAlbums", [])
                request = sharedAlbums.list_next(request, result)
            return list(filter(lambda a: ("id" in a and "title" in a), album_list))

        albums = await self.hass.async_add_executor_job(get_albums)
        album_selection = dict({CONF_ALBUM_ID_FAVORITES: "Favorites"})
        for album in albums:
            album_selection[album.get("id")] = "{0} ({1} items)".format(
                album.get("title"), album.get("mediaItemsCount", "?")
            )

        return vol.Schema(
            {
                vol.Required(CONF_ALBUM_ID): vol.In(album_selection),
            }
        )

    async def async_step_init(self, user_input=None):
        """Handle options flow."""
        return self.async_show_menu(
            step_id="init",
            menu_options=["albumselect", "settings"],
            description_placeholders={
                "model": "Example model",
            },
        )

    async def async_step_albumselect(
        self, user_input: dict[str, Any] = None
    ) -> FlowResult:
        """Set the album used."""
        self.logger.debug(
            "async_albumselect_confirm called with user_input: %s", user_input
        )

        # user input was not provided.
        if user_input is None:
            data_schema = await self._get_albumselect_schema()
            return self.async_show_form(step_id="albumselect", data_schema=data_schema)

        album_id = user_input[CONF_ALBUM_ID]
        albums = self.config_entry.options.get(CONF_ALBUM_ID, []).copy()
        if album_id not in albums:
            albums.append(album_id)
        data = self.config_entry.options.copy()
        data.update({CONF_ALBUM_ID: albums})
        return self.async_create_entry(title="", data=data)

    async def async_step_settings(self, user_input=None):
        """Handle options flow."""
        if user_input is not None:
            data = self.config_entry.options.copy()
            data.update(user_input)
            return self.async_create_entry(title="", data=data)

        data_schema = vol.Schema(
            {
                vol.Optional(
                    CONF_WRITEMETADATA,
                    default=self.config_entry.options.get(
                        CONF_WRITEMETADATA, WRITEMETADATA_DEFAULT_OPTION
                    ),
                ): bool,
            }
        )
        return self.async_show_form(step_id="settings", data_schema=data_schema)


"""
json2yolo：将Honeybee2d的json转为适合yolo的txt格式
"""
import json

for i in range(480):
    # 读取JSON文件
    with open(f'annotation/{i:06}.json', 'r') as f:
        data = json.load(f)

    # 解析JSON文件并处理结果
    results = []
    for shape in data['shapes']:
        # 提取label、points、width、height信息
        points = shape['points']
        x = points[1][0] + points[0][0]
        x /= 2
        y = points[1][1] + points[0][1]
        y /= 2
        w = points[1][0] - points[0][0]
        h = points[1][1] - points[0][1]
        # 归一化坐标和尺寸到[0, 1]范围内
        x /= 1920
        y /= 1080
        w /= 1920
        h /= 1080
        # 将矩形信息添加到结果列表中
        results.append([0, abs(x), abs(y), abs(w), abs(h)])

    # 将结果保存到txt文件中
    with open(f'labels/{i:06}.txt', 'w') as f:
        for line in results:
            f.write(' '.join(map(str, line)) + '\n')


__credits__ = ["Evan Bolyen"]

import sys
from unittest import TestCase, main

if sys.version_info.major == 2:
    from StringIO import StringIO
else:
    from io import StringIO

from pyqi.core.exception import IncompetentDeveloperError
from pyqi.core.interfaces.html.input_handler import (load_file_lines,
        load_file_contents)

class HTMLInputHandlerTests(TestCase):
    def setUp(self):
        self.file_like_object = StringIO()
        #Note the whitespace, this tests strip()
        self.file_like_object.write("This is line 1\n")
        self.file_like_object.write(" This is line 2\n")
        self.file_like_object.write("This is line 3 \n")
        #Place it at the beginning of the file again
        self.file_like_object.seek(0)

    def tearDown(self):
        self.file_like_object.close()

    def test_load_file_lines(self):
        """Correctly returns file lines as a list of strings"""
        # can't load a string, etc...
        self.assertRaises(IncompetentDeveloperError, load_file_lines, 'This is not a file')
        result = load_file_lines(self.file_like_object)
        self.assertEqual(result,
                         ["This is line 1",
                          "This is line 2",
                          "This is line 3"])

    def test_load_file_contents(self):
        """Correctly returns file contents"""
        # can't load a string, etc...
        self.assertRaises(IncompetentDeveloperError, load_file_contents, 'This is not a file')

        result = load_file_contents(self.file_like_object)
        #Note the whitespace
        self.assertEqual(result, "This is line 1\n This is line 2\nThis is line 3 \n")

if __name__ == '__main__':
    main()


import streamlit as st
import pickle
import numpy as np
import pandas as pd
import time
from PIL import Image
image = Image.open('cover.jpg')

df = pd.read_csv("EDA_dp.csv")

# st.write(df.head())

st.image(image, use_column_width=True)

st.title('Data Scientist Salary Predictor')

st.markdown('<style>h1{color: brown;}</style>', unsafe_allow_html=True)

st.info("This Web Application is created and maintained by *_DHEERAJ_ _KUMAR_ _K_*")

st.subheader('Company Details \n Data Scrapped from GlassDoor ')

Rating = st.slider('Glassdoor Rating of the Company',min_value=1.0, max_value=5.0, step=0.1)

# st.subheader('Number of Competitors')

No_of_Competitors = st.slider('Number of Competitors',min_value=0.0, max_value=4.0, step=1.0)

# st.subheader('Company Age')

Age = st.slider('Age of the Company', step=1.0, min_value=0.0,max_value=330.0)

## description length
# st.subheader("Choose Approximate length of job description")

desc_length = st.slider('Choose Approximate length of job description',min_value=110.0, max_value=15121.0, step=10.0)

# st.subheader("Choose Revenue of the company")
Revenue_1,Revenue_Less_than_10_million,Revenue_Unknown_Non_Applicable, Revenue_1_to_5_billion,Revenue_10_to_50_billion, Revenue_10_to_50_million,Revenue_100_to_500_billion,Revenue_100_to_500_million, Revenue_5_to_10_billion,Revenue_50_to_100_billion,Revenue_50_to_100_million,Revenue_500_million_to_1_billion,Revenue_500_billion = 0,0,0,0,0,0,0,0,0,0,0,0,0

list_of_revenue = list(df['Revenue'].unique())
for i in range(len(list_of_revenue)):
    if list_of_revenue[i] == "-1":
        list_of_revenue[i] = "₹1 to ₹5 billion (INR)"
        break

revenue = st.selectbox('Revenue', list_of_revenue,index=0)

# st.write(list(df['Revenue'].unique()))

if revenue == "₹1 to ₹5 million (INR)":
    Revenue_1 = 1
elif revenue =="Less than ₹10 million (INR)":
    Revenue_Less_than_10_million = 1
elif revenue == "Unknown / Non-Applicable":
    Revenue_Unknown_Non_Applicable = 1 #dont use and operator
elif revenue == '₹1 to ₹5 billion (INR)':
    Revenue_1_to_5_billion = 1
elif revenue == "₹10 to ₹50 billion (INR)":#5
    Revenue_10_to_50_billion = 1
elif revenue == "₹10 to ₹50 million (INR)":
    Revenue_10_to_50_million = 1
elif revenue == "₹100 to ₹500 billion (INR)":
    Revenue_100_to_500_billion = 1
elif revenue == "₹10 to ₹500 million (INR)":
    Revenue_100_to_500_million = 1
elif revenue == "₹5 to ₹10 billion (INR)":
    Revenue_5_to_10_billion = 1
elif revenue == "₹50 to ₹100 billion (INR)":
    Revenue_50_to_100_billion = 1
elif revenue == "₹50 to ₹100 million (INR)":
    Revenue_50_to_100_million = 1
elif revenue == "₹500 million to ₹1 billion (INR)":
    Revenue_500_million_to_1_billion = 1
elif revenue == "₹500+ billion (INR)":#13
    Revenue_500_billion = 1

# st.write(Revenue_1,
#        Revenue_Less_than_10_million,
#        Revenue_Unknown_Non_Applicable, Revenue_1_to_5_billion,
#        Revenue_10_to_50_billion, Revenue_10_to_50_million,
#        Revenue_100_to_500_billion,
#        Revenue_100_to_500_million, Revenue_5_to_10_billion,
#        Revenue_50_to_100_billion,
#        Revenue_50_to_100_million,
#        Revenue_500_million_to_1_billion,
#        Revenue_500_billion)

# st.subheader("Choose size of the company")

Size_1,Size_1_to_50_employees, Size_10000_employees,Size_1001_to_5000_employees,Size_201_to_500_employees,Size_5001_to_10000_employees, Size_501_to_1000_employees,Size_51_to_200_employees, Size_Unknown =0,0,0,0,0,0,0,0,0

list_of_size = list(df['Size'].unique())
for i in range(len(list_of_size)):
    if list_of_size[i] == "-1":
        list_of_size[i] = "N/A"
        break

# st.write(list_of_size)

size = st.selectbox('Company Size',list_of_size,index=0)

# st.write(list(df['Size'].unique()))

if  size == "N/A":#1
    Size_1 = 1
elif size =="1 to 50 employees":
    Size_1_to_50_employees = 1
elif size == "10000+ employees":
    Size_10000_employees = 1 #dont use and operator
elif size == '1001 to 5000 employees':
    Size_1001_to_5000_employees = 1
elif size == "201 to 500 employees":#5
    Size_201_to_500_employees = 1
elif size == "5001 to 10000 employees":
    Size_5001_to_10000_employees = 1
elif size == "501 to 1000 employees":
    Size_501_to_1000_employees = 1
elif size == "51 to 200 employees":
    Size_51_to_200_employees = 1
elif size == "Unknown":#9
    Size_Unknown = 1

# st.write(Size_1,
#   Size_1_to_50_employees, Size_10000_employees,
#            Size_1001_to_5000_employees,Size_201_to_500_employees,
#        Size_5001_to_10000_employees, Size_501_to_1000_employees,
#        Size_51_to_200_employees, Size_Unknown)

# st.subheader("Job Sector")

# st.write(list(df['Sector'].unique()))

Sector_1,Sector_Accounting_Legal, Sector_Aerospace_Defence,Sector_Agriculture_Forestry,Sector_Arts_Entertainment_Recreation, Sector_Biotech_Pharmaceuticals, Sector_Business_Services,Sector_Consumer_Services, Sector_Education, Sector_Finance,Sector_Government, Sector_Healthcare,Sector_Information_Technology, Sector_Insurance,Sector_Manufacturing, Sector_Media, Sector_Non_Profits,Sector_Oil_Gas_Utilities, Sector_Real_Estate,Sector_Restaurants_Food_Service, Sector_Retail,Sector_Telecommunications, Sector_Transportation_Logistics,Sector_Travel_Tourism = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

list_of_sector = list(df['Sector'].unique())
for i in range(len(list_of_sector)):
    if list_of_sector[i] == "-1":
        list_of_sector[i] = "N/A"
        break

sector = st.selectbox('Job Sector', list_of_sector,index=0)
# st.write(list(df['Sector'].unique()))

if sector == "Biotech & Pharmaceuticals":#1
    Sector_Biotech_Pharmaceuticals = 1
elif sector =="Business Services":
    Sector_Business_Services = 1
elif sector == "Aerospace & Defence":
    Sector_Aerospace_Defence = 1 #dont use and operator
elif sector == 'Information Technology':
    Sector_Information_Technology = 1
elif sector == "Insurance":
    Sector_Insurance = 1
elif sector == 'Manufacturing':
    Sector_Manufacturing = 1
elif sector == "Agriculture & Forestry":
    Sector_Agriculture_Forestry = 1
elif sector == "Retail":
    Sector_Retail = 1
elif sector == 'Travel & Tourism':
    Sector_Travel_Tourism = 1
elif sector == "N/A": #10th
    Sector_1 = 1
elif sector == "Finance": #10th
    Sector_Finance = 1
elif sector == "Oil, Gas, Energy & Utilities":
    Sector_Oil_Gas_Utilities = 1
elif sector == "Healthcare":
    Sector_Healthcare = 1
elif sector == "Government":
    Sector_Government = 1
elif sector == "Education":
    Sector_Education = 1
elif sector == "Restaurants, Pubs, Bars & Food Service":
    Sector_Restaurants_Food_Service= 1
elif sector == "Accounting & Legal":
    Sector_Accounting_Legal = 1
elif sector == "Media":
    Sector_Media = 1
elif sector == "Telecommunications":
    Sector_Telecommunications = 1
elif sector == "Transportation & Logistics":
    Sector_Transportation_Logistics = 1
elif sector == "Real Estate":
    Sector_Real_Estate = 1
elif sector == "Arts, Entertainment & Recreation":
    Sector_Arts_Entertainment_Recreation = 1
elif sector == "Consumer Services":
    Sector_Consumer_Services = 1
elif sector == "Non-Profits":
    Sector_Non_Profits = 1

# st.write(Sector_1,Sector_Accounting_Legal, Sector_Aerospace_Defence,Sector_Agriculture_Forestry,
# Sector_Arts_Entertainment_Recreation, Sector_Biotech_Pharmaceuticals, Sector_Business_Services,
# Sector_Consumer_Services, Sector_Education, Sector_Finance,Sector_Government, Sector_Healthcare,
# Sector_Information_Technology, Sector_Insurance,
# Sector_Manufacturing, Sector_Media, Sector_Non_Profits,Sector_Oil_Gas_Utilities, Sector_Real_Estate,Sector_Restaurants_Food_Service, Sector_Retail,Sector_Telecommunications, Sector_Transportation_Logistics,Sector_Travel_Tourism)

# st.write(sector)

st.subheader('Language skills')

python_yn = st.checkbox('Python')
if python_yn:
    python_yn = 1
else:
    python_yn = 0

r = st.checkbox('R')
if r:
    r = 1
else:
    r = 0

sas = st.checkbox('SaS')
if sas:
    sas = 1
else:
    sas = 0

aws = st.checkbox('AWS')
if aws:
    aws = 1
else:
    aws = 0

spark = st.checkbox('Spark')
if spark:
    spark = 1
else:
    spark = 0

hadoop = st.checkbox('Hadoop')
if hadoop:
    hadoop = 1
else:
    hadoop = 0

tensorFlow = st.checkbox('TensorFlow')
if tensorFlow:
    tensorFlow = 1
else:
    tensorFlow = 0

sql = st.checkbox('SQL')
if sql:
    sql = 1
else:
    sql = 0

st.subheader("Web Deployment Skill")

flask = st.checkbox('Flask')
if flask:
    flask = 1
else:
    flask = 0

st.subheader("Statistical Skill")

stats = st.checkbox('Statistics')
if stats:
    stats = 1
else:
    stats = 0

st.subheader("Data Visualization Skills")

tableau = st.checkbox('Tableau')
if tableau:
    tableau = 1
else:
    tableau = 0

powerBI = st.checkbox('PowerBI')
if powerBI:
    powerBI = 1
else:
    powerBI = 0

st.subheader("Other Skills")

excel = st.checkbox('Excel')
if excel:
    excel = 1
else:
    excel = 0

st.subheader("Location Selection")

Job_State_CA,Job_State_MA,Job_State_CT,Job_State_NJ,Job_State_NY,Job_State_WA =0,0,0,0,0,0

state = st.selectbox(
     'States',  ('California', 'Massachusetts', 'Connecticut','Massachusetts','New Jersey','New York','Washington'),index=0)

if state == 'California':
    Job_State_CA = 1
elif state =='Massachusetts':
    Job_State_MA = 1
elif state == 'Connecticut':
    Job_State_CT = 1
elif state == 'New Jersey':
    Job_State_NJ = 1
elif state == 'New York':
    Job_State_NY = 1
elif state == 'Washington':
    Job_State_WA = 1

# st.write(Job_State_CA,Job_State_MA,Job_State_CT,Job_State_NJ,Job_State_NY,Job_State_WA)

Seniority_junior,Seniority_na,Seniority_senior =0,0,0

same_state = st.radio("Would you like to work in the in Same State Headquarters Office ?",('Yes','No'), index=0)

if same_state == 'Yes':
    same_state = 1
elif same_state == 'No':
    same_state = 0

## Job Seniority

st.subheader("Experience Level")

Seniority_junior,Seniority_na,Seniority_senior =0,0,0

seniority = st.radio("Choose Seniority Level",('NA','Junior Level','Senior Level'), index=0)

if seniority == 'Junior Level':
    Seniority_junior = 1
elif seniority == 'NA':
    Seniority_na = 1
elif seniority == 'Senior Level':
    Seniority_senior = 1

# st.info('**NA - Not Applicable')

# st.write(Seniority_junior,Seniority_na,Seniority_senior)

features = [Rating,No_of_Competitors,same_state,Age,r,python_yn,
aws,excel,spark,tableau,sql,tensorFlow,powerBI,
sas,flask,hadoop,stats,desc_length,Size_1,Size_1_to_50_employees, Size_10000_employees,Size_1001_to_5000_employees,Size_201_to_500_employees,
Size_5001_to_10000_employees, Size_501_to_1000_employees,Size_51_to_200_employees, Size_Unknown,Sector_1,Sector_Accounting_Legal,
Sector_Aerospace_Defence,Sector_Agriculture_Forestry,Sector_Arts_Entertainment_Recreation, Sector_Biotech_Pharmaceuticals, Sector_Business_Services,
Sector_Consumer_Services, Sector_Education, Sector_Finance,Sector_Government, Sector_Healthcare,
Sector_Information_Technology, Sector_Insurance,Sector_Manufacturing, Sector_Media, Sector_Non_Profits,Sector_Oil_Gas_Utilities,
Sector_Real_Estate,Sector_Restaurants_Food_Service, Sector_Retail,Sector_Telecommunications, Sector_Transportation_Logistics,Sector_Travel_Tourism,
Revenue_1,
       Revenue_Less_than_10_million,
       Revenue_Unknown_Non_Applicable, Revenue_1_to_5_billion,
       Revenue_10_to_50_billion, Revenue_10_to_50_million,
       Revenue_100_to_500_billion,
       Revenue_100_to_500_million, Revenue_5_to_10_billion,
       Revenue_50_to_100_billion,
       Revenue_50_to_100_million,
       Revenue_500_million_to_1_billion,
       Revenue_500_billion,Job_State_CA,Job_State_MA,Job_State_CT,Job_State_NJ,Job_State_NY,Job_State_WA,
       Seniority_junior,Seniority_na,Seniority_senior]

# st.write(len(features))
float_feature_list = []
for i in features:
    float_feature_list.append(float(i))
# st.write(features)
final_features = np.array(float_feature_list).reshape(1, -1)

# model_building
file_name = "model_file.p"
with open(file_name, 'rb') as pickled:
    data = pickle.load(pickled)
    model = data['model']

#predict_button call
if st.button('Predict The Salary'):
    prediction = model.predict(final_features)
    st.success(f'Your predicted salary is US$ {round(prediction[0],3)*1000} ')


from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse, reverse_lazy
from rest_framework import status
from rest_framework.test import APIClient

from books.models import Book
from books.serializers import BookSerializer

BOOK_URL = reverse_lazy("books:book-list")

def sample_book(**params) -> Book:
    defaults = {
        "title": "title",
        "author": "author",
        "cover": "H",
        "inventory": 100,
        "daily_fee": 25,
    }
    defaults.update(params)

    return Book.objects.create(**defaults)

class UnauthenticatedBookApiTests(TestCase):
    def setUp(self) -> None:
        self.client = APIClient()

    def test_auth_requirement(self):
        response = self.client.get(BOOK_URL)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

class AuthenticatedBookApiTests(TestCase):
    def setUp(self) -> None:
        self.client = APIClient()
        self.user = get_user_model().objects.create_user(
            "test@test.com",
            "test12345",
        )
        self.client.force_authenticate(self.user)

    def test_list_book(self):
        sample_book()

        response = self.client.get(BOOK_URL)

        book = Book.objects.all()
        serializer = BookSerializer(book, many=True)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data, serializer.data)

    def test_retrieve_book_detail(self):
        book = sample_book()
        url = reverse("books:book-list") + f"{book.pk}/"

        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_delete_book_not_allowed(self):
        book = sample_book()
        url = reverse("books:book-list") + f"{book.pk}/"

        res = self.client.delete(url)

        self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)

class AdminBookApiTests(TestCase):
    def setUp(self) -> None:
        self.client = APIClient()
        self.user = get_user_model().objects.create_user(
            "test@admin.com",
            "test12345",
            is_staff=True,
        )
        self.client.force_authenticate(self.user)

    def test_book_create(self):
        payload = {
            "title": "Test title",
            "author": "Test author",
            "cover": "H",
            "inventory": 25,
            "daily_fee": 100,
        }

        response = self.client.post(BOOK_URL, payload)
        book = Book.objects.get(id=response.data["id"])

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(payload["title"], getattr(book, "title"))
        self.assertEqual(payload["author"], getattr(book, "author"))

    def test_book_update(self):
        data = {
            "title": "Test",
            "author": "Test",
            "cover": "H",
            "inventory": 250,
            "daily_fee": 50,
        }
        book = sample_book()
        url = reverse("books:book-list") + f"{book.pk}/"

        response = self.client.put(url, data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_delete_book(self):
        book = sample_book()
        url = reverse("books:book-list") + f"{book.pk}/"

        res = self.client.delete(url)

        self.assertEqual(res.status_code, status.HTTP_204_NO_CONTENT)


import os
import requests
from datetime import datetime

GENDER = "male"
WEIGHT_KG = 60
HEIGHT_CM = 150
AGE = 22

nutritionix_url = "https://trackapi.nutritionix.com/v2/natural/exercise"

APP_ID = os.environ["Nutitionix_ID"]
APP_KEY = os.environ["Nutritionix_KEY"]

sheety_url = "https://api.sheety.co/fb09aa1b7ec09c49e471bf28fadae6a2/myWorkouts/workouts"

SHEETY_API_KEY = os.environ["Sheety_API_KEY"]

sheety_header = {
    "Authorization": SHEETY_API_KEY
}

headers = {
    "x-app-id": APP_ID,
    "x-app-key": APP_KEY
}

nutritionix_params = {
    "query": input("Tell me which exercise you did: "),
    "gender": GENDER,
    "weight_kg": WEIGHT_KG,
    "height_cm": HEIGHT_CM,
    "age": AGE
}

nutritionix_response = requests.post(url=nutritionix_url, json=nutritionix_params, headers=headers)
exercise_data = nutritionix_response.json()

today = datetime.now()

exercise_detail = exercise_data["exercises"]

body = {}
for exercise in exercise_detail:
    exercise_sheet = {
        "date": today.strftime("%d/%m/%Y"),
        "time": today.strftime("%H:%M:%S"),
        "exercise": exercise["name"].title(),
        "duration": round(exercise["duration_min"]),
        "calories": round(exercise["nf_calories"])
    }

    body["workout"] = exercise_sheet
    sheety_response = requests.post(url=sheety_url, json=body, headers=sheety_header)

print("Added Successfully!!")


import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset
from torch.autograd import Variable
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt

# HyperParameters
EPOCH = 10
BATCH_SIZE = 64
TIME_STEP = 28
INPUT_SIZE = 28
LR = 0.01
DOWNLOAD_MNIST = False

# I was changed in dev branch

# Prepare the datasets and the dataloader
training_data = dsets.MNIST(
    root='/media/benben/0ECABB60A248B50C/MNIST',
    train=True,
    transform=transforms.ToTensor(),
    download=False
)
# print(training_data.train_data.size())
# print(training_data.train_labels.size())
# plt.imshow(training_data.train_data[0].numpy(), cmap='gray')
# plt.title('%i' % training_data.train_labels[0])
# plt.show()
# train_data = dsets.MNIST(root)

train_loader = torch.utils.data.DataLoader(dataset=training_data, batch_size=BATCH_SIZE, shuffle=True)

test_data = dsets.MNIST(
    root='/media/benben/0ECABB60A248B50C/MNIST',
    train=False,
    transform=transforms.ToTensor()
)
test_x = test_data.test_data.type(torch.FloatTensor)[:]/255
test_y = test_data.test_labels.numpy()[:]

# build your model
class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.LSTM(
            input_size=INPUT_SIZE,
            hidden_size=64,
            num_layers=1, # number of hidden layer
            batch_first=True # (batch, time_step, input)的batch_first = True结果
        )

        self.Linear = nn.Linear(64, 10)
    def forward(self, x):
        r_out, (h_n, h_c) = self.rnn(x, None)
        # x (batch, time_step, input_size)
        # (h_n, h_c) represents the hidden and states
        out = self.Linear(r_out[:, -1, :])
        return out
        # x.shape (batch, time_step, input_size)

rnn = RNN()
print(rnn)

# choose your loss_function and optimizer

optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)
critizer = nn.CrossEntropyLoss()

# Forward and Backpropagation

for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x.view(-1, 28, 28)) # reshape x to (batch, time_step, input_size)
        b_y = Variable(y)

        output = rnn(b_x)
        loss = critizer(output, b_y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 50 == 0:
            test_output = rnn(test_x)
            pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
            # accuracy = sum(pred_y == test_y) /test_output.size
            accuracy = float((pred_y == test_y).astype(int).sum())/ float(test_y.size) # why
            print('Epoch:', epoch, '|train loss:%.4f' % loss.data.numpy(), '| test accuracy:%.4f' % accuracy)


def test_async_shell_with_spur():
    import io
    import time
    import spur

    shell = spur.LocalShell()

    output_file = io.StringIO()
    process = shell.spawn(
        ["bash", "-c", r'echo 3; sleep 3; echo -e "\u2603"hello; read dont_care'],
        stdout=output_file,
        encoding="utf-8",
    )
    line = ""
    while not ('hello' in line):
        line = output_file.getvalue()
        time.sleep(1)
        print(line)
    assert 'hello' in line
    print(output_file.getvalue())
    assert process.is_running()
    process.stdin_write(b"\n")

    assert u"3\n☃hello\n" == process.wait_for_result().output