from selenium import webdriver
from bs4 import BeautifulSoup
import requests
import re
import json

def scrapping_data(DL_no, DOB):
    options = webdriver.ChromeOptions()
    options.add_argument('headless')

    driver = webdriver.Chrome(
        '/home/ahaloans/Documents/AhaLoans/Production/Selenium/DrivingLicenseSarathi/Selenium-Google-Takeout/chromedriver',
        options=options)
    driver.set_window_size(1024, 600)
    driver.maximize_window()
    driver.delete_all_cookies()
    print("Working")

    try:
        driver.get('https://sarathi.nic.in:8443/nrportal/sarathi/DlDetRequest.jsp')
        # driver.find_element_by_id('dlform:DLNumber').send_keys('Up8720140002671')
        # driver.find_element_by_id('dlform:dob').send_keys('06/07/1989')

        driver.find_element_by_id('dlform:DLNumber').send_keys('Up6320140016332')
        driver.find_element_by_id('dlform:dob').send_keys('20/07/1994')

        # driver.find_element_by_id('dlform:DLNumber').send_keys(DL_no)
        # driver.find_element_by_id('dlform:dob').send_keys(DOB)

        driver.find_element_by_id('dlform:sub').click()
        html = driver.page_source
        soup = BeautifulSoup(html)

        result = dict()
        result_inner = dict()

        form_fetch = soup.find_all('table')
        ### Driving Licence Details
        ##Details of Driving Licence

        row_fetch = form_fetch[1].find_all('tr')
        data_fetch = row_fetch[0].get_text()
        data = data_fetch.split('\n')[1].split(':')
        result_inner[data[0]] = data[1]
        title = data[0]

        ## Status

        row_fetch = form_fetch[2].find_all('tr')
        data_fetch = row_fetch[0].get_text()
        data = data_fetch.split('\n')
        result_inner[data[2][:-2]] = data[3]

        ## Last Transacted
        row_fetch = form_fetch[3].find_all('td')
        array_text = []
        for data in row_fetch:
            array_text.append(data.get_text())
        result_inner[array_text[0][1:-2]] = array_text[1]
        result_inner[array_text[2][1:-2]] = array_text[3]

        row_fetch = form_fetch[4].find_all('td')
        result_inner[row_fetch[0].get_text()[1:-2]] = row_fetch[1].get_text()
        result[title] = result_inner

        ### DL Validity
        title = 'DL Validity'
        result_inner = dict()
        result_inner_text = dict()
        row_fetch = form_fetch[5].find_all('td')
        array_text = []
        array_text = row_fetch[0].get_text()
        array_text = array_text.split('\n')[4:-21]
        # array_text = filter(bool, array_text) # fastest

        result_inner_text[array_text[2][:-2]] = array_text[3]
        result_inner_text[array_text[5][:-2]] = array_text[6]
        result_inner[array_text[0][:-2]] = result_inner_text

        result_inner_text = dict()
        result_inner_text[array_text[12][:-2]] = array_text[13]
        result_inner_text[array_text[15][:-2]] = array_text[16]
        result_inner[array_text[10][:-1]] = result_inner_text

        result_inner[array_text[20][:-2]] = array_text[21]
        result_inner[array_text[23][:-2]] = array_text[24]
        result[title] = result_inner

        ## COV Details

        row_fetch = form_fetch[7].get_text().split('\n')
        title = row_fetch[3][:-3]
        result_inner = dict()
        result_inner_text = dict()
        list_inner = list()

        result_inner_text[row_fetch[10]] = row_fetch[17]
        result_inner_text[row_fetch[11]] = row_fetch[18]
        result_inner_text[row_fetch[12]] = row_fetch[19]
        list_inner.append(result_inner_text)
        result_inner_text = dict()
        result_inner_text[row_fetch[10]] = row_fetch[22]
        result_inner_text[row_fetch[11]] = row_fetch[23]
        result_inner_text[row_fetch[12]] = row_fetch[24]
        list_inner.append(result_inner_text)
        result[title] = list_inner

        ## Badge Details

        result_inner_text = dict()
        row_fetch = form_fetch[9].get_text().split('\n')
        title = row_fetch[3][:-3]
        result_inner_text[row_fetch[10][:-1]] = row_fetch[17]
        result_inner_text[row_fetch[11][:-1]] = row_fetch[18]
        result_inner_text[row_fetch[12][:-1]] = row_fetch[19]
        result[title] = result_inner_text

        json_result = json.dumps(result)
        print(json_result)

    except:
        print("Data Not Found")

if __name__ == '__main__':
    DL_no = 'Up8720140002671'
    DOB = '06/07/1989'

    scrapping_data(DL_no, DOB)


import os
from functools import wraps, WRAPPER_ASSIGNMENTS

from blogging.create_class import CreateClass, CreateTemplate
import re
from django.utils.functional import keep_lazy_text
import six
from django.utils.safestring import mark_safe
from django.contrib.auth.decorators import user_passes_test
import unicodedata
from django.http.response import HttpResponseForbidden

def create_content_type(name,form_dict,is_leaf):
	"""
	This function will create the form and template for new contentype
	"""
	form_filename = os.path.abspath(os.path.dirname(__file__))+"/custom/"+name.lower()+".py"
	template_filename = os.path.abspath(os.path.dirname(__file__))+"/templates/blogging/includes/"+name.lower()+".html"
	flag = False
	try:
		fd = open(form_filename, 'r')
		fd.close()
		fd1 = open(template_filename, 'r')
		fd1.close()
	except IOError:
		flag = True
	if flag:
		#We are good to go. Create the Output string that must be put in it
		create_class_object = CreateClass(name, form_dict,is_leaf)
		form_string = create_class_object.form_string()
		template_object = CreateTemplate(name, form_dict,is_leaf)
		template_string = template_object.form_string()

		try:
			fd = os.fdopen(os.open(form_filename,os.O_CREAT| os.O_RDWR , 0o555),'w')
			fd.write(form_string)
			fd.close()
			fd = os.fdopen(os.open(template_filename,os.O_CREAT| os.O_RDWR , 0o555),'w')
			fd.write(template_string)
			fd.close()

			print((file(form_filename).read()))
			return True
		except IOError:
			print ("Error Opening File for Writing")
			return False
	else:
		return False

def get_imageurl_from_data(data):

	try:
		matches = re.findall(
				r'(<img[^>].*?src\s*=\s*"([^"]+)")', data
			)
		if matches:
			return str(matches[0][1])
		else:
			return None
	except:
		print("Error in get_imageurl_from_data")
		return None

def strip_image_from_data(data):
	p = re.compile(r'<img.*?/>',flags=re.DOTALL)
	line = p.sub('', data)
	print ("LOGS:: Stripping images from data")
	return line

def truncatewords(Value,limit=30):
	try:
		limit = int(limit)
		# invalid literal for int()
	except ValueError:
		# Fail silently.
		return Value

	# Make sure it's unicode
	Value = str(Value)

	# Return the string itself if length is smaller or equal to the limit
	if len(Value) <= limit:
		return Value

	# Cut the string
	Value = Value[:limit]

	# Break into words and remove the last
	words = Value.split(' ')[:-1]

	# Join the words and return
	return ' '.join(words) + '...'

@keep_lazy_text
def slugify_name(value):
	value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
	value = re.sub('[^\w\s-]', '', value).strip().lower()
	return re.sub('[-\s]+', '_', value)

def user_has_group(test_func):
    """
    Decorator for views that checks that the user has the group,
    raising HttpResponseForbidden page if necessary. The test should be a callable
    that takes the user object and returns True if the user passes.
    """

    def decorator(view_func):
        @wraps(view_func, assigned=WRAPPER_ASSIGNMENTS)
        def _wrapped_view(request, *args, **kwargs):
            if test_func(request.user):
                return view_func(request, *args, **kwargs)
            return HttpResponseForbidden()
        return _wrapped_view
    return decorator

def group_required(*group_names):
    """Requires user membership in at least one of the groups passed in."""
    def in_groups(u):
        if u.is_authenticated:
            if bool(u.groups.filter(name__in=group_names)) | u.is_superuser:
                return True
        return False
    return user_has_group(in_groups)

#slugify_name = allow_lazy(slugify_name, six.text_type)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 24 14:57:13 2019

@author: user
"""

import os
import skimage.io
import skimage.transform
import numpy as np
from keras.layers import Conv2D,Input,Dense,GlobalAveragePooling2D,Dropout,Activation,BatchNormalization
from keras.optimizers import SGD
from keras.models import Model
from sklearn.cross_validation import train_test_split
import matplotlib.pyplot as plt;
from skimage.color import gray2rgb
from skimage.filters import threshold_niblack
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19
from PIL import Image
# ori data path
data_path = '850nm'
#data_path = 'Finger Vein Database'
# target data path
dae_path = '1'

X = []
y = []
h = os.listdir(data_path)
count = 0
for filename in h:
    im = skimage.io.imread(os.path.join(data_path,filename))
    resized_img = skimage.transform.resize(im, (224, 224),mode='reflect')
    img = resized_img.flatten()
    img = img[np.newaxis,:]
    if count == 0 :
        X = img
        count = 1
    else:
        X = np.vstack((X,img))
    label = filename.replace('.bmp', '').split('_')
    y = np.append(y,label[0])
print (X.shape)
print (y.shape)
print ("Complicate!")

X = np.reshape(X, (len(X),224, 224))
X = gray2rgb(X)
def conbine_img(x,y):
    comb_x = []
    comb_y = []
    count = 0
    for i in range(len(x)):
        if i == (len(x)-1):
            break;
        else:
            for j in range(len(x)-i-1):
                ori_img = x[i]
                compare_img = x[j+i+1]
#                img = np.zeros((1,224,224,2))
                img = ori_img + compare_img
                img = img.reshape([1,224,224,3])
                if count == 0 :
                    comb_x = img
                    count = 1
                else :
                    comb_x = np.vstack((comb_x,img))
                if y[i] == y[j+i+1] :
                    comb_y.append(1)
                else :
                    comb_y.append(0)
    return comb_x,comb_y

c = X[:60]
d = y[:60]
Comb_x,Comb_y = conbine_img(c,d)

#
#X_train, X_test, y_train, y_test = train_test_split(Comb_x, Comb_y)
#
#
#base_model = VGG16(weights='imagenet', include_top=False)
base_model = VGG19(weights='imagenet', include_top=False)

x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(2048, activation='relu')(x)
x = Dropout(0.25)(x)
predictions = Dense(1, activation='sigmoid')(x)
model = Model(input=base_model.input, output=predictions)

model.compile(optimizer=SGD(lr=0.001,momentum=0.9), loss='binary_crossentropy',metrics=['accuracy'])
history = model.fit(Comb_x,Comb_y,epochs=320,
                    nb_epoch=20,
                    validation_data=(Comb_x,Comb_y))
model_save = os.path.join('roc/sensors_SDU','SDU_'+model_name+'_'+str(Epochs)+'.h5')
model.save(model_save)


# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import requests
import re
import sys
print(sys.executable)
from bs4 import BeautifulSoup
import logging
from requests import Request, Session
from requests.exceptions import ConnectionError, Timeout, TooManyRedirects
# from airflow.operators.python_operator import BranchPythonOperator
# from airflow.operators.bash_operator import BashOperator
from bs4 import BeautifulSoup
import requests
import json
from datetime import datetime, timedelta
# from airflow.contrib.hooks.aws_hook import AwsHook
# from airflow.models import Variable
# from airflow.hooks.S3_hook import S3Hook
import gzip
import os
from io import StringIO
import boto3
import time
import shutil
from tqdm import tqdm
import time

### Use list ###
basic_date_list = []
basic_news_article = []
depth_date_list = []
depth_news_article = []
clear_word = []

### Crawler 1 ###
def basic_crawler():
    """
    Crawler(data gathering)
    """
    d = []
    a = []

    for i in tqdm(range(1,300), desc="Extracting Web page.."):
        url = 'https://www.coindeskkorea.com/news/articleList.html?page={}&total=6048&box_idxno=&view_type=sm'.format(i)
        resp = requests.get(url)
        soup = BeautifulSoup(resp.content, 'lxml')
        time.sleep(0.01)

        for j in range(1,21):
            date = soup.select('#user-container div.float-center.custom-m.mobile.template.list.max-width-1250 div.user-content section article div.article-list section div:nth-of-type({}) div.text-block div.list-dated'.format(j))
            article = soup.select(
            '#user-container div.float-center.custom-m.mobile.template.list.max-width-1250 div.user-content section article div.article-list section div:nth-of-type({}) div.text-block p a'.format(
                j))

            d.append(date)
            a.append(article)

    for _ in d:
        if _:
            basic_date_list.append(_)

    for _ in a:
        if _:
            basic_news_article.append(_)

    return basic_date_list, basic_news_article

### Crawler 2 ###
def depth_crawler():
    """
    Optimization basic_crawl data
    """
    # depth_news_article
    processing_news = []
    for i in tqdm(basic_news_article, desc="Extracting News url.."):
        url = 'https://www.coindeskkorea.com'+str(i).split(' ')[2].split('"')[1]

        processing_news.append(url)

    for i in tqdm(processing_news, desc="Crawling News article.."):
        resq = requests.get(i)
        soup = BeautifulSoup(resq.text,'lxml')
        n = str(soup.find_all('p')).split('
<a href=')[0]

        depth_news_article.append(n)

    # depth_date_list
    for i in tqdm(basic_date_list, desc="Crawling News datetime.."):
        d = i[0].text.split(' ')[-2]

        depth_date_list.append(d)

    return depth_news_article, depth_date_list

### pre-processing ###
def processing():
    """
    Article pre-processing
    """
    process = []
    for i in tqdm(depth_news_article, desc="processing complie 1"):
        a = re.compile('[가-힣]+').findall(i)

        process.append(a)

    for i in tqdm(process, desc="processing complie 2"):
        a = ' '.join(i)
        b = re.compile('[제보-보내주세요]').sub(' ',a)
        # c = b.replace('도자료','')

        clear_word.append(' '+b)

    return clear_word

### dataframe ###
def dataframe():
    df_article = pd.DataFrame(clear_word, columns=['article'])
    df_date = pd.DataFrame(depth_date_list, columns=['created_date'])
    df_total = pd.concat([df_date, df_article], axis=1)
    df_total = df_total.groupby('created_date').sum(str(df_total['article']))
    print("Make DataFrame Structure")

    return df_total.to_csv('/Users/yoo/Data-dev/nlp/reference/DataFrame/article.csv', encoding='utf-8')
    # return df_total

# ### Upload S3 bucket ###
# def DataFrameUploader(df_total):
#     s3_bucket = 'russo-mydata'
#     s3_key = 'article_{{ tomorrow_ds_nodash }}.csv'
#     s3_hook = S3Hook(bucket)
#
#     return df_total.to_csv

### main_compile ###
basic_crawler()
depth_crawler()
processing()
dataframe()
# DataFrameUploader(dataframe())
print("Done")


import logging
import requests
from switchml.protobuf.service_pb2 import (
    EvalRes,
    FitRes,
    Parameters,
    WeightsInvocation,
    WeightsResponse,
)
from switchml.utils import parameters_to_weights, weights_to_parameters

class ProxyController:

    default_headers = {
        "Accept": "application/json",
        "Content-Type": "application/json",
    }

    def __init__(self, host: str, port: str):
        self.host = host
        self.port = port

    def send_weights(self, weights):
        register_uri = "/api/v1/state/"
        try:

            proxy_url = "http://{}:{}{}".format(self.host, self.port, register_uri)
            parameters = weights_to_parameters(weights.get("weights"))

            fit_res = FitRes(
                parameters=parameters,
                num_examples=weights.get("fit_examples"),
                metrics=weights.get("fit_metrics"),
            )
            eval_res = EvalRes(
                loss=weights.get("loss"),
                num_examples=weights.get("eval_examples"),
                metrics=weights.get("eval_metrics"),
            )

            weights_invocation = WeightsInvocation(fit_res=fit_res, eval_res=eval_res)

            binary_payload = weights_invocation.SerializeToString()

            resp = requests.post(
                proxy_url, data=binary_payload, headers=self.default_headers
            )

            logging.info("response %s", resp)
        except Exception as e:
            logging.error("ERROR: %s", e)
            logging.error("Shit %s", e.__cause__)

    def fetch_weights(self):
        register_uri = "/api/v1/server-weights/"
        try:

            proxy_url = "http://{}:{}{}".format(self.host, self.port, register_uri)

            weights_request = requests.get(proxy_url, headers=self.default_headers)

            databytes = bytes(weights_request.content)
            weights_response = WeightsResponse()
            weights_response.ParseFromString(databytes)

            return {
                "weights": parameters_to_weights(weights_response.parameters),
                "config": weights_response.config,
            }

        except Exception as e:
            logging.error("ERROR: %s", e)
            logging.error("Shit %s", e.__cause__)


from netgen.geom2d import SplineGeometry
from ngsolve import *
from dream import CompressibleHDGSolver, SolverConfiguration
# from dream.utils.geometries import MakeOCCRectangle, MakeOCCCircle, MakeOCCCirclePlane
from dream.utils.meshes import Get_Omesh

ngsglobals.msg_level = 0
SetNumThreads(8)

##################################################################
geo = SplineGeometry()
R = 1
R_farfield = R * 30
mesh = Mesh(Get_Omesh(R, R_farfield, 36, 16, geom=1.5))
Draw(mesh)
##################################################################
cfg = SolverConfiguration()

cfg.formulation = "conservative"
cfg.dynamic_viscosity = "constant"
cfg.mixed_method = "strain_heat"
cfg.riemann_solver = "lax_friedrich"

cfg.Reynolds_number = 10
cfg.Prandtl_number = 1  # 0.72
cfg.Mach_number = 0.3
cfg.heat_capacity_ratio = 1.4

cfg.order = 2
cfg.time.simulation = "stationary"
cfg.time.scheme = "IE"
cfg.time.step = 0.1
cfg.time.interval = (0, 200)
cfg.linear_solver = "pardiso"
cfg.damping_factor = 1
cfg.max_iterations = 100
cfg.convergence_criterion = 1e-12
cfg.compile_flag = True
cfg.static_condensation = True

mesh.Curve(cfg.order)
##################################################################
gamma = cfg.heat_capacity_ratio
M_inf = cfg.Mach_number

u_inf = CF((1, 0))
p_inf = 1
rho_inf = p_inf * gamma / (u_inf[0]/M_inf)**2

solver = CompressibleHDGSolver(mesh, cfg)
solver.boundary_conditions.set_farfield("inflow", u_inf, rho_inf,  p_inf)
solver.boundary_conditions.set_outflow("outflow", p_inf)
solver.boundary_conditions.set_adiabatic_wall("cylinder")
solver.domain_conditions.set_initial(u_inf, rho_inf, pressure=p_inf)

with TaskManager():
    solver.setup()

    solver.drawer.draw_acoustic_pressure(p_inf)
    solver.drawer.draw_particle_velocity(u_inf)
    solver.drawer.draw_mach_number()
    solver.drawer.draw_deviatoric_stress_tensor()

    solver.solve_transient()


OK = 'OK\n'
FAIL = 'FAIL\n'
ERROR = 'ERROR\n'

class PackageIndexer:
    def __init__(self):
        self.INDEX = {}
        self.PackageMap = {}

    def remove(self, package):
        if package not in self.INDEX:
            return OK
        if package in self.PackageMap:
            return FAIL

        keys = [k for k in self.PackageMap]
        for k in keys:
            dependants = self.PackageMap[k]
            if package in dependants:  # if package if one of dependant of the package , remove it from set
                dependants.remove(package)

            if len(dependants) == 0:  # if nothing is depended on the package, remove it from the packageMap
                del self.PackageMap[k]
        del self.INDEX[package]
        return OK

    def index(self, package, dependencies):

        if dependencies is not None:
            for d in dependencies:
                if d not in self.INDEX:
                    return FAIL
                if d not in self.PackageMap:  # if dependency not in PackageMap add it
                    self.PackageMap[d] = {package}  # set PackageMap[dependency]
                else:  # if dependency already there add to the set
                    self.PackageMap[d].add(package)

        self.INDEX[package] = dependencies
        return OK

    def query(self, package):
        if package in self.INDEX:
            return OK
        else:
            return FAIL

    def validate_msg(self, msg):

        parsed_msg = msg.split('|')

        if len(parsed_msg) != 3:
            return ERROR, 'Missing mandatory arguments', None

        if not parsed_msg[1] or ',' in parsed_msg[1]:
            return ERROR, 'Invalid package name', None

        if parsed_msg[0] not in ['INDEX', 'REMOVE', 'QUERY']:
            return ERROR, 'Invalid command', None

        dependencies = parsed_msg[2].split(',')
        if dependencies == ['']:
            dependencies = None
        return parsed_msg[0], parsed_msg[1], dependencies


from colorama import *
from tabulate import tabulate
import nash_v2
import aversionalriesgov1
import estrategias_estrictamente_dominantes
import aversionalriesgolog

init(autoreset=True)

print(Style.BRIGHT+Fore.GREEN+"""              _____  _______  _    _  ______  ____   _____ __     __
             / ____||__   __|| |  | ||  ____|/ __ \ |  __ \\ \   / /
            | |  __    | |   | |__| || |__  | |  | || |__) |\ \_/ /
            | | |_ |   | |   |  __  ||  __| | |  | ||  _  /  \   /
            | |__| |   | |   | |  | || |____| |__| || | \ \   | |
             \_____|   |_|   |_|  |_||______|\____/ |_|  \_\  |_|
                                                                    """)
print()
print()
introduccion = " PER  ASPERA  AD  ASTRA "

print(Style.BRIGHT+Fore.YELLOW+introduccion.center(80, "="))

print()
print()

print(Style.BRIGHT+Fore.WHITE+"Bienvenido: ")

print()

while True:
    print()

    opciones = " Menú de Opciones "
    print(Style.BRIGHT+Fore.CYAN+opciones.center(80, "*"))

    lista = [[0, "Salir"],
    [1, "Aversión al Riesgo (Exponencial, Lineal, Radical) "],
    [2, "Aversión al Riego (Logaritmica) "],
    [3, "Estrategias Estrictamentes Dominantes"],
    [4, "Estrategia Mixta con Matrices Cuadradas (Gauss-Jordan-Nash)"]]

    print(Style.BRIGHT+Fore.GREEN+tabulate(lista))

    print()
    print()

    a = int(input("Ingrese un número según el cálculo que desea realizar: "))

    if a==0:
        break
    elif a==1:
        aversionalriesgov1.main()
    elif a==2:
        aversionalriesgolog.main()
    elif a==3:
        estrategias_estrictamente_dominantes.main()
    elif a==4:
        nash_v2.main()

    print()


import numpy as np
import json

feat2val = json.loads(open('features.json').read())
val2feat = {}
feat2int = {}
int2feat = {}
val2int = {}
char2int = {}
int2char = {}
i = 0
for featCat in feat2val:
    feat2int[featCat] = i
    int2feat[i] = featCat
    i += 1
i = 0
for featCat in feat2val:
    featVals = feat2val[featCat]
    for val in featVals:
        val2feat[val] = featCat
        val2int[val] = i
        i += 1
i = 0
def get_feat_val(val):
    featCat = val2feat[val]
    i = feat2val[featCat] .index(val)
    return i, featCat

rev_val2feat = {}
j = 0
for feat in feat2val.keys():
    val_list = feat2val[feat]
    max_len = len(val_list) + 1
    for i in range(len(val_list)):
        val = val_list[i]
        rev_val2feat[val] = [max_len, i]

def get_rev_feat(max_len, index=-1):
    vec = np.zeros((max_len,))
    vec[index] = 1
    return vec
def get_reverse_feature_array():
    lines = open('final.txt', encoding='utf-8').readlines()
    n_featval = sum([len(feat2val[k]) for k in feat2val])
    featArray = []
    maxroot, maxword = 15, 0
    words = []
    roots = []
    k = 0
    for line in lines:
        splited = line[:-1].split(' ')
        word = splited[0]
        root = splited[1]
        wordFeats = [s[:-1] for s in splited[2].split('<')[2:]]
        words.append(word)
        roots.append(root)
        pred_feat = []
        for key in rev_val2feat:
            max_len, index = rev_val2feat[key]
            if key in wordFeats:
                vec = get_rev_feat(max_len, index)
                pred_feat.append(vec)
            else:
                vec = get_rev_feat(max_len)
                pred_feat.append(vec)
        featArray.append(pred_feat)
        k += 1
        if len(word) > maxword:
            maxword = len(word)
        # if len(root) > maxroot:
        #     maxroot = len(root)
        for char in word:
            if char not in char2int:
                temp = len(char2int)
                char2int[char] = temp
                int2char[temp] = char
    # start code
    int2char[len(char2int)] = '&'
    char2int['&'] = len(char2int)
    int2char[len(char2int)] = ' '
    char2int[' '] = len(char2int)
    for i, c in enumerate(sorted(char2int.keys())):
        char2int[c] = i
        int2char[i] = c
    n_features = len(featArray[0])
    return roots, words, featArray, maxroot, maxword, n_features

def get_feature_array(data):
    lines = open(data, encoding='utf-8').readlines()
    n_featval = sum([len(feat2val[k]) for k in feat2val])
    featArray = np.zeros((len(lines), n_featval), dtype=np.int32)
    maxroot, maxword = 15, 0
    words = []
    roots = []
    k = 0
    for line in lines:
        splited = line[:-1].split(' ')
        word = splited[0]
        root = splited[1]
        wordFeats = [s[:-1] for s in splited[2].split('<')[2:]]
        words.append(word)
        roots.append(root)
        for feat in wordFeats:
            featArray[k][val2int[feat]] = 1
        k += 1
        if len(word) > maxword:
            maxword = len(word)
        # if len(root) > maxroot:
        #     maxroot = len(root)
        for char in word:
            if char not in char2int:
                temp = len(char2int)
                char2int[char] = temp
                int2char[temp] = char
    # start code
    int2char[len(char2int)] = '&'
    char2int['&'] = len(char2int)
    int2char[len(char2int)] = ' '
    char2int[' '] = len(char2int)
    for i, c in enumerate(sorted(char2int.keys())):
        char2int[c] = i
        int2char[i] = c
    return roots, words, featArray, maxroot, maxword


import boto3
import botocore
import datetime

class awsClient:
    BUCKET_NAME = "bitsassignment"
    ACCESS_KEY = "*******"
    SECRET_KEY = "********"
    REGION = "us-east-1"
    CDN_URL = "https://d1vmo6aju6p6pp.cloudfront.net/"

    def __init__(self, resource_name):
        self.client = boto3.client(
            resource_name,
            region_name=awsClient.REGION,
            aws_access_key_id=awsClient.ACCESS_KEY,
            aws_secret_access_key=awsClient.SECRET_KEY
        )

    def upload_file(self, file_object, acl="public-read"):
        self.client.upload_fileobj(file_object, awsClient.BUCKET_NAME, file_object.filename, ExtraArgs={
                "ACL": acl,
                "ContentType": file_object.content_type
            })

    def download_files(self, file_key, file_name):
        try:
            self.client.Bucket(awsClient.BUCKET_NAME).download_file(file_key, file_name)
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "404":
                return None
            else:
                raise

    def list_files(self):
        file_list = dict()
        file_objects = self.client.list_objects_v2(Bucket=awsClient.BUCKET_NAME)
        for file_object in file_objects["Contents"]:
            # Check for URL format : Object Key Trimming.
            file_object['URL'] = awsClient.CDN_URL + file_object['Key']
            file_object['Name'] = file_object['Key'].split('.')[0]
            file_list.update({file_object['Key']: file_object})
        return file_list

    def get_file_details(self, file_key):
        file_details = dict()
        response = dict()
        file_object = self.client.get_object(Bucket=awsClient.BUCKET_NAME, Key=file_key)
        file_details['Key'] = file_key
        file_details['URL'] = awsClient.CDN_URL + file_key
        file_details['Name'] = file_key.split('.')[0]
        file_details['ContentType'] = file_object['ContentType']
        file_details['UploadedOn'] = file_object['LastModified'].strftime("%B %d, %Y")
        response.update({0: file_details})
        return response

    def delete_file(self, file_key):
        resp = self.client.delete_object(Bucket=awsClient.BUCKET_NAME, Key=file_key)
        return resp['ResponseMetadata']['HTTPStatusCode']

"""if __name__ == "__main__":
    aws = awsClient('s3')
    files = aws.list_files()"""


from distutils.file_util import write_file
import requests
import json
import pprint
import csv
import os.path

# Access API from https://db.ygoprodeck.com
response_API = requests.get('https://db.ygoprodeck.com/api/v7/cardinfo.php')

# Save data as Text and load into JSON
data_access = response_API.text
data_text= json.loads(data_access)
data= data_text['data']
inventory=[[],[],[]]

# Check if database.csv already exists
file_exists = os.path.exists('database.csv')
if file_exists == False:

   # Access Card ID and Name and Save into Array

   for id in data:
       card=[id['id'],id['name'],'not in Inventory']
       inventory.append(card)

   # Write database in CSV file
   with open('database.csv', 'w', newline='') as file:
      mywriter = csv.writer(file, delimiter=',')
      mywriter.writerows(inventory)

   print('db did not exist')

else:
   with open("database.csv") as csvfile:
    reader = csv.reader(csvfile, delimiter=',')
    for row in reader: # each row is a list
        inventory.append(row)

   print('db did exist')

#print(len(inventory))
#pprint.pprint(inventory)
#pprint.pprint(data)
#print(f"{id}{name}")


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def nodesBetweenCriticalPoints(self, head: Optional[ListNode]) -> List[int]:
        #iterate through the linked list and keep 2 pointers prev and prev2 which are the last and middle elements
        #for each element if both prev and prev2 exists check if prev is a local minima or maxima
        minhead=head
        ans=list()
        count=0
        prev=None
        prev2=None

        while minhead:
            if not prev:
                prev=minhead.val
                minhead=minhead.next
                count+=1
                continue
            if not prev2:
                prev2=prev
                prev=minhead.val
                minhead=minhead.next
                count+=1
                continue
            curr=minhead.val
            if prev<curr and prev<prev2:
                ans.append(count-1)
            if prev>curr and prev>prev2:
                ans.append(count-1)
            prev2=prev
            prev=curr
            minhead=minhead.next
            count+=1

        if len(ans)<2:
            return [-1,-1]

        return [min([ans[i+1]-ans[i] for i in range(len(ans)-1)]),ans[-1]-ans[0]]


import os
import random
import warnings
# import mxnet as mx
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from statsmodels.tsa.stattools import adfuller
warnings.filterwarnings("ignore")
plt.style.use('dark_background')

def seed_everything():
    """
    Reproductibilidad de resultados
    Returns
    -------
    """
    random.seed(20)
    np.random.seed(20)
    # mx.random.seed(20)

def plot_time_series(df, fecha_inicial="2014-12-01",
                     fecha_final="2014-12-14",
                     title="Consumo Electrico",
                     ylabel="Consumo Electrico [kW]",
                     sample=10):
    """
    Plot de la serie de tiempo que tiene como indice la fehca en formato
    timestamp

    Parameters
    ----------
    df : dataframe
        datos de las series de tiempo ordenados hacia el lado.
    fecha_inicial : str
        fecha inicial en el formato %y-%m-%d. The default is "2014-12-01".
    fecha_final : TYPE
        fecha final en el formato %y-%m-%d. The default is "2014-12-14".
    title : str, optional
        titulo. The default is "Consumo Electrico".
    ylabel : TYPE, optional
        nombre de eje Y. The default is "Consumo Electrico [kW]".
    sample : TYPE, optional
        cuantas columans quieres tomar. The default is 10.
    Returns
    -------
    Gráficos en una sola plana
    """
    fig, axs = plt.subplots(5, 4, figsize=(40, 40), sharex=True)
    axx = axs.ravel()
    for i in range(0, sample):
        df[df.columns[i]].loc[fecha_inicial:fecha_final].plot(ax=axx[i])
        axx[i].set_xlabel("Fecha [dias]")
        axx[i].set_ylabel(ylabel)
        axx[i].set_title(title)
        axx[i].grid(which='minor', axis='x')

def plot_prob_forecasts(ts_entry, forecast_entry, prediction_lentgh,
                        prediction_intervals=(80.0, 95.0),
                        problem="caso_electricidad",
                        color="k"):
    """
    Plot del conjunto de testeo con intervalos de confianza definidos

    Parameters
    ----------
    ts_entry : dataframe
        dataframe con fecha y cantidad consumida.
    forecast_entry : TYPE
        DESCRIPTION.
    prediction_lentgh : TYPE
        DESCRIPTION.
    prediction_intervals : TYPE, optional
        DESCRIPTION. The default is (80.0, 95.0).

    Returns
    -------
    None.

    """
    plot_length = prediction_lentgh
    legend = ["observaciones", "mediana de la predicción"] + \
        [f"{k}% intervalo de la predicción" for k in prediction_intervals][
            ::-1]
    fig, ax = plt.subplots(1, 1, figsize=(20, 14))
    ts_entry[-plot_length:].plot(ax=ax, color='red')
    forecast_entry.plot(prediction_intervals=prediction_intervals,
                        color=color)
    plt.grid(which="both")
    plt.legend(legend, loc="upper left", fontsize=22)
    ax.set_ylabel("Observaciones", fontsize=25)
    ax.set_xlabel("Tiempo", fontsize=25)
    ax.set_title("Observacion vs Predicciones + IC", fontsize=30)
    plt.show()
    try_create_folder(path="images")
    problem = problem + "_" + str(ts_entry.columns[0])
    fig.savefig(f"images/{problem}.png")

def try_create_folder(path="images"):
    """
    Intentar crear carpeta
    Parameters
    ----------
    path : string
        direccion.
    """
    try:
        os.mkdir(path)
    except Exception as e:
        pass

def extract_base(string):
    """
    Extrer la base del sku
    Parameters
    ----------
    string : string
        skus.
    Returns
    -------
    base : TYPE
        DESCRIPTION.
    """
    ind = string.find("|")
    base = string[0: ind]
    return base

def drop_spaces_data(df):
    """
    sacar los espacios de columnas que podrián venir interferidas
    Parameters
    ----------
    df : dataframe
        input data
    column : string
        string sin espacios en sus columnas
    Returns
    -------
    """
    for column in df.columns:
        try:
            df[column] = df[column].str.lstrip()
            df[column] = df[column].str.rstrip()
        except Exception as e:
            print(e)
            pass
    return df

def make_empty_identifiable(value):
    """
    Parameters
    ----------
    value : int, string, etc
        valor con el que se trabaja.
    Returns
    -------
    nans en los vacios.
    """
    if value == "":
        output = np.nan
    else:
        output = value
    return output

def replace_empty_nans(df):
    """
    Parameters
    ----------
    df : int, string, etc
        valor con el que se trabaja.
    Returns
    -------
    nans en los vacios.
    """
    for col in df.columns:
        print("buscando vacios en:", col, "...")
        df[col] = df[col].apply(lambda x: make_empty_identifiable(x))
    return df

def df_convert_float(df):
    """
    Pasa por las columnas tratando de convertirlas a float64
    Parameters
    ----------
    df : dataframe
        df de trabajo.
    Returns
    -------
    df : dataframe
        df con las columnas númericas en float.
    """
    for col in df.columns:
        try:
            df[col] = df[col].apply(float)
        except Exception as e:
            print(e)
    df.reset_index(drop=True, inplace=True)
    return df

def comentary_stationarity(p):
    """
    Comentario de la estacionaridad de las

    Parameters
    ----------
    p : TYPE
        DESCRIPTION.

    Returns
    -------
    comments : TYPE
        DESCRIPTION.

    """
    if p <= 0.05:
        comments =\
            "Rechaza la hipótesis nula (H0), los datos son estacionarios"
    else:
        comments =\
            "No se rechaza la hipótesis nula (H0), los datos no son estacionarios"
    return comments

def creating_rolling_dataset(data, mean_rolling=30):
    """
    Entregado un dataset, crear el mismo dataset pero a través de medias
    moviles, de tal forma de generar predicciones en ella
    Parameters
    ----------
    data : dataframe
        dataframe con las demandas.
    mean_rolling : int, optional
        tamaño de la ventana temporal para hacer las medias moviles.
        The default is 30.
    Returns
    -------
    result : dataframe
        dataframe de medias moviles de data.
    """
    result = data[["fecha"]]
    # columnas a iterar sobre
    columns = list(data.columns)
    columns.remove("fecha")
    for col in columns:
        col_name = f"rolling_{col}"
        datai = data[["fecha", col]]
        datai.set_index("fecha", inplace=True)
        datai[col_name] = datai[col].rolling(mean_rolling).mean()
        datai = datai[[col_name]]
        datai.reset_index(drop=False, inplace=True)
        result = result.merge(datai, on=["fecha"], how="outer")
    result.dropna(inplace=True)
    result.reset_index(drop=True, inplace=True)
    return result

def index_date(df):
    """
    Indexar la columna de las fechas
    Parameters
    ----------
    df : dataframe
        dataframe de demandas de stock en el tiempo.
    Returns
    -------
    df : dataframe
        dataframe con la fecha como index.
    """
    df.rename(columns={"fecha": "index"}, inplace=True)
    df.set_index(["index"], inplace=True)
    return df

def stationary_adf_test(df):
    """
    Test de estacionaridad
     Augmented Dickey-Fuller puede ser una de las más utilizadas.
     Utiliza un modelo autorregresivo y optimiza un criterio de información
     a través de múltiples valores de retardo (lags) diferentes. La hipótesis
     nula de la prueba es que la serie de tiempo se puede representar
     mediante una raíz unitaria, que no es estacionaria (tiene alguna
     estructura dependiente del tiempo). La hipótesis alternativa
     (que rechaza la hipótesis nula) es que la serie de tiempo es
     estacionaria.

    * Hipótesis nula (H0): si no se rechaza, sugiere que la serie de tiempo
    tiene una raíz unitaria, lo que significa que no es estacionaria.
    Tiene alguna estructura dependiente del tiempo --> problemas.
    * Hipótesis alternativa (H1): Se rechaza la hipótesis nula; sugiere que
    la serie de tiempo no tiene una raíz unitaria, lo que significa que es
    estacionaria. No tiene una estructura dependiente del tiempo.

    Voy a interpretar este resultado utilizando el valor p de la prueba.
    Un valor p por debajo de un umbral (como 5% o 1%) sugiere que rechazamos
    la hipótesis nula (estacionaria); de lo contrario, un valor p por encima
    del umbral sugiere que no rechazamos la hipótesis nula (no estacionaria),
    este es el lo clásico en tests estadísticos.

    * Valor p> 0.05: No se rechaza la hipótesis nula (H0),
        los datos no son estacionarios
    * Valor de p <= 0.05: Rechaza la hipótesis nula (H0),
        los datos son estacionarios

    Parameters
    ----------
    df : dataframe
        dataframe al cual se le harán pruebas de estacionaridad a todas sus
        columnas.
    Returns
    -------
    output : dataframe
        resultados del test.
    """
    output = []
    for col in df.columns:
        if "fecha" in col:
            pass
        else:
            datai = df[[col]]
            # datai = datai[datai[col] > 0]
            result = adfuller(datai.values)
            # descomprimir valores
            p = result[1]
            print("Para la columna: ", col)
            print(comentary_stationarity(p))
            print('ADF estadisticas: %f' % result[0])
            print('Valor de p: %f' % result[1])
            print('Valores criticos:')
            for key, value in result[4].items():
                print('\t%s: %.3f' % (key, value))
            output.append([col, comentary_stationarity(p),
                          p, list(result[4].items())])
    output = pd.DataFrame(output, columns=["columna", "resultado",
                                           "valor_p", "intervalos"])
    return output

def downcast_dtypes(df):
    """
    Función super util para bajar la cantidad de operaciones flotante que
    se van a realizar en el proceso de entrenamiento de la red
    Parameters
    ----------
    df : dataframe
        df a disminuir la cantidad de operaciones flotantes.
    Returns
    -------
    df : dataframe
        dataframe con los tipos int16 y float32 como formato número
    """
    float_cols = [c for c in df if df[c].dtype == "float64"]
    int_cols = [c for c in df if df[c].dtype in ["int64", "int32"]]
    df[float_cols] = df[float_cols].astype(np.float32)
    df[int_cols] = df[int_cols].astype(np.int16)
    return df

def lstm_preparation(array, timesteps=30):
    """
    Preparar los datos para la predicción con la lstm
    Parameters
    ----------
    array : numpy.array
        array.
    timesteps : int, optional
        cantidad de tiemsteps que se harán las predicciones.
        The default is 30.
    Returns
    -------
    x_train : array
        matriz de entrenamiento de las celdas lstm.
    y_train : array
        salida de las celdas.
    """
    x_train = []
    y_train = []
    for i in range(timesteps, array.shape[0]):
        x_train.append(array[i-timesteps:i])
        y_train.append(array[i][0:array.shape[1]])
    x_train = np.array(x_train, dtype='float32')
    y_train = np.array(y_train, dtype='float32')
    return x_train, y_train

def always_number(df):
    """
    Pasa por las columnas del dataframe poniendo valores > 0
    Parameters
    ----------
    df : dataframe
        df de trabajo.
    Returns
    -------
    df : dataframe
        df con las columnas númericas en float.
    """
    for col in df.columns:
        try:
            df[col] = df[col].apply(lambda x: 10e-20 if x == 0 else x)
        except Exception as e:
            print(e)
    df.reset_index(drop=True, inplace=True)
    return df

def delete_negatives(predictions):
    """
    No pueden haber predicciones negativas, asi que nos aseguramos de eso
    Parameters
    ----------
    predictions : array
        predicciones para todos los sku.
    Returns
    -------
    predictions : array
        predicciones con 0 en los casos en que estás eran negativas.
    """
    predictions = pd.DataFrame(predictions)
    for col in predictions.columns:
        predictions[col] = predictions[col].apply(
            lambda x: 0 if x < 0 else x)
    predictions = predictions.to_numpy()
    return predictions

def lstm_metric_evaluation(predictions, y_test, fechas, filter_names,
                           save=False):
    """
    Evaluar la suma de la demanda predecida para el ciclo, con la suma de
    la demanda real en el ciclo de test
    Parameters
    ----------
    predictions : array
        predicciones.
    y_test : array
        testing.
    fechas : array
        array con las fechas de testing.
    filter names : array
        array con los nombres de los articulos.
    save : boolean, optional
        Decide si se guardan o no las images de los resultados.
        The default is False.
    Returns
    -------
    mean : dataframe
        metricas de evaluación.
    """
    mean = []
    for i in range(y_test.shape[1]):
        print("columna: ", i)
        predi = predictions[:, i]
        testi = y_test[:, i]
        plot_sequence(predi, testi, fechas, filter_names[i], save)
        error = np.abs(predi - testi).mean()
        suma_pred = predi.sum()
        suma_test = testi.sum()
        pt = np.abs(suma_test - suma_pred) / suma_test * 100
        acc = calculate_accuracy(suma_test, suma_pred)
        mean.append([i, error, suma_pred, suma_test, pt, acc])
    mean = pd.DataFrame(mean, columns=["id_columna", "mae", "suma_pred",
                                       "suma_test", "mape", "acc"])
    # mean = delete_negatives(mean)
    # mean = pd.DataFrame(mean, columns=["id_columna", "mae", "suma_pred",
    #                                    "suma_test", "mape", "acc"])
    return mean

def calculate_accuracy(real, predict):
    """
    Calcular accuracy según metodologia de:
    [https://github.com/huseinzol05/Stock-Prediction-Models/blob/master/
    deep-learning/16.attention-is-all-you-need.ipynb]
    Parameters
    ----------
    real : float, array
        real.
    predict : float, array
        predicciones.
    Returns
    -------
    TYPE
        float, array.
    """
    real = np.array(real)
    predict = np.array(predict)
    percentage = 1 - np.sqrt(np.mean(np.square((real - predict) / real)))
    return percentage * 100

def plot_instance_training(history, epocas_hacia_atras, model_name,
                           filename):
    """
    Sacar el historial de entrenamiento de epocas en partivular
    Parameters
    ----------
    history : object
        DESCRIPTION.
    epocas_hacia_atras : int
        epocas hacia atrás que queremos ver en el entrenamiento.
    model_name : string
        nombre del modelo.
    filename : string
        nombre del archivo.
    Returns
    -------
    bool
        gráficas de lo ocurrido durante el entrenamiento.
    """
    letter_size = 20
    # Hist training
    largo = len(history.history['loss'])
    x_labels = np.arange(largo-epocas_hacia_atras, largo)
    x_labels = list(x_labels)
    # Funciones de costo
    loss_training = history.history['loss'][-epocas_hacia_atras:]
    loss_validation = history.history['val_loss'][-epocas_hacia_atras:]
    # Figura
    fig, ax = plt.subplots(1, figsize=(16, 8))
    ax.plot(x_labels, loss_training, 'b', linewidth=2)
    ax.plot(x_labels, loss_validation, 'r', linewidth=2)
    ax.set_xlabel('Epocas', fontname="Arial", fontsize=letter_size-5)
    ax.set_ylabel('Función de costos', fontname="Arial",
                  fontsize=letter_size-5)
    ax.set_title(f"{model_name}", fontname="Arial", fontsize=letter_size)
    ax.legend(['Entrenamiento', 'Validación'], loc='upper left',
              prop={'size': letter_size-5})
    # Tamaño de los ejes
    for tick in ax.get_xticklabels():
        tick.set_fontsize(letter_size-5)
    for tick in ax.get_yticklabels():
        tick.set_fontsize(letter_size-5)
    plt.show()
    return fig

def training_history(history, model_name="Celdas LSTM", filename="LSTM"):
    """
    Según el historial de entrenamiento que hubo plotear el historial
    hacía atrás de las variables
    Parameters
    ----------
    history : list
        lista con errores de validación y training.
    model_name : string, optional
        nombre del modelo. The default is "Celdas LSTM".
    filename : string, optional
        nombre del archivo. The default is "LSTM".

    Returns
    -------
    None.

    """
    size_training = len(history.history['val_loss'])
    fig = plot_instance_training(history, size_training, model_name,
                                 filename + "_ultimas:" +
                                 str(size_training) + "epocas")

    fig = plot_instance_training(history, int(1.5 * size_training / 2),
                                 model_name,
                                 filename + "_ultimas:" +
                                 str(1.5 * size_training / 2) + "epocas")
    # guardar el resultado de entrenamiento de la lstm
    fig.savefig(f"results/{model_name}_training.png")

    fig = plot_instance_training(history, int(size_training / 2),
                                 model_name,
                                 filename + "_ultimas:" + str(
                                     size_training / 2) + "epocas")

    fig = plot_instance_training(history, int(size_training / 3), model_name,
                                 filename + "_ultimas:" +
                                 str(size_training / 3) + "epocas")
    fig = plot_instance_training(history, int(size_training / 4), model_name,
                                 filename + "_ultimas:" + str(
                                     size_training / 4) + "epocas")
    print(fig)

def plot_sequence(predictions, real, fechas, indice, save):
    """
    Plot sequence de la secuecnia
    Parameters
    ----------
    predictions : array
        predicciones.
    real : array
        valores reales.
    fechas : array
        array de fechas.
    indice : string
        indice de la columna o nombre.
    save : boolean
        guarda o no guarda el archivo.
    Returns
    -------
    plot de prediciones vs real.
    """
    letter_size = 20
    new_fechas = []
    for fecha in fechas:
        fecha = fecha[0:10]
        new_fechas.append(fecha)

    plt.style.use('dark_background')
    fig, ax = plt.subplots(1, figsize=(20, 12))
    ax.plot(new_fechas, real, 'gold', linewidth=2)
    ax.plot(new_fechas, predictions, 'orangered', linewidth=2)
    ax.set_xlabel('Tiempo', fontname="Arial", fontsize=letter_size)
    ax.set_ylabel('Predicción vs Real', fontname="Arial",
                  fontsize=letter_size+2)
    ax.set_title(f"Predicciones vs real {str(indice)}",
                 fontname="Arial", fontsize=letter_size+10)
    ax.legend(['real', 'predicción'], loc='upper left',
              prop={'size': letter_size+5})
    # Tamaño de los ejes
    for tick in ax.get_xticklabels():
        tick.set_fontsize(letter_size)
    for tick in ax.get_yticklabels():
        tick.set_fontsize(letter_size)
    try_create_folder("results/lstm")
    plt.xticks(rotation=75)
    plt.show()

    path = f"results/lstm/{indice}.png"
    path = path.replace(" ", "").replace("-", "_")
    print("Nombre: ", path)
    print("Indice: ", indice)

    if save:
        fig.savefig(path)

def grouping_df(df, days=10, arg="sum"):
    """
    Dado un dataframe que posee una columna de

    Parameters
    ----------
    df : dataframe
        dataframe a agrupar en una fecha dada.
    days : int, optional
        dias de la fecha. The default is 10.
    arg : string, optional
        sum o mean como argumentos. The default is "sum".
    Returns
    -------
    df : dataframe
        dataframe agrupado en esos dias.
    """
    df["fecha"] = df["fecha"].apply(
        lambda x: datetime.strptime(x, "%Y-%m-%d %H-%M-%S"))
    df["fecha_aprox"] = df["fecha"].apply(lambda x: x.round(f"{days}d"))
    if arg == "sum":
        print("Se agrupa por suma")
        df = df.groupby("fecha_aprox").sum()
    elif arg == "mean":
        print("Se agrupa por promedio")
        df = df.groupby("fecha_aprox").mean()
    else:
        print("Argumentos no validos, no se ha efectuado la operación")
    df.reset_index(drop=False, inplace=True)
    df.rename(columns={"fecha_aprox": "fecha"}, inplace=True)
    df["fecha"] = df["fecha"].apply(
        lambda x: x.strftime("%Y-%m-%d %H-%M-%S"))
    df.reset_index(drop=True, inplace=True)
    return df

def plot_prob_forecasts_deep_renewal(ts_entry, forecast_entry, title):
    """
    Plot del conjunto de testeo con intervalos de confianza definidos

    Parameters
    ----------
    ts_entry : dataframe
        dataframe con fecha y cantidad consumida.
    forecast_entry : TYPE
        DESCRIPTION.
    prediction_lentgh : TYPE
        DESCRIPTION.
    prediction_intervals : TYPE, optional
        DESCRIPTION. The default is (80.0, 95.0).

    Returns
    -------
    None.

    """
    plot_length = 100
    prediction_intervals = (50.0, 90.0)
    legend = ["observations", "median prediction"] + \
        [f"{k}% prediction interval" for k in prediction_intervals][::-1]
    title =\
        title if forecast_entry.item_id is None else title +\
        "|"+forecast_entry.item_id
    fig, ax = plt.subplots(1, 1, figsize=(10, 7))
    ts_entry[-plot_length:].plot(ax=ax)
    forecast_entry.plot(prediction_intervals=prediction_intervals, color='g')
    plt.grid(which="both")
    plt.legend(legend, loc="upper left")
    plt.title(title)
    plt.show()

def get_demand_prediction(array, demand, fechas, names, rolling_window,
                          args):
    """
    Hacer transformaciones para hacer predicciones sobre la demanda real
    no la ventana deslizante.

    Parameters
    ----------
    array : array de prediciones
        DESCRIPTION.
    original : dataframe
        dataframe de datos originales de la demanda.
    fechas : list
        fechas donde se hace el testing.
    names : list
        nombres de las columnas.
    rolling_window: int
        largo de la ventana deslizante movil
    rolling_window: args-parser
        argumentos de setting del proyecto
    Returns
    -------
    Metricas de resultado en función de la demanda
    """
    # valores de default para probar
    # array = predictions.copy()
    # demand = demand_real.copy()

    # ventana deslizante resultados
    rolling = pd.DataFrame(array, columns=names)
    rolling["fecha"] = pd.Series(fechas)
    rolling["fecha"] = rolling["fecha"].apply(
        lambda x: datetime.strptime(x, args.date_format))

    # formato fecha
    demand["fecha"] = demand["fecha"].apply(
        lambda x: datetime.strptime(x, args.date_format))
    # filtrar los datos necesarios para el filtrado de la ventana temporal
    fecha_inicial = rolling["fecha"].min() - timedelta(days=rolling_window)
    demand = demand[demand["fecha"] >= fecha_inicial]
    demand.reset_index(drop=True, inplace=True)
    # columnas a iterar
    columns = list(rolling.columns)
    columns.remove("fecha")
    # descomprimir demanda
    for rolling_col in columns:
        original_col = rolling_col.replace("rolling_", "")
        print(original_col)
        rollingi = rolling[[rolling_col]].to_numpy()
        for i in range(rolling_window, demand.shape[0]):
            # recalcular el vector de demanda nuevamente
            demandi = demand[[original_col]].to_numpy()
            # sacar la media movil predicha
            mean_rolling = rollingi[i-rolling_window][0]
            # calcula la suma acumulada que se deberia tener
            suma_rolling1 = demandi[i-rolling_window: i-1].sum()
            # calcula la demanda estimada
            predict_demandi = mean_rolling * rolling_window - suma_rolling1
            # en el caso de ser negativa la setea a cero
            predict_demandi = max(predict_demandi, 0)
            # cambia el valor en el dataframe
            demand[original_col].iloc[i] = predict_demandi
    # filtra para que queden solo las predicciones hechas
    demand = demand[demand["fecha"] >= rolling["fecha"].min()]
    demand.reset_index(drop=True, inplace=True)
    return demand

def mape_computation(real, predict):
    """
    Mean porcentage error computation
    Parameters
    ----------
    real : float
        valor real.
    predict : float
        valor de la prediccion.
    Returns
    -------
    mape : float
        mean percentage error.
    """
    error = np.abs(real - predict)
    mape = error / real * 100
    return mape

def evaluate_demand_predictions(demand_predictions, demand_real, fechas,
                                args):
    """
    Evaluar la predicción de la demanda

    Parameters
    ----------
    demand_predictions : dataframe
        dataframe con las predicciones de demanda descomprimida
    demand_real : dataframe
        demanda real del articulo
    fechas : list
        fechas de evaluacion.
    args : arg-parser
        parametros.
    Returns
    -------
    output : dataframe
        resultados.
    """
    # fechas en las que se esta haciendo las predicciones
    df_fechas = pd.DataFrame(fechas, columns=["fecha"])
    df_fechas["fecha"] = df_fechas["fecha"].apply(
        lambda x: datetime.strptime(x, args.date_format))
    # formato fecha
    demand_real["fecha"] = demand_real["fecha"].apply(str)
    demand_real["fecha"] = demand_real["fecha"].apply(
        lambda x: datetime.strptime(x, args.date_format))
    # filtrar en las fechas utilizadas solamente
    demand_real = demand_real[demand_real["fecha"]
                              >= df_fechas["fecha"].min()]
    demand_real.reset_index(drop=True, inplace=True)
    # columnas a iterar
    columns = list(demand_real.columns)
    columns.remove("fecha")
    output = []
    # iterar sobre estas columnas
    for col in columns:
        # print("Calculando accuracy:", col, "...")
        reali = demand_real[col].sum()
        preidictionsi = demand_predictions[col].sum()
        if reali > 0:
            acc = calculate_accuracy(reali, preidictionsi)
            mape = mape_computation(reali, preidictionsi)
            # print(mape, 100-mape, acc)
        else:
            acc = -1
            mape = -1
        output.append([col, mape, acc])
    output = pd.DataFrame(output, columns=["columna", "mape", "accuracy"])
    output.reset_index(drop=True, inplace=True)

    promedio_error = output[output["mape"] > 0]["mape"].mean()
    promedio_acc = output[output["mape"] > 0]["accuracy"].mean()
    print("Error promedio de los modelos", promedio_error)
    print("Accuracy promedio de los modelos", promedio_acc)
    output["mape"] = output["mape"].apply(
        lambda x: "No determinado" if x == -1 else x)
    output["accuracy"] = output["accuracy"].apply(
        lambda x: "No determinado" if x == -1 else x)
    return output


#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the miniMaxSum function below.
def miniMaxSum(arr):
    min_a = arr[0]
    max_a = arr[0]
    sum_a = 0

    for x in arr:
        if x < min_a:
            min_a = x
        if x > max_a:
            max_a = x
        sum_a += x

    print("{0} {1}".format(sum_a-max_a, sum_a-min_a))

if __name__ == '__main__':
    arr = list(map(int, input().rstrip().split()))

    miniMaxSum(arr)


# https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV4suNtaXFEDFAUf&
import sys
sys.stdin = open('input.txt','r')

dx = [0,1,0,-1,0]
dy = [1,0,-1,0,0]

# 십자 방향으로 다른 코어가 길을 막고 있는지 조사
def search(v):
    direction=[0,1,2,3,4]
    for i in sideCore+allCore:
        if i==v:
            continue
        if v[0]==i[0] or v[1]==i[1]:
            if v[0]-i[0]==0:
                if v[1]-i[1]>0:
                    direction[3]=-1
                else:
                    direction[1]=-1
            if v[1]-i[1]==0:
                if v[0]-i[0]>0:
                    direction[2]=-1
                else:
                    direction[0]=-1
    return direction

def solution(k,arr,cnt):
    global Maxcore,Minlines
    # 시간 단축의 핵심, 이후에 진행해도 최대치를 못넘으면 생략한다.
    if allCoreCnt-k+cnt<Maxcore:
        return
    if k < allCoreCnt:
        v=allCore[k]
        for i in search(v):
            if i==-1:
                continue
            sx=v[1]+dx[i]
            sy=v[0]+dy[i]
            line=[]
            while -1<sx<n and -1<sy<n and i!=4:
                if [sy,sx] not in arr:
                    line+=[[sy,sx]]
                    sx=sx+dx[i]
                    sy=sy+dy[i]
                else:
                    break
            else:
                if i!=4:
                    cnt+=1
                solution(k+1,arr+line,cnt)
                if i!=4:
                    cnt-=1
    else:
        if Maxcore<cnt:
            Maxcore=cnt
            Minlines=0xffffff
        elif Maxcore==cnt:
            Minlines=min(Minlines,len(arr))

TC = int(input())
for num in range(1,TC+1):
    n = int(input())
    mp = [list(map(int, input().split())) for _ in range(n)]
    allCore=[]
    sideCore=[]
    allCoreCnt=0
    Maxcore=0
    Minlines=0xffffff
    for y in range(0,n):
        for x in range(0,n):
            if (x==0 or y==0 or x==n-1 or y==n-1) and mp[y][x]==1:
                sideCore+=[[y,x]]
            else:
                if mp[y][x]==1:
                    allCore+=[[y,x]]
                    allCoreCnt+=1
    solution(0,[],0)
    print(f'#{num}',Minlines)

import sys

sys.stdin = open("sampleA_input.txt")

# 세환이 코드
# DFS를 활용한 백트래킹
# 칩마다 전선 연결 여부로 판단
def connect(k, cores, length):
    # print("I AM : ", k, cores, length)
    global cores_num, max_cores, min_length, N
    # 완전탐색 종료 후 결과 갱신 시도
    if k == cores_num:
        # 코어 개수가 같으면 길이 비교
        if cores == max_cores:
            if length < min_length:
                min_length = length
        # 코어 개수가 더 많으면 무조건 갱신
        elif cores > max_cores:
            max_cores = cores
            min_length = length
        return
    # 코어 최대값 도달 가능성 확인
    if cores + cores_num - k >= max_cores:
        # 최대 코어가 같으면서 길이가 이미 최소치를 넘으면 탈락
        if cores + cores_num - k == max_cores and length > min_length:
            return
        # 만약 가장자리 core 라면 전선 없이 통과
        if core_info[k][0] == 0 or core_info[k][0] == N-1 or core_info[k][1] == 0 or core_info[k][1] == N-1:
            connect(k+1, cores+1, length)
            # print("{} if free!!".format(k))
        else:
            # 전선 둘 수 있는 방향 체크
            direction = line_check(k)
            # print("{} can go : {}".format(k, direction))
            # 전선을 위로 연결
            if direction[0]:
                core_info[k][2] = 1
                connect(k+1, cores+1, length + core_info[k][0])
                core_info[k][2] = 0
            # 전선을 아래로 연걸
            if direction[1]:
                core_info[k][3] = 1
                connect(k+1, cores+1, length + N - core_info[k][0] - 1)
                core_info[k][3] = 0
            # 전선을 오른쪽으로 연결
            if direction[2]:
                core_info[k][4] = 1
                connect(k+1, cores+1, length + N - core_info[k][1] - 1)
                core_info[k][4] = 0
            # 전선을 왼쪽으로 연걸
            if direction[3]:
                core_info[k][5] = 1
                connect(k+1, cores+1, length + core_info[k][1])
                core_info[k][5] = 0
            # 전선 연결안하고 다음으로
            connect(k+1, cores, length)

def line_check(k):
    row, col = core_info[k][0], core_info[k][1]
    # 전선 연결 가능성. 위 아 오 왼.
    # info : [row, col, up, down, right, left]
    direction = [True, True, True, True]
    cnt = 4

    # 가능성 확인
    for info in core_info:
        # 위쪽 가능성
        if direction[0]:
            if info[1] == col and info[0] < row:
                direction[0] = False
                cnt -= 1
            if info[4] == 1:
                if info[0] < row and info[1] < col:
                    direction[0] = False
                    cnt -= 1
            if info[5] == 1:
                if info[0] < row and info[1] > col:
                    direction[0] = False
                    cnt -= 1
        # 아래쪽 가능성
        if direction[1]:
            if info[1] == col and info[0] > row:
                direction[1] = False
                cnt -= 1
            if info[4] == 1:
                if info[0] > row and info[1] < col:
                    direction[1] = False
                    cnt -= 1
            if info[5] == 1:
                if info[0] > row and info[1] > col:
                    direction[1] = False
                    cnt -= 1
        # 오른쪽 가능성
        if direction[2]:
            if info[0] == row and info[1] > col:
                direction[2] = False
                cnt -= 1
            if info[2] == 1:
                if info[0] > row and info[1] > col:
                    direction[2] = False
                    cnt -= 1
            if info[3] == 1:
                if info[0] < row and info[1] > col:
                    direction[2] = False
                    cnt -= 1
        # 왼쪽 가능성
        if direction[3]:
            if info[0] == row and info[1] < col:
                direction[3] = False
                cnt -= 1
            if info[2] == 1:
                if info[0] > row and info[1] < col:
                    direction[3] = False
                    cnt -= 1
            if info[3] == 1:
                if info[0] < row and info[1] < col:
                    direction[3] = False
                    cnt -= 1
        # 갈 곳 없으면 중단
        if cnt == 0:
            break
    return direction

testcase = int(input())

for tc in range(1, testcase + 1):
    N = int(input())
    chip = []
    for _ in range(N):
        chip.append(input().split())

    # for _ in range(N):
    #     print(chip[_])

    # chip에서 1의 위치 기록하기
    core_info = []
    for r in range(N):
        for c in range(N):
            if chip[r][c] == '1':
                core_info.append([r, c, 0, 0, 0, 0])
    cores_num = len(core_info)

    # 답변용 변수 초기화
    max_cores = 0
    min_length = 99999

    # 완전탐색 시작
    connect(0, 0, 0)

    # 답 출력
    print("#{} {}".format(tc, min_length))

Algorithm/SWEA/개인 문제/1767. [SW Test 샘플문제] 프로세서 연결하기.py


# Dictonary is key value pairs
d1 = {}
# print(type(d1))
d2 = {"Anant":"Chole Bhature", "Haris":"Pizza", "Olivia":"Burger",
"Shubham":{"B":"Maggie", "L":"Chaval", "D":"Pav Bhaji"}}
# d2["Rohit"] = "Chicken"
# d2[9211] = "Meat"
# del d2["Rohit"]
# print(d2[Shubham])
d3 = d2
del d3["Anant"]
print(d2)
# print(d2)


#!/usr/bin/env python3

from collections import Counter
from datetime import date
import re
from wordcloud import WordCloud, STOPWORDS
from matplotlib import pylab
import matplotlib.pyplot as plt
import numpy as np
import regex
import emoji

datelist=[]  #this will contail all the list of the date on which the message has been sent
timelist=[]  #this will contail all the list of the time on which the message has been sent
senderlist=[]#this will contail the list of the person who has sent the mesage
messagelist=[]# this will contail the list of message send by the user
graphdata=[]          #contains total no of message sent by a person only top 10
messagedata=[]        #contains total no of messges send on particular date only top 10
activegraph=[]        #contains maximum no of messges send on particular time only top 15
hourlytime=[]         #contians all the hour in which messages were sent
mediagraph=[]         #contains total no of media file shared by a particular person
activehourlygraph=[]  #contains total no of messages sent on the particluar hour
emojilist=[]          #contains all list of all the emoji used in the chat
diffSname=[]          #contains list of all different person in the chat
diffSdate=[]          #contains list of all the different date on which the message was sent
wordlist=[]           #contains list of all the words in the chat by different person
location=[]           #contains list of line in which file is either deleted or ommited
ltofs=[]
htforS=[]
ahourlyforsgraph=[]

notification=0 #this will count the no of notification sent in the chat like videocall disconnected or staring meesage of whatsapp

path='/media/abhishek/Partition 2/mycodes/python codes/data analysis/WhatsApp Chat with Tanya Friend.txt'
# path='/home/abhishek/Downloads/text.txt'
file=open(path,'r',encoding='utf')

count=0
while True:
	line = file.readline()
	if not line:
		break
	if count==0:
		count=1
	else:
		line = ' '.join(line.split('\n'))
		line =' '.join(line.split())

		test_string = line
		matched = re.match("\d+/\d+/\d+, \d+:\d+ [a-z]{2} -\s", test_string)
		matched1 = re.match("\d+/\d+/\d+, \d+:\d+ [A-Z]{2} -\s", test_string)
		if bool(matched)==True or bool(matched1)==True:
			a = test_string
		else:
			a = a+test_string
			datelist.pop()
			timelist.pop()
			senderlist.pop()
			messagelist.pop()

		##date
		line = a.split(", ")
		datelist.append(line[0])
		#time
		time= line[1].split("-")
		timelist.append(time[0])
		##sender
		totalcolon = time[1].count(':')
		sender = time[1].split(":")
		senderlist.append(sender[0])
		##message
		if totalcolon > 1:
			message=":".join(time[1].split(":")[1:])
			messagelist.append(message)
		elif totalcolon == 0:
			notification = notification +1
			senderlist.pop()
			datelist.pop()
			timelist.pop()
		else:
			messagelist.append(sender[1])

file.close()

def get_index_positions(list_of_elems, element):
    ''' Returns the indexes of all occurrences of give element in
    the list- listOfElements '''
    index_pos_list = []
    index_pos = 0
    while True:
        try:
            # Search for item in list from indexPos to the end of list
            index_pos = list_of_elems.index(element, index_pos)
            # Add the index position in list
            index_pos_list.append(index_pos)
            index_pos += 1
        except ValueError as e:
            break
    return index_pos_list

#clearning of data ie. removing file omitted and the chat is deleted
stopwords=[' <Media omitted>',' This message was deleted']
messagelist1 = list(filter(lambda w: w not in stopwords, messagelist))
for i in range(len(stopwords)):
	index_pos_list = list(get_index_positions(messagelist,stopwords[i]))
	location.extend(index_pos_list)
senderlist1 = [i for j, i in enumerate(senderlist) if j not in location]

##for getting the list of different sender
counts = Counter(senderlist)
diffSname=[i for i in counts]

##for getting the list of different date of when the sender sent the message
counts=Counter(datelist)
diffSdate=[i for i in counts]

##this will show the total no of member in the chat
count_of_sender=Counter(senderlist)

nameoffilesender=list(np.array(senderlist)[index_pos_list])

def return_emoji(text):
	"""This functino will return list of all the emoji present in the line
		i dont know why but this function is not working properly when i
		use it to find all the emoji in whatsapp data file it is just returning
		the are or the first sentence with the dual collon in side with that """
	text = emoji.demojize(text)
	text = re.findall(r'(:[^:]*:)', text)
	list_emoji = [emoji.emojize(x) for x in text]
	return list_emoji

def sort_list(list1, list2):
    zipped_pairs = zip(list2, list1)
    z = [x for _, x in sorted(zipped_pairs)]
    return z

def check_all_value():
	"""For checking the data is successfully parsed or not"""
	print(len(datelist))
	print(len(timelist))
	print(len(messagelist))
	print(len(senderlist))

def all_list():
	print(datelist)
	print('*'*100)
	print(timelist)
	print('*'*100)
	print(senderlist)
	print('*'*100)
	print(messagelist)

def readable_table_of_chat():
	"""for printing th dat ain readable format"""
	try:
		print('   DATE       DAY         NAME           MESSAGE     ')
		for i in range(0,len(datelist)):
			print(f'{datelist[i]}  {timelist[i]}   {senderlist[i]}   {messagelist[i]}')
	except:
		pass

print('*'*100+'\n')
def most_active_person():
	"""will give the name of person who is most active in the group with number of comversation only top 10"""
	print("+++++++ List of active in the chat +++++++")
	print("+++++++----------------------------+++++++")
	for item in count_of_sender.most_common(10):
		print(item)
	print('+----------------------------+\n')

def most_file_shared():
	"""who has send the most of the media file like audio, video, sticker etc"""
	index_pos_list = get_index_positions(messagelist, ' <Media omitted>')
	nameoffilesender=list(np.array(senderlist)[index_pos_list])
	count_of_sender=Counter(nameoffilesender)
	print("List of person who sent the most media file:-")
	print('+----------------------------+')
	for item in count_of_sender.most_common(10):
		print(item)
	print('+----------------------------+\n')

def total_missed_calls():
	"""This will show the number of missed video calls"""
	video_call =messagelist.count(' Missed video call')
	print(f'Total no. of missesd video video_call are {video_call}\n')

def mised_audio_call():
	""""This will show you number of missed audio calls"""
	audio_call=messagelist.count(' Missed audio call')
	print(f'Total no. of missed audio calls are {audio_call}\n')

def total_notification():
	"""Total no. of notification in the chat this will include the notification realtead to how many people left or joied the chat or
	    and also some whats data staring notificaiton which is due to phone number change or due to changing their account to an bussiness account"""
	print(f'Total no. of notification are {notification}\n')

def total_chats():
	"""this will show you total no of chats in the data"""
	totalchats = len(messagelist)
	print(f'The total no. of chats is {totalchats}\n')

def average_chat():
	"""total no of chats per day"""
	'''
	#This function will calculate the chat per day by just getting the date of when the first chat happend
	#and the when the last chat happended by dividing the length of all the chat
	#ignoring that if the chat happened on the particular day or not
	if len(datelist[0].split('/')[2])==4:
		firstdate=date(int(datelist[0].split('/')[2]),int(datelist[0].split('/')[1]),int(datelist[0].split('/')[0]))
		lastdate=date(int(datelist[-1].split('/')[2]),int(datelist[-1].split('/')[1]),int(datelist[-1].split('/')[0]))
	else:
		firstdate=date(int('20'+datelist[0].split('/')[2]),int(datelist[0].split('/')[1]),int(datelist[0].split('/')[0]))
		lastdate=date(int('20'+datelist[-1].split('/')[2]),int(datelist[-1].split('/')[1]),int(datelist[-1].split('/')[0]))
	average=totalchats//(lastdate-firstdate).days             #it will remove decimal places in the result '''

	"""this way is much smater and earier this will only take the average of the char on which the chat is happened not like
		above where it will take the aveage or all the day including the day in which the chat is not happened"""
	average=len(messagelist)//len(diffSdate)
	print(f'Total no. of messages per day is {average}\n')

def total_deleted_chat():
	"""This will show total no. of chat is which deleted"""
	totaldeleted = messagelist.count(' This message was deleted')
	print(f'Total no. of deleted messages are {totaldeleted}\n')

def total_words_in_chat():
	"""This will show you total no. of words in the chat"""
	tword=0
	for i in range(len(diffSname)):
		index_pos_list = get_index_positions(senderlist1, diffSname[i])
		nameoffilesender=list(np.array(messagelist1)[index_pos_list])
		t=0
		for j in range(0,len(nameoffilesender)):
			res=len(nameoffilesender[j].split())
			t=t+res
			tword=tword+res
		wordlist.append(t)
		# print(f'The total no. of word send by {diffSname[i]} is {t}')
	print(f'Total no. of word send is {tword}\n')

def total_emoji():
	"""This will show you the total no. of differrent emoji sent in the chat by only top 15 emoji in chat"""
	for i in range(0,len(messagelist)):
		counter = return_emoji(messagelist[i])
		emojilist.extend(counter)
	# print(emojilist)
	count_of_emoji=Counter(emojilist)
	print("list of emoji used:-")
	print('+----------------------------+')
	for item in count_of_emoji.most_common(15):
		print(item)
	print('+----------------------------+\n')

def graph_most_message() :
	"""this will show the graph on which the most message were sent"""
	count_of_message=Counter(datelist)
	messagedata=[item for item in count_of_message.most_common(10)]
	x_value = [x[0] for x in messagedata]
	y_value = [x[1] for x in messagedata]
	plt.figure(1)
	plt.bar(x_value,y_value ,color ='red',width = 0.4)
	plt.title("Graph of most message sent on a particular day")
	plt.xlabel("DATE")
	plt.gcf().autofmt_xdate()
	plt.ylabel('Number of messages')
	# plt.show()      #if you only want to show the this value than only activate this or it will activated from word cloud

def graph_most_active():
	""""this will show the graph of the most active person in the chat but only list the top 10 person in the chat"""
	graphdata=[item for item in count_of_sender.most_common(10)]
	x_val = [x[0] for x in graphdata]
	y_val = [x[1] for x in graphdata]
	plt.figure(2)
	plt.bar(x_val,y_val ,color ='blue',width = 0.4)
	plt.title("No. of message sent by different member\nonly top 10")
	plt.xlabel("Name of member")
	plt.gcf().autofmt_xdate()
	plt.ylabel('Total number of message')

def graph_most_media():
	"""this will show the graph on mosty media sent by user in the chat """
	mediagraph=[item for item in Counter(nameoffilesender).most_common(10)]
	x_value = [x[0] for x in mediagraph]
	y_value = [x[1] for x in mediagraph]

	def func(pct, allvalues):
	    absolute = int(pct / 100.*np.sum(allvalues))
	    return "{:.1f}%\n{:d}".format(pct, absolute)

	fig, ax = plt.subplots()
	ax.pie(y_value,autopct = lambda pct: func(pct, y_value),labels = x_value,shadow = True,)
	fig = pylab.gcf()
	fig.canvas.set_window_title('Figure 3')
	ax.set_title("Percentage of media shared by the members")

def graph_most_word():
	"""this will show the graph os most word sent by different user in the chat"""
	diffSendername=sort_list(diffSname,wordlist)
	wordlists=sorted(wordlist)

	x_value = diffSendername[-20:]
	y_value = wordlists[-20:]
	plt.figure(4)
	ax_sort = sorted(zip(y_value,x_value), reverse=True)
	y_axis = [i[0] for i in ax_sort]
	x_axis = [i[1] for i in ax_sort]
	x_label_pos = range(len(x_axis))
	plt.bar(x_label_pos, y_axis,align="center")
	plt.xticks(x_label_pos,x_axis)
	plt.title("Graph of number of word sent by different member")
	plt.xlabel("Name")
	plt.gcf().autofmt_xdate()
	plt.ylabel('Number of messages')

def graph_most_active_minute_hour():
	"""This will show the hour and minute in which the most message were sent in the group by the person"""
	activetime=Counter(timelist)
	# print("Time when most are active:-")
	activegraph=[ item for item in activetime.most_common(15)]
	# print(item)
	x_val = [x[0] for x in activegraph]
	y_val = [x[1] for x in activegraph]
	plt.figure(5)
	plt.bar(x_val,y_val ,color ='blue',width = 0.4)
	plt.title("Maximum message is sent at this time")
	plt.xlabel("Time")
	plt.gcf().autofmt_xdate()
	plt.ylabel('Total number of message')

def graph_most_active_hour():
	"""this will show the hour in which the most person the chat are active"""
	for a in timelist:
		b=a.split(' ')
		if b[1]=='pm' or b[1]=='PM':
			time=a.split(':')[0]
			time=int(time)+12
			hourlytime.append(time)
		else:
			time=a.split(':')[0]
			hourlytime.append(int(time))
	activehourly=Counter(hourlytime)
	# print("Time when most are active hourly:-")
	activehourlygraph=[item for item in activehourly.most_common(24)]
	# print(item)
	x_value = [x[0] for x in activehourlygraph]
	y_value = [x[1] for x in activehourlygraph]
	plt.figure(6)
	plt.locator_params(axis="x", nbins=len(x_value))
	plt.bar(x_value,y_value ,color ='blue',width = 0.4)
	plt.title("Maximum message is sent in which hour of the day")
	plt.xlabel("Hour")
	plt.gcf().autofmt_xdate()
	plt.ylabel('Total number of message')

def word_cloud():
	"""this will make the word cloud of he word in the chat whcih has been sent by different user  multiple times"""
	unique_string=(" ").join(messagelist)
	stopwords = STOPWORDS.update(['hmm','this','message','was','deleted','Media','omitted','call','missed','video','lo','na','ok', 'will'])
	wordcloud = WordCloud(width = 1000, height = 500,stopwords = stopwords).generate(unique_string)
	plt.figure(figsize=(15,8))
	plt.title("WordCloud of commanly used word")
	plt.imshow(wordcloud)
	plt.axis("off")

##for getting the time when the particular person send the message with graph

def filter2():
	print("\nselect the name of the sender to find the message sent by him")
	for i in range(len(diffSname)):
		print(f'\nFor the detail of {diffSname[i]} type {i+1}')
	print('\nFor previous option press "z"')
	a=input('\nEnter your value here:- ')
	if 'z' in a:
		option()
	elif 'exit' in a:
		exit()
	else:
		try:
			a=int(a)-1
			mainfilter(a)
		except:
			print('Please enter the right value')

def mainfilter(a):
	if bool(diffSname[a])==True:
		print(diffSname[a])
		index_pos_list = list(get_index_positions(senderlist,diffSname[a]))
		print('\nTo apply filter by word press 1')
		print('\nTo apply filter by date press 2')
		print('\nTo apply filter by time press 3')
		print('\nFor previous option press "z"')
		choice=input('\nEnter your choice:- ')
		if choice=='z':
			filter2(a)
		elif choice=='1':
			find=input('Enter to word to search in his chat:- ')
			print('    DATE     TIME          MESSAGE')
			for i in index_pos_list:
				if find in messagelist[i].lower():                   #only use this part if you want to filter the mesagges
					print(f'{datelist[i]} {timelist[i]} {messagelist[i]}')
		elif choice=='2':
			print('*Date must be in the format of "DD/MM/YYYY"')
			find=input('Enter to date to search in his chat:- ')
			print('    DATE     TIME          MESSAGE')
			for i in index_pos_list:
				if find in datelist[i]:                        #only use if you want to filter the message with cetain date
					print(f'{datelist[i]} {timelist[i]} {messagelist[i]}')
		elif choice=='3':    #if you want to get the message of a person about the certain time
			print('*After and before time must be in the form of "HH:MM am/pm"')
			after=input('Enter the after time in which you want to find all the chat:- ')
			before=input('Enter the before time in which you want to find all the chat:- ')
			between=[after,before]
			betweentime=[]
			for a in between:
				b=a.split(' ')
				if b[1]=='pm' or b[1]=='PM':
					time=b[0].split(':')
					if '12' in time[0]:
						time=720+int(time[1])
					else:
						time=(int(time[0])+12)*60+int(time[1])
					betweentime.append(time)
				else:
					time=b[0].split(':')
					if '12' in time[0]:
						time=int(time[1])
					else:
						time=(int(time[0]))*60+int(time[1])
					betweentime.append(int(time))

			for i in index_pos_list:
				b=timelist[i].split(' ')
				if b[1]=='pm' or b[1]=='PM':
					time=b[0].split(':')
					if '12' in time[0]:
						time=720+int(time[1])
					else:
						time=(int(time[0])+12)*60+int(time[1])
				else:
					time=b[0].split(':')
					if '12' in time[0]:
						time=int(time[1])
					else:
						time=(int(time[0]))*60+int(time[1])
				if  betweentime[0]-1 < time and betweentime[1]+1 > time:
					print(f'{datelist[i]} {timelist[i]} {messagelist[i]}')

def option():
	print('+'+('*'*80)+'+')
	print("\nIf you want to get the detail of time of chat of particular person then press 1")
	print("\nIf you want to apply filter on the chat for a particular person then press 2")
	print("\nIf you want to get the detail of all the messages sent by a particular person then press 3")
	print("\nIf you want to exit type exit in command")
	while True:
		command=input('\nEnter your command here:- ')
		print('\n+'+('*'*80)+'+')
		if command=='1':
			print("\nSelect the name of the sender to find the time when the he send the messages")
			for i in range(len(diffSname)):
				print(f'\nFor the detail of {diffSname[i]} type {i+1}')
			print('\nFor previous option press "z"')
			while True:
				a=input('\nEnter your value here:- ')
				if 'z' in a:
					option()
				elif 'exit' in a:
					exit()
				else:
					try:
						a=int(a)-1
						if bool(diffSname[a])==True:
							print(diffSname[a])
							index_pos_list = list(get_index_positions(senderlist,diffSname[a]))
							# ltofs=[timelist[index_pos_list[i]]
							for i in range(len(index_pos_list)):
								ltofs.append(timelist[index_pos_list[i]])
							for j in ltofs:
								f=j.split(' ')
								if f[1]=='pm' or f[1]=='PM':
									time=j.split(':')[0]
									htforS.append(str(int(time)+12))
								else:
									time=j.split(':')[0]
									htforS.append(str(time))
							ahourlyfors=Counter(htforS)
							ahourlyforsgraph=[item for item in ahourlyfors.most_common(24)]
							x_val = [x[0] for x in ahourlyforsgraph]
							y_val = [x[1] for x in ahourlyforsgraph]
							plt.figure(10)
							plt.bar(x_val,y_val ,color ='blue',width = 0.4)
							plt.title(f"Number of message sent by {diffSname[a]} with respect to time")
							plt.xlabel("Time")
							plt.gcf().autofmt_xdate()
							plt.ylabel('Total number of message')
							plt.show()
							ltofs.clear()
							htforS.clear()
							ahourlyforsgraph.clear()
					except:
						print('please enter the right value')
		elif command=='2':
			while True:
				filter2()

		elif command=='3':
			print("\nSelect the name of the sender to show all the message sent by him:-")
			for i in range(len(diffSname)):
				print(f'For the detail of {diffSname[i]} type {i+1}')
			print('For previous option press "z"')
			while True:
				a=input('\nEnter your value here:- ')
				if 'z' in a :
					option()
				elif 'exit' in a:
					exit()
				else:
					try:
						a=int(a)-1
						if bool(diffSname[a])==True:
							print(diffSname[a])
							index_pos_list = list(get_index_positions(senderlist,diffSname[a]))
							print('    DATE     TIME          MESSAGE')
							for i in index_pos_list:
								print(f'{datelist[i]} {timelist[i]} {messagelist[i]}')
					except:
						print("Please enter the right value")
		elif command.lower() == 'exit':
			exit()

		else:
			print('\n---------------: Please enter the right value :------------')
			option()

def show_text_form():
	"""this will show the information in the text format"""
	most_active_person()
	most_file_shared()
	total_missed_calls()
	mised_audio_call()
	total_notification()
	total_chats()
	average_chat()
	total_deleted_chat()
	total_words_in_chat()
	total_emoji()

def show_graph_form():
	"""This will show all the graphs realted to the chats"""
	graph_most_message()
	graph_most_active()
	graph_most_media()
	graph_most_word()
	graph_most_active_minute_hour()
	graph_most_active_hour()
	word_cloud()
	plt.show()

if __name__ == "__main__":
	show_text_form()

	print("\nDo you want to see the graph :- ")
	ans=input("\t").lower()
	if 'yes' in ans:
		show_graph_form()
	else:
		if ans =='exit' or ans == 'z':
			exit()

	option()


import binascii
import hexutils
from ihex import IHex
import os.path
from pgm_error import PgmError
from protocol import Protocol
import time

class Operations:
    def __init__(self, part, io, sync=True):
        """part - Part object, io - *IO object. If sync is True do protocol
        synchronization (if supported by device."""
        self._part = part
        self._io = io
        protocolPath = self._part.getProtocolFileName(self._io.getHardware())
        protocolPath = os.path.join('ProtocolDescriptionFiles', protocolPath)
        self._protocol = Protocol(protocolPath)
        self._wdelay = 1
        """Write delay hack"""
        if sync:
            self.opSync()

    def _opDotOperation(self, operation, **argv):
        """Common function for operation with no result."""
        cmd = self._protocol.getCmd(operation, **argv)
        self._opDotCmd(cmd)

    def _opDotCmd(self, cmd):
        """Common function for operation with no result."""
        self._io.send(cmd)
        data = self._io.recv()
        if data != '.':
            raise PgmError("Invalid response, expected '.' got: %s" % data)

    def opBlankCheck(self, addr_start, size=None):
        if size is None:
            size = self._part.getMemory('FLASH').getSize() - addr_start

        addr = addr_start
        addr_hi_prev = None
        while size > 0:
            addr_hi, addr_lo = divmod(addr, 0x10000)
            if addr_hi != addr_hi_prev:
                addr_hi_prev = addr_hi
                cmd = self._protocol.getCmd('select_memory_page', PPPP=addr_hi)
                self._opDotCmd(cmd)
            addr_end = addr_lo + size - 1
            if addr_end >= 0x10000:
                addr_end = 0xffff
            cmd = self._protocol.getCmd('blank_check', PPPP=addr_lo, QQQQ=addr_end)
            self._opDotCmd(cmd)
            addr = addr_hi * 0x10000 + addr_end + 1
            size = size - (addr_end - addr_lo + 1)

    def opErase(self):
        self._opDotOperation('erase')
        self._wdelayHack()

    def opMemory(self, name):
        self._memory_name = name
        operation = 'select_memory_' + name.lower()
        self._opDotOperation(operation)

    def opProgram(self, data, addr_start=0):
        addr_hi_prev = None
        addr = addr_start
        while data:
            addr_hi, addr_lo = divmod(addr, 0x10000)
            if addr_hi != addr_hi_prev:
                addr_hi_prev = addr_hi
                cmd = self._protocol.getCmd('select_memory_page', PPPP=addr_hi)
                self._opDotCmd(cmd)

            addr_end = addr_lo + len(data)
            if addr_end >= 0x10000:
                addr_end = 0xffff
            size = addr_end + 1 - addr_lo
            buf, data = data[:size], data[size:]
            cmd = self._protocol.getCmd('program_start', PPPP=addr_lo, QQQQ=addr_end)
            self._opDotCmd(cmd)
            self._wdelayHack()
            addr = addr + size

            # send data
            ihex = IHex()
            ihex.insert_data(addr_lo, buf)
            ihex.set_row_bytes(255)
            buf = ihex.write()
            # split to lines, remove, empty strings
            buf = [b for b in buf.splitlines() if b]
            # remove hex end if file
            buf = buf[:-1]
            for d in buf:
                self._opDotCmd(str(d, 'ascii').upper())
                self._wdelayHack()

    def opRead(self, addr_start, size=None):
        if size is None:
            addr_stop = self._part.getMemory(self._memory_name).getSize()
        else:
            addr_stop = addr_start + size
        page_size = self._part.getPageSize()

        data = ''
        addr = addr_start
        addr_hi_prev = None

        while addr < addr_stop:
            addr_hi, addr_lo = divmod(addr, 0x10000)
            if addr_hi != addr_hi_prev:
                addr_hi_prev = addr_hi
                cmd = self._protocol.getCmd('select_memory_page', PPPP=addr_hi)
                self._opDotCmd(cmd)
            addr_end = addr_lo + page_size - 1
            if addr_end > addr_stop:
                addr_end = addr_stop - 1
            if addr_end >= 0x10000:
                addr_end = 0x10000 - 1
            cmd = self._protocol.getCmd('read_memory', PPPP=addr_lo, QQQQ=addr_end)
            self._io.send(cmd)

            r_addr = addr
            while addr_lo <= addr_end:
                buf = self._io.recv()
                # AAAA=ddddddd....
                r_addr, r_eq, r_data = buf[:4], buf[4:5], buf[5:]
                if r_eq != '=':
                    raise PgmError("Expected 'xxxx=...' in :%s" % buf)
                if r_addr != ("%.4X" % addr_lo):
                    raise PgmError("Invalid address in response got: %s exp: %s data: %s" %
                            (r_addr, addr_lo, bug))
                addr_lo = addr_lo + len(r_data) / 2
                data = data + r_data

            addr = addr_hi * 0x10000 + addr_end + 1

        return binascii.unhexlify(data)

    def opStartAppl(self, reset):
        if reset:
            cmd = self._protocol.getCmd('startAppliWithReset')
        else:
            cmd = self._protocol.getCmd('startAppliWithoutReset')
        self._io.send(cmd)
        # read \x00 if follows by reset, or timeout
        self._io.readRaw(1)

    def opSync(self):
        """Called only once to synchronize bytestream."""
        if self._protocol.hasCmd('sync'):
            sync = self._protocol.getCmd('sync')
            sync = bytes(sync, 'ascii')
            self._io.writeRaw(sync)
            r = self._io.readRaw(len(sync))
            if r != sync:
                raise PgmError('Synchronization failed, invalid response: %s' % r)

    def _wdelayHack(self):
        time.sleep(self._wdelay)