import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import sys
import psycopg2
from psycopg2.extensions import AsIs
from datetime import timedelta
sys.path.append('/home/mike/dsi/capstones/climbing_gym_checkins_eda')

def parse_datetime(df, col='index', hour=True, dow=True, date=True, week=True, month=True, season=True, year=True):

        if col == 'index':
            datetime_col = df.reset_index().iloc[:, 0]
        else:
            datetime_col = df.reset_index()[col]

        datetime_col.index = df.index

        parsed_cols = []
        parsed_col_names = []

        if hour:
            parsed_cols.append(datetime_col.dt.hour)
            parsed_col_names.append('hour')

        if dow:
            parsed_cols.append(datetime_col.dt.dayofweek)
            parsed_col_names.append('dow')

        if date:
            parsed_cols.append(datetime_col.dt.date)
            parsed_col_names.append('date')

        if date:
            parsed_cols.append(datetime_col.dt.week)
            parsed_col_names.append('week')

        if month:
            parsed_cols.append(datetime_col.dt.month)
            parsed_col_names.append('month')

        if season:
            seasons_col = datetime_col.apply(find_season)
            parsed_cols.append(seasons_col)
            parsed_col_names.append('season')

        if year:
            parsed_cols.append(datetime_col.dt.year)
            parsed_col_names.append('year')

        df_parsed = pd.concat(parsed_cols, axis=1)

        df_parsed.columns = parsed_col_names

        df_merged = pd.concat([df, df_parsed], axis=1)

        df_merged.index = datetime_col

        return df_merged

def conditions_dict(df, dt_col='index', hour=True, dow=True, date=True, week=True, month=True, season=True, year=True):

    if dt_col == 'index':
        datetime_col = df.reset_index().iloc[:, 0].dt
        season = False
    elif dt_col == 'parsed':
        datetime_col = df
    else:
        datetime_col = pd.to_datetime(df[dt_col]).dt

    cond_dict = {}

    if hour:

        hour_cond = {}
        hours = range(0, 24)

        for hour in hours:
            hour_cond[hour] = (datetime_col.hour == hour).values

        cond_dict.update({'hour':hour_cond})

    if dow:

        dow_cond = {}
        dow = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']

        for i, day in enumerate(dow):
            if dt_col == 'parsed':
                dow_cond[day] = (datetime_col.dow == i).values
            # elif dt_col == 'index':
            else:
                dow_cond[day] = (datetime_col.dayofweek == i).values

        cond_dict.update({'dow':dow_cond})

    if date:

        date_cond = {}
        dates = np.unique(datetime_col.date)

        for date in dates:
            date_cond[date] = (datetime_col.date == date).values

        cond_dict.update({'date':date_cond})

    if week:

        week_cond = {}
        weeks = range(53)

        for week in weeks:
            week_cond[week] = (datetime_col.week == week).values

        cond_dict.update({'week':week_cond})

    if month:

        month_cond = {}
        months = range(1, 13)

        for month in months:
            month_cond[month] = (datetime_col.month == month).values

        cond_dict.update({'month':month_cond})

    if season:

        season_cond = {}
        seasons = range(0, 4)

        for season in seasons:
            seasons_col=datetime_col.season

        for season in seasons:
            season_cond[season] = (seasons_col == season).values

        cond_dict.update({'season':season_cond})

    if year:

        year_cond = {}
        years = np.unique(datetime_col.year)

        for year in years:
            year_cond[year] = (datetime_col.year == year).values

        cond_dict.update({'year':year_cond})

    return cond_dict

def resample(df, freq, func, as_period=False):

    gb_df_res = df.resample(freq)

    if func == 'interpoloate':
        df_res = gb_df_res.interpolate().dropna()
    if isinstance(func, dict):
        df_res = gb_df_res.agg(func).dropna()
    else:
        df_res = gb_df_res.apply(func).dropna()

    if isinstance(df_res, pd.DataFrame):
        if 'tot_checkins' in df_res.columns:

            tot_counts_zero = df_res.iloc[:,0] == 0
            df_res = df_res[~tot_counts_zero]

    if as_period:

        df_res.index = df_res.index.to_period(freq)

    return df_res

def find_season(ts):

        m = ts.month
        season_sets = {
                0:{3, 4, 5},    #Spring
                1:{6, 7, 8},    #Summer
                2:{9, 10, 11},  #Fall
                3:{12, 1, 2}}   #Winter

        for season, season_set in season_sets.items():
            if m in season_set:
                return season

def get_freq(df):

    time_diff = pd.to_timedelta(df.index[1] - df.index[0])

    if time_diff < timedelta(hours = 2):
        return 'H'

    if time_diff < timedelta(hours=30):
        return 'D'

    if time_diff < timedelta(days=8):
        return 'W'

    if time_diff < timedelta(days=35):
        return 'M'

    if time_diff < timedelta(days=100):
        return 'Q'

    if time_diff < timedelta(weeks=55):
        return 'Y'

    raise ValueError('Could not determine frequency')

if __name__ == '__main__':

    # Test funcs
    gol_sql = SqlExec('eng')
    df_ch1 = gol_sql.checkins()
    df_us1 = gol_sql.users()
    df_co1 = gol_sql.hour_counts()
    df_w1 = gol_sql.weather()

    print('executed')

    df_ch2 = gol_sql.checkins()
    df_us2 = gol_sql.users()
    df_co2 = gol_sql.hour_counts()
    df_w2 = gol_sql.weather()

    print('recall')

    print('checkins parsed')
    print(df_ch2.iloc[0])
    print('checkins not parsed')
    print(gol_sql.checkins(update=True, parse_datetime=False).iloc[0])
    print('users')
    print(df_us2.iloc[0])
    print('counts')
    print(df_co2.iloc[0])
    print('weather')
    print(df_w2.iloc[0])

    print(conditions_dict(df_ch1)['dow']['thu'][:10])
    print(df_ch1.dow.iloc[:10])


#!/usr/bin/env python
# Designed for use with boofuzz v0.0.8
import sys

from boofuzz import *

if len(sys.argv) < 3:
    sys.exit(-1)
s_initialize("query")
if s_block_start("header"):
    s_word(123, name="id")
    s_byte(1)
    s_byte(0)
    s_byte(0)
    s_byte(1)
    s_word(0, name="AnCount", endian=">")
    s_word(0, name="NsCount", endian=">")
    s_word(0, name="ArCount", endian=">")
s_block_end()

if s_block_start("question"):
    if s_block_start("qname"):
        s_byte(6)
        s_static("google")
        s_byte(3)
        s_static("com")
        s_byte(0)
    s_block_end()
    s_word(0x00ff, endian=">")
    s_word(0x0001, endian=">")
s_block_end()

sess = Session(target=Target(connection=SocketConnection(sys.argv[1], int(sys.argv[2]), proto='tcp')))
sess.connect(s_get("query"))

sess.fuzz()


# 병합정렬

def merge_sort(list1):
    # 종료조건
    if len(list1) <= 1:
        return list1

    # 분해작업
    mid = len(list1) // 2  # 중간 값 구하기
    g1 = list1[:mid]  # 재귀호출로 첫 번째 그룹 g1 = [6, 8, 3, 9, 10] => g1[6, 8] & g2[3, 9, 10]
    g2 = list1[mid:]

    merge_sort(g1)
    merge_sort(g2)

    # 병합
    i1, i2, ia = 0, 0, 0

    while i1 < len(g1) and i2 < len(g2):
        if g1[i1] > g2[i2]:
            list1[ia] = g1[i1]
            i1 += 1
            ia += 1
        else:
            list1[ia] = g2[i2]
            i2 += 1
            ia += 1

    # 남아 있는 자료 결과에 추가
    while i1 < len(g1):
        list1[ia] = g1[i1]
        i1 += 1
        ia += 1
    while i2 < len(g2):
        list1[ia] = g2[i2]
        i2 += 1
        ia += 1
    return list

if __name__ == "__main__":
    list1 = [6, 8, 3, 9, 10, 1, 2, 4, 7, 5]
    print(merge_sort(list1))


"""
Flask Documentation:     http://flask.pocoo.org/docs/
Jinja2 Documentation:    http://jinja.pocoo.org/2/documentation/
Werkzeug Documentation:  http://werkzeug.pocoo.org/documentation/
This file creates your application.
"""

import os
from werkzeug.utils import secure_filename
from app import app, db
from flask import render_template, request, redirect, url_for, flash
from app.forms import ProfileForm
from app.models import UserProfile
import datetime

###
# Routing for your application.
###

@app.route('/')
def home():
    """Render website's home page."""
    return render_template('home.html')

@app.route('/about/')
def about():
    """Render the website's about page."""
    return render_template('about.html')

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTS']

@app.route('/profile',methods = ["GET","POST"])
def profile():
    """Render the website's profile page"""
    form   = ProfileForm()
    user_no = len(UserProfile.query.all())

    if request.method == "POST" and form.validate_on_submit():

        first_name = form.first_name.data
        last_name  = form.last_name.data
        gender     = form.gender.data
        location   = form.location.data
        email      = form.email.data
        bio        = form.biography.data
        date       = datetime.datetime.now()
        image      = form.image.data
        imageName  = first_name + last_name + str(user_no) + ".png"

        # file = form.upload.data
        # filename = secure_filename(file.filename)
        # file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename))

        new_user = UserProfile( first_name = first_name,
                                last_name  = last_name,
                                gender     = gender,
                                location   = location,
                                email      = email,
                                biography  = bio,
                                created_on = date,
                                profilePic = imageName)
        db.session.add(new_user)
        db.session.commit()

        image.save(os.path.join(app.config['UPLOAD_FOLDER'],imageName))

        # image.save("app/static/profilepictures/" + imageName + ".png")

        flash("New User Profile Created", "success")
        return redirect(url_for("profiles"))

    return render_template("profile.html",form=form)

@app.route('/profile/<userid>')
def userProfile(userid):
    """Display individual user profile given the userid"""
    user = UserProfile.query.filter_by(userid = userid).first()
    return render_template('userprofile.html',user = user, date= user.created_on.strftime("%B %d, %Y"))

@app.route('/profiles')
def profiles():
    """Render the website's list of profiles"""
    users = UserProfile.query.all()
    return render_template("profiles.html", users = users)

###
# The functions below should be applicable to all Flask apps.
###

@app.route('/<file_name>.txt')
def send_text_file(file_name):
    """Send your static text file."""
    file_dot_text = file_name + '.txt'
    return app.send_static_file(file_dot_text)

@app.after_request
def add_header(response):
    """
    Add headers to both force latest IE rendering engine or Chrome Frame,
    and also to cache the rendered page for 10 minutes.
    """
    response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
    response.headers['Cache-Control'] = 'public, max-age=0'
    return response

@app.errorhandler(404)
def page_not_found(error):
    """Custom 404 page."""
    return render_template('404.html'), 404

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


from PySide2.QtCore import Qt
from PySide2.QtWidgets import QWidget, QMainWindow, QLabel, QApplication, QDockWidget, QPushButton, QGridLayout, \
    QVBoxLayout, QTabWidget, QInputDialog
from PySide2.QtGui import QIcon
from gui.EditMenu import EditMenu
from gui.HelpMenu import HelpMenu
from gui.ViewMenu import ViewMenu
from gui.FileMenu import FileMenu
from gui.MyToolbar import MyToolbar
from view.tree.HierarchyTreeModel import HierarchyTreeModel
from view.tree.HierarchyTreeView import HierarchyTreeView
from model.Book import Book
from model.Chapter import Chapter
from model.Page import Page

class MainWindow(QMainWindow):
    """
    Gui komponenta MainWindow
    """

    def __init__(self):
        """
        Konstruktor
        """
        super(MainWindow, self).__init__()
        self.init_toolbar()
        self.init_menu_bar()
        self.init_tree_main_widget()
        self.setFixedHeight(800)
        self.setFixedWidth(1000)
        self.setWindowIcon(QIcon("src/MuMijA_mainmenu.png"))
        self.statusBarLabel = QLabel("StatusBar")
        self.statusBar().addWidget(self.statusBarLabel, 1)

    def init_tree_main_widget(self):
        """
        Inicijalizuje layout main window-a, layout strane, tree, tabove, dugmadi i labele
        """
        self.tabs = QTabWidget()
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.closeMyTab)
        leftDock = QDockWidget()
        leftDock.setFixedWidth(250)
        leftDock.setWidget(self.tabs)
        leftDock.setAllowedAreas(Qt.LeftDockWidgetArea)
        leftDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        layout=QGridLayout()
        self.page = QVBoxLayout()
        self.central = QWidget()
        self.central.setFixedSize(730, 700)
        self.central.setLayout(self.page)
        self.central.setStyleSheet("background-color:white")
        self.LeftButton = QPushButton()
        self.PageLabel=QLabel()
        self.PageLabel.setAlignment(Qt.AlignCenter)
        self.PageLabel.setText("Nema trenutno otvorene strane")
        self.RightButton = QPushButton()
        self.LeftButton.setFixedSize(30, 30)
        self.RightButton.setFixedSize(30, 30)
        self.LeftButton.setIcon(QIcon("src/lbutton.png"))
        self.RightButton.setIcon(QIcon("src/rbutton.png"))
        layout.addWidget(self.central,0,0,1,5)
        layout.addWidget(self.LeftButton, 1, 1, 2, 1)
        layout.addWidget(self.PageLabel,1,2,2,1)
        layout.addWidget(self.RightButton, 1, 3, 2, 1)
        tmpWidget=QWidget()
        tmpWidget.setLayout(layout)
        self.setCentralWidget(tmpWidget)
        self.addDockWidget(Qt.LeftDockWidgetArea, leftDock)

    def init_toolbar(self):
        """
        Inicijalizuje toolbar
        """
        self.addToolBar(Qt.TopToolBarArea, MyToolbar(self))

    def init_menu_bar(self):
        """
        Inicijalizuje menu bar
        """
        self.menuBar().addMenu(FileMenu())
        self.menuBar().addMenu(EditMenu())
        self.menuBar().addMenu(ViewMenu())
        self.menuBar().addMenu(HelpMenu())

    def newTab(self, root):
        """
        Inicijalizuje novi tab

        Return:
             Objekat book
        """
        if len(root.getChildren()) == 0:
            newName, ok = QInputDialog.getText(None, "New Chapter name", "Enter desired first chapter name")
            if not ok or newName == "":
                while not ok or newName == "":
                    newName, ok = QInputDialog.getText(None, "New Chapter name", "Enter desired first chapter name")
            root.addChild(Chapter(newName))
        book = Book(root.getName())
        book.setPath(root.getPath())
        book.setParent(QApplication.instance().model)
        rootModel = HierarchyTreeModel(book)
        rootView = HierarchyTreeView(rootModel)
        for chapter in root.getChildren():
            tmpChapter = Chapter(chapter.getName())
            book.addChild(tmpChapter)
            for page in chapter.getChildren():
                tmpPage = Page(page.getName())
                tmpChapter.addChild(tmpPage)
                for element in page.getChildren():
                    element.setParent(tmpPage)
                    tmpPage.addChild(element)
        self.tabs.addTab(rootView, root.getName())
        self.LeftButton.clicked.connect(rootView.leftButtonPressed)
        self.RightButton.clicked.connect(rootView.rightButtonPressed)
        rootView.SelectRoot()
        return book

    def closeMyTab(self, index):
        """
        Omogucava zatvaranje tab-a
        """
        child = self.tabs.widget(index).model().getRoot()
        child.getParent().removeChild(child.getIndex())
        self.tabs.removeTab(index)


from flask import Blueprint, session, render_template, flash, make_response, \
    url_for
from werkzeug.utils import redirect
from flask import request
from dataengine.common.log import logger
from dataengine.server.routes.annotations import requires_auth
from dataengine.server.routes.validator.user_metric import (
    validate_user_metric_form
)
from dataengine.service.db.user_metric import get_user_metrics, put_user_metric

user_metric_bp = Blueprint('user_metric', __name__, url_prefix='/user/metric')

@user_metric_bp.route('/')
@requires_auth
def index():
    profile = session['profile']
    user_metrics = get_user_metrics(profile['user_id'])

    return render_template(
        'user_metric/index.html',
        user_profile=profile,
        user_metrics=user_metrics,
    )

@user_metric_bp.route('/', methods=["POST"])
@requires_auth
def new():
    profile = session['profile']
    try:
        validate_user_metric_form(request.form)
        put_user_metric(profile['user_id'], request.form)
        flash(f"ðŸ‘Œ Event was recorded", 'success')
    except Exception as e:
        logger.error(f'Failed to write to database due to error {e}')
        flash('Failed to record event due to error', 'error')

    return make_response(redirect(url_for('user_metric.index')))


# 중복된 결과 값을 stack에 저장해서 실행속도를 줄이는 방법
# 피보나치 실행시간을 줄이기가 목적

def fibo(n):
    if n<=2: return 1
    return fibo(n-1)+fibo(n-2)
print(fibo(35))

memo =[0,1,1]+[0]*100

def fibo_memo(n):
    if n<=2: return 1
    if memo[n]:return memo[n]

    memo[n]= fibo_memo(n-1)+fibo_memo(n-2)
    return memo[n]
print(fibo(35))


from bson import ObjectId
from flask_restplus import abort, marshal

from rest.entities.templates.models import entity_template_response
from rest.entities.models import set_bson_object
from rest.common.constants import ENTITY_TEMPLATE_COLLECTION, ID
from rest.common.constants import META, IS_DELETED, UPDATED, INTERNAL_SERVER_ERROR, \
    ENTITY_NOT_FOUND, ENTITY_ALREADY_EXISTS, ENTITY_TYPE, ENTITY_TYPE_DETAILS
from rest.utils.dateutils import get_current_time
from rest.utils.db_service import Base
from rest.entities.service import EntityService

ASSET_SERVICE = EntityService()

class EntityTemplateService(Base):
    """
    AssetTemplate Type Service
    """

    def create_entity_template(self, req_data, entity_type_obj):
        """
        create templates
        :param req_data:
        :param entity_type_obj:
        :return: created entity template
        """
        _count, _entity_template = self.get(ENTITY_TEMPLATE_COLLECTION,
                                            {f"{META}.{IS_DELETED}": False,
                                             ENTITY_TYPE: entity_type_obj.get('name')})

        if _count == 1 and _entity_template:
            abort(ENTITY_ALREADY_EXISTS, message="Asset template already exists with given name.",
                  status=ENTITY_ALREADY_EXISTS)

        req_data[ENTITY_TYPE] = entity_type_obj.get('name')
        req_data[ENTITY_TYPE_DETAILS] = entity_type_obj
        _result, _id = self.create(ENTITY_TEMPLATE_COLLECTION, req_data)

        if _result:
            req_data = set_bson_object(req_data, ID, _id)
            return marshal(req_data, entity_template_response)
        else:
            abort(INTERNAL_SERVER_ERROR,
                  message='Error in inserting records to {} collection'.format(ENTITY_TEMPLATE_COLLECTION),
                  status=INTERNAL_SERVER_ERROR)

    def get_all_entity_templates(self):
        """
        get all templates
        :return: list templates by entity
        """
        _count, _entity_templates = self.get(ENTITY_TEMPLATE_COLLECTION, {f"{META}.{IS_DELETED}": False})
        return {'records': marshal(_entity_templates, entity_template_response), 'count': _count}

    def get_all_entity_templates_by_entity(self, entity_type):
        """
        list all entity templates by entity
        :param entity_type:
        :return:
        """
        _count, _entity_templates = self.get(ENTITY_TEMPLATE_COLLECTION,
                                             {f"{META}.{IS_DELETED}": False, ENTITY_TYPE: entity_type})
        return {'records': marshal(_entity_templates, entity_template_response), 'count': _count}

    def get_entity_template_by_id(self, entity_type, entity_template_id):
        """
        get templates by _id
        :param entity_type
        :param entity_template_id:
        :return:
        """
        _count, _entity_template = self.get(ENTITY_TEMPLATE_COLLECTION, {f"{META}.{IS_DELETED}": False,
                                                                         ENTITY_TYPE: entity_type,
                                                                         ID: ObjectId(entity_template_id)})
        if _count == 1 and _entity_template:
            return marshal(_entity_template[0], entity_template_response)
        else:
            abort(ENTITY_NOT_FOUND, message="Asset templates with ID {} does not exists.".format(entity_template_id),
                  status=ENTITY_NOT_FOUND)

    def get_entity_template_by_entity_type(self, entity_type, raise_error=True):
        """
        get templates by _id
        :param entity_type
        :return:
        """
        _count, _entity_template = self.get(ENTITY_TEMPLATE_COLLECTION, {f"{META}.{IS_DELETED}": False,
                                                                         ENTITY_TYPE: entity_type})
        if _count == 1 and _entity_template:
            return marshal(_entity_template[0], entity_template_response)
        elif raise_error:
            abort(ENTITY_NOT_FOUND, message="Asset templates for entity type {} does not exists.".format(entity_type),
                  status=ENTITY_NOT_FOUND)
        else:
            return None

    def update_entity_template(self, req_data, entity_template_id):
        """
        update templates
        :param req_data:
        :param entity_template_id:
        :return:
        """
        _entity_template = self.get_entity_template_by_id(req_data.get('entity_type'), entity_template_id)
        if _entity_template:

            if not req_data.get('force'):
                # check if user is removing the field which already having some value for any entity.
                self.validate_field_updates(req_data.get('entity_type'), _entity_template.get('fields'),
                                            req_data.get('fields'))

            req_data[META] = _entity_template[META]
            req_data[META][UPDATED] = get_current_time()
            self.update(ENTITY_TEMPLATE_COLLECTION,
                        query={f"{META}.{IS_DELETED}": False, ID: ObjectId(entity_template_id)},
                        updated_record=req_data)

            # TODO : remove fields from all entity fields too

        else:
            abort(ENTITY_NOT_FOUND,
                  message="Asset templates with id {} doesn't exists to update".format(entity_template_id),
                  status=ENTITY_NOT_FOUND)

        return self.get_entity_template_by_id(req_data.get('entity_type'), entity_template_id)

    def validate_field_updates(self, entity_type, original_fields, fields_to_be_updated):
        """
        Check or Cross verify fields to be removed from templates.
        :param entity_type:
        :param original_fields:
        :param fields_to_be_updated
        :return:
        """
        updated_keys = self.diff_lists(original_fields, fields_to_be_updated)
        for key in updated_keys:
            # filter entities
            _filtered_entitys = ASSET_SERVICE.filter_entitys({f"fields.{key}": {'$exists': True, '$ne': ''}},
                                                             entity_type)
            if _filtered_entitys.get('count') > 0:
                abort(INTERNAL_SERVER_ERROR, message=f"Fields trying to remove is already used in \
                entitys : {[i.get('name') for i in _filtered_entitys.get('records')]}", status=INTERNAL_SERVER_ERROR)

    def diff_lists(self, li1, li2):
        """
        diff of two lists
        :param li1:
        :param li2:
        :return:
        """
        li_dif = list({dict2['key'] for dict2 in li1} - {dict1['key'] for dict1 in li2})
        return li_dif

    def delete_entity_template(self, entity_template_id):
        """
        delete templates by _id
        :param entity_template_id:
        :return:
        """
        self.update(ENTITY_TEMPLATE_COLLECTION, query={ID: ObjectId(entity_template_id)},
                    update_query={"$set": {f"{META}.{IS_DELETED}": True}})


# coding=utf-8
"""

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""

import logging
import logging.config
import os
import time

clevel_default = logging.ERROR
flevel_default = logging.INFO

standard_format = (
    '[%(asctime)s %(levelname)s %(process)d] - [%(filename)s:%(lineno)d] '
    + '%(module)s.%(funcName)s.%(lineno)d: %(message)s'
)
simple_format = '[%(asctime)s %(levelname)s] %(message)s'

class Logger(object):
    def __init__(self, logfile='', clevel=clevel_default, flevel=flevel_default):
        # init file name
        self.log_path = os.getcwd() + '/logs/'
        if not logfile:
            self.rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
            self.logfile = self.log_path + self.rq + '.log'
        else:
            self.logfile = self.log_path + logfile
        logging_dict = {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'standard': {'format': standard_format},
                'simple': {'format': simple_format},
            },
            'filters': {},
            'handlers': {
                'console': {
                    'level': clevel,
                    'class': 'logging.StreamHandler',
                    'formatter': 'simple',
                },
                'default': {
                    'level': flevel,
                    'formatter': 'simple',
                    'filename': self.logfile,
                    'class': 'logging.handlers.TimedRotatingFileHandler',
                    'when': 'D',
                    'interval': 1,
                    'backupCount': 3,
                    'encoding': 'utf-8',
                },
            },
            'loggers': {
                '': {
                    'handlers': ['default', 'console'],
                    'level': flevel_default,
                    'propagate': False,
                },
            },
        }
        logging.config.dictConfig(logging_dict)
        self.logger = logging.getLogger()

    def debug(self, message):
        self.logger.debug(message)

    def info(self, message):
        self.logger.info(message)

    def warn(self, message):
        self.logger.warning(message)

    def error(self, message):
        self.logger.error(message)

    def critical(self, message):
        self.logger.critical(message)

    def exception(self, message):
        self.logger.exception(message)


#----ANIMAL FAVORITO---#
class Animal ():
    def __init__(self,caracteristica1,tamaño,caracteristica2):
        self.raza = 'pastor aleman'
        self.caracteristica= caracteristica1
        self.estaturaa= tamaño
        self.otracaracteristica= caracteristica2

    def atributos (self):
        print(f'''hola mi nombre es santiago y te hablare de algunos atributos sobre
        mi raza de perro favorita el {self.raza},
        1) primero {self.caracteristica}
        2) la estatura promedio es {self.estaturaa} centimetros
        3) {self.otracaracteristica}
        ''')

    def Correr (self, distancia, tiempo):
        for i in range (distancia):
            print(f''' mi raza de perro favorita es capaz de correr largas distancias
            en estos momentos se encuentra corriendo y lleva recorrido {i+1} metros
            en {i+1} segundos
            ''')

pastorAleman= Animal ('son muy obedientes y nobles ', 62 ,'y por ultimo es muy usado en la labor de inteligencia policial')

print(pastorAleman.caracteristica)
print(pastorAleman.estaturaa)
print(pastorAleman.otracaracteristica)

pastorAleman.atributos()
pastorAleman.Correr(20,10)


import pyposeidon.meteo as pmeteo
import pytest
import pandas as pd
import xarray as xr
import os
import numpy as np
import shutil

from . import DATA_DIR

METEO_NC = DATA_DIR / "meteo.nc"
ERA5_GRIB = DATA_DIR / "era5.grib"
DATASET = xr.Dataset(data_vars=dict(lat=(("node", [1, 2, 3]))))

def test_dispatch_meteo_source_unknown_object_raises():
    obj = 3
    with pytest.raises(ValueError) as exc:
        pmeteo.dispatch_meteo_source(obj=3)
    assert "Can't determine meteo_type" in str(exc)

def test_dispatch_meteo_source_unknown_string_raises():
    obj = "gibberish"
    with pytest.raises(ValueError) as exc:
        pmeteo.dispatch_meteo_source(obj=obj)
    assert f"Can't determine meteo_type from string: {obj}" in str(exc)

def test_dispatch_meteo_source_multiple_types_raises():
    obj = ["asdf", 123]
    with pytest.raises(ValueError) as exc:
        pmeteo.dispatch_meteo_source(obj=obj)
    assert "Multiple types in iterable:" in str(exc)

@pytest.mark.parametrize(
    "expected_func, meteo_source",
    [
        pytest.param(pmeteo.netcdf, METEO_NC, id="netcdf pathlib single"),
        pytest.param(pmeteo.netcdf, METEO_NC.as_posix(), id="netcdf str single"),
        pytest.param(pmeteo.netcdf, [METEO_NC], id="netcdf list pathlib"),
        pytest.param(pmeteo.netcdf, [METEO_NC.as_posix()], id="netcdf list str"),
        pytest.param(pmeteo.cfgrib, ERA5_GRIB, id="grib pathlib single"),
        pytest.param(pmeteo.cfgrib, ERA5_GRIB.as_posix(), id="grib str single"),
        pytest.param(pmeteo.cfgrib, [ERA5_GRIB], id="grib list pathlib"),
        pytest.param(pmeteo.cfgrib, [ERA5_GRIB.as_posix()], id="grib list str"),
        pytest.param(pmeteo.from_url, "https://example.com", id="https url"),
        pytest.param(pmeteo.from_url, "http://example.com", id="http url"),
        pytest.param(pmeteo.passthrough, DATASET, id="passthrough"),
    ],
)
def test_meteo_dispatch_netcdf(expected_func, meteo_source):
    func = pmeteo.dispatch_meteo_source(meteo_source)
    assert func is expected_func

@pytest.mark.parametrize(
    "meteo_source",
    [
        pytest.param(METEO_NC, id="netcdf"),
        pytest.param(ERA5_GRIB, id="grib"),
        pytest.param(DATASET, id="passthrough"),
    ],
)
def test_meteo_returns_dataset(meteo_source):
    meteo = pmeteo.Meteo(meteo_source)
    assert isinstance(meteo, pmeteo.Meteo)
    assert isinstance(meteo.Dataset, xr.Dataset)

def test_meteo_passthrough():
    original_meteo = pmeteo.Meteo(DATASET)
    new_meteo = pmeteo.Meteo(meteo_source=original_meteo.Dataset)
    assert new_meteo.Dataset.equals(original_meteo.Dataset)

@pytest.mark.slow
def test_meteo_url():
    geometry = {
        "lon_min": -25.0,  # lat/lon window
        "lon_max": -9.0,
        "lat_min": 56.0,
        "lat_max": 74.0,
    }
    cdate = pd.to_datetime("today") - pd.DateOffset(days=1)  # step back one day for availability.
    r = [0, 6, 12, 18]
    h = np.argmin([n for n in [cdate.hour - x for x in r] if n > 0])
    url = "https://nomads.ncep.noaa.gov/dods/gfs_0p25_1hr/gfs{}/gfs_0p25_1hr_{:0>2d}z".format(
        cdate.strftime("%Y%m%d"), r[h]
    )
    meteo = pmeteo.Meteo(meteo_source=url, **geometry)
    assert isinstance(meteo.Dataset, xr.Dataset)

def test_meteo_empty():
    meteo = pmeteo.Meteo(meteo_source=None)
    assert meteo.Dataset == None

def test_meteo_defaults():
    meteo = pmeteo.Meteo()
    assert meteo.Dataset == None


import random
import math
from sympy import isprime, mod_inverse
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin

app = Flask(__name__)

CORS(app, support_credentials=True, resources={r'/make_key': {'origins': '*'}})

@app.route("/make_key", methods=['GET'])
@cross_origin()
def make_key():

    def generate_random_prime(min_value, max_value):
        p = random.randint(min_value, max_value)
        while not isprime(p):
            p += 1
        return p

    p = generate_random_prime(2, 1024)
    q = generate_random_prime(1031, 2**20)

    n = p * q

    p1q1 = (p - 1) * (q - 1)

    def generate_coprime(p1q1):
        e = random.randint(2, p1q1)

        if math.gcd(e, p1q1) ==1:
            return e

        return generate_coprime(p1q1)

    e = generate_coprime(p1q1)

    def solve_congruence(e, p1q1):

        d = mod_inverse(e, p1q1) * 1 % p1q1

        return d

    d = solve_congruence(e, p1q1)

    publicKey = str(e) + ", " + str(n)
    privateKey = str(d) + ", " + str(n)

    finalmsg = 'Your Public Key is: '+publicKey+'. Your Private Key is: '+privateKey+"."
    finalmsg = jsonify(finalmsg)

    return finalmsg

@app.route("/encrypt", methods=['POST'])
@cross_origin()
def encrypt():
    data = request.get_json()
    pkey = data['values']['publicKey']
    m = data['values']['message']
    temp_pkey = pkey.split()
    e = int(temp_pkey[0])
    n = int(temp_pkey[1])
    final = encrypt_handler(m, e, n)
    final = jsonify(final)
    return final

def encrypt_handler(m, e, n):

    temp_arr = m.split()
    arr = [eval(i) for i in temp_arr]
    for  j in range(len(arr)):
        raised = arr[j] ** e
        arr[j] = raised % n
    encrypted = ' '.join(str(k) for k in arr)
    return encrypted

@app.route("/decrypt", methods=['POST'])
@cross_origin()
def decrypt():

    data = request.get_json()
    pkey = data['values']['privateKey']
    c = data['values']['message']
    temp_pkey = pkey.split()
    d = int(temp_pkey[0])
    n = int(temp_pkey[1])
    final = decrypt_handler(c, d, n)
    final = jsonify(final)
    return final

def decrypt_handler(c, d, n):

    temp_arr = c.split()
    arr = [eval(i) for i in temp_arr]
    for  j in range(len(arr)):
        raised = arr[j] ** d
        arr[j] = raised % n
    decrypted = ' '.join(str(k) for k in arr)
    return decrypted

@app.route("/textASCII", methods=['POST'])
@cross_origin()
def textASCII():

    data = request.get_json()
    temp_msg = data['values']
    msg = temp_msg.get('message')
    print(msg)
    temp_asciichar = []
    for c in msg:
        temp_asciichar.append(c)
    print(temp_asciichar)
    first_temp_asciichar = [ord(h) for h in temp_asciichar]
    asciichar = ' '.join(str(k) for k in first_temp_asciichar)
    asciichar = jsonify(asciichar)
    return asciichar

@app.route("/ASCIItext", methods=['POST'])
@cross_origin()
def ASCIItext():

    data = request.get_json()
    temp_msg = data['values']
    msg = temp_msg.get('message')
    msg = msg.split()
    print(msg)
    temp_textchar = []
    for c in msg:
        try:
            temp_textchar.append(int(c))
        except ValueError:
            pass
    print(temp_textchar)
    first_temp_textchar = [chr(h) for h in temp_textchar]
    textchar = ''.join(first_temp_textchar)
    textchar = jsonify(textchar)
    return textchar

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


import matplotlib
import re
import os
import sys
import shutil

# get config file path

config_file = matplotlib.matplotlib_fname()

# move wenquanyi open source TTF font file in

if sys.platform == 'win32':
    ttf_font_path = config_file.replace('\\matplotlibrc', '\\fonts\\ttf')
else:
    ttf_font_path = config_file.replace('/matplotlibrc', '/fonts/ttf')

shutil.copy2("wenquanyi-micro-hei.ttf", ttf_font_path)

# clear fontlist

import glob

try:

    dot_matplotlib_path = os.path.expanduser("~/.matplotlib")

    fontlist_files = glob.glob(dot_matplotlib_path+"/fontList*")

    for file in fontlist_files:
        os.remove(file)

    print("Please restart the kernel in Jupyter Notebook and rerun plot command. Enjoy Chinese Display!")

except:

    print('Can not delete font list files in ~/.matplotlib')


import sys
sys.stdin = open('input_7562.txt', 'r')

def BFS(row, col):
    queue = []
    dx = [-2, -1, +1, +2, +2, +1, -1, -2]
    dy = [+1, +2, +2, +1, -1, -2, -2, -1]
    queue.append([row, col])
    visited[row][col] = True
    move_cnt = 0
    while True:
        temp_list = []
        move_cnt += 1
        while len(queue) != 0:
            element = queue.pop(0)
            for idx in range(8):
                new_row, new_col = element[0] + dx[idx], element[1] + dy[idx]
                if 0 <= new_row < I and 0 <= new_col < I:
                    if not visited[new_row][new_col]:
                        if new_row == goal[0] and new_col == goal[1]:
                            return move_cnt
                        else:
                            visited[new_row][new_col] = True
                            temp_list.append([new_row, new_col])
        for temp in temp_list:
            queue.append(temp)

for _ in range(int(input())):
    I = int(input())
    start = list(map(int, input().split()))
    goal = list(map(int, input().split()))
    visited = [[False] * I for _ in range(I)]
    if start == goal:
        print(0)
    else:
        print(BFS(start[0], start[1]))


#########################################################
# Holds value and weights for types of recycling
# value: represents the value of each 1 unit of recycling
# amount:_weighted is a value that can be used as a
#           multiplying to the amount donated to weigh
#                       it as needed
#########################################################

POINTS = {
    "Mixed Recycling" : {
        "value" : 5,
        "amount_weighted" : 1,

    } ,
    "Aluminium Cans" : {
        "value" : 4,
        "amount_weighted" : 1
    } ,
    "Sorted Recycling" : {
        "value" : 3,
        "amount_weighted" : 1
    } ,
}
# UNITS TO DIVIDE BY
UNITS ={
    "Number of Objects" : 2,
    "Weight(lbs)": 1,
    "Money" : 1,
    "":1,

}

#########################################################
# FUNCTION TO CALCULATE NUMBER OF POINTS
# takes in:
#       type-- string representation of type of drop off
#       amount -- integer representing amount donated
# returns: integer value representing the amount of points
#            OR returns an error reporting the type is not
#                                       reconginzed
##########################################################
def score_calculator(type, amount, unit):

    try:
       return POINTS[type]['value'] * (( amount * POINTS[type]['amount_weighted'])/UNITS[unit])
    except:
       print(("%s is not a reconginzed type of recycling or %s is not a reconginzed type of unit" % (type, unit) ))
       return ("%s is not a reconginzed type of recycling or %s is not a reconginzed type of unit" % (type, unit) )


# coding: utf-8
# This is the deepseg_gm model definition for the
# Spinal Cord Gray Matter Segmentation.
#
# Reference paper:
#     Perone, C. S., Calabrese, E., & Cohen-Adad, J. (2017).
#     Spinal cord gray matter segmentation using deep dilated convolutions.
#     URL: https://arxiv.org/abs/1710.01269

import keras.backend as K
from keras.models import Model
from keras.layers import Input
from keras.layers import Conv2D, Dropout
from keras.layers import RepeatVector, Reshape
from keras.layers import BatchNormalization
from keras.layers import concatenate, GlobalAveragePooling2D
from keras.optimizers import Adam

# Models
# Tuple of (model, metadata)
MODELS = {
    'challenge': ('challenge_model.hdf5', 'challenge_model.json'),
    'large': ('large_model.hdf5', 'large_model.json'),
}

def dice_coef(y_true, y_pred):
    """Dice coefficient specification

    :param y_true: ground truth.
    :param y_pred: predictions.
    """
    dice_smooth_factor = 1.0
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    return (2. * intersection + dice_smooth_factor) / \
           (K.sum(y_true_f) + K.sum(y_pred_f) + dice_smooth_factor)

def dice_coef_loss(y_true, y_pred):
    """Dice loss specification.

    :param y_true: ground truth.
    :param y_pred: predictions.
    """
    return -dice_coef(y_true, y_pred)

def create_model(nfilters, input_size=(200, 200)):
    """Create the ASPP model.

    :param nfilters: number of filters at each block.
    :param input_size: the network input size (H, W)
    """
    drop_rate_concat = 0.4
    drop_rate_hidden = 0.4
    bn_momentum = 0.1

    input_height, input_width = input_size

    inputs = Input((input_height, input_width, 1))

    conv1 = Conv2D(nfilters, (3, 3), activation='relu', padding='same')(inputs)
    conv1 = BatchNormalization(momentum=bn_momentum)(conv1)
    conv1 = Dropout(drop_rate_hidden)(conv1)
    conv1 = Conv2D(nfilters, (3, 3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization(momentum=bn_momentum)(conv1)
    conv1 = Dropout(drop_rate_hidden)(conv1)

    # Rate 2
    conv3 = Conv2D(nfilters, (3, 3), dilation_rate=(2, 2), activation='relu',
                   padding='same', name="rate2_1")(conv1)
    conv3 = BatchNormalization(momentum=bn_momentum)(conv3)
    conv3 = Dropout(drop_rate_hidden)(conv3)
    conv3 = Conv2D(nfilters, (3, 3), dilation_rate=(2, 2), activation='relu',
                   padding='same', name="rate2_2")(conv3)
    conv3 = BatchNormalization(momentum=bn_momentum)(conv3)
    conv3 = Dropout(drop_rate_hidden)(conv3)

    # Branches for ASPP

    # Branch for 1x1
    conv3a = Conv2D(nfilters, (3, 3), activation='relu',
                    padding='same', name="branch1x1_1")(conv3)
    conv3a = BatchNormalization(momentum=bn_momentum)(conv3a)
    conv3a = Dropout(drop_rate_hidden)(conv3a)
    conv3a = Conv2D(nfilters, (1, 1), activation='relu',
                    padding='same', name="branch1x1_2")(conv3a)
    conv3a = BatchNormalization(momentum=bn_momentum)(conv3a)
    conv3a = Dropout(drop_rate_hidden)(conv3a)

    # Branch for 3x3 rate 6
    conv4 = Conv2D(nfilters, (3, 3), dilation_rate=(6, 6), activation='relu',
                   padding='same', name="rate6_1")(conv3)
    conv4 = BatchNormalization(momentum=bn_momentum)(conv4)
    conv4 = Dropout(drop_rate_hidden)(conv4)
    conv4 = Conv2D(nfilters, (3, 3), dilation_rate=(6, 6), activation='relu',
                   padding='same', name="rate6_2")(conv4)
    conv4 = BatchNormalization(momentum=bn_momentum)(conv4)
    conv4 = Dropout(drop_rate_hidden)(conv4)

    # Branch for 3x3 rate 12
    conv5 = Conv2D(nfilters, (3, 3), dilation_rate=(12, 12), activation='relu',
                   padding='same', name="rate12_1")(conv3)
    conv5 = BatchNormalization(momentum=bn_momentum)(conv5)
    conv5 = Dropout(drop_rate_hidden)(conv5)
    conv5 = Conv2D(nfilters, (3, 3), dilation_rate=(12, 12), activation='relu',
                   padding='same', name="rate12_2")(conv5)
    conv5 = BatchNormalization(momentum=bn_momentum)(conv5)
    conv5 = Dropout(drop_rate_hidden)(conv5)

    # Branch for 3x3 rate 18
    conv6 = Conv2D(nfilters, (3, 3), dilation_rate=(18, 18), activation='relu',
                   padding='same', name="rate18_1")(conv3)
    conv6 = BatchNormalization(momentum=bn_momentum)(conv6)
    conv6 = Dropout(drop_rate_hidden)(conv6)
    conv6 = Conv2D(nfilters, (3, 3), dilation_rate=(18, 18), activation='relu',
                   padding='same', name="rate18_2")(conv6)
    conv6 = BatchNormalization(momentum=bn_momentum)(conv6)
    conv6 = Dropout(drop_rate_hidden)(conv6)

    # Branch for 3x3 rate 24
    conv7 = Conv2D(nfilters, (3, 3), dilation_rate=(24, 24), activation='relu',
                   padding='same', name="rate24_1")(conv3)
    conv7 = BatchNormalization(momentum=bn_momentum)(conv7)
    conv7 = Dropout(drop_rate_hidden)(conv7)
    conv7 = Conv2D(nfilters, (3, 3), dilation_rate=(24, 24), activation='relu',
                   padding='same', name="rate24_2")(conv7)
    conv7 = BatchNormalization(momentum=bn_momentum)(conv7)
    conv7 = Dropout(drop_rate_hidden)(conv7)

    # Branch for the global context
    global_pool = GlobalAveragePooling2D()(conv1)
    global_pool = RepeatVector(input_height * input_width)(global_pool)
    global_pool = Reshape((input_height, input_width, nfilters))(global_pool)

    # Concatenation
    concat = concatenate([conv3a, conv4, conv5,
                          conv6, global_pool, conv7], axis=3)
    concat = BatchNormalization(momentum=bn_momentum)(concat)
    concat = Dropout(drop_rate_concat)(concat)

    amort = Conv2D(64, (1, 1), activation='relu',
                   padding='same', name="amort")(concat)
    amort = BatchNormalization(momentum=bn_momentum)(amort)
    amort = Dropout(drop_rate_hidden)(amort)

    predictions = Conv2D(1, (1, 1), activation='sigmoid',
                         padding='same', name="predictions")(amort)

    model = Model(inputs=[inputs], outputs=[predictions])

    opt = Adam(lr=0.001)
    model.compile(optimizer=opt,
                  loss=dice_coef_loss,
                  metrics=["accuracy"])

    return model


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def pathSum(self, root: TreeNode, total: int) -> List[List[int]]:
        if not root:
            return []
        res = [root]
        answer = []
        self.pathSumHelper(root, total, res, answer)
        return answer

    def pathSumHelper(self, node, total, res, answer):
        if node.left is None and node.right is None and self.checkSum(res) == total:
            answer.append([node.val for node in res])

        if node.left:
            res.append(node.left)
            self.pathSumHelper(node.left, total, res, answer)
            res.pop()

        if node.right:
            res.append(node.right)
            self.pathSumHelper(node.right, total, res, answer)
            res.pop()

    def checkSum(self, li):
        return sum(node.val for node in li)


#!/usr/bin/python3
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk
from .Labeler import Labeler
from .LabeledMultiWidget import LabeledMultiWidgetMixin
from .SuperWidget import SuperWidgetMixin
from typing import Callable

class ActiveOptionMenu(ttk.OptionMenu, SuperWidgetMixin):
    """ttk.OptionMenu with added features and SuperWidgetMixin"""

    def __init__(
        self,
        parent: ttk.Frame,
        options: list,
        default: int = 0,
        on_keystroke: bool = False,
        bind_enter: bool = True,
        bind_escape_clear: bool = True,
        command: Callable = None,
        widgetargs: dict = {},
    ):
        self.var = tk.StringVar(value=options[default])
        ttk.OptionMenu.__init__(self, parent, self.var, options[default], *options)
        SuperWidgetMixin.__init__(self, **widgetargs)
        self.options, self.default, self._command = options, default, command
        self.var.trace("w", self._on_execute_command)
        if on_keystroke:
            self.bind("<KeyRelease>", self._on_execute_command)
        if bind_enter:
            self.bind("<Return>", self._on_execute_command)
        if bind_escape_clear:
            self.bind("<Escape>", self.clear)

    def enable(self) -> None:
        """Enable OptionMenu. `Returns None`"""
        self["state"] = tk.NORMAL

    def disable(self) -> None:
        """Disable OptionMenu. `Returns None`"""
        self["state"] = tk.DISABLED

    def get(self) -> str:
        """Get OptionMenu value. `Returns a String`"""
        return self.var.get()

    def set(self, val) -> None:
        """Set OptionMenu value. `Returns None`"""
        self.var.set(val)

    def clear(self) -> None:
        """Sets OptionMenu to its default value. `Returns None`"""
        self.var.set(self.options[self.default])

    def _on_execute_command(self, *args, **kw) -> None:
        """Handles execution of provided command"""
        if self._command:
            self._command(self.get())

class LabeledOptionMenu(Labeler, ActiveOptionMenu):
    """Labeled ActiveOptionMenu"""

    def __init__(
        self,
        parent: ttk.Frame,
        labeltext: str,
        *args,
        is_child: bool = False,
        **kw,
    ):
        self.is_child = is_child
        Labeler.__init__(self, parent, labeltext, header=not is_child)
        ActiveOptionMenu.__init__(self, self.frame, *args, **kw)
        ActiveOptionMenu.pack(self, fill="x", expand=False, side=tk.TOP)

class LabeledMultiOptionMenu(LabeledMultiWidgetMixin):
    """Labeled MultiWidget LabeledOptionMenu"""

    def __init__(
        self,
        parent: ttk.Frame,
        labeltext: str,
        config: dict,
        is_child: bool = False,
        labelside: str = tk.TOP,
        **kw,
    ):
        LabeledMultiWidgetMixin.__init__(
            self,
            parent,
            labeltext,
            LabeledOptionMenu,
            config,
            is_child,
            labelside,
            **kw,
        )


# This file contains an attempt at actually putting the network trained in EncDec.py to practice
import keras
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Model, load_model
import pandas as pd
import pandas_ml as pdml
from matplotlib.widgets import Slider

def decode(onehot):
    return np.argmax(onehot)

SNR = 6
M = 64
C = 1
L = 5
graph = False
confusion = False
graph_pretty = True
# Generate random signal of length 32 with 64 possible values
siglength = 100000
sig = np.random.randint(0, M, siglength)

data = np.array(sig)
data = keras.utils.to_categorical(data, num_classes=M)
data = data.astype(int)
data = np.reshape(data, (data.shape[0], 1, 1, data.shape[1]))
# Load model and compile encoder and decoder portions
model = load_model('Trained/inputs_'+str(M)+'_L_'+str(L)+'_snr_20.h5')
x = keras.layers.Input(shape=(1,1,M))
encoder = Model(x, model.layers[2](model.layers[1](x)))
decoder = model.layers[3]
encoder.save_weights('encoder_weights.h5')
decoder.save_weights('decoder_weights.h5')
encoder.compile(optimizer='Adam', loss='categorical_crossentropy', metrics=['accuracy'])
decoder.compile(optimizer='Adam', loss='categorical_crossentropy', metrics=['accuracy'])
encoder.load_weights('encoder_weights.h5')
decoder.load_weights('decoder_weights.h5')
# Pass input through network and decode output (implement a LUT)
predicted = encoder.predict(data)
noise = np.random.normal(0, np.sqrt(C/(10**(SNR/10))), predicted.size)
noisysig = np.reshape(noise, predicted.shape)+predicted
encoded = decoder.predict(noisysig)
sig_hat = np.zeros(siglength)
for i in range(encoded.shape[0]):
    sig_hat[i] = decode(encoded[i])

# Check what kind of plot we want
if graph == True:
    if graph_pretty == False:
        SIG = sig
        SIG_HAT = sig_hat
        numpoints = siglength
    else:
        SIG = np.zeros(siglength*10-9)
        SIG[:] = np.nan
        for n in np.arange(0, siglength*10-9, 10):
            SIG[n] = (sig[int(n/10)]-M/2) * 5 / (M/2)
        SIG_HAT = np.zeros(siglength*10-9)
        SIG_HAT[:] = np.nan
        for n in np.arange(0, siglength*10-9, 10):
            SIG_HAT[n] = (sig_hat[int(n/10)]-M/2) * 5 / (M/2)
        numpoints = siglength*10-9
    # Plot both signals
    sigtoplot = pd.Series(SIG)
    sigtoplot.set_axis(np.linspace(0.0, 9.9, num=numpoints, endpoint=True), inplace=True)
    sigtoplot = sigtoplot.interpolate(method='cubic')
    sigtoplot.plot(linewidth=3, color='red')
    sigtoplot = pd.Series(SIG_HAT)
    sigtoplot.set_axis(np.linspace(0.0, 9.9, num=numpoints, endpoint=True), inplace=True)
    sigtoplot = sigtoplot.interpolate(method='cubic')
    sigtoplot.plot(linestyle='--', color='black')
    plt.title('Signal Comparison')
    plt.ylabel('Signal Voltage')
    plt.xlabel('Time (s)')
    plt.legend(['Input', 'Output'], loc='upper left')
    plt.show()

symbol_diff = 0
for n in np.arange(sig_hat.size):
    if (sig_hat[n] != sig[n]):
        symbol_diff += 1
SER = symbol_diff / siglength
print(SER)
print('\n\n'+str(100*(siglength-symbol_diff)/siglength)+'\n\n')

if confusion == True:
    confusion_matrix = pdml.ConfusionMatrix(sig, sig_hat)
    stats = confusion_matrix.stats()
    confusion_matrix.plot(normalized=True)
    plt.xticks([])
    plt.yticks([])
    plt.savefig('ForPub/Confusion_M'+str(M)+'_L'+str(L)+'_SNR'+str(SNR))
    plt.show()


# -*- coding: utf-8 -*-
"""metrics module
Define our metrics module that encapsulates attributes and methods related to
the metrics we use for our lunar anomalies project.
"""
import matplotlib.pyplot as plt
import numpy as np
from inspect import signature
from sklearn.metrics import average_precision_score, auc
from sklearn.metrics import precision_recall_curve, roc_curve
from sklearn.metrics import PrecisionRecallDisplay

class Curve:
    def __init__(
        self,
        y_test: [] = None,
        y_scores: [] = None,
        pos_label: int = None,
        feature_str: str = None,
        save_to_disk_fp: str = None,
    ):
        """Init method for our Curve class. This is intended to be the parent
        class for children classes like PrecisionRecallCurve and
        RecieverOperatorCharacteristicCurve.

        Args:
            y_test: the list of true labels
            y_scores: the list of model scores
            pos_label: the torch index to use as our positive class
            save_to_disk_fp: the string where to save the plot

        Returns:
            None

        """
        self.y_test = y_test
        self.y_scores = y_scores
        self.pos_label = pos_label
        self.feature_str = feature_str
        self.save_to_disk_fp = save_to_disk_fp

    def make_plot(
        self,
        show: bool = None,
        verbose: bool = False,
        plot_type: str = None,
    ):
        """Makes a Curve plot. This is intended to be overriden by Curve
        children classes like PrecisionRecallCurve or
        RecieverOperatingCharacteristicCurve.

        Args:
            show: Whether to show the plot on-scren via e.g. plt.show()
            verbose: Whether to enable verbose mode to print various
                information on screen.
            plot_type: String of plot type to use. Possible choices include
                "pr" and "roc".

        Returns:
           None
        """

        xlarge_fontsize = 24
        large_fontsize = 20
        medium_fontsize = 18

        if plot_type == "pr":
            self.x_axis_values = self.recalls
            self.y_axis_values = self.precisions
            self.x_axis_label = "Recall"
            self.y_axis_label = "Precision"
            self.plot_title = self.feature_str.title()

        elif plot_type == "roc":
            self.x_axis_values = self.fpr
            self.y_axis_values = self.tpr
            self.x_axis_label = "False Positive Rate"
            self.y_axis_label = "True Positive Rate"
            self.plot_title = f"ROC Curve. AUC={self.roc_auc:0.2f}"

        # Set plot title, labels.
        plt.title(self.plot_title, fontsize=xlarge_fontsize, fontweight="bold")
        plt.xlabel(self.x_axis_label, fontsize=large_fontsize, fontweight="bold")
        plt.ylabel(self.y_axis_label, fontsize=large_fontsize, fontweight="bold")

        # Set axes limits.
        plt.xlim([0.0, 1.0])
        if plot_type == "pr":
            plt.ylim([0.0, 1.05 * max(self.y_axis_values[:-2])])
        elif plot_type == "roc":
            plt.ylim([0.0, 1.05])
        # Hack for s3 ylim.
        if self.feature_str == "s3":
            plt.ylim([0.0, 5.0e-5])

        # Plot the curve.
        plt.plot(
            self.x_axis_values,
            self.y_axis_values,
            label="Model",
        )

        # Fill the area under the curve.
        plt.fill_between(
            self.x_axis_values,
            self.y_axis_values,
            alpha=0.2,
            color="b",
            interpolate=False,
        )

        # Horizontal line at the random baseline, if plot_type is "pr".
        if plot_type == "pr":
            plt.axhline(
                y=self.random_precision,
                color="#FF0000",
                linestyle="--",
                label="Random baseline",
            )

        # Show the AP versus random baseline improvement factor.
        plt.text(
            0.05,
            0.25,
            f"Improvement factor = {self.improvement_factor:0.2f}",
            fontsize=medium_fontsize,
            fontweight="bold",
            transform=plt.gca().transAxes,
        )

        # Show the AP.
        plt.text(
            0.05,
            0.15,
            f"Model average precision = {self.average_precision:0.2e}",
            fontsize=medium_fontsize,
            fontweight="normal",
            transform=plt.gca().transAxes,
        )

        # Show the random baseline.
        plt.text(
            0.05,
            0.05,
            f"Random baseline = {self.random_precision:0.2e}",
            fontsize=medium_fontsize,
            fontweight="normal",
            transform=plt.gca().transAxes,
        )

        # Make x, y axis labels, ticks bigger.
        plt.xlabel(self.x_axis_label, fontsize=large_fontsize, fontweight="bold")
        plt.ylabel(self.y_axis_label, fontsize=large_fontsize, fontweight="bold")
        plt.xticks(fontsize=large_fontsize)
        plt.yticks(fontsize=large_fontsize)

        # Make y axis have scientific notation.
        plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0))

        # Plot the legend, setting the order of the legend.
        handles, labels = plt.gca().get_legend_handles_labels()
        order = [0, 1]
        plt.legend(
            [handles[idx] for idx in order],
            [labels[idx] for idx in order],
            loc="upper right",
            fontsize=medium_fontsize,
        )

        # Save, show, close.
        if self.save_to_disk_fp is not None:
            plt.savefig(
                self.save_to_disk_fp,
                dpi=300,
                bbox_inches="tight",
            )
        if show:
            plt.show()
        plt.close()

class RecieverOperatingCharacteristicCurve(Curve):
    def __init__(
        self,
        y_test: [] = None,
        y_scores: [] = None,
        pos_label: int = None,
        drop_intermediate: bool = True,
        save_to_disk_fp: str = None,
    ):
        """Init method for the RecieverOperatingCharacteristicCurve class.
        Args:
            y_test: the list of true labels
            y_scores: the list of model scores
            pos_label: the torch index to use as our positive class
            save_to_disk_fp: the string where to save the plot

        Returns:
            None
        """
        super().__init__(
            y_test, y_scores, pos_label=pos_label, save_to_disk_fp=save_to_disk_fp
        )
        self.drop_intermediate = drop_intermediate
        self.fpr, self.tpr, self.thresholds = roc_curve(
            self.y_test,
            self.y_scores,
            pos_label=self.pos_label,
            drop_intermediate=self.drop_intermediate,
        )
        self.roc_auc = auc(self.fpr, self.tpr)

    def make_plot(
        self,
        show: bool = None,
        verbose: bool = False,
        plot_type: str = "roc",
    ):
        """Makes a reciever operating characteristic plot. This overrides Curve's
        implementaiton of this method.

        Args:
            show: Whether to show the plot on-scren via e.g. plt.show()
            verbose: Whether to enable verbose mode to print various
                information on screen.
            plot_type: String of plot type to use. Possible choices include
                "pr" and "roc".

        Returns:
           None
        """
        super().make_plot(show=show, verbose=verbose, plot_type=plot_type)

class PrecisionRecallCurve(Curve):
    def __init__(
        self,
        y_test: [] = None,
        y_scores: [] = None,
        pos_label: int = None,
        feature_str: str = None,
        save_to_disk_fp: str = None,
    ):
        """Init method for our PrecisionRecallCurve class.

        Args:
            y_test: the list of true labels
            y_scores: the list of model scores
            pos_label: the torch index to use as our positive class
            save_to_disk_fp: the string where to save our PR curve

        Returns:
            None
        """
        super().__init__(
            y_test,
            y_scores,
            pos_label=pos_label,
            feature_str=feature_str,
            save_to_disk_fp=save_to_disk_fp,
        )

        self.precisions, self.recalls, self.thresholds = precision_recall_curve(
            y_test, y_scores, pos_label=self.pos_label
        )
        self.average_precision = average_precision_score(
            y_test, y_scores, pos_label=self.pos_label
        )
        self.dataset_size = len(y_scores)
        self.count_positives = np.count_nonzero(y_test)
        if pos_label == 0:
            self.count_positives = self.dataset_size - self.count_positives
        self.random_precision = float(self.count_positives / self.dataset_size)
        self.improvement_factor = float(self.average_precision / self.random_precision)

    def make_plot(
        self,
        show: bool = None,
        verbose: bool = False,
        plot_type: str = "pr",
    ):
        """Makes a precision recall curve plot. This overrides Curve's
        implementaiton of this method.

        Args:
            show: Whether to show the plot on-scren via e.g. plt.show()
            verbose: Whether to enable verbose mode to print various
                information on screen.
            plot_type: String of plot type to use. Possible choices include
                "pr" and "roc".

        Returns:
           None
        """
        super().make_plot(show=show, verbose=verbose, plot_type=plot_type)