import sys
import logging
import datetime
import webbrowser
from PyQt5 import QtWidgets, QtCore, QtGui

import serial
from serial.tools import list_ports

import HvGUI
import HvController as hv
import workers

ICON_RED_LED = ":/icons/led-red-on.png"
ICON_GREEN_LED = ":/icons/green-led-on.png"

class MainWindow(QtWidgets.QMainWindow, HvGUI.Ui_MainWindow):
    '''
    Main instance for the GUI of the HV controller panel

    HvControllerGUI is designed to operate a HV power supply from
    Glassman remotely through a graphical user interface. It was
    developped for use with a FJ model +40kV 3.0 mA.

    It makes use of QRunnables and QThreadPool for running small
    repetitive opperations without freezing the GUI. It also makes
    extensive use of PyQt signal and slot design for communication
    between threads.

    '''

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        # Setup application logger
        self.logger = logging.getLogger('hvController')
        self.logger.setLevel(logging.INFO)
        # create file handler which logs info messages
        fh = logging.FileHandler('hvCtrl.log', mode='w')
        fh.setLevel(logging.INFO)
        # create formatter and add it to the handler
        formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        # add the handler to the logger
        self.logger.addHandler(fh)

        self.hvdevice = hv.HvController()
        self.querytimer = QtCore.QTimer()
        self.checktimer = QtCore.QTimer()
        self.setupTimers()
        self.threadpool = QtCore.QThreadPool()
        self._setupUiDesign()

        # Extract some useful values from the GUI
        self.targetHV = self.voltValueToSet.value()
        self.targetI = self.curValueToSet.value()
        # TODO : add settings for saving preferences

    def _setupUiDesign(self):
        '''Prepare the initial desgin of the GUI. '''
        self.voltValueToSet.setMaximum(self.hvdevice.MAX_VOLTAGE)
        self.curValueToSet.setMaximum(self.hvdevice.MAX_CURENT)
        self.disableAll()
        for name, desc, add in sorted(list_ports.comports()):
            self.prtList.addItem(name)
        # Put COM4 port as default: adapt to workstation or improve
        # and implement with QSettings
        if self.prtList.findText('COM4') >= 0:
            self.prtList.setCurrentIndex(self.prtList.findText('COM4'))

    def setupTimers(self):
        '''Configure the timers for query and stability check'''
        # The Glassman HV has a communication timeout of 1.5 s
        # so we perform a query every 500 ms
        self.querytimer.setInterval(500)
        self.querytimer.timeout.connect(self.hvdevice.queryHV)
        self.querytimer.timeout.connect(self.updateStatus)

        self.checktimer.setInterval(60000)  # can be changed to longer
        self.checktimer.timeout.connect(self.checkStability)

        self.now = datetime.datetime.today()
        self.lastEntryTime = datetime.datetime.today()

    # ---------------- Slots --------------
    # define here pyqtslot using connectSlotsByName() convention
    @QtCore.pyqtSlot()
    def on_actionAbout_triggered(self):
        self.showMessage("HvControllerGUI Copyright (C) 2018-2019 "
                         "Aurélie Vancraeyenest"
                         "\n\n This program is licensed under the"
                         " Apache License, Version 2.0 "
                         "\n\nThis program comes with ABSOLUTELY NO WARRANTY."
                         "\nThis is free software, and you are welcome to "
                         "redistribute it under certain conditions. "
                         "See LICENSE file for details.")

    @QtCore.pyqtSlot()
    def on_actionHV_firmware_version_triggered(self):
        if self.hvdevice.device.is_open:
            message = self.hvdevice.version()
            self.showMessage(message)
        else:
            self.showMessage('The device COM port should be open'
                             ' to get the firmware version.'
                             '\nOpen the port and try again.')

    @QtCore.pyqtSlot()
    def on_actionOnline_documentation_triggered(self):
        webbrowser.open('https://github.com/avancra/HvControllerGUI')

    @QtCore.pyqtSlot()
    def on_prtOpenBtn_clicked(self):
        '''
        Open the selected port and instantiate an HV controller

        Get the port from the GUI, open it and init the hv controler.
        If success, start a timer which will query the HV every 0.5s.
        '''
        # ??? : check for opened port and close it
        portName = self.prtList.currentText()

        try:
            self.hvdevice.openPortHV(portName)
        except serial.SerialException:
            QtWidgets.QMessageBox.warning(
                    self, 'HV ctrl',
                    'Serial Exception: could not open the {} port'
                    .format(portName))
        else:
            self.querytimer.start()
            self.checktimer.start()
            self.enableAll()
            self.prtList.setEnabled(False)
            self.prtOpenBtn.setEnabled(False)
            self.updateStatus()

    @QtCore.pyqtSlot()
    def on_prtCloseBtn_clicked(self):
        ''' Close the current port and disable the GUI widget once closed '''

        self.querytimer.stop()
        try:
            output = self.hvdevice.closePortHV()
        except serial.SerialException:
            QtWidgets.QMessageBox.warning(
                    self, 'HV ctrl',
                    '''Serial Exception: could not close the {} port'''
                    .format(self.hvdevice.device.port))
        else:
            self.prtList.setEnabled(True)
            self.prtOpenBtn.setEnabled(True)
            self.disableAll()
            self.cmdOutText.append(output)

    @QtCore.pyqtSlot()
    def on_queryBtn_clicked(self):
        '''
        Method to launch the query thread worker through the threadpool

        Keyword arguments
        -----------------
        verbosity : bool
        '''

        queryWk = workers.HvWorker(self.hvdevice.queryHV)
        queryWk.kwargs['verbosity'] = True
        queryWk.signals.output.connect(self.printOutput)
        queryWk.signals.done.connect(self.updateStatus)
        queryWk.signals.done.connect(self.querytimer.start)

        self.querytimer.stop()
        self.threadpool.start(queryWk)

    @QtCore.pyqtSlot()
    def on_setBtn_clicked(self):
        '''
        Method to launch the set HV thread worker through the threadpool

        Keyword arguments
        -----------------
        voltToSet : float
            voltage
        curToSet : float
            current
        verbosity : bool
        '''
        self.targetHV = round(self.voltValueToSet.value(), 2)
        self.targetI = round(self.curValueToSet.value(), 2)
        setWk = workers.HvWorker(self.hvdevice.setHV)
        setWk.kwargs['voltToSet'] = self.targetHV
        setWk.kwargs['curToSet'] = self.targetI
        setWk.kwargs['verbosity'] = True

        setWk.signals.done.connect(self.updateStatus)
        setWk.signals.done.connect(self.querytimer.start)
        setWk.signals.output.connect(self.printOutput)

        self.querytimer.stop()
        self.threadpool.start(setWk)

    @QtCore.pyqtSlot()
    def on_resetBtn_clicked(self):
        '''
        Method to launch the reset HV thread worker through the threadpool

        Keyword arguments
        -----------------
        verbosity : 'bool'
        '''
        self.voltValueToSet.setValue(0.0)
        self.curValueToSet.setValue(0.0)
        self.targetHV = 0.0
        self.targetI = 0.0

        resetWK = workers.HvWorker(self.hvdevice.resetHV)
        resetWK.kwargs['verbosity'] = True

        resetWK.signals.done.connect(self.updateStatus)
        resetWK.signals.done.connect(self.querytimer.start)
        resetWK.signals.output.connect(self.printOutput)

        self.querytimer.stop()
        self.threadpool.start(resetWK)

    @QtCore.pyqtSlot()
    def on_actionExit_triggered(self):
        self.querytimer.stop()
        self.checktimer.stop()
        if self.hvdevice.device.is_open:
            self.hvdevice.closePortHV()
        self.close()

    # ---------------- Other slots --------------
    # define here other pyqtslots
    @QtCore.pyqtSlot()
    def updateStatus(self):
        '''
        Update the values/icons of the GUI corresponding to the HV status

        Updated values
        --------------
        hvOn : bool
            True if HV is on
        fault : bool
            True if HV is faulty
        ctrlMode : str
            'voltage' or 'current'
        voltage : float
            Voltage value in kV
        current : float
            Current value in mA
        '''

        self.voltValueRead.display(self.hvdevice.voltage)
        self.curValueRead.display(self.hvdevice.current)
        if self.hvdevice.ctrlMode == "voltage":
            self.ctrlModeVoltBtn.setChecked(True)
        elif self.hvdevice.ctrlMode == "current":
            self.ctrlModeCurBtn.setChecked(True)

        if self.hvdevice.hvOn is True:
            self.hvOnLed.setPixmap(QtGui.QPixmap(ICON_GREEN_LED))
        elif self.hvdevice.hvOn is False:
            self.hvOnLed.setPixmap(QtGui.QPixmap(ICON_RED_LED))
        else:
            self.hvOnLed.setEnabled(False)

        if self.hvdevice.fault is True:
            self.faultLed.setPixmap(QtGui.QPixmap(ICON_RED_LED))
        else:
            self.faultLed.setEnabled(False)

    @QtCore.pyqtSlot(str)
    def printOutput(self, s):
        '''
        Append command outputs to the text box of the GUI

        Parameters
        ----------
        s : str
            emitted via threadpool threads
        '''
        self.cmdOutText.append(s)

    @QtCore.pyqtSlot()
    def checkStability(self):
        ''' Check if the voltage is within a 0.2 V from the targetted one '''
        delta = 0.2
        if (self.targetHV-delta < self.hvdevice.voltage < self.targetHV+delta):
            # if last log entry more than 1min:
            self.makeLogEntry('HV stability ok: %.2f',
                              value=self.hvdevice.voltage, level='info')
        else:
            self.makeLogEntry('HV stability fails: %.2f',
                              value=self.hvdevice.voltage, level='warning')
            self.makeLogEntry('Try to return to target value...  %.2f',
                              value=self.targetHV, level='warning')
            self.on_setBtn_clicked()
            if (self.targetHV-delta < self.hvdevice.voltage < self.targetHV+delta):
                self.makeLogEntry('HV back to target voltage: %.2f',
                                  value=self.hvdevice.voltage, level='info')
            else:
                self.makeLogEntry('Tentative failed, voltage value: %.2f',
                                  value=self.hvdevice.voltage, level='warning')

    @QtCore.pyqtSlot()
    def programEnded(self):
        QtWidgets.QMessageBox.warning(self, "Warning", "Thread is done")

    # --------------- Other class methods --------
    def disableAll(self):
        ''' Disable all the widgets for HV control of the GUI '''

        self.voltValueToSet.setEnabled(False)
        self.curValueToSet.setEnabled(False)
        self.queryBtn.setEnabled(False)
        self.setBtn.setEnabled(False)
        self.resetBtn.setEnabled(False)
        self.faultLed.setEnabled(False)
        self.hvOnLed.setEnabled(False)
        self.prtCloseBtn.setEnabled(False)
        self.prgSelectBtn.setEnabled(False)
        self.prgStartBtn.setEnabled(False)
        self.prgStopBtn.setEnabled(False)
        self.prgPlotVoltBtn.setEnabled(False)
        self.prgFilenameLineEdit.setEnabled(False)

    def enableAll(self):
        ''' Enable all the widgets of the GUI for HV control '''

        self.voltValueToSet.setEnabled(True)
        self.curValueToSet.setEnabled(True)
        self.queryBtn.setEnabled(True)
        self.setBtn.setEnabled(True)
        self.resetBtn.setEnabled(True)
        self.faultLed.setEnabled(True)
        self.hvOnLed.setEnabled(True)
        self.prtCloseBtn.setEnabled(True)
        # for future use when functionnality is implemented
#        self.prgSelectBtn.setEnabled(True)
#        self.prgStartBtn.setEnabled(True)
#        self.prgStopBtn.setEnabled(True)
#        self.prgPlotVoltBtn.setEnabled(True)
#        self.prgFilenameLineEdit.setEnabled(True)

    def showMessage(self, message):
        '''
        Display a message in an "Information" message box with 'OK' button.

        Parameters:
        -----------
        message : str
            Message to print in the message box
        '''

        messageBox = QtWidgets.QMessageBox()
        messageBox.setText(message)
        messageBox.setWindowTitle("Info")
        messageBox.setIcon(QtWidgets.QMessageBox.Information)
        messageBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
        messageBox.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)

        # Show the window
        messageBox.raise_()
        messageBox.exec_()

    def makeLogEntry(self, message, **kwargs):
        '''
        Make a new entry if the last one was done less than 10 min ago

        Parameters
        ---------
        message : str
            Message to print to the log file
        kwargs : dict
            keyword arguments

        keyword arguments
        -----------------
        value : obj
            Variable to log (type must match the format given in the message)
        level : str
            Level of the log entry (lower case)
        '''

        self.now = datetime.datetime.today()
        dtime = self.now - self.lastEntryTime
        if dtime.total_seconds()/60 > 10:
            if kwargs['level'] == 'debug':
                self.logger.debug(message, kwargs['value'])
                self.lastEntryTime = self.now
            elif kwargs['level'] == 'info':
                self.logger.info(message, kwargs['value'])
                self.lastEntryTime = self.now
            elif kwargs['level'] == 'warning':
                self.logger.warning(message, kwargs['value'])
                self.lastEntryTime = self.now
            elif kwargs['level'] == 'error':
                self.logger.error(message, kwargs['value'])
                self.lastEntryTime = self.now
            elif kwargs['level'] == 'critical':
                self.logger.critical(message, kwargs['value'])
                self.lastEntryTime = self.now

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    form = MainWindow()
    form.show()
    app.exec()


import os,sys
from collections import  Counter
from typing import Optional
import json

from sklearn.model_selection import train_test_split

import numpy as np
from pandas import DataFrame
import pandas as pd

from sentiment.exception import SentimentException
from sentiment.logger import logging
from sentiment.entity.config_entity import DataTransformationConfig
from sentiment.entity.artifact_entity import DataTransformationArtifact, DataValidationArtifact
from sentiment.utils.main_utils import read_yaml_file, save_numpy_array_data
from sentiment.constant.training_pipeline import SCHEMA_FILE_PATH, STOPWORD, CORPUS,\
            S3_ARTIFACTS_URI, ENCODING, VOCAB_FILE_PATH
from sentiment.configuration.s3_operations import S3Operation
from sentiment.cloud_storage.s3_syncer import S3Sync

#nltk
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')
from nltk.util import ngrams
stop=set(stopwords.words(STOPWORD))
nltk.download(CORPUS)

class DataTransformation:

    def __init__(self, data_transformation_config: DataTransformationConfig, data_validation_artifacts: DataValidationArtifact) -> None:
        try:
            self.data_transformation_config=data_transformation_config
            self.data_validation_artifacts = data_validation_artifacts
            self._schema_config = read_yaml_file(SCHEMA_FILE_PATH)
        except Exception as e:
            raise SentimentException(e,sys)

    def change_target_values(self, raw_data_path: str) -> DataFrame:
        """Change the initial target values of 4 to 2

        Returns:
            DataFrame: transformed dataframe
        """
        t = []
        raw_data = pd.read_csv(raw_data_path, encoding=ENCODING)
        for i in raw_data.target.values:
            if i ==0: t.append(0)
            else: t.append(1)

        selected_df = pd.DataFrame({"text":raw_data.text.values, "target":t})
        return selected_df

    def _delete_unwanted_symbols(self) -> dict:
        """Return the dictionary having ord() of all the symbols

        Returns:
            dict: _description_
        """
        remove_dict = {ord(c):f'' for c in self.data_transformation_config.symbols_to_delete}
        return remove_dict

    def _handle_punctuation(self, x):
        remove_dict = self._delete_unwanted_symbols()
        x = x.translate(remove_dict)
        return x

    def preprocess_string(self, x: str):
        """
        Applying all the preprocessing steps defined above.

        """
        try:
            x = x.lower()
            x = self._handle_punctuation(x)
            return x
        except Exception as e:
            raise SentimentException(e, sys)

    def _remove_stopwords(self, df: Optional[np.array]) -> list:
        """Returns all the words in whole dataset after transformation
        """
        try:
            word_list = []
            stop_words = set(stopwords.words('english'))
            for sent in df:
                for word in sent.lower().split():
                    word = self.preprocess_string(word)
                    if word not in stop_words and word != '':
                        word_list.append(word)
            return word_list
        except Exception as e:
            raise SentimentException(e, sys)

    def split_dataset(self, df: DataFrame):
        try:
            logging.info("Starting Splitting of dataset>>>>")
            X,y = df['text'].values, df['target'].values
            x_train,x_test,y_train,y_test = train_test_split(X,y,stratify=y, test_size=self.data_transformation_config.test_size)
            logging.info(f'shape of train data is {x_train.shape}')
            logging.info(f'shape of train data is {x_test.shape}')
            logging.info(">>>>>>> Splitting of dataset Completed")
            return x_train,x_test,y_train,y_test
        except Exception as e:
            raise SentimentException(e, sys)

    def tockenize(self, x_train, y_train, x_test, y_test, word_list: list):
        """Tokenize and Vectorize using One hot encoding
        """
        try:
            logging.info("Starting Tokenizationm>>>>>>")
            corpus = Counter(word_list)
            # sorting on the basis of most common words
            corpus_ = sorted(corpus,key=corpus.get,reverse=True)[:1000]
            # creating a dict
            onehot_dict = {w:i+1 for i,w in enumerate(corpus_)}

            # tockenize
            final_list_train,final_list_test = [],[]
            for sent in x_train:
                    final_list_train.append([onehot_dict[self.preprocess_string(word)] for word in sent.lower().split()
                                            if self.preprocess_string(word) in onehot_dict.keys()])
            for sent in x_test:
                    final_list_test.append([onehot_dict[self.preprocess_string(word)] for word in sent.lower().split()
                                            if self.preprocess_string(word) in onehot_dict.keys()])

            return np.array(final_list_train), np.array(y_train), np.array(final_list_test), np.array(y_test), onehot_dict
        except Exception as e:
            raise SentimentException(e, sys)

    def padding_(self, sentences, seq_len):
        try:
            features = np.zeros((len(sentences), seq_len),dtype=int)
            for ii, review in enumerate(sentences):
                if len(review) != 0:
                    features[ii, -len(review):] = np.array(review)[:seq_len]
            return features
        except Exception as e:
            raise SentimentException(e, sys)

    def initiate_data_transformation(self) -> DataTransformationArtifact:
        try:
            selected_df = self.change_target_values(self.data_validation_artifacts.valid_file_path)
            x_train,x_test,y_train,y_test = self.split_dataset(selected_df[:10000]) # 1600000
            all_words = self._remove_stopwords(x_train)
            x_train,y_train,x_test,y_test,vocab = self.tockenize(x_train,y_train, x_test,y_test, all_words)
            x_train_pad = self.padding_(x_train,self.data_transformation_config.seq_len)
            x_test_pad = self.padding_(x_test,self.data_transformation_config.seq_len)
            logging.info("Saving Transformed data to artifacts>>>")

            os.makedirs(self.data_transformation_config.train_data_dir, exist_ok= True)
            os.makedirs(self.data_transformation_config.test_data_dir, exist_ok= True)

            save_numpy_array_data(self.data_transformation_config.train_data_file_path, x_train_pad)
            save_numpy_array_data(self.data_transformation_config.train_labels_file_path, y_train)
            save_numpy_array_data(self.data_transformation_config.test_data_file_path, x_test_pad)
            save_numpy_array_data(self.data_transformation_config.test_labels_file_path, y_test)
            data_transformation_artifact = DataTransformationArtifact(
                            train_data_file_path = self.data_transformation_config.train_data_file_path,
                            train_labels_file_path = self.data_transformation_config.train_labels_file_path,
                            test_data_file_path = self.data_transformation_config.test_data_file_path,
                            test_labels_file_path =  self.data_transformation_config.test_labels_file_path,
                            vocab = vocab)
            transformation_artifacts_dir = self.data_transformation_config.data_transformation_artifacts_dir

            # Save vocab for prediction
            with open(VOCAB_FILE_PATH, 'w') as fp:
                json.dump(vocab, fp)

            s3_sync = S3Sync()
            logging.info("Sync transformation files to S3 transformation artifacts folder...")
            s3_sync.sync_folder_to_s3(folder=transformation_artifacts_dir, aws_bucket_url=S3_ARTIFACTS_URI)
            logging.info("Finished Syncing files to S3 transformation artifacts folder")
            return data_transformation_artifact
        except Exception as e:
            raise SentimentException(e, sys)


# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Data.csv')
dataset = dataset.drop(['Unnamed: 0'], axis=1)
#PREPROCESSING DATA
#Counting the number of Nan values
dataset.isna().sum()
#The below is the output we get
'''
Name                    0
Location                0
Year                    0
Kilometers_Driven       0
Fuel_Type               0
Transmission            0
Owner_Type              0
Mileage                 2            -> 7th index
Engine                 36
Power                  36
Seats                  42
New_Price            5195
Price                   0
dtype: int64
'''
#Adjusting the unknown values in the dataset
dataset['Engine'].fillna(value='unknown',inplace=True)
dataset['Mileage'].fillna(value='unknown',inplace=True)
dataset['Power'].fillna(value='unknown',inplace=True)
dataset['Seats'].fillna(value=dataset['Seats'].mean(), inplace=True)

#now let's see the unkown values again
dataset.isna().sum()
'''
Name                    0
Location                0
Year                    0
Kilometers_Driven       0
Fuel_Type               0
Transmission            0
Owner_Type              0
Mileage                 0
Engine                  0
Power                   0
Seats                   0
New_Price            5195
Price                   0
dtype: int64
'''

#As New_Price has many unknown values let's drop the whole column.
dataset = dataset.drop(['New_Price'], axis = 1)

#Now our data is clean so we can proceed to further steps
#Dividing the data into two variables X-> Independent and Y-> Dependent
X = pd.DataFrame(dataset.iloc[:, :-1].values)
X.columns = dataset.columns[:-1]        #Setting the columns for the X
y = dataset.iloc[:, -1].values

# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 0)

X_train["Name"].value_counts()
make_train = X_train["Name"].str.split(" ", expand=True)
make_test  = X_test["Name"].str.split(" ", expand=True)

#I will add a Manufacturer column to the dataset as the sale depends mostly on the Manufacturer.
X_train["Manufacturer"] = make_train[0]
X_test["Manufacturer"] = make_test[0]

#Extracting the numerical values of Milage, Engine, Power
milage_train = X_train["Mileage"].str.split(" ", expand=True)
milage_test = X_test["Mileage"].str.split(" ", expand=True)
X_train["Mileage"] = pd.to_numeric(milage_train[0], errors = 'coerce')
X_test["Mileage"] = pd.to_numeric(milage_test[0], errors = 'coerce')

engine_train = X_train["Engine"].str.split(" ", expand=True)
engine_test  = X_test["Engine"].str.split(" ", expand=True)
X_train["Engine"] = pd.to_numeric(engine_train[0], errors = 'coerce')
X_test["Engine"]  = pd.to_numeric(engine_test[0], errors = 'coerce')

power_train = X_train["Power"].str.split(" ", expand=True)
power_test  = X_test["Power"].str.split(" ", expand=True)
X_train["Power"] = pd.to_numeric(power_train[0], errors = 'coerce')
X_test["Power"]  = pd.to_numeric(power_test[0], errors = 'coerce')

#Replacing the Null values with Mean of all the values in that column
X_train["Engine"].fillna(X_train["Engine"].astype("float64").mean(), inplace = True)
X_test["Engine"].fillna(X_train["Engine"].astype("float64").mean(), inplace = True)

X_train["Mileage"].fillna(X_train["Mileage"].astype("float64").mean(), inplace = True)
X_test["Mileage"].fillna(X_train["Mileage"].astype("float64").mean(), inplace = True)

X_train["Power"].fillna(X_train["Power"].astype("float64").mean(), inplace = True)
X_test["Power"].fillna(X_train["Power"].astype("float64").mean(), inplace = True)

X_train["Seats"].fillna(X_train["Seats"].astype("float64").mean(), inplace = True)
X_test["Seats"].fillna(X_train["Seats"].astype("float64").mean(), inplace = True)

#Dropping all the unnecessary columns in the dataset
#Name is no longer required as we are considering the Manufacturer as the sole base.
X_train = X_train.drop("Name", axis = 1)
X_test = X_test.drop("Name", axis = 1)
#Location should not determine the price of the car.
X_train = X_train.drop("Location", axis = 1)
X_test = X_test.drop("Location", axis = 1)
#Year has no significance unless we consider how old the given car is
X_train = X_train.drop("Year", axis = 1)
X_test = X_test.drop("Year", axis = 1)

#EXPLORATORY DATA ANALYSIS
#Manufacturers VS Number of cars plotting
plt.figure(figsize = (14, 10))
plot = sns.countplot( x = "Manufacturer", data = X_train)
plt.xticks(rotation = 90)
#Annotating the plot
for p in plot.patches:
    plot.annotate(p.get_height(),
                        (p.get_x() + p.get_width() / 2.0,
                         p.get_height()),
                        ha = 'center',
                        va = 'center',
                        xytext = (0, 5),
                        textcoords = 'offset points')

plt.title("Count of cars based on manufacturers")
plt.xlabel("Manufacturer")
plt.ylabel("Count of cars")

plt.figure(figsize = (14, 10))
plt.hist(X_train["Kilometers_Driven"], bins =[0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000] )
plt.xlabel("Kilometers Driven")
plt.ylabel("Count of cars")
plt.show()

plt.figure(figsize = (14, 10))
plt.bar(X_train["Fuel_Type"], height = np.arange(len(X_train["Fuel_Type"])), width = 0.4, color = ['red', 'blue', 'yellow', 'green'])
plt.xlabel("Fuel Type")
plt.ylabel("Count")
plt.show()

plt.figure(figsize = (14, 10))
plt.bar(X_train["Transmission"], height = np.arange(len(X_train["Transmission"])), width = 0.4, color = ['orange','green'])
plt.xlabel("Transmission")
plt.ylabel("Count")
plt.show()

plt.figure(figsize = (14, 10))
plt.bar(X_train["Owner_Type"], height = np.arange(len(X_train["Owner_Type"])), width = 0.4, color = ['orange','green'])
plt.xlabel("Owner Type")
plt.ylabel("Count")
plt.show()

plt.figure(figsize = (14, 10))
plt.scatter(X_train["Mileage"], np.arange(len(X_train["Mileage"])), color = 'r')
plt.xlabel("Mileage")
plt.ylabel("Count")
plt.show()

plt.figure(figsize = (14, 10))
plot = sns.countplot( x = "Seats", data = X_train)
plt.xticks(rotation = 90)
#Annotating the plot
for p in plot.patches:
    plot.annotate(p.get_height(),
                        (p.get_x() + p.get_width() / 2,
                         p.get_height()),
                        ha = 'center',
                        va = 'center',
                        xytext = (0, 5),
                        textcoords = 'offset points')

#Categorical Data
#let's create dummy columns for categorical columns before we begin training.
X_train = pd.get_dummies(X_train,
                         columns = ["Manufacturer", "Fuel_Type", "Transmission", "Owner_Type"],
                         drop_first = True)
X_test = pd.get_dummies(X_test,
                         columns = ["Manufacturer", "Fuel_Type", "Transmission", "Owner_Type"],
                         drop_first = True)
#It might be possible that the dummy column creation would be different in test and train data, thus, I'd fill in all missing columns with zeros
missing_cols = set(X_train.columns) - set(X_test.columns)
for col in missing_cols:
    X_test[col] = 0
X_test = X_test[X_train.columns]

#Feature Scaling the data
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)

#Fitting simple Linear Regression to the Training set
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train, y_train)
#predicting the Test set results
y_pred = regressor.predict(X_test)

from sklearn.metrics import r2_score
r2_score(y_test, y_pred)

from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor(n_estimators = 100)
rf.fit(X_train, y_train.ravel())
y_pred = rf.predict(X_test)
r2_score(y_test, y_pred)

'''
    Output : 0.8104532069495102
'''


import pygame
import time

pygame.init()
pygame.mixer.pre_init(44100, 16, 2, 4096) #setting 16 bit size; 32 or 64 bit dosent work.
pygame.mixer.init()
win =  pygame.display.set_mode((500,480))

pygame.display.set_caption("First Game")

#loading images of our character. images of enemy in enemy class
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
bg = pygame.image.load('bg.jpg')
char = pygame.image.load('standing.png')

#loading audio files
t = pygame.mixer.music
t.load('bullet.wav')
t.load('hit.wav')

clock = pygame.time.Clock()

class player():
    def __init__(self, x, y, height, width):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.vel = 10
        self.isJump = False
        self.jumpcount = 10
        self.left = False
        self.right = False
        self.walkcount = 0
        self.standing = True
        self.hitbox = (self.x + 17, self.y+ 11, 29, 52) #(x,y, width, height)

    def draw(self, win):
        if self.walkcount +1>= 27:
            self.walkcount = 0

        if not(self.standing):
            if self.left:
                win.blit(walkLeft[man.walkcount//3], (self.x,self.y))
                self.walkcount +=1
            elif self.right:
                win.blit(walkRight[man.walkcount//3], (man.x,man.y))
                self.walkcount +=1
        else:
            if self.right:
                win.blit(walkRight[0],(self.x,self.y))
            else:
                win.blit(walkLeft[0],(self.x,self.y))
        self.hitbox = (self.x + 17, self.y+ 11, 29, 52)  #to make hitbox move with the player
        #pygame.draw.rect(win, (255,0,0), self.hitbox, 2)

    def hit(self):
        self.isJump = False #because if jumping man hits goblin, it continues its downward jump.
        self.jumpcount = 10
        self.x = 60
        self.y = 410
        goblin.x = 300
        goblin.y = 410
        walkcount = 0
        font1 = pygame.font.SysFont('corbel', 100)
        text = font1.render('-5',1, (255, 0, 0))
        win.blit(text,(250 - (text.get_width()/2), 240- (text.get_height()/2) ))
        pygame.display.update()
        time.sleep(2)

class Projectile():
    def __init__(self, x, y, radius, color, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing
        self.vel = 5

    def draw(self, win):
        pygame.draw.circle( win, self.color, (self.x, self.y), self.radius)

class Enemy():
    walkRight = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'), pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'), pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'), pygame.image.load('R10E.png'), pygame.image.load('R11E.png')]
    walkLeft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'), pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'), pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'), pygame.image.load('L10E.png'), pygame.image.load('L11E.png')]

    def __init__(self, x, y, width, height, end):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.end = end
        self.path = [self.x,self.end]
        self.walkcount = 0
        self.vel = 3
        self.hitbox = (self.x + 17, self.y+2, 31, 57)
        self.health = 10
        self.visible = True

    def draw(self,win):
        if self.visible:
            self.move()  #very importanat to call on move function
            if self.walkcount + 1 >= 33:
                self.walkcount = 0
            if self.vel > 0:
                win.blit(self.walkRight[self.walkcount//3],(self.x, self.y))
                self.walkcount += 1
            else:
                win.blit(self.walkLeft[self.walkcount//3], (self.x, self.y))
                self.walkcount += 1
            pygame.draw.rect(win,(255,0,0), (self.hitbox[0],self.hitbox[1]- 20,50, 10))
            pygame.draw.rect(win,(0,128,0), (self.hitbox[0],self.hitbox[1]-20,50 -(5 * (10 - self.health)), 10))
            self.hitbox = (self.x + 17, self.y+2, 31, 57)
            #pygame.draw.rect(win, (255,0,0), self.hitbox, 2)

    def move(self):
        if self.vel>0:
            if self.x +self.vel < self.path[1]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkcount = 0
        else:
            if self.x - self.vel > self.path[0]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkcount = 0

    def hit(self):
        if self.health > 1:
            self.health -= 1
        else:
            self.visible = False
            walkcount = 0

def redrawgamewindow():
    win.blit(bg, (0,0))
    man.draw(win)
    goblin.draw(win)
    for bullet in bullets:
        bullet.draw(win)
    if goblin.visible:
        global font
        font = pygame.font.SysFont('corbel', 30, True)
        text = font.render('Score: ' + str(score),1 , (0,0,0))
        win.blit(text, (380,10))
    else:
        text3 = font.render('Your score is '+ str(score), 1, (0,0,110))
        win.blit(text3,(250 - (text3.get_width()/2), 240- (text3.get_height()/2)))
    pygame.display.update()

#creating instances of characters
man = player(300, 410, 64, 64)
goblin = Enemy(50,410,64,64,450)

bulletsound = pygame.mixer.Sound('bullet.wav')
hitsound = pygame.mixer.Sound('hit.wav')
bgsound = pygame.mixer.Sound('bgmusic (2).wav')
bgsound.play(-1)

score = 0
shootcount = 0
bullets = []

run = True
while run:
    clock.tick(27)
    if shootcount in range(3): #basic timer for bullets
        shootcount += 1
    else:
        shootcount =  0

    for event in pygame.event.get(): #an entry in the list of events, get means get the entry.
        if event.type == pygame.QUIT:
            run = False

    for bullet in bullets:
        if bullet.x < 500 and bullet.x > 0:
            bullet.x += bullet.vel*bullet.facing
        else:
            bullets.pop(bullets.index(bullet))
        if goblin.visible:
            if pygame.Rect(goblin.hitbox).collidepoint(bullet.x, bullet.y):
                goblin.hit()
                score += 1
                hitsound.play()
                bullets.pop(bullets.index(bullet))

    if goblin.visible:
        if pygame.Rect(goblin.hitbox).colliderect(man.hitbox):
            man.hit()
            score -= 5

    keys = pygame.key.get_pressed()
    if man.left:
        facing = -1
    else:
        facing = 1
    if keys[pygame.K_SPACE] and shootcount == 0:
        bulletsound.play()
        if len(bullets)<5:
            bullets.append(Projectile(round(man.x + man.width//2),round(man.y +man.height//2),5, (0,0,0), facing))

    if keys[pygame.K_RIGHT] and man.x < 500-man.width-man.vel: #alwasys put man.width rather than arbitary value
        man.x += man.vel                                    #so that you dont have to remember .
        man.right = True
        man.left = False
        man.standing = False

    elif keys[pygame.K_LEFT] and man.x > man.vel:
        man.x -= man.vel
        man.left = True
        man.right = False
        man.standing = False

    else:
        man.standing = True
        man.walkcount = 0

    if not(man.isJump):
        if keys[pygame.K_UP]:
            man.isJump = True
            man.right = False
            man.left = False
            man.walkcount = 0

    else:
        if man.jumpcount >= -10:
            neg =1
            if man.jumpcount<0:
                neg = -1
            man.y -= (man.jumpcount**2)/2 *neg
            man.jumpcount -= 1
        else:
            man.isJump = False
            man.jumpcount = 10

    redrawgamewindow()

pygame.quit()


from typing import Dict, Union, Tuple, Any

from django.http import JsonResponse

from utils.data import verify_data, verify_dict

def verify_city(data: Dict[str, Any]) -> Union[Tuple[bool, None], Tuple[bool, JsonResponse]]:
    name = data.get('name')

    is_valid, error_message = verify_data(data=name, required=True, data_type=str, max_length=40, error_messages={
        'required': 'Қала атауы міндетті өріс',
        'data_type': 'Қала атауы string типінде болу керек',
        'max_length': 'Қала атауының ұзындығы 40-ден артық',
    })

    if not is_valid:
        return False, JsonResponse({'message': error_message}, status=400)

    is_valid_or_key_name, reason_or_none = verify_dict(
        data, [{'key_name': 'name'}])

    if is_valid_or_key_name != True:
        return False, JsonResponse({'message': reason_or_none}, status=400)

    return True, None

def verify_dorm(data: Dict[str, Any]) -> Union[Tuple[bool, None], Tuple[bool, JsonResponse]]:
    name = data.get('name')
    desciption = data.get('desciption')
    city = data.get('city')
    address = data.get('address')
    images = data.get('images')

    for is_valid, error_message in (verify_data(data=name, required=True, data_type=str, max_length=40, error_messages={
        'required': 'Жатақхана атауы міндетті өріс',
        'data_type': 'Жатақхана атауы string типінде болу керек',
        'max_length': 'Жатақхана атауының ұзындығы 40-ден артық',
    }), verify_data(data=desciption, required=False, data_type=str, max_length=254, error_messages={
        'data_type': 'Жатақхана сипаттамасы string типінде болу керек',
        'max_length': 'Жатақхана сипаттамасының ұзындығы 254-ден артық',
    }), verify_data(data=city, required=True, data_type=int, error_messages={
        'required': 'Жатақхананың орналасқан қаласы міндетті өріс',
        'data_type': 'Жатақхананың орналасқан қаласы int типінде болу керек',
    }), verify_data(data=address, required=True, data_type=str, max_length=60, error_messages={
        'required': 'Жатақхананың нақты мекен-жайы міндетті өріс',
        'data_type': 'Жатақхананың нақты мекен-жайы string типінде болу керек',
        'max_length': 'Жатақхананың нақты мекен-жайының ұзындығы 60-ден артық',
    })):
        if not is_valid:
            return False, JsonResponse({'message': error_message}, status=400)

    is_valid_or_key_name, reason_or_none = verify_dict(data, [{'key_name': 'name'}, {'key_name': 'description', 'required': False}, {
        'key_name': 'city'}, {'key_name': 'address'}])

    if is_valid_or_key_name != True:
        return False, JsonResponse({'message': reason_or_none}, status=400)

    return True, None


from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split

import numpy as np

def data_preparation(digits, filter=None, test_size=0.33, random_seed=12345):
    """
    Prepare data with given filters

    :param digits: dict
        Dictionary containing data set.
        digits['data'] contains all features of design matrix
        digits['target'] contains respective target labels

    :param filter: array-like of shape (n, ), default=None
        Array with targets to be filters from data

    :param test_size: int, default=0.33
        Percentage of test data after splitting

    :param random_seed: int, default=12345
        Random seed to make results reproducible

    :return:
    """
    data = digits['data']
    target = digits['target']

    # Data filtering
    if filter:
        # List of n_filters ndarrays wit boolean variables for each filter
        filters = [target == f for f in filter]
        mask = np.sum(filters, axis=0)
        data = data[np.argwhere(mask)]
        target = target[np.where(mask)]

        # Relable targets
        for i, f in enumerate(filter):
            target[target == f] = i

    # Random split
    X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=test_size, random_state=random_seed)

    train_std = np.std(X_train, axis=0) + 1e-99
    train_mean = np.mean(X_train, axis=0)
    # Standardize training data
    X_train_std = (X_train - train_mean)/train_std
    # Standardize test data
    X_test_std = (X_test - train_mean)/train_std

    X_train = X_train.squeeze()
    X_train_std = X_train_std.squeeze()
    X_test = X_test.squeeze()
    X_test_std = X_test_std.squeeze()

    return X_train, X_train_std, X_test, X_test_std, y_train, y_test


from django.views.generic import TemplateView
import os
from django.shortcuts import render
from config import settings
import csv
import requests
import uuid
from django.http import HttpResponse
from datetime import datetime
from .models import StarWarsData

class IndexView(TemplateView):
    template_name = 'base.html'

def list_csv_files(request):
    csv_folder_path = os.path.join(settings.MEDIA_ROOT, 'csv_files')
    csv_files = [f for f in os.listdir(csv_folder_path) if f.endswith('.csv')]
    context = {
        "data" : csv_files
    }
    return render(request, 'index.html', context)

def download_csv(request):
    response = requests.get('https://swapi.dev/api/people')
    data = response.json().get('results', [])
    unique_filename = f'{uuid.uuid4()}.csv'

    StarWarsData(filename=unique_filename, data=data).save()

    csv_folder_path = os.path.join(settings.MEDIA_ROOT, 'csv_files')
    csv_file_path = os.path.join(csv_folder_path, unique_filename)
    with open(csv_file_path, mode='w', newline='') as csv_file:
        writer = csv.writer(csv_file)
        for item in data:
            writer.writerow([item.get('name', ''), item.get('height', ''), item.get('mass', ''),
                            item.get('hair_color', ''), item.get('skin_color', ''), item.get('eye_color', ''),
                            item.get('birth_year', ''), item.get('gender', ''), parse_homeword(item.get('homeworld', '')),
                            datetime.now().strftime("%Y-%m-%d")
                            ])
    return HttpResponse(status=200)

def display_csv_content(request, file_name):
    csv_folder_path = os.path.join(settings.MEDIA_ROOT, 'csv_files')
    csv_file_path = os.path.join(csv_folder_path, file_name)

    with open(csv_file_path, 'r', newline='') as csv_file:
        reader = csv.reader(csv_file)
        csv_data = list(reader)

    context = {
        'file_name': file_name,
        'csv_data': csv_data,
    }
    return render(request, 'display_csv_content.html', context)

def parse_homeword(url):
    response = requests.get(url)
    data = response.json()
    return data.get("name", "")

def save_to_db(item):
    pass


import datetime
from model import Config

def check_time(config: Config, time: datetime.datetime, check_period: datetime.timedelta):
    time_array = config.schedules.split(',')
    runs = []
    for i in time_array:
        hour, minutes = map(int, i.split(':'))
        time_for_check = datetime.datetime(
            year=time.year, month=time.month,
            day=time.day, hour=hour, minute=minutes)
        runs.append(time_for_check)

    for i in runs:
        if i <= time < i+check_period:
            return True
    return False


from urllib.parse import urlencode

from django.http import QueryDict

from service.utils.cases import deep_snake_case_transform

def convert_query_params_to_snake_case(func):
    def func_wrapper(request, *args, **kwargs):
        updated_params = deep_snake_case_transform(request.GET)
        querystring = urlencode(updated_params)
        request.GET = QueryDict(querystring)
        return func(request, *args, **kwargs)
    return func_wrapper


try:
    import concurrent.futures
    import requests
    import time
    import os
    from fake_useragent import UserAgent
    from bs4 import BeautifulSoup
    import pandas as pd
except Exception as e:
    print("Some modules could not be imported")
    exit(1)

def get_free_proxies():
    ua = UserAgent()
    # generate a random user agent for the request
    user_agent = ua.random

    # store the url of the proxy site as a string
    url = 'https://free-proxy-list.net/'

    # structure request header
    ua_header = {'User-Agent': user_agent}

    # make a GET request from the url
    content = requests.get(url, headers = ua_header).text

    soup = BeautifulSoup(content,'html.parser')
    rows=[]
    for row in soup.findAll("tr"):
        rows.append(row)

    elite_https_proxies = []

    # Find the rows that are elite proxy and 'Yes' to the https column
    for row in rows:
        i = row.findAll('td')
        try:
            if i[4].text == 'elite proxy' and i[6].text == 'yes':
                # Append IP to a list (column 0 is the IP, column 1 is the port)
                elite_https_proxies.append(i[0].text + ':' + i[1].text)
        except:
            continue

    df = pd.DataFrame(elite_https_proxies, columns=["proxy_ip"])
    proxy_filepath = os.path.normpath('app/outputs/free_proxies.csv')

    df.to_csv(proxy_filepath, index_label='id')
    return elite_https_proxies

def get_poster_image_path(imdb_id, proxy):
    print("Imdb :",imdb_id, "Proxy :", proxy)
    ua = UserAgent()
    user_agent = ua.random
    ua_header = {'User-Agent': user_agent}
    page = requests.get("https://www.imdb.com/title/"+imdb_id.strip(), headers = ua_header, proxies={"https":"https://"+proxy, "http":"http://"+proxy})

    '''
    page.content is the whole html content.
    BeautifulSoup helps parsing the html content.
    '''
    bsoup = BeautifulSoup(page.content, 'html.parser')

    '''
    as there are 16 elements which have exactly this class but, the first one has the poster path of the movie concerned
    '''
    poster_img_element = bsoup.select('.ipc-poster--baseAlt .ipc-media--poster img.ipc-image')[0]

    poster_path_url =  poster_img_element.get('src')
    print("URL: ", poster_path_url)
    return poster_path_url

def get_poster_path_urls(imdb_id_list):
    # get the list of proxies
    proxy_filepath = os.path.normpath('app/outputs/free_proxies.csv')

    if not os.path.exists(proxy_filepath):
        get_free_proxies()

    proxy_df = pd.read_csv(proxy_filepath, index_col='id')
    proxy_list = proxy_df['proxy_ip'].tolist()

    MAX_THREADS = 100
    threads = min(MAX_THREADS, len(imdb_id_list))
    poster_urls = []

    with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
        result_iterator = executor.map(get_poster_image_path, imdb_id_list, proxy_list)

        for future in concurrent.futures.as_completed(result_iterator):
            imdb_id_temp = result_iterator[future]
            try:
                poster_urls.append((imdb_id_temp, imdb_id_temp.result()))
            except Exception as exc:
                print('%r generated an exception: %s' % (imdb_id_temp, exc))

    return poster_urls

if __name__ == "__main__":
    print("----Web Scraping Poster Path Generator----")
    # imdb_id = input("Enter the movie's imdb id: ").strip()

    # print("\nPoster path url for the given imdb id is :\n\n",get_poster_image_path(imdb_id=imdb_id))

    df = pd.read_csv("app/outputs/metadata_smd_small.csv", index_col="Id")

    print("Started method execution..")
    t0 = time.time()

    poster_urls = get_poster_path_urls(df["imdb_id"].tolist())
    t1 = time.time()
    print(f"{t1-t0} seconds to execute thread version on small dataset of approx. 9k entries...")

    poster_url_imdb_mapping = {
        "imdb_id": [i[0] for i in poster_urls],
        "poster_path": [i[1] for i in poster_urls]
    }
    df = pd.DataFrame(poster_url_imdb_mapping, columns=["imdb_id", "poster_path"])

    print('Saving the urls to csv file..')
    poster_urls_filepath = os.path.normpath('app/outputs/poster_path_urls.csv')

    df.to_csv(poster_urls_filepath, index_label="imdb_id")


import urllib,urllib2,cgi
import simplejson
from picplz.errors import PicplzError

def build_request_code_url(client_id,redirect_uri):
    request_url = "https://picplz.com/oauth2/authenticate?client_id=%s&response_type=code&redirect_uri=%s" %(client_id,redirect_uri)
    return request_url

def build_access_token_url(client_id,client_secret,redirect_uri,code):
    access_token_url = "https://picplz.com/oauth2/access_token?client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s" % (client_id,client_secret,redirect_uri,code)
    return access_token_url

class PicplzOauthToken():
    """ Object to represent picplz oauth tokens, since they call the secret 'oauth_secret' instead of 'oauth_token_scret' like everyone else """

    key = None
    secret = None
    picplz_prefix = None

    def __init__(self, picplz_prefix, key, secret):
        if picplz_prefix is None:
            ## assume it's '1|'
            self.picplz_prefix = '1|'
        self.picplz_prefix = picplz_prefix
        self.key = key
        self.secret = secret

    def to_string(self):
        data = {
            'oauth_token': self.key,
            'oauth_secret': self.secret,
        }
        return "%s%s" % (self.picplz_prefix,urllib.urlencode(data))

    def from_string(oauth_token_string):
        """ Returns a token from something like:
        1|oauth_secret=xxx&oauth_token=xxx
        no idea know why the '1|' is there
        """

        split_string = oauth_token_string.split('|')
        try:
            s1 = "%s%s" % (split_string[0],"|")
            s2 = split_string[1]
        except:
            ## just do our best, maybe the pipe thing went away
            s1=''
            s2 = oauth_token_string

        params = cgi.parse_qs(s2, keep_blank_values=False)
        picplz_prefix = s1
        key = params['oauth_token'][0]
        secret = params['oauth_secret'][0]
        token = PicplzOauthToken(picplz_prefix,key, secret)
        return token

    from_string = staticmethod(from_string)

    def __str__(self):
        return self.to_string()

class PicplzAuthenticator():

    client_id = None
    client_secret=None
    redirect_uri=None
    request_code=None
    access_token=None
    authenticated=False

    def __init__(self,picplz_client_id,picplz_client_secret,registered_redirect_uri,access_token=None):
        if access_token is not None:
            self.access_token = access_token
        self.client_id = picplz_client_id
        self.client_secret = picplz_client_secret
        self.redirect_uri = registered_redirect_uri

    def get_authorization_url(self):
        return build_request_code_url(self.client_id, self.redirect_uri)

    def get_access_token(self,code=None):
        if self.request_code is None and code is None:
            raise PicplzError("Authenticator does not have a valid request code and no code was passed in. A valid code is required to obtain an access token")

        if code is not None:
            self.request_code = code

        at_url = build_access_token_url(self.client_id, self.client_secret, self.redirect_uri, self.request_code)

        response = urllib2.urlopen(at_url)
        json = response.read()
        try:
            picplz_response = simplejson.loads(json)
            access_token_crazy_picplz_string = picplz_response['access_token']
            #why does this have '1|' in it? who knows... let's just deal with it
            #access_token_string = access_token_crazy_picplz_string.split('|')[1]
            access_token_string = access_token_crazy_picplz_string
            self.access_token = PicplzOauthToken.from_string(access_token_string)
            return self.access_token
        except:
            raise PicplzError("failed to obtain access token, picplz response was: %s" % (json))


from django.shortcuts import render
from django.http import HttpResponse, request
from django.views import View
from django.shortcuts import get_list_or_404, get_object_or_404
from myapp.models import Estilo
from myapp.models import Interprete
from myapp.models import Cancion
from django.views.generic import ListView
from django.db.models import Q
from itertools import chain

def index(request):
 elementos_list = Estilo.objects.all()
 canciones = Cancion.objects.all().order_by('popularidad')[:100]
 context = {'elementos' : elementos_list, "canciones" : canciones}
 return render(request, 'myapp/index.html', context)

def cancion_detalle(request, id_cancion):
 cancion = Cancion.objects.get(id = id_cancion)
 interpretes = cancion.interprete.all()
 estilo = Estilo.objects.get(nombre = cancion.estilo)
 context = {"cancion" : cancion, "interpretes" : interpretes, "estilo" : estilo}

 return render(request, 'myapp/cancion.html', context)

def estilo_detalle(request, id_estilo):
 estilo = Estilo.objects.get(id = id_estilo)
 cancion_list = Cancion.objects.all()
 context = {"estilo" : estilo, "canciones" : cancion_list}

 return render(request, 'myapp/estilo.html', context)

def interprete_detalle(request, id_interprete):
 interprete = Interprete.objects.get(id = id_interprete)
 interpretes = interprete.cancion_set.all()
 context = {"interprete" : interprete, "interpretes" : interpretes}

 return render(request, 'myapp/interprete.html', context)

class BusquedaCancion(ListView):
    model = Cancion

    template_name = 'busqueda.html'

    def get_queryset(self):
        query = self.request.GET.get('q')
        object_list1 = Cancion.objects.filter(
            Q(titulo=query) | Q(interprete=query)
        )

        object_list2 = Interprete.objects.filter(
            Q(nombre=query) | Q(DNI=query)
        )

        object_list = list(chain(object_list2, object_list1))

        return object_list


import cv2
import mediapipe as mp
import time
from ohbot import ohbot

cap = cv2.VideoCapture(0)

mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
                      max_num_hands=2,
                      min_detection_confidence=0.5,
                      min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils

pTime = 0
cTime = 0

success, img = cap.read()
rows, cols, _ = img.shape

x_medium = int(cols / 2)
x_center = int(cols / 2)
y_medium = int(rows / 2)
y_center = int(rows / 2)
x_position = 5 #środkowa pozycja
y_position = 4

print(x_medium, x_center)

# ohbot.move(0,x_position)
# ohbot.move(1,y_position)

while True:
    success, img = cap.read()
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)

    if results.multi_hand_landmarks:
        for handLms in results.multi_hand_landmarks:
            for id, lm in enumerate(handLms.landmark):
                h, w, c = img.shape
                cx, cy = int(lm.x *w), int(lm.y*h)
                cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)

                if id == 9:
                    if cx < x_center - 100:
                        if x_position >= 0.15:
                            x_position -= 0.15
                    elif cx > x_center + 100:
                        if x_position <= 9.45:
                            x_position += 0.15
                    print(f'cy {cy}, cx {cx}')
                    if cy < y_center - 100:
                        if y_position >= 0.15:
                            y_position -= 0.15
                    elif cy > y_center + 100:
                        if y_position <= 9.45:
                            y_position += 0.15

                print(y_position)
                # ohbot.move(1,y_position)
                # ohbot.move(0,x_position)

            mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)

    cTime = time.time()
    fps = 1/(cTime-pTime)
    pTime = cTime

    cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)

    cv2.imshow("Image", img)
    cv2.waitKey(1)


"""Models for Blogly."""

import datetime
from flask_sqlalchemy import SQLAlchemy

DEFAULT_IMG_URL = "https://www.freeiconspng.com/uploads/icon-user-blue-symbol-people-person-generic--public-domain--21.png"

db = SQLAlchemy()

def connect_db(app):
    """Connect to database."""

    db.app = app
    db.init_app(app)

class User(db.Model):
    """User"""

    __tablename__ = "users"

    id = db.Column(db.Integer,
                    primary_key=True,
                    autoincrement=True)
    first_name = db.Column(db.String(50),
                    nullable=False,
                    unique=False)
    last_name = db.Column(db.String(50),
                    nullable=False,
                    unique=False)
    image_url = db.Column(db.Text,
                    nullable=False,
                    default=DEFAULT_IMG_URL)

    posts = db.relationship("Post", backref="user")

class Post(db.Model):
    """Post"""

    __tablename__ = "posts"

    id = db.Column(db.Integer,
                    primary_key=True,
                    autoincrement=True)
    title = db.Column(db.String(100),
                    nullable=False)
    content = db.Column(db.Text,
                    nullable=False)
    created_at = db.Column(db.DateTime,
                    nullable=False,
                    default=datetime.datetime.now)
    user_id = db.Column(db.Integer,
                    db.ForeignKey("users.id"),
                    nullable=False)

    tags = db.relationship('Tag',
                               secondary='post_tag',
                               backref='posts')

class PostTag(db.Model):
    """M to M table for posts and tags"""

    __tablename__ = "post_tag"

    post_id = db.Column(db.Integer,
                    db.ForeignKey("posts.id"),
                    nullable=False,
                    primary_key=True)

    tag_id = db.Column(db.Integer,
                    db.ForeignKey("tags.id"),
                    nullable=False,
                    primary_key=True)

class Tag(db.Model):
    """Tag"""

    __tablename__ = "tags"

    id = db.Column(db.Integer,
                    primary_key=True,
                    autoincrement=True)
    name = db.Column(db.String(50),
                    nullable=False,
                    unique=True)


from django.shortcuts import render
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from .models import *
from .forms import *
from dashboard.models import HostelAnnouncements
from django.contrib.auth.decorators import login_required
from api_integration.models import Student
import datetime
from api_integration.models import Student
import os

@login_required
def get_admin_status(request):
	st = 0
	dr = Student.objects.filter(student_first_name = str(request.user))
	if(len(dr) == 0):
            return 0
	print(dr, "ASDAS")
	if(dr[0].is_hostel_admin == True):
		st = 1
	elif(dr[0].is_mess_admin == True):
		st = 2
	elif(dr[0].is_medical_admin == True):
		st = 3
	return st

# Create your views here.

@login_required
def hostel_dashboard(request):
	h_announce = HostelAnnouncements.objects.all().filter(isDeleted=0)
	scrollL_announce = len(h_announce)
	if scrollL_announce <= 3:
		scrollL_announce = '140px'
	else:
		scrollL_announce = str(3 * 70)+ 'px'

	self_help = SelfHelpGroup.objects.all().filter(isDeleted=0)
	scrollL_self = len(self_help)

	if scrollL_self <= 3:
		scrollL_self = '70px'
	else:
		scrollL_self = str(3 * 70)+ 'px'

	courier_data = Courrier.objects.all().filter(isDeleted=0)
	#.filter(student=Student.objects.get(user = request.user))
	courier_data = list(filter(lambda x: x.student.user == request.user, courier_data))
	scrollL_courier = len(courier_data)
	if scrollL_courier <= 3:
		scrollL_courier = '140px'
	else:
		scrollL_courier = str(3 * 70)+ 'px'
	context = {'h_announce':h_announce , 'self_help':self_help , 'courier_data':courier_data,
	'scrollL_announce':scrollL_announce,'scrollL_self':scrollL_self,'scrollL_courier':scrollL_courier,'admin_status': get_admin_status(request)}
	return render(request,'hostel/hostel_dashboard.html',context)

@login_required
def leave_form(request):
	form = HostelLeaveForm()
	return render(request,'hostel/leave.html',{'form':form,'admin_status': get_admin_status(request)})

@login_required
def complaint_form(request):
	form = HostelComplaintForm()
	return render(request,'hostel/complaint.html',{'form':form,'admin_status': get_admin_status(request)})

'''@login_required
def complaint_ack(request):
	return render(request,'hostel/complaint-ack.html')'''

def getDate(dat):
	dat = dat.split('-')
	year = int(dat[0])
	month = int(dat[1])
	day = int(dat[2])

	return datetime.date(year,month,day)

@login_required
def addComplaint(request):
	if request.method == 'POST':
		form = HostelComplaintForm(request.POST,request.FILES)
		if form.is_valid():
			complaint_form = form.save(commit=False)
			complaint_form.student = Student.objects.get(user = request.user)
			subject = request.POST['subject']
			comp = subject +' '+request.POST['complaint']
			checkVal = vulgarCheck(comp)
			print(checkVal)
			if(checkVal==0):
				complaint_form.complaint = comp
			elif(checkVal==1):
				return render(request,'hostel/vulgar-ack.html',{'admin_status': get_admin_status(request)})

			if len(request.FILES) > 0:
				complaint_form.comp_img = request.FILES['image']
			else:
				complaint_form.comp_img = ""
			complaint_form.room_no = request.POST['room_no']
			complaint_form.completed = False
			complaint_form.timestamp = datetime.datetime.now()
			complaint_form.created_at = datetime.datetime.now().date()
			complaint_form.created_by = Student.objects.get(user = request.user)
			complaint_form.modified_at = datetime.datetime.now().date()
			complaint_form.modified_by = Student.objects.get(user = request.user)
			complaint_form.save()
			return render(request,'hostel/complaint-ack.html',{'admin_status': get_admin_status(request)})
	else:
		form =  HostelComplaintForm()
		return render(request,'hostel/complaint.html',{'form':form,'error_message':'','admin_status': get_admin_status(request)})

@login_required
def applyHostelLeave(request):
	if request.method == 'POST':
		form = HostelLeaveForm(request.POST)
		if form.is_valid():
			leave_form = form.save(commit=False)
			leave_form.student = Student.objects.get(user = request.user)
			leave_form.leave_from = getDate(request.POST['leave_from'])
			leave_form.leave_to = getDate(request.POST['leave_to'])
			leave_form.timestamp = datetime.datetime.now()
			leave_form.created_at = datetime.datetime.now().date()
			leave_form.modified_at = datetime.datetime.now().date()

			leave_form.created_by = Student.objects.get(user = request.user)
			leave_form.modified_by = Student.objects.get(user = request.user)

			mess_leave = request.POST['select_opt']
#--------------------------------------------------------------------------------------------
			if(mess_leave=='Yes'):
				#Update the mess models with creating an instance of the mess models
				print(mess_leave)
#--------------------------------------------------------------------------------------------
			if(leave_form.leave_from >=  leave_form.leave_to):
				error_message = "Please enter valid From and TO dates"
				return render(request,'hostel/leave.html',{'form':form,'error_message':error_message})
			leave_form.save()
			return render(request, 'hostel/leave-ack.html',{'admin_status': get_admin_status(request)})
		else:
			error_message = "Please enter data in YYYY-MM-DD format"
			return render(request,'hostel/leave.html',{'form':form,'error_message':error_message,'admin_status': get_admin_status(request)})

	form =  HostelLeaveForm()
	return render(request,'hostel/leave.html',{'form':form,'error_message':'','admin_status': get_admin_status(request)})

def vulgarCheck(s):
	vul = dict()
	with open(os.getcwd()+"/vulgar.txt",'r') as file:
		text = file.readlines()
		for i in range(len(text)):
			text[i]=text[i].strip()
			if(text[i] not in vul):
				vul[text[i]] = 1

	s = s.split(' ')
	for j in range(len(s)):
		if(s[j] in vul):
			return 1

		if(j>0):
			if((s[j-1]+' '+s[j]) in vul):
				return 1

		if(j>1):
			if((s[j-2]+' '+s[j-1]+' '+s[j]) in vul):
				return 1

		if(j>2):
			if((s[j-3]+' '+s[j-2]+' '+s[j-1]+' '+s[j]) in vul):
				return 1

	return 0


#!/usr/bin/env python3

#import commands
import sys, math
import os, shutil, signal
import subprocess as commands
import re
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import time
import itertools
import timeit
from cosy import cosyrun, write_fox
import pygmo as pg
from problem import optimizeRes
import pandas as pd
from kmeans_cluster import run_kmeans
from view_db import is_pareto_efficient_simple

# specify Tex details for pretty plots
os.environ['PATH'] = os.environ['PATH'] + ':/mnt/misc/sw/indep/all/texlive/2013/bin/x86_64-linux/latex'
#os.environ['PATH'] = os.environ['PATH'] + ':/usr/bin/tex'
plt.rcParams.update({
    "text.usetex": True,
})

script, filename = sys.argv
optimized_params = 5
fNom = np.zeros(optimized_params)+1
fNames = [r"{FP1-res}${}^{-1}$",r"{FP2-res}${}^{-1}$",r"{FP3-res}${}^{-1}$",r"MaxBeamWidth",r"BeamSpotSize"]
fNames = fNames[:optimized_params]
#print(len(fNames))
magnet_dim = 19
objectives = ['FP1_res','FP2_res','FP3_res','MaxBeamWidth','DSSD_BeamSpot']
fNom1 = np.array([2384.9360856494263, 109.61548781662407, 510.8029152516118, 1.6251646888022029, 0.12574090408565933])

# read pop from h5 file (i.e. after running view_db.py)
def read_pop_df(filename, pop=None):
    df = pd.read_hdf(filename)
    magnet_dim = 19
    p_optimizeRes = pg.problem(optimizeRes(magnet_dim))
    nobj = p_optimizeRes.get_nobj()
    if pop == None:
        pop = pg.population(p_optimizeRes)
    nrow, ncol = df.shape
    for i in df.index:
        append=True
        xs = []
        for j in range(1,magnet_dim+1):
            xs.append(df["q"+str(j)][i])
        xs = np.asarray(xs)
        fs = []
        for j in range(magnet_dim,magnet_dim+nobj):
#            if i == 0:
#                print(df.iloc[i,magnet_dim:magnet_dim+p_optimizeRes.get_nobj()])
            fs.append(df.iloc[i,j])
        if append:
            pop.push_back(xs,f=fs)
    if 'PCA' in filename:
        costs = df[objectives]
        costs = np.array(costs)
        pareto = is_pareto_efficient_simple(costs)
        # add pareto column to df
        df['pareto'] = pareto
        # restrict df to only those points on the pareto front
        df = (df.loc[(df['pareto']==True)])
        df = df.reset_index(drop=True)
        df = df.drop(columns=['kcluster','closest'])
        df = run_kmeans(df, magnet_dim, 4)
    return pop, df

# read in pop from csv output file
def read_pop(filename,pop=None):
    # get magnet dimensions
    magnet_dim = len(pd.read_csv(filename).columns)-optimized_params
    # init problem for creating pop
    p_optimizeRes = pg.problem(optimizeRes(magnet_dim))
    obj_dim = p_optimizeRes.get_nobj()
    quads = []
    # construct columns to read from csv
    for i in range(magnet_dim):
        quads.append("x{}".format(i))
    columns = quads
    for i in range(obj_dim):
        columns.append("f{}".format(i))
    # read df from csv
    df = pd.read_csv(filename,names=columns)
    # initialize pop if none
    if pop == None:
        pop = pg.population(p_optimizeRes)

    # construct pop from df
    nrow, ncol = df.shape
    for i in df.index:
        xs = []
        for j in range(magnet_dim):
            xs.append(df["x"+str(j)][i])
        xs = np.asarray(xs)
        fs = []
        for j in range(ncol-magnet_dim):
            # if not a valid obj value throw out point
            if df["f"+str(j)][i] < 0 or np.isnan(df["f"+str(j)][i]):
                print("error: ", df["f"+str(j)][i], i)
                df["f"+str(j)][i] = 1e10
            fs.append(df["f"+str(j)][i])
        # add point to population
        pop.push_back(xs,f=fs)
    # return population to main()
    return pop

# 2d functions are not updated, this one was for creating pngs for a movie of the evolution
#   movie made from pngs using ffmpeg
def plot_2d_evo(popi):

    magnet_dim = len(popi.get_x()[0])
    ndf, dl, dc, ndl = pg.fast_non_dominated_sorting(popi.get_f())
    print(pg.sort_population_mo(popi.get_f()))
    ndf_champ = []
#    for j in range(2,200):
    print(pg.ideal(popi.get_f())[0])
    x = np.linspace(pg.ideal(popi.get_f())[0],0)
    y = np.zeros(50)+(1)
    for j in range(2,100):
        plt.cla()
        plt.plot(x,y,linestyle="dashed",color="red")
        print(ndf[0])
        ndf_champ.append([popi.get_f()[i] for i in ndf[j]])
#        ax = pg.plot_non_dominated_fronts(ndf_champ[0],comp=[0,j])
#    ax.plot(color="C{}".format(j))
        ax = pg.plot_non_dominated_fronts(popi.get_f()[0:j])
        ax.set_xlabel('resolution')
        ax.set_ylabel('xangle_e_min')
        ax.set_ylim(1e-3,1000)
        ax.set_yscale('log')
#    print(ndf_champ, ndf[0])
#    print(ndf)
        plt.savefig("popi{}".format(j))
    return

# outdated
def output_2d_cosy(popi,filename):

    hv = pg.hypervolume(popi)
    ref_point = hv.refpoint()
    best_point = (popi.get_f()[hv.greatest_contributor(ref_point)])
    ndf, dl, dc, ndl = pg.fast_non_dominated_sorting(popi.get_f())
    magnet_dim = len(popi.get_x()[0])
    ndf_champ = []
    sorted_ndf = []
    sort_param = 3
    for i in ndf[0]:
        if i == ndf[0][0]:
            sorted_ndf.append(i)
        else:
            for j in range(len(sorted_ndf)):
                if j == len(sorted_ndf)-1:
                    sorted_ndf.append(i)
                    break
                elif j == 0 and popi.get_f()[i][sort_param] < popi.get_f()[sorted_ndf[j]][sort_param]:
                    sorted_ndf.insert(j,i)
                    break
                elif (popi.get_f()[i][sort_param] < popi.get_f()[sorted_ndf[j]][sort_param]) and j>0:
                    if(popi.get_f()[i][sort_param] >= popi.get_f()[sorted_ndf[j-1]][sort_param]):
#                        print(popi.get_f()[i][0],popi.get_f()[sorted_ndf[j]][0],popi.get_f()[sorted_ndf[j-1]][0])
                        sorted_ndf.insert(j,i)
                    break
    print(ndf[0], sorted_ndf)

    for i in range(len(sorted_ndf)):
        j = sorted_ndf[i]
        write_fox(np.power(np.zeros(magnet_dim)+2,popi.get_x()[j]), i, "2f_FP3/")
    return

# write cosy draw files from the best points
def output_4d_cosy(popi,filename,df):

    hv = pg.hypervolume(popi)
    ref_point = hv.refpoint()
    ref_point = np.zeros(optimized_params)+1e10
    best_point = (popi.get_f()[hv.greatest_contributor(ref_point)])
    ndf, dl, dc, ndl = pg.fast_non_dominated_sorting(popi.get_f())
    magnet_dim = len(popi.get_x()[0])
    ndf_champ = []
    sorted_ndf = []
    sorted_pop = []
    sorted_xs = []
    sort_param = 4
    for i in ndf[0]:
        if np.all(np.array(popi.get_f()[i]) < 1) == True or True:
#            print(popi.get_f()[i])
            ndf_champ.append(i)
    ndf = [ndf_champ]
    for i in ndf[0]:
#        print(i)
        go_next = False
        if len(sorted_ndf) > 1:
            for j in range(len(sorted_ndf)):
#                print( j, sorted_ndf)
                if np.array_equal(popi.get_f()[i],sorted_pop[j]) and np.array_equal(popi.get_x()[i],sorted_xs[j]):
                    go_next=True
                    break
        if go_next:
            continue
        if i == ndf[0][0]:
            sorted_ndf.append(i)
            sorted_pop.append(popi.get_f()[i])
            sorted_xs.append(popi.get_x()[i])
        else:
            for j in range(len(sorted_ndf)):
                if j == len(sorted_ndf)-1:
                    sorted_ndf.append(i)
                    sorted_pop.append(popi.get_f()[i])
                    sorted_xs.append(popi.get_x()[i])
                    break
                elif j == 0 and popi.get_f()[i][sort_param] < popi.get_f()[sorted_ndf[j]][sort_param]:
                    sorted_ndf.insert(j,i)
                    sorted_pop.insert(j,popi.get_f()[i])
                    sorted_xs.insert(j,popi.get_x()[i])
                    break
                elif (popi.get_f()[i][sort_param] < popi.get_f()[sorted_ndf[j]][sort_param]) and j>0:
                    if(popi.get_f()[i][sort_param] >= popi.get_f()[sorted_ndf[j-1]][sort_param]):
#                        print(popi.get_f()[i][0],popi.get_f()[sorted_ndf[j]][0],popi.get_f()[sorted_ndf[j-1]][0])
                        sorted_ndf.insert(j,i)
                        sorted_pop.insert(j,popi.get_f()[i])
                        sorted_xs.insert(j,popi.get_x()[i])
                    break
#    print(ndf[0], sorted_ndf)

    df_closest = df.loc[df['closest']==True]
    print(df_closest, len(ndf[0]), len(sorted_ndf))
    results_path = os.path.split(filename)[0]
    PROFILES_PATH = results_path+'/profiles/'
    if os.path.exists(PROFILES_PATH) and os.path.isdir(PROFILES_PATH):
        files_in_dir = os.listdir(PROFILES_PATH)     # get list of files in the directory
        for file in files_in_dir:                  # loop to delete each file in folder
            os.remove(f'{PROFILES_PATH}/{file}')
        shutil.rmtree(PROFILES_PATH)
    os.mkdir(PROFILES_PATH)
    qNew = np.array([1.0371301857113335,1.4897519431921593,0.5402003843384104,0.6080163749223835,0.5965351874518491,0.5279178522813484,0.8474952322221544,0.8290931192132953,0.7350223112146984,0.5049139345530922,0.969681779928563 ,0.8465270119223961,0.7261232553654523,0.6805787940919176,0.6772214286022437,1.6737045402403927,1.3151418622198896,0.8914897696929639,0.6144362243855045])
    qNew = np.zeros(19)+1
#    qNew = np.array([0.82281,0.83116,0.94706,0.75348,0.64679,1.23591,2.51027,0.80262,0.8017,2.70642,1.20897,0.62487,0.38632,1.11944,0.86569,1.19812,1.64921,1.13609,0.28077])
    write_fox((qNew), 0, PROFILES_PATH, 'SECAR_an_Optics_draw.fox' )
    write_fox((qNew), str(0)+"_DE", PROFILES_PATH, 'SECAR_an_Optics_DE_draw.fox' )
#    write_fox((qNew), str(0)+"_DE_FP1", PROFILES_PATH, 'SEC_neutrons_WF_off_DE_rays_v1_draw_FP1.fox' )
    count_dups = 0
#    for i in range(1,len(sorted_ndf)+1):
#    print(df_closest,df_closest.index)
    plot_i = 1
    for i in df_closest.index:
        i = i + 1
        j = sorted_ndf[i-1]
#        print(popi.get_f()[j])
#        if i > 1:
#            for k in range(i-1):
#                if np.array_equal(sorted_pop[i-1],sorted_pop[k]):
#                    count_dups += 1
#                    break
#        write_fox(np.power(np.zeros(magnet_dim)+2,popi.get_x()[j]), plot_i, PROFILES_PATH, 'SECAR_an_Optics_draw.fox')
#        write_fox(np.power(np.zeros(magnet_dim)+2,popi.get_x()[j]), str(plot_i)+"_DE", PROFILES_PATH, 'SECAR_an_Optics_DE_draw.fox')
        write_fox(popi.get_x()[j], plot_i, PROFILES_PATH, 'SECAR_an_Optics_draw.fox')
        write_fox(popi.get_x()[j], str(plot_i)+"_DE", PROFILES_PATH, 'SECAR_an_Optics_DE_draw.fox')
#        write_fox(np.power(np.zeros(magnet_dim)+2,popi.get_x()[j]), str(plot_i)+"_DE_FP1", PROFILES_PATH, 'SEC_neutrons_WF_off_DE_rays_v1_draw_FP1.fox')
        plot_i += 1
#    print(len(sorted_ndf), count_dups)
    return

def plot_4d(popi,filename,df):

    sort_param = 4
    good_results=0
    magnet_dim = len(popi.get_x()[0])
#    hv = pg.hypervolume(popi)
#    ref_point = np.zeros(optimized_params)+1e10
    ndf, dl, dc, ndl = pg.fast_non_dominated_sorting(popi.get_f())
    plot_x, plot_y = 0,0
    fig, axs = plt.subplots(optimized_params-1,sharex=True)
    fig.suptitle('Pareto Fronts of each parameter vs. BeamSpotSize at FP4')
    axs[optimized_params-2].set_xlabel(fNames[sort_param])
    reduced_ndf = []
    first = True
    df_closest = df
    cmap = matplotlib.colors.ListedColormap(matplotlib.cm.get_cmap("Pastel1").colors[:3])

    for j in range(0,optimized_params-1):
        ndf_champ = []
        axs[plot_y].axvline(x=fNom1[sort_param],linestyle="dashed",color="red")
        axs[plot_y].axhline(y=fNom1[j],linestyle="dashed",color="red")
        for i in ndf[0]:
            check_val=1e9
            if np.all(np.array(popi.get_f()[i]) < check_val) == True:
                good_results+=1
#                print(filename[-6:-4], good_results, popi.get_f()[i])
                transform_f = popi.get_f()[i]
                for k in range(len(transform_f)):
                    if k < 3:
                        transform_f[k] = fNom1[k] / transform_f[k]
                    else:
                        transform_f[k] = transform_f[k] * fNom1[k]
                ndf_champ.append(transform_f)
                reduced_ndf.append(i)
        try:
            pg.plot_non_dominated_fronts(ndf_champ,comp=[sort_param,j],axes=axs[plot_y])
#            if j == 1:
#                print(filename[-6:-4], len(ndf_champ))
        except:
            print(filename[-6:-4], "no better than nominal solutions")
            return
        if "closest" in df.columns:
            df_closest = df.loc[df['closest']==True]
            df_closest = df_closest.reset_index(drop=True)
#            print(df_closest.iloc[:,15:19])
#            for i_closest in df_closest.index:
#                axs[plot_y].text(df_closest.iloc[:,magnet_dim+sort_param][i_closest],df_closest.iloc[:,magnet_dim+j][i_closest],str(i_closest+1),color='red')
        axs[plot_y].set_ylabel(fNames[j])
#        axs[plot_y].set_yscale('log')
#        print(axs[plot_y].get_xlim(),axs[plot_y].get_ylim())
#        max_y = max(abs(np.log10(axs[plot_y].get_ylim())))
        ndf_champ_array = np.array(ndf_champ)
        max_lim = max(abs(ndf_champ_array[:,j].min()-fNom1[j]),abs(ndf_champ_array[:,j].max()-fNom1[j]))
        axs[plot_y].set_ylim(ndf_champ_array[:,j].min()-max_lim,ndf_champ_array[:,j].max()+max_lim)
#        axs[plot_y].set_xscale('log')
#        max_x = max(abs(np.log10(axs[plot_y].get_xlim())))
        max_lim = max(abs(ndf_champ_array[:,sort_param].min()-fNom1[sort_param]),abs(ndf_champ_array[:,sort_param].max()-fNom1[sort_param]))
        axs[plot_y].set_xlim(ndf_champ_array[:,sort_param].min()-max_lim,ndf_champ_array[:,sort_param].max()+max_lim)
#        axs[plot_y].set_xlim(np.power(10,-max_x),np.power(10,max_x))
#        print(math.ceil(max(axs[plot_y].get_ylim())),math.ceil(max(axs[plot_y].get_ylim())))
#        colors = np.zeros((int(math.ceil(max(axs[plot_y].get_ylim()))),int(math.ceil(max(axs[plot_y].get_xlim()))))) + 1
#        for colori in range(1,colors.shape[0]):
#            for colorj in range(1, colors.shape[1]):
#                colors[colori,colorj] = 0
#        colors[0,0] = 2
##        print(colors)
#        axs[plot_y].pcolormesh(colors, cmap=cmap)
        plot_y += 1

    fig.tight_layout()
    fig.savefig(filename+"_paretos_inverse.png")
    plt.cla()
    fig2, axs2 = plt.subplots(5,4)
    plot_x, plot_y = 0,0
    reduced_qs = np.array(popi.get_x())[reduced_ndf]
    ycolumns = []
    for i in range(magnet_dim):
        ycolumns.append('y{}'.format(i))
    df = pd.DataFrame(reduced_qs, columns = ycolumns)
    qNom = np.zeros(magnet_dim)
    write_qnames = ['q1','q2','q3','q4','q5','q6','q7','q8','q9','q10','q11','q12','q13','q14','q15','h1','h2','h3','o1']
    for i in range(magnet_dim):
        if plot_x > 3:
            plot_x, plot_y = 0, plot_y+1
        axs2[plot_y,plot_x] = df['y{0}'.format(i)].plot.hist(ax=axs2[plot_y,plot_x],bins=100,range=(-3,3))
#        axs2[plot_y,plot_x].axvline( x = qNom[i], ymin=0,ymax=20,color='red',linestyle='dashed')
#        axs[plot_y,plot_x].axvline( x = max_y[i], ymin=0,ymax=20,color='green',linestyle='dashed')
        axs2[plot_y,plot_x].axes.yaxis.set_visible(False)
#        axs2[plot_y,plot_x].axes.set_yscale("log")
#        axs2[plot_y,plot_x].axes.set_ylim(0.1,20)
        xlower, xupper = popi.problem.get_bounds()
        xlower, xupper = np.min(xlower), np.max(xupper)
        axs2[plot_y,plot_x].axes.set_xlim(xlower,xupper)
        axs2[plot_y,plot_x].set_title("{0}".format(write_qnames[i]))
        y_min, y_max = axs2[plot_y,plot_x].get_ylim()
        df_closest['yplot'] = pd.Series(df_closest.index).apply(lambda x: x/len(df_closest.index)*(y_max-y_min)+y_min)
#        print(df_closest.iloc[:,:15])
#        if "closest" in df.columns:
        for i_closest in df_closest.index:
            axs2[plot_y,plot_x].text(df_closest["q{0}".format(i+1)][i_closest],df_closest['yplot'][i_closest],str(i_closest+1),color='red')

        plot_x += 1

    axs2[plot_y,plot_x].axis('off')
    axs2[plot_y,plot_x].text(0.3, 0.5, 'x-axis is in log2', horizontalalignment='center', verticalalignment='center', transform=axs2[plot_y,plot_x].transAxes)
    fig2.tight_layout()
#    plt.savefig(filename + "_magnet_hists.png")
    return

def plot_hists(df, df_reduce, filename):

    write_qnames = {'q1':'q1','q2':'q2','q3':'q3','q4':'q4','q5':'q5','q6':'q6','q7':'q7','q8':'q8','q9':'q9','q10':'q10','q11':'q11','q12':'q12','q13':'q13','q14':'q14','q15':'q15','q16':'h1','q17':'h2','q18':'h3','q19':'o1'}
    df = df.iloc[:,:19]
    df_reduce = df_reduce.iloc[:,:19]
    df = df.rename(columns=write_qnames)
#    fig = plt.figure(1)
    fig, axs = plt.subplots(5,4)
    print(axs)
    fig.delaxes(axs[4][3])
    axs = (fig.axes)
    bins = np.linspace(-3,3,100)
    bins = np.logspace(-3,3,100,base=2.0)
    hists = df.hist(bins=bins,log=True,ax=axs,grid=False)
#    print(hists[0].bins)
#    fig.yscale('log')
    fig.tight_layout()
    fig.set_figheight(10)
    fig.set_figwidth(19)
#    ax = plt.gca()
#    print(ax.get_ylim())
    axs2 = axs
    for i in range(len(axs)):
#    for j in range(len(axs[i])):
        print(axs[i].get_ylim())
        axs[i].set_ylim([100,50000])
        axs[i].set_ylabel('all points')
        if i != 9:
#            axs[i].set_xlim([-2,2])
            axs[i].set_xlim([0.25,4])
        else:
#            axs[i].set_xlim([-3,3])
            axs[i].set_xlim([0.125,8])
        axs2[i] = axs[i].twinx()
        axs2[i].set_ylim([1,1000])
        axs2[i].set_ylabel('optimized points',rotation=-90)
    hist = df_reduce.hist(bins=bins,log=True,ax=axs2,color='red',grid=False)
    for i in range(len(axs)):
        axs2[i].set_title("")

    print(hist)
    plt.savefig(filename+'_full_hist.png')

    return

def main(filename):

    file_extension = os.path.splitext(filename)[-1]
    print(os.path.split(filename))
    popi = None
    print("reading {} file".format(file_extension))
    df = None
    if file_extension == ".h5":
        popi, df = read_pop_df(filename)
#        output_4d_cosy(popi, filename, df)
    else:
        popi = read_pop(filename)
#    print(df)
    plot_4d(popi,filename,df)

if __name__=='__main__':
    main(filename)


from ..errors import AngrExitError
from . import ExplorationTechnique

import logging

l = logging.getLogger(name=__name__)

class Slicecutor(ExplorationTechnique):
    """
    The Slicecutor is an exploration that executes provided code slices.
    """

    def __init__(self, annotated_cfg, force_taking_exit=False, force_sat: bool = False):
        """
        All parameters except `annotated_cfg` are optional.

        :param annotated_cfg:       The AnnotatedCFG that provides the code slice.
        :param force_taking_exit:   Set to True if you want to create a successor based on our slice in case of
                                    unconstrained successors.
        :param force_sat:           If a branch specified by the slice is unsatisfiable, set this option to True if you
                                    want to force it to be satisfiable and be taken anyway.
        """
        super().__init__()

        self._annotated_cfg = annotated_cfg
        self._force_taking_exit = force_taking_exit
        self._force_sat = force_sat

    def setup(self, simgr):
        for stash in ("cut", "mysteries"):
            simgr.populate(stash, [])

    def filter(self, simgr, state, **kwargs):
        l.debug("Checking state %s for filtering...", state)
        return simgr.filter(state, **kwargs)

    def step_state(self, simgr, state, **kwargs):
        l.debug("%s ticking state %s at address %#x.", self, state, state.addr)
        stashes = simgr.step_state(state, **kwargs)

        new_active = []
        new_cut = []
        new_mystery = []

        # SimulationManager returns new active states in the None stash by default.
        flat_successors = stashes.get(None, None)
        if flat_successors is None:
            # Did the user explicitly put them into the 'active' stash instead?
            flat_successors = stashes.pop("active", [])

        for successor in flat_successors:
            l.debug("... checking exit to %#x from %#x.", successor.addr, state.addr)

            try:
                taken = self._annotated_cfg.should_take_exit(state.addr, successor.addr)
            except AngrExitError:  # TODO: which exception?
                l.debug("... annotated CFG did not know about it!")
                new_mystery.append(successor)
            else:
                if taken:
                    l.debug("... taking the exit.")
                    new_active.append(successor)
                    # the else case isn't here, because the state should set errored in this
                    # case and we'll catch it below
                else:
                    l.debug("... not taking the exit.")
                    new_cut.append(successor)

        unconstrained_successors = stashes.get("unconstrained", [])
        if not new_active and unconstrained_successors and self._force_taking_exit:
            stashes["unconstrained"] = []
            # somehow there is no feasible state. We are forced to create a successor based on our slice
            if len(unconstrained_successors) != 1:
                raise Exception("This should absolutely never happen, what?")
            for target in self._annotated_cfg.get_targets(state.addr):
                successor = unconstrained_successors[0].copy()
                successor.regs._ip = target
                new_active.append(successor)
            l.debug("Got unconstrained: %d new states are created based on AnnotatedCFG.", len(new_active))

        unsat_successors = stashes.get("unsat", None)
        if not new_active and unsat_successors and self._force_sat:
            stashes["unsat"] = []
            # find the state
            targets = self._annotated_cfg.get_targets(state.addr)
            if targets is None:
                targets = []
            for target in targets:
                try:
                    suc = next(iter(u for u in unsat_successors if u.addr == target))
                except StopIteration:
                    continue

                # drop all constraints
                if suc.mode == "fastpath":
                    # dropping constraints and making the state satisfiable again under fastpath mode is easy
                    suc.solver._solver.constraints = []
                    suc._satisfiable = True
                    new_active.append(suc)
                    l.debug("Forced unsat at %#x to be sat again.", suc.addr)
                else:
                    # with multiple possible solver frontends, dropping states in other state modes is not
                    # straightforward. I'll leave it to the next person who uses this feature
                    l.warning("force_sat is not implemented for solver mode %s.", suc.moe)

        stashes[None] = new_active
        stashes["mystery"] = new_mystery
        stashes["cut"] = new_cut
        return stashes

    def successors(self, simgr, state, **kwargs):
        kwargs["whitelist"] = self._annotated_cfg.get_whitelisted_statements(state.addr)
        kwargs["last_stmt"] = self._annotated_cfg.get_last_statement_index(state.addr)
        return simgr.successors(state, **kwargs)


import time
import unittest
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

from src.home_work.part_2_automation.pages.button_page import Button
from src.home_work.part_2_automation.pages.checkbox_page import CheckBox
from src.home_work.part_2_automation.pages.datepicker_page import DatePicker
from src.home_work.part_2_automation.pages.drag_drop_page import DragAndDrop
from src.home_work.part_2_automation.pages.drop_down_page import DropDown
from src.home_work.part_2_automation.pages.enables_disabled_page import EnabledDisabled
from src.home_work.part_2_automation.pages.file_upload_page import FileUpload
from src.home_work.part_2_automation.pages.home_page import HomePage
from src.home_work.part_2_automation.pages.scroll_page import Scroll

class Test(unittest.TestCase):
    def setUp(self) -> None:
        self._driver = webdriver.Chrome(ChromeDriverManager().install())

    def test_1(self):
        self._driver.get('https://formy-project.herokuapp.com/')
        main_page = HomePage(self._driver)
        return main_page

    def test_drag_and_drop(self):
        self._driver.get('https://formy-project.herokuapp.com/dragdrop')
        test = DragAndDrop(self._driver)
        test.drag_and_drop()

    def test_input_text(self):
        main_page = self.test_1()
        main_page.go_to_enb_and_disab_elem()
        test = EnabledDisabled(self._driver)
        test.enter_text('this is enabled text box')

    def test_upload_file(self):
        main_page = self.test_1()
        main_page.go_to_file_upload()
        test = FileUpload(self._driver)
        test.upload_file("C:\\Users\\Moldoveanu\\Pictures\\ASUS.png")
        time.sleep(5)
        test.upload_reset()

    def test_scroll_page(self):
        main_page = self.test_1()
        main_page.go_to_page_scroll()
        test = Scroll(self._driver)
        test.scroll_page()

    def tearDown(self) -> None:
        time.sleep(2)
        self._driver.quit()