import re
import urllib.parse
from bs4 import BeautifulSoup

from . import url

def name(soup):
	title_bar = soup.find('div', {"class": "titleBar"})
	name = title_bar.h1.text
	#logger.debug("parse_brewery_name: name: {}".format(name))
	return name

def beers(soup):
	baContent = soup.find("div", {"id":"ba-content"})
	#logger.debug("parse_beers_from_brewery: ba-content: {}".format(baContent))

	sortable_table = soup.find("table", {"class": "sortable"})
	if not sortable_table:
		return []
	t_body = sortable_table.tbody

	this_brewery_beers = []

	for row in t_body:
		cols = row.find_all('td')
		beer = {}

		# Get Link and Name from 1st col
		#a = cols[0].find('a', href=re.compile('/beer/profile/'))
		a = cols[0].a
		link = a['href']
		beer['id'] = url.beer_id(link)
		# NOTE The brewery ID is extracted from the link to every beer because
		#				some places list beers that redirect to different breweries.
		beer['brewery_id'] = url.brewery_id(link)
		beer['name'] = a.text

		# Get Style from 2nd col
		beer['style'] = a = cols[1].a.text

		# Get ABV from 3rd col
		abv_text = cols[2].text
		try:
			beer['abv'] = float(abv_text)
		except:
			beer['abv'] = None

		# Get Ratings from 4th col
		ratings_text = cols[3].text
		try:
			beer['ratings'] = float(ratings_text)
		except:
			beer['ratings'] = None

		# Get Score from 5th col
		score_text = cols[4].text
		try:
			beer['score'] = float(score_text)
		except:
			beer['score'] = None

		this_brewery_beers.append(beer)

	return this_brewery_beers


from .models import Order, Customer
from django.http import HttpResponse

def cartData(request):
    try:
        customer = request.user.customer
    except:
        device = request.COOKIES['device']
        customer, created = Customer.objects.get_or_create(device=device)

    order, created = Order.objects.get_or_create(customer=customer, complete=False)
    items = order.orderitem_set.all()
    counterCartItems = order.get_amount_of_items_cart
    cartItems = order.get_cart_items

    return {'cartItems': cartItems, 'counterCartItems': counterCartItems, 'customer': customer, 'order': order, 'items':items}


def is_pent(n):
    quad = (1 + (1+24 * n)**(1/2))/6
    if quad == int(quad):
        return True
    return False

def is_hex(n):
    quad = (1 + (1+ 8 * n)**(1/2))/4
    if quad == int(quad):
        return True
    return False

stop = False

i = 286
while not stop:
    tn = i * (i+1) / 2
    if is_hex(tn):
        if is_pent(tn):
            stop = True
            print('Tn: ',tn)

    i+=1

print(is_hex(7906276))


# Api Agenda Lionx
from src.infrastructures.mongo.mongo_infrastructure import MongoInfrastructure

# Third party
from decouple import config
from pymongo.cursor import Cursor
from pymongo.collection import InsertOneResult, UpdateResult

class MongoRepository:
    def __init__(self):
        self.mongo_client = MongoInfrastructure.get_client()
        self.database = self.mongo_client.get_database(config("DATABASE_NAME"))
        self.collection = self.database.get_collection(config("COLLECTION_NAME"))

    def get_all_contacts(self) -> Cursor:
        remove_pymongo_id = {"_id": 0}
        contacts_cursor = self.collection.find({}, remove_pymongo_id)
        return contacts_cursor

    def get_contact_by_id(self, id) -> dict:
        filter_by_id = {"contact_id": id, "situation": "active"}
        remove_pymongo_id = {"_id": 0}
        contact = self.collection.find_one(filter_by_id, remove_pymongo_id)
        return contact

    def get_contacts_by_first_letters(self, letters) -> Cursor:
        regex_first_letters_contact = {"$regex": f"^{letters}", "$options": "i"}
        filter_by_first_name_letters = {"firstName": regex_first_letters_contact, "situation": "active"}
        remove_pymongo_id = {"_id": 0}
        contacts_cursor = self.collection.find(filter_by_first_name_letters, remove_pymongo_id)
        return contacts_cursor

    def register_contact(self, new_contact) -> InsertOneResult:
        insert_result = self.collection.insert_one(new_contact)
        return insert_result

    def update_contact(self, edited_contact, id) -> UpdateResult:
        filter_by_id = {"contact_id": id}
        new_values = {"$set": edited_contact}
        update_result = self.collection.update_one(filter_by_id, new_values)
        return update_result

    def soft_delete_contact(self, id) -> UpdateResult:
        filter_by_id = {"contact_id": id}
        field_to_update = {"$set": {"situation": "deactivated"}}
        update_result = self.collection.update_one(filter_by_id, field_to_update)
        return update_result


#!/usr/bin/env python2.6
# -*- coding: utf-8 -*-

# mainframe.py
# Pomodoro
#
# Created by Roman Rader on 22.06.11.
# New BSD License 2011 Antigluk https://github.com/antigluk/Pomodoro

"""

Contains main frame of application.

"""

import wx
from state import PomodoroStateProxy as PomodoroState
from NotificationCenter.NotificationCenter import NotificationCenter
import logging
logging.getLogger('Pomodoro')

class MainFrameController(wx.Frame):
    """Main frame of Pomodoro"""
    def __init__(self):
        wx.Frame.__init__(
            self,
            None,
            -1,
            'Pomodoro it!',
            style=wx.BORDER_DEFAULT | wx.STAY_ON_TOP,
            size=(220, 120),
            )
        state = PomodoroState()
        self.__state_dict = {
            state.StateNoState: {'bs': '...'},
            state.StateInPomodoro: {'bs': u"Отменить..."},
            state.StateInRest: {'bs': u"Отдыхайте!"},
            state.StateWaitingPomodoro: {'bs': u"Начать помидору"},
            state.StateWaitingRest: {'bs': u"Начать отдых"},
            state.StatePomodoroKilled: {'bs': u"Начать помидору"},
            }
        self.buildFrame()
        self.updateUI()
        self.makeMenu()
        self.Show(False)
        NotificationCenter().addObserver(self,self.onDBUpdate,"dbUpdated")
        NotificationCenter().addObserver(self,self.onUpdateUI,"updateUI")

    def buildFrame(self):
        self.panel = wx.Panel(self)
        self.txt = wx.StaticText(self.panel, pos=(10, 10),
                                 label='Pomodoro!')
        self.times_l = wx.StaticText(self.panel, pos=(120, 10),
                label=u"0 помидор")
        self.timer_ctrl = wx.TextCtrl(self.panel, pos=(10, 30),
                size=(200, -1), style=wx.TE_READONLY | wx.TE_CENTER)
        self.start_button = wx.Button(self.panel, pos=(20, 70), label=''
                , size=(170, -1))
        self.start_button.Bind(wx.EVT_BUTTON, self.bClick)

    def onUpdateUI(self, event):
        self.updateUI()

    def updateUI(self):
        #TODO: проверять видимо ли окно. иначе не обновлять
        #TODO: remove this ugly method
        state = PomodoroState()
        self.timer_ctrl.SetValue(state.text)
        self.start_button.SetLabel(self.__state_dict[state.active]['bs'])
        self.txt.SetLabel(state.caption)
        self.times_l.SetLabel(u"%d помидор" % state.GetTodayCount())

    def bClick(self, m):
        logging.debug("Toggle state called from menu")
        self.controller.toggleState()

    def onExit(self,m):
        logging.debug("Quit called from menu")
        self.controller.quit()

    def makeMenu(self):
        self.menuBar = wx.MenuBar()

        self.filemenu = wx.Menu()
        self.pomodmenu = wx.Menu()

        item = self.filemenu.Append(wx.ID_ANY, "Hide")
        self.Bind(wx.EVT_MENU, self.hideFrame, item)
        item = self.filemenu.Append(wx.ID_ANY, "Toggle pomodoro")
        self.Bind(wx.EVT_MENU, self.bClick, item)
        self.filemenu.AppendSeparator()
        item = self.filemenu.Append(wx.ID_EXIT, "&Quit", "quit")
        self.Bind(wx.EVT_MENU, self.onExit, id=wx.ID_EXIT)

        item = self.pomodmenu.Append(wx.ID_ANY, "All", "List of pomodoros")
        self.Bind(wx.EVT_MENU, self.showListOfPomodoros, item)
        item = self.pomodmenu.Append(wx.ID_ANY, "Statistics", "Statistics")
        self.Bind(wx.EVT_MENU, self.showStatistics, item)

        self.menuBar.Append(self.filemenu, "&File")
        self.menuBar.Append(self.pomodmenu, "&Pomodors")

        self.SetMenuBar(self.menuBar)

    def onDBUpdate(self, obj):
        pass

    def hideFrame(self, m):
        logging.debug("Hide frame called from menu")
        self.Show(False)

    def showListOfPomodoros(self, m):
        logging.debug("Show list of pomodors called from menu")
        self.controller.showListOfPomodoros()

    def showStatistics(self, m):
        logging.debug("Show statistics of pomodors called from menu")
        self.controller.showStatistics()


#encoding:UTF-8

import urllib
import urllib.request
import json
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
import matplotlib.lines as mlines
import numpy as np
import time

data = urllib.request.urlopen('https://stationdata.wunderground.com/cgi-bin/stationdata?iconsize=3&width=2048&height=2048&maxage=3600&format=json&maxstations=100000&rf_filter=1&minlat=38&minlon=-85&maxlat=48&maxlon=-73').read()
record = data.decode('UTF-8')
record = record.replace('},}', '}}')
a = open("/Users/hsw/Desktop/CA_region_rawdata.txt", "w+")
a.write(record)
a.close()

data = json.loads(record)
#print(data)

print(data['conds'])
preprocess = data['conds']

station = []
T = []
lats = []
lons = []

for o in preprocess:
    id = str(o)
    station.append(preprocess[id]['id'])
    T.append(5/9*(float(preprocess[id]['tempf'])-32))
    lats.append(float(preprocess[id]['lat']))
    lons.append(float(preprocess[id]['lon']))

# ============================================ # plot
# ============================================initialize the plot
plt.figure(figsize=(11, 8), dpi=120)
axes = plt.subplot(111)
# set up map projection with
# use low resolution coastlines.
map = Basemap(llcrnrlon=-87, llcrnrlat=38, urcrnrlon=-73, urcrnrlat=48, \
              rsphere=(6378137.00, 6356752.3142), \
              resolution='i', projection='merc', \
              lat_0=40., lon_0=-20., lat_ts=20.)
# draw coastlines, country boundaries, fill continents.
map.drawcoastlines(linewidth=0.25)
map.drawcountries(linewidth=0.25)
# draw the edge of the map projection region (the projection limb)
map.drawmapboundary(fill_color='#87CEFA')#689CD2
# draw lat/lon grid lines every 30 degrees.

#map.drawmeridians(np.arange(0, 360, 10))
map.drawmeridians(np.arange(0, 360, 10),labels=[0,0,0,1],fontsize=10)
#map.drawparallels(np.arange(-90, 90, 10))
map.drawparallels(np.arange(-90, 90, 10),labels=[1,0,0,0],fontsize=10)

# Fill continent wit a different color
map.fillcontinents(color='#FFFFFF', lake_color='#EEEEEE', zorder=0)

# ============================================draw the stations and data
# compute native map projection coordinates of lat/lon grid.
x, y = map(lons, lats)
max_T = max(T)
# Plot each city in a loop.
# Set some parameters
size_factor = 100.0
x_offset = 20.0
y_offset = -20.0
rotation = 0
temp=0

f = open("/Users/hsw/Desktop/CA_region_Tdata.txt", "w+")
f.close()
#draw station point

analyze = ''

for i, j, k, l in zip(x, y, T, station):
    temp = temp+1
    size = size_factor * k / max_T
    if k <= -10.0 and k >= -100.0:
        cs1 = map.scatter(i, j, s=15, marker='o', color='#00008F')
    if -10 < k and k <= -5:
        cs2 = map.scatter(i, j, s=15, marker='o', color='#00009F')
    if -5 < k and k <= -2:
        cs3 = map.scatter(i, j, s=15, marker='o', color='#0000FF')
    if -2 < k and k <= 2:
        cs4 = map.scatter(i, j, s=15, marker='o', color='#006FFF')
    if 2 < k and k <= 6:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#00BFFF')
    if 6 <= k and k <= 10:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#00FFFF')
    if 10 <= k and k <= 14:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#4FFFAF')
    if 14 <= k and k <= 18:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#7FF77F')
    if 18 <= k and k <= 22:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#FFFF00')
    if 22 <= k and k <= 26:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#FFBF00')
    if 26 <= k and k <= 30:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#FF6F00')
    if 30 <= k and k <= 35:
        cs5 = map.scatter(i, j, s=15, marker='o', color='#FF0000')
    if 35 < k and k <= 100:
        cs6 = map.scatter(i, j, s=15, marker='o', color='#7F0000')

    #if k != 9999:
    #    plt.text(i, j, str(k) + '°C', rotation=rotation, fontsize=10)

    f = open("/Users/hsw/Desktop/CA_region_Tdata.txt", "a+")
    f.write(' Station:'+ l + ' Temperature:' + str(k) + '\n')
    f.close()

title = '多伦多及附近地区气温分布图\n' + '数据更新时间:' + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()- 8 * 60 * 60 * 1000)) + 'UTC\n数据来自：wunderground weather, 绘制@Louis_He'
# ============================================#define legends
a = mlines.Line2D([], [], color='#7F0000', marker='o',
                              markersize=5, label='>35°C',ls='')
b = mlines.Line2D([], [], color='#FF0000', marker='o',
                              markersize=5, label='>30°C',ls='')
c = mlines.Line2D([], [], color='#FF6F00', marker='o',
                              markersize=5, label='26~30°C',ls='')
d = mlines.Line2D([], [], color='#FFBF00', marker='o',
                          markersize=5, label='22~26°C',ls='')
e = mlines.Line2D([], [], color='#FFFF00', marker='o',
                          markersize=5, label='18~22°C',ls='')
f = mlines.Line2D([], [], color='#7FF77F', marker='o',
                          markersize=5, label='14~18°C',ls='')
g = mlines.Line2D([], [], color='#4FFFAF', marker='o',
                          markersize=5, label='10~14°C',ls='')
h = mlines.Line2D([], [], color='#00FFFF', marker='o',
                          markersize=5, label='6~10°C',ls='')
i = mlines.Line2D([], [], color='#00BFFF', marker='o',
                          markersize=5, label='2~6°C',ls='')
j = mlines.Line2D([], [], color='#006FFF', marker='o',
                          markersize=5, label='-2~2°C',ls='')
k = mlines.Line2D([], [], color='#0000FF', marker='o',
                          markersize=5, label='-5~-2°C',ls='')
l = mlines.Line2D([], [], color='#00009F', marker='o',
                          markersize=5, label='-10~-5°C',ls='')
m = mlines.Line2D([], [], color='#00008F', marker='o',
                          markersize=5, label='<-10°C',ls='')
plt.legend(handles=[b, c, d, e, f, g, h, i, j, k, l, m])
plt.title(title)

save = '/Users/hsw/Desktop/CA_region_Tsample.png'
plt.savefig(save, dpi=120)


# 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

from collections import deque

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []

        queue = deque([root])
        result = []

        while queue:
            levelLength = len(queue)
            levelResult = []

            for i in range(levelLength):
                current_node = queue.popleft()
                levelResult.append(current_node.val)

                if current_node.left:
                    queue.append(current_node.left)

                if current_node.right:
                    queue.append(current_node.right)

            result.append(levelResult)

        return result


from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_insertar(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(570, 518)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setFlat(True)
        self.groupBox.setObjectName("groupBox")
        self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox)
        self.verticalLayout_9.setObjectName("verticalLayout_9")
        self.frame_11 = QtWidgets.QFrame(self.groupBox)
        self.frame_11.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_11.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_11.setObjectName("frame_11")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame_11)
        self.horizontalLayout_5.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.verticalLayout_9.addWidget(self.frame_11)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.verticalLayout_9.addItem(spacerItem)
        self.frame_12 = QtWidgets.QFrame(self.groupBox)
        self.frame_12.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_12.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_12.setObjectName("frame_12")
        self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.frame_12)
        self.verticalLayout_10.setObjectName("verticalLayout_10")
        self.label_12 = QtWidgets.QLabel(self.frame_12)
        self.label_12.setFrameShadow(QtWidgets.QFrame.Plain)
        self.label_12.setAlignment(QtCore.Qt.AlignCenter)
        self.label_12.setObjectName("label_12")
        self.verticalLayout_10.addWidget(self.label_12)
        self.verticalLayout_9.addWidget(self.frame_12)
        self.frame_13 = QtWidgets.QFrame(self.groupBox)
        self.frame_13.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_13.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_13.setObjectName("frame_13")
        self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.frame_13)
        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
        self.frame_14 = QtWidgets.QFrame(self.frame_13)
        self.frame_14.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_14.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_14.setObjectName("frame_14")
        self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.frame_14)
        self.verticalLayout_11.setObjectName("verticalLayout_11")
        self.label_13 = QtWidgets.QLabel(self.frame_14)
        self.label_13.setObjectName("label_13")
        self.verticalLayout_11.addWidget(self.label_13)
        self.label_14 = QtWidgets.QLabel(self.frame_14)
        self.label_14.setObjectName("label_14")
        self.verticalLayout_11.addWidget(self.label_14)
        self.label_15 = QtWidgets.QLabel(self.frame_14)
        self.label_15.setObjectName("label_15")
        self.verticalLayout_11.addWidget(self.label_15)
        self.horizontalLayout_6.addWidget(self.frame_14)
        self.frame_15 = QtWidgets.QFrame(self.frame_13)
        self.frame_15.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_15.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_15.setObjectName("frame_15")
        self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.frame_15)
        self.verticalLayout_12.setObjectName("verticalLayout_12")
        self.text_act1 = QtWidgets.QLineEdit(self.frame_15)
        self.text_act1.setObjectName("text_act1")
        self.verticalLayout_12.addWidget(self.text_act1)
        self.text_act2 = QtWidgets.QLineEdit(self.frame_15)
        self.text_act2.setObjectName("text_act2")
        self.verticalLayout_12.addWidget(self.text_act2)
        self.text_act3 = QtWidgets.QLineEdit(self.frame_15)
        self.text_act3.setObjectName("text_act3")
        self.verticalLayout_12.addWidget(self.text_act3)
        self.horizontalLayout_6.addWidget(self.frame_15)
        self.frame_16 = QtWidgets.QFrame(self.frame_13)
        self.frame_16.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_16.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_16.setObjectName("frame_16")
        self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.frame_16)
        self.verticalLayout_13.setObjectName("verticalLayout_13")
        self.label_16 = QtWidgets.QLabel(self.frame_16)
        self.label_16.setObjectName("label_16")
        self.verticalLayout_13.addWidget(self.label_16)
        self.label_17 = QtWidgets.QLabel(self.frame_16)
        self.label_17.setObjectName("label_17")
        self.verticalLayout_13.addWidget(self.label_17)
        self.label_18 = QtWidgets.QLabel(self.frame_16)
        self.label_18.setObjectName("label_18")
        self.verticalLayout_13.addWidget(self.label_18)
        self.horizontalLayout_6.addWidget(self.frame_16)
        self.frame_17 = QtWidgets.QFrame(self.frame_13)
        self.frame_17.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_17.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_17.setObjectName("frame_17")
        self.verticalLayout_14 = QtWidgets.QVBoxLayout(self.frame_17)
        self.verticalLayout_14.setObjectName("verticalLayout_14")
        self.text_act4 = QtWidgets.QLineEdit(self.frame_17)
        self.text_act4.setObjectName("text_act4")
        self.verticalLayout_14.addWidget(self.text_act4)
        self.text_act5 = QtWidgets.QLineEdit(self.frame_17)
        self.text_act5.setObjectName("text_act5")
        self.verticalLayout_14.addWidget(self.text_act5)
        self.text_act6 = QtWidgets.QLineEdit(self.frame_17)
        self.text_act6.setObjectName("text_act6")
        self.verticalLayout_14.addWidget(self.text_act6)
        self.horizontalLayout_6.addWidget(self.frame_17)
        self.verticalLayout_9.addWidget(self.frame_13)
        self.frame_18 = QtWidgets.QFrame(self.groupBox)
        self.frame_18.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_18.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_18.setObjectName("frame_18")
        self.verticalLayout_15 = QtWidgets.QVBoxLayout(self.frame_18)
        self.verticalLayout_15.setObjectName("verticalLayout_15")
        self.label_19 = QtWidgets.QLabel(self.frame_18)
        self.label_19.setAlignment(QtCore.Qt.AlignCenter)
        self.label_19.setObjectName("label_19")
        self.verticalLayout_15.addWidget(self.label_19)
        self.verticalLayout_9.addWidget(self.frame_18)
        self.frame_19 = QtWidgets.QFrame(self.groupBox)
        self.frame_19.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_19.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_19.setObjectName("frame_19")
        self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.frame_19)
        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
        self.label_20 = QtWidgets.QLabel(self.frame_19)
        self.label_20.setObjectName("label_20")
        self.horizontalLayout_7.addWidget(self.label_20)
        self.text_estado = QtWidgets.QLineEdit(self.frame_19)
        self.text_estado.setObjectName("text_estado")
        self.horizontalLayout_7.addWidget(self.text_estado)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_7.addItem(spacerItem1)
        self.verticalLayout_9.addWidget(self.frame_19)
        self.verticalLayout.addWidget(self.groupBox)
        self.frame_10 = QtWidgets.QFrame(Form)
        self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_10.setFrameShadow(QtWidgets.QFrame.Plain)
        self.frame_10.setObjectName("frame_10")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.frame_10)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem2)
        self.btn_guardar = QtWidgets.QPushButton(self.frame_10)
        self.btn_guardar.setObjectName("btn_guardar")
        self.horizontalLayout_4.addWidget(self.btn_guardar)
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem3)
        self.verticalLayout.addWidget(self.frame_10)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Insetar datos"))
        self.groupBox.setTitle(_translate("Form", "Insertar datos de entrenamiento"))
        self.label_12.setText(_translate("Form", "Para cada actividad, introduce \"A\" si aprobo, \"R\" si reprobo o \"NP\" si no presento."))
        self.label_13.setText(_translate("Form", "Actividad 1:"))
        self.label_14.setText(_translate("Form", "Actividad 2:"))
        self.label_15.setText(_translate("Form", "Actividad 3:"))
        self.label_16.setText(_translate("Form", "Actividad 4:"))
        self.label_17.setText(_translate("Form", "Actividad 5:"))
        self.label_18.setText(_translate("Form", "Actividad 6:"))
        self.label_19.setText(_translate("Form", "Introduce \"SI\" o \"NO\""))
        self.label_20.setText(_translate("Form", "Aprobo: "))
        self.text_estado.setPlaceholderText(_translate("Form", "Ingrese \"SI\" o \"NO\""))
        self.btn_guardar.setText(_translate("Form", "Guardar datos"))


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from rp_ui_harness import RequestPolicyTestCase
from marionette import expectedFailure
from marionette_driver import Wait
import re

msg = ("Marionette -- test_logging_error_detection -- "
       "this test is expected to fail")

class ErrorDetectionTests(object):

    ################
    # Test Methods #
    ################

    def test_normal_error(self, n=1):
        self.error_triggerer.trigger_error(
            "error", "backgroundscript", msg=msg)
        self._do_checks(
            n,
            r'^console.error:\s+\[RequestPolicy\] ' + msg + '$')

    def test_reference_error(self, n=1):
        self.error_triggerer.trigger_error(
            "ReferenceError", "backgroundscript")
        self._do_checks(
            n,
            (
                r"^JavaScript error: "
                r"chrome://rpcontinued/content/ui-testing/services\.js, "
                r"line [0-9]+: ReferenceError: "
            )
        )

    def test_reference_error_in_promise_chain(self, n=1):
        self.error_triggerer.trigger_error(
            "ReferenceError:Promise", "backgroundscript")
        self._do_checks(
            n,
            (
                r"^JavaScript error: "
                r"chrome://rpcontinued/content/ui-testing/services\.js, "
                r"line [0-9]+: ReferenceError: "
            )
        )

    ##########################
    # Private Helper Methods #
    ##########################

    def _do_checks(self, n, message_regexp):
        raise NotImplementedError

class ErrorDetectionTestCase(RequestPolicyTestCase):

    expected_error = False

    def setUp(self):
        super(ErrorDetectionTestCase, self).setUp()
        self.gecko_log.start_ignoring_errors(expected=self.expected_error)

    def tearDown(self):
        try:
            self.gecko_log.stop_ignoring_errors()
        finally:
            super(ErrorDetectionTestCase, self).tearDown()

class TestGeckoLog(ErrorDetectionTests, ErrorDetectionTestCase):

    def setUp(self):
        super(TestGeckoLog, self).setUp()

        self._assert_n_errors(0)

    ##########################
    # Private Helper Methods #
    ##########################

    def _do_checks(self, n, message_regexp):
        self._assert_n_errors(n)
        self._assert_error(message_regexp)

    def _get_error_lines_including_ignored_errors(self):
        return self.gecko_log.get_error_lines_of_current_test(
            return_ignored_as_well=True)

    def _get_error_lines(self):
        return self.gecko_log.get_error_lines_of_current_test()

    def _assert_n_errors(self, n):
        Wait(self.marionette).until(
            lambda _: (
                len(self._get_error_lines_including_ignored_errors()) == n
            )
        )
        self.assertEqual(0, len(self._get_error_lines()))

    def _assert_error(self, message_regexp):
        error_lines = self._get_error_lines_including_ignored_errors()
        line = error_lines[-1]
        self.assertTrue(
            re.search(message_regexp, line),
            msg=("String \"" + line + "\" matched!"))

class TestFailureOnTearDown(ErrorDetectionTests, ErrorDetectionTestCase):

    expected_error = True

    @expectedFailure
    def tearDown(self):
        super(TestFailureOnTearDown, self).tearDown()

    ##########################
    # Private Helper Methods #
    ##########################

    # Explicitly do *not* perform checks in _do_checks(), to test if the
    # TestRunner's tearDown fn waits long enough to detect all logging errors.

    def _do_checks(self, n, message_regexp):
        pass


# 给你 二维 平面上两个 由直线构成且边与坐标轴平行/垂直 的矩形，请你计算并返回两个矩形覆盖的总面积。

# 每个矩形由其 左下 顶点和 右上 顶点坐标表示：

# 第一个矩形由其左下顶点 (ax1, ay1) 和右上顶点 (ax2, ay2) 定义。
# 第二个矩形由其左下顶点 (bx1, by1) 和右上顶点 (bx2, by2) 定义。

class Solution(object):
    def computeArea(self, ax1, ay1, ax2, ay2, bx1, by1, bx2, by2):
        """
        :type ax1: int
        :type ay1: int
        :type ax2: int
        :type ay2: int
        :type bx1: int
        :type by1: int
        :type bx2: int
        :type by2: int
        :rtype: int
        """
        lengthX = max(min(ax2, bx2) - max(ax1, bx1), 0)
        lengthY = max(min(ay2, by2) - max(ay1, by1), 0)

        area1 = (ax2 - ax1) * (ay2 - ay1)
        area2 = (bx2 - bx1) * (by2 - by1)

        return area1 + area2 - lengthX * lengthY

ax1 = -3
ay1 = 0
ax2 = 3
ay2 = 4
bx1 = 0
by1 = -1
bx2 = 9
by2 = 2

a = Solution()
print(a.computeArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2))


# -*- coding: utf-8 -*-
"""
Created on Wed Nov 23 12:32:47 2022

@author: maksi
"""

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.datasets import load_digits
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

data = load_digits()
X = data.data
y = data.target
y = pd.Categorical(y)
y = pd.get_dummies(y).values
class_num = y.shape[1]

model = Sequential()
model.add(Dense(64, input_shape = (X.shape[1],), activation = 'relu'))
model.add(Dense(64, activation = 'relu'))
model.add(Dense(64, activation = 'relu'))
model.add(Dense(class_num, activation = 'softmax'))
learning_rate = 0.0001
model.compile(optimizer= Adam(learning_rate), loss='categorical_crossentropy',metrics=('accuracy'))
model.summary()

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
model.fit(X_train, y_train, batch_size=32, epochs=100, validation_data=(X_test, y_test), verbose=2)

historia = model.history.history
floss_train = historia['loss']
floss_test = historia['val_loss']
acc_train = historia['accuracy']
acc_test = historia['val_accuracy']
fig,ax = plt.subplots(1,2, figsize=(20,10))
epochs = np.arange(0, 100)

ax[0].plot(epochs, floss_train, label = 'floss_train')
ax[0].plot(epochs, floss_test, label = 'floss_test')
ax[0].set_title('Funkcje strat')
ax[0].legend()

ax[1].set_title('Dokladnosci')
ax[1].plot(epochs, acc_train, label = 'acc_train')
ax[1].plot(epochs, acc_test, label = 'acc_test')
ax[1].legend()


#!/usr/bin/python3
"""
This is a file to print squares with a given number
I am making up some words to get a better score I think
"""

def print_square(size):
    """Prints a square with a given size"""
    if type(size) is not int:
        TypeError("size must be an integer")
    if size < 0:
        ValueError("size must be >= 0")
    for i in range(size):
        for j in range(size):
            print("#", end="")
        print()


"""
Here we test a basic strategy that includes an indicator and FX rate movements.

We'll start with an ($100K) AUD denominated portfolio and buy 100 shares of SPY
only if the VIX < 26.

Also, buying in SPY will make us short USD.
Generate funding trades, to be executed the day after we buy SPY, so that
we aren't short USD.

For the sake of testing we'll focus on the dates 1st Sep -> 1st Oct.
Points to note:
-  We'll buy 100 shares of SPY @337.11 on Sep 14th VIX=25.85
-  Hold until Oct 1st when SPY=337.04, AUDUSD=0.7167
-  Because our portfolio is denominated in AUD we need to calculate AUD prices.
-  So buying SPY at 337.11 (Sep 14th price) / 0.729682 (fx 15th) = AUD 462
-  And holding to a value of 337.04 / 0.716651 = AUD 470.30
-  PNL will be $8.30 (= 470.30 - 462.00) for each of 100 shares purchased.
"""
from datetime import date
import pandas as pd
from pxtrade import Trade
from pxtrade.assets import reset, Stock, Cash, FxRate, Portfolio
from pxtrade.backtest import Backtest
from pxtrade.strategy import Strategy
from pxtrade.events.yahoo import load_yahoo_prices
from pxtrade.compliance import Compliance, UnitLimit
from pxtrade.history import History

def test_buy_spy_with_indicator():
    # create your stock and portfolio
    reset()
    spy = Stock("SPY", currency_code="USD")
    aud = Cash("AUD")
    usd = Cash("USD")
    audusd = FxRate("AUDUSD")
    portfolio = Portfolio("AUD")
    starting_value = 1e5  # start with $100K AUD
    portfolio.transfer(aud, starting_value)

    # impose a compliance rule so we are unable to
    # hold more than 100 shares.
    portfolio.compliance = Compliance().add_rule(UnitLimit(spy, 100))

    # define a strategy to buy 100 shares of SPY
    # if we are short USD then also fund this shortfall with AUD
    class BuySpyWithIndicator(Strategy):
        def show(self, trades):
            if len(trades) == 0:
                return
            print(backtest.datetime)
            print("^VIX: ", backtest.get_indicator("^VIX"))
            print("AUDUSD: ", audusd.rate)
            print("SPY: ", spy.price)
            for trade in trades:
                print(trade)
            print("-------")

        def generate_trades(self):
            trades = list()
            usd_holding = portfolio.get_holding_units("USD")
            if usd_holding < 0:
                trades.append(Trade(portfolio, usd, int(-usd_holding) + 1))

            if backtest.get_indicator("^VIX") >= 26:
                # don't buy any spy, just fund usd (if required)
                self.show(trades)
                return trades

            trades.append(Trade(portfolio, spy, 100))
            self.show(trades)
            return trades

    # create your backtest instance
    backtest = Backtest(BuySpyWithIndicator())
    history = History(
        portfolios=portfolio,
        backtest=backtest,
    )

    # load price events from yahoo for spy, audusd, vix
    start_date = date(2020, 9, 1)
    end_date = date(2020, 10, 1)
    load_yahoo_prices(
        [spy, audusd, "^VIX"],
        backtest,
        start_date=start_date,
        end_date=end_date,
    )

    # run the backtest and check pnl
    backtest.run()
    df = history.get()
    # print(portfolio)
    # print(audusd.rate)
    print(backtest.datetime)
    print(df)

    # Note that when running on windows the last FX rate we get from yahoo
    # is on the 30 Sep AUDUSD = 7.716651. However, running on linux we get
    # a price from 1 Oct of AUDUSD = 0.718288.
    # This looks to be an issue with the yahoo api, but it has implications
    # for our assertions around portfolio value.
    starting_aud_price = 462  # this has not changed
    ending_aud_price = 337.04 / audusd.rate
    expected_pnl = (ending_aud_price - starting_aud_price) * 100
    expected_value = starting_value + expected_pnl
    assert round(portfolio.value, -1) == round(expected_value, -1)

    start_date = pd.Timestamp(start_date)
    end_date = pd.Timestamp(end_date)
    assert int(df.at[start_date, "Portfolio"]) == int(starting_value)
    assert round(df.at[end_date, "Portfolio"], -1) == round(expected_value, -1)
    assert round(df.at[pd.Timestamp(date(2020, 9, 14)), "^VIX"], 2) == 25.85


from pynput.keyboard import Listener, Key
import time
from threading import Thread
from canvas import Canvas
from pedal import Pedal
from snake import Snake
from ball import Ball
import os

def on_press(key):
    if hasattr(key, 'char'):  # Write the character pressed if available
      print(key.char)

    elif key == Key.up:  # If space was pressed, write a space
      print('up')
      snake.up()
    elif key == Key.down:  # If space was pressed, write a space
      print('down')
      snake.down()

    elif key == Key.left:  # If space was pressed, write a space
      print('left')
      snake.left()

    elif key == Key.right:  # If space was pressed, write a space
      print('right')
      snake.right()

canvas = Canvas(15, 50)
snake = Snake(10, 5)
snake.left()
pedal = Pedal(1, 7)
ball = Ball(8,7)

gameover = False
while(not gameover):
  with Listener(on_press=on_press) as ls:
    def time_out(period_sec: int):
        time.sleep(period_sec)  # Listen to keyboard for period_sec seconds
        ls.stop()
        os.system('cls' if os.name == 'nt' else 'clear')
    Thread(target=time_out, args=(0.5,)).start()
    ls.join()
    #move entities
    ball.collision(canvas)
    ball.move()
    snake.move()
    pedal.move(canvas)
    canvas.clear()
    canvas.createBorder()

    if(snake.detectColission(canvas) or ball.getgameOver()):
      gameover = True
    #print entities
    canvas = snake.drawSnake(canvas)
    canvas = pedal.print(canvas)
    canvas = ball.print(canvas)
    canvas.print()
    print("your score: ",ball.score)
os.system('cls' if os.name == 'nt' else 'clear')
print("Loser your score was: ",ball.score)


# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

import time
from collections import defaultdict
from datetime import datetime

from odoo import api, models

class ManagementDashboard(models.Model):
    _name = 'management.dashboard'
    _description = "Project Management Dashboard"

    @api.model
    def get_task_chart_data(self):
        """
        Map the Stage Colour and Name to id

        Returns:
            dictionary -- stage_id as key and details as value
        """
        task_obj = self.env['project.task']
        task_rec = task_obj.search([])
        groups = defaultdict(list)

        for obj in task_rec:
            groups[obj.stage_id].append(obj)
        result = {}
        for rec in groups.items():
            result.update({
                rec[0].name: {
                    'count': len(rec[1]),
                    'color': rec[0].color,
                    'name': rec[0].name,
                }})
        return result

    @api.model
    def get_config_values(self):
        """
        To get the Colour value for dashboard.
        Using sudo env to bypass the access right.
        Returns:
            dictionary -- Dictionary of config colours.
        """
        result = self.env['res.config.settings'].sudo().get_values()
        return {
            'color_close_state': result.get('color_close_state', False),
            'color_control_state': result.get('color_control_state', False),
            'color_execute_state': result.get('color_execute_state', False),
            'color_init_state': result.get('color_init_state', False),
            'color_plan_state': result.get('color_plan_state', False),
            'card_header_color': result.get('card_header_color', False),
        }

    @api.model
    def get_color_code(self, project):
        # 0:Green, 1:Orange, 2:Red
        open_task = 0
        open_issue = 0
        spent_budget = 0
        pending_invoice = 0
        # ('date_start', '>=', self._context.get('start_date')),
        # ('date_start', '<=', self._context.get('end_date')),
        project_tasks = self.env['project.task'].search(
            [('project_id', '=', project['id']),
             ('stage_id.name',
                'not in',
                ("Done", "Completed", "Approval",
                 "Canceled", "Closure", "Release",
                 "Implementation")),
             ('date_end', '=', False)])

        today_date = datetime.strptime(
            time.strftime('%Y-%m-%d'), '%Y-%m-%d').date()
        for task in project_tasks:
            if task.schedule_date:
                schedule_date = datetime.strptime(
                    str(task.schedule_date), '%Y-%m-%d %H:%M:%S').date()
                daysdiff = (schedule_date - today_date).days
                if daysdiff <= 1:
                    open_task = 2
                if daysdiff <= 7 and daysdiff > 1 and open_task != 2:
                    open_task = 1
                if daysdiff > 7 and open_task not in (2, 1):
                    open_task = 0

        project_issues = self.env['helpdesk.ticket'].with_context(
            view_project_issues=1).search([
                ('stage_id.closed', '!=', True),
                ('project_id.id', '=', project['id']),
                ('closed_date', '=', False)])
        for issue in project_issues or []:
            if ((int(int(issue.ticket_aging)) > 30 and issue.priority == '0') or
                    (int(issue.ticket_aging) > 10 and issue.priority == '1') or
                    (int(issue.ticket_aging) > 2 and issue.priority in
                        ('2', '3'))):
                open_issue = 2
            if ((int(issue.ticket_aging) > 10 and int(issue.ticket_aging) <= 30 and
                    issue.priority == '0') or
                    (int(issue.ticket_aging) > 2 and int(issue.ticket_aging) <= 10 and
                        issue.priority == '1') or
                    (int(issue.ticket_aging) > 0 and int(issue.ticket_aging) <= 2 and
                        issue.priority in ('2', '3')) and
                    open_issue != 2):
                open_issue = 1
            if ((int(issue.ticket_aging) <= 10 and issue.priority == '0') or
                    (int(issue.ticket_aging) <= 2 and issue.priority == '1') or
                    (int(issue.ticket_aging) == 0 and issue.priority in
                        ('2', '3')) and
                    open_issue not in (2, 1)):
                open_issue = 0

        budget = 0
        if project['spent_budget'] > 0 and project['actual_budget'] > 0:
            budget = ((project['spent_budget'] - project['actual_budget'])/project['actual_budget']) * 100

        if budget > 30:
            spent_budget = 2
        elif budget > 10 and budget <= 30:
            spent_budget = 1
        elif budget <= 10:
            spent_budget = 0

        invoices = self.env['timesheet.invoice'].search([
            ('project_id', '=', project['id']),
            ('state', 'in', ('draft', 'confirm', 'pre-approved'))])

        for inv in invoices or []:
            if int(inv.timesheet_inv_age) > 30:
                pending_invoice = 2
            elif int(inv.timesheet_inv_age) > 10 and int(inv.timesheet_inv_age) < 30 and pending_invoice != 2:
                pending_invoice = 1
            elif int(inv.timesheet_inv_age) < 10 and pending_invoice not in (2, 1):
                pending_invoice = 0
        return {
                'spent_budget': spent_budget,
                'pending_invoice': pending_invoice,
                'open_task': open_task,
                'open_issue': open_issue}

    @api.model
    def get_treeview_id(self, view):
        return self.env.ref(view).id,


from pyswarms.base.base_discrete import DiscreteSwarmBase
import numpy as np
from scipy.spatial import cKDTree

class PerezPSO(DiscreteSwarmBase):

    def assertions(self):
        """Assertion method to check various inputs.

        Raises
        ------
        KeyError
            When one of the required dictionary keys is missing.
        ValueError
            When the number of neighbors is not within the range
                :code:`[0, n_particles]`.
            When the p-value is not in the list of values :code:`[1,2]`.
        """
        super(PerezPSO, self).assertions()

        if not all(key in self.options for key in ('k', 'p')):
            raise KeyError('Missing either k or p in options')
        if not 0 <= self.k <= self.n_particles:
            raise ValueError('No. of neighbors must be between 0 and no. of'
                             'particles.')
        if self.p not in [1, 2]:
            raise ValueError('p-value should either be 1 (for L1/Minkowski)'
                             'or 2 (for L2/Euclidean).')

    def __init__(self, n_particles, dimensions, alpha, options, velocity_clamp=None):
        """Initializes the swarm.

        Attributes
        ----------
        n_particles : int
            number of particles in the swarm.
        dimensions : int
            number of dimensions in the space.
        velocity_clamp : tuple (default is :code:`None`)
            a tuple of size 2 where the first entry is the minimum velocity
            and the second entry is the maximum velocity. It
            sets the limits for velocity clamping.
        options : dict with keys :code:`{'c1', 'c2', 'k', 'p'}`
            a dictionary containing the parameters for the specific
            optimization technique
                * c1 : float
                    cognitive parameter
                * c2 : float
                    social parameter
                * w : float
                    inertia parameter
                * k : int
                    number of neighbors to be considered. Must be a
                    positive integer less than :code:`n_particles`
                * p: int {1,2}
                    the Minkowski p-norm to use. 1 is the
                    sum-of-absolute values (or L1 distance) while 2 is
                    the Euclidean (or L2) distance.
        """
        # Initialize logger
        # self.logger = logging.getLogger(__name__)

        binary = False
        # Assign k-neighbors and p-value as attributes
        self.k, self.p = options['k'], options['p']
        # Initialize parent class
        super(PerezPSO, self).__init__(n_particles, dimensions, binary,
                                        options, velocity_clamp)
        # Invoke assertions
        self.assertions()
        # Initialize the resettable attributes
        self.reset()
        # Set initial glo
        self.glo = np.full((1, self.dimensions), np.inf)
        self.glo_cost = np.inf
        self.y = np.full(self.n_particles, 0)
        self.alpha = alpha
        self.loc_pos = 0

    def optimize(self, objective_func, iters, print_step=1, verbose=1):
        """Optimizes the swarm for a number of iterations.

        Performs the optimization to evaluate the objective
        function :code:`f` for a number of iterations :code:`iter.`

        Parameters
        ----------
        objective_func : function
            objective function to be evaluated
        iters : int
            number of iterations
        print_step : int (the default is 1)
            amount of steps for printing into console.
        verbose : int  (the default is 1)
            verbosity setting.

        Returns
        -------
        tuple
            the local best cost and the local best position among the
            swarm.
        """
        for i in range(iters):
            # Compute cost for current position and personal best
            current_cost = objective_func(self.pos)

            # Obtain the indices of the best position for each
            # neighbour-space, and get the local best cost and
            # local best positions from it.
            nmin_idx = self._get_neighbors(current_cost)  # get index of loc for each neighborhood of the cur position
            self.best_cost = current_cost[nmin_idx]  # the loc optimum cost for each particle

            cost_abs = np.abs(current_cost)
            loc_min = cost_abs.min()
            if loc_min < np.abs(self.glo_cost):
                pos_min_index = np.where(cost_abs == loc_min)[0][0]  # index of pos min
                self.glo = self.pos[pos_min_index]
                self.glo_cost = current_cost[pos_min_index]
            del loc_min, cost_abs

            # Get the local min realative to each point
            self.loc_pos = self.pos[nmin_idx]
            self.y = self._get_y(self.loc_pos)

            # Perform position velocity update
            self._update_velocity()  # must be called first
            self._update_position()

            care = r"""
Iter: {}
glo: {}, {}
Cur_cost: {}
loc_pos: {}
nmin_idx: {}
y: {}
velocity: {}
position: {}
            """.format(i, self.glo, self.glo_cost, current_cost, self.loc_pos,
                       nmin_idx, self.y, self.velocity, self.pos)

            if i % print_step == 0:
                print(care + "\n\n")
                if all_eq(self.pos):
                    break

            if self.glo_cost == 0:
                break

        # Obtain the final best_cost and the final best_position
        # final_best_cost_arg = np.argmin(self.best_cost)
        # final_best_cost = np.min(self.best_cost)
        # final_best_pos = self.best_pos[final_best_cost_arg]
        return self.glo_cost, self.glo

    def _get_neighbors(self, pbest_cost):
        """Helper function to obtain the best position found in the
        neighborhood. This uses the cKDTree method from :code:`scipy`
        to obtain the nearest neighbours

        Parameters
        ----------
        pbest_cost : numpy.ndarray of size (n_particles, )
            the cost incurred at the historically best position. Will be used
            for mapping the obtained indices to its actual cost.

        Returns
        -------
        array of size (n_particles, ) dtype=int64
            indices containing the best particles for each particle's
            neighbour-space that have the lowest cost
        """
        # Use cKDTree to get the indices of the nearest neighbors
        tree = cKDTree(self.pos)
        _, idx = tree.query(self.pos, p=self.p, k=self.k)

        # Map the computed costs to the neighbour indices and take the
        # argmin. If k-neighbors is equal to 1, then the swarm acts
        # independently of each other.
        if self.k == 1:
            # The minimum index is itself, no mapping needed.
            best_neighbor = pbest_cost[idx][:, np.newaxis].argmin(axis=1)
        else:
            idx_min = pbest_cost[idx].argmin(axis=1)
            best_neighbor = idx[np.arange(len(idx)), idx_min]
        return best_neighbor

    def _update_velocity(self):
        """Updates the velocity matrix of the swarm.

        This method updates the attribute :code:`self.velocity` of
        the instantiated object. It is called by the
        :code:`self.optimize()` method.
        """
        # Define the hyperparameters from options dictionary
        c1, c2, w = self.options['c1'], self.options['c2'], self.options['w']

        # Compute for cognitive and social terms
        cognitive = (c1 * np.random.uniform(0, 1) * (-1 - self.y))
        social = (c2 * np.random.uniform(0, 1)
                  * (1 - self.y))
        temp_velocity = (w * self.velocity) + cognitive + social

        # Create a mask to clamp the velocities
        if self.velocity_clamp is not None:
            # Create a mask depending on the set boundaries
            min_velocity, max_velocity = self.velocity_clamp[0], \
                                         self.velocity_clamp[1]
            _b = np.logical_and(temp_velocity >= min_velocity,
                                temp_velocity <= max_velocity)
            # Use the mask to finally clamp the velocities
            self.velocity = np.where(~_b, self.velocity, temp_velocity)
        else:
            self.velocity = temp_velocity

    def _update_position(self):
        """Updates the position matrix of the swarm.

        This method updates the attribute :code:`self.pos` of
        the instantiated object. It is called by the
        :code:`self.optimize()` method.
        """
        del self.pos
        next_pos = np.random.randint(-2000, 2000, size=self.swarm_size)
        _decision = self.y + self.velocity
        # print("des: {}".format(_decision))
        # mext_pos = np.where(_decision > self.alpha, self.glo, next_pos)
        # next_pos = np.where(_decision < self.alpha, self.loc_pos, next_pos)
        for i in range(self.n_particles):
            if _decision[i] > self.alpha:
                next_pos[i] = self.glo
            elif _decision[i] < -self.alpha:
                next_pos[i] = self.loc_pos[i]
        self.pos = next_pos

    def _get_y(self, loc):
        _y = np.array([])
        for i in range(self.n_particles):
            if np.array_equal(self.glo, self.pos[i]):
                _y = np.concatenate((_y, [1]))
            elif np.array_equal(loc[i], self.pos[i]):
                _y = np.concatenate((_y, [-1]))
            else:
                _y = np.concatenate((_y, [0]))
        return _y

    def _sigmoid(self, x):
        """Helper sigmoid function.

        Inputs
        ------
        x : numpy.ndarray
            Input vector to compute the sigmoid from

        Returns
        -------
        numpy.ndarray
            Output sigmoid computation
        """
        return 1 / (1 + np.exp(x))

def all_eq(position):
    first = position[0]
    for x in position:
        if not np.array_equal(x, first):
            return False
    return True

if __name__ == "__main__":
    record_holder = np.fromstring("-1251  -555 -1024  1119   273 -1101  1728 -1835     3  1968  1375   139  -1051  -547 -1531   298")  # -16047022661760
    # print(record_holder)
    from Particle import majic_func as obj_func
    from pyswarms.utils.environments import PlotEnvironment
    file = open("best_record.txt", "a")
    for loop in range(10):
        test = PerezPSO(12345, 16, 0.3, {"k": 10, 'c1': 0.8, 'c2': 0.2, 'w': 0.75, 'p': 2})
        test.pos = np.random.randint(-2000, 2000, size=test.swarm_size)
        test.velocity = np.full(test.n_particles, 0)
        # test.pos[0] = record_holder

        # print(test.pos)
        proposed = test.optimize(obj_func, iters=200, print_step=50)
        file.write("{}: {}\n\n".format(proposed[0], proposed[1]))
    file.close()


__author__ = 'Vivek'
def nextPermutation(A):
    """
    :param: List of integer
    :return : numerically next greater permutation of integers
    """
    i = -1
    last = False
    for k in range(len(A)-1) :
        if A[k] < A[k+1] :
            i = k
    if i == -1 :
        last = True
    j = -1
    if not last :
        for k in range(len(A)) :
            if k > i and A[k] > A[i] :
                j = k
        A[i], A[j] = A[j], A[i]
        temp = A[i+1:]
        temp.reverse()
        temp1 = A[:i+1]
        temp1.extend(temp)
        return temp1
    if last :
        A.reverse()
        return A

print(nextPermutation([1,4,3,2])) # will return [2, 1, 3, 4]
print(nextPermutation([1,2,3,4])) # Will return [1, 2, 4, 3]


import logging
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, Dict, List, Union

from pandas import DataFrame, to_datetime
from tabulate import tabulate

from freqtrade.constants import (DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT,
                                 Config)
from freqtrade.data.metrics import (calculate_cagr, calculate_csum, calculate_market_change,
                                    calculate_max_drawdown)
from freqtrade.misc import decimals_per_coin, file_dump_joblib, file_dump_json, round_coin_value
from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename

logger = logging.getLogger(__name__)

def store_backtest_stats(
        recordfilename: Path, stats: Dict[str, DataFrame], dtappendix: str) -> None:
    """
    Stores backtest results
    :param recordfilename: Path object, which can either be a filename or a directory.
        Filenames will be appended with a timestamp right before the suffix
        while for directories, <directory>/backtest-result-<datetime>.json will be used as filename
    :param stats: Dataframe containing the backtesting statistics
    :param dtappendix: Datetime to use for the filename
    """
    if recordfilename.is_dir():
        filename = (recordfilename / f'backtest-result-{dtappendix}.json')
    else:
        filename = Path.joinpath(
            recordfilename.parent, f'{recordfilename.stem}-{dtappendix}'
        ).with_suffix(recordfilename.suffix)

    # Store metadata separately.
    file_dump_json(get_backtest_metadata_filename(filename), stats['metadata'])
    del stats['metadata']

    file_dump_json(filename, stats)

    latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN)
    file_dump_json(latest_filename, {'latest_backtest': str(filename.name)})

def store_backtest_signal_candles(
        recordfilename: Path, candles: Dict[str, Dict], dtappendix: str) -> Path:
    """
    Stores backtest trade signal candles
    :param recordfilename: Path object, which can either be a filename or a directory.
        Filenames will be appended with a timestamp right before the suffix
        while for directories, <directory>/backtest-result-<datetime>_signals.pkl will be used
        as filename
    :param stats: Dict containing the backtesting signal candles
    :param dtappendix: Datetime to use for the filename
    """
    if recordfilename.is_dir():
        filename = (recordfilename / f'backtest-result-{dtappendix}_signals.pkl')
    else:
        filename = Path.joinpath(
            recordfilename.parent, f'{recordfilename.stem}-{dtappendix}_signals.pkl'
        )

    file_dump_joblib(filename, candles)

    return filename

def _get_line_floatfmt(stake_currency: str) -> List[str]:
    """
    Generate floatformat (goes in line with _generate_result_line())
    """
    return ['s', 'd', '.2f', '.2f', f'.{decimals_per_coin(stake_currency)}f',
            '.2f', 'd', 's', 's']

def _get_line_header(first_column: str, stake_currency: str,
                     direction: str = 'Entries') -> List[str]:
    """
    Generate header lines (goes in line with _generate_result_line())
    """
    return [first_column, direction, 'Avg Profit %', 'Cum Profit %',
            f'Tot Profit {stake_currency}', 'Tot Profit %', 'Avg Duration',
            'Win  Draw  Loss  Win%']

def generate_wins_draws_losses(wins, draws, losses):
    if wins > 0 and losses == 0:
        wl_ratio = '100'
    elif wins == 0:
        wl_ratio = '0'
    else:
        wl_ratio = f'{100.0 / (wins + draws + losses) * wins:.1f}' if losses > 0 else '100'
    return f'{wins:>4}  {draws:>4}  {losses:>4}  {wl_ratio:>4}'

def _generate_result_line(result: DataFrame, starting_balance: int, first_column: str) -> Dict:
    """
    Generate one result dict, with "first_column" as key.
    """
    profit_sum = result['profit_ratio'].sum()
    # (end-capital - starting capital) / starting capital
    profit_total = result['profit_abs'].sum() / starting_balance

    return {
        'key': first_column,
        'trades': len(result),
        'profit_mean': result['profit_ratio'].mean() if len(result) > 0 else 0.0,
        'profit_mean_pct': result['profit_ratio'].mean() * 100.0 if len(result) > 0 else 0.0,
        'profit_sum': profit_sum,
        'profit_sum_pct': round(profit_sum * 100.0, 2),
        'profit_total_abs': result['profit_abs'].sum(),
        'profit_total': profit_total,
        'profit_total_pct': round(profit_total * 100.0, 2),
        'duration_avg': str(timedelta(
                            minutes=round(result['trade_duration'].mean()))
                            ) if not result.empty else '0:00',
        # 'duration_max': str(timedelta(
        #                     minutes=round(result['trade_duration'].max()))
        #                     ) if not result.empty else '0:00',
        # 'duration_min': str(timedelta(
        #                     minutes=round(result['trade_duration'].min()))
        #                     ) if not result.empty else '0:00',
        'wins': len(result[result['profit_abs'] > 0]),
        'draws': len(result[result['profit_abs'] == 0]),
        'losses': len(result[result['profit_abs'] < 0]),
    }

def generate_pair_metrics(pairlist: List[str], stake_currency: str, starting_balance: int,
                          results: DataFrame, skip_nan: bool = False) -> List[Dict]:
    """
    Generates and returns a list  for the given backtest data and the results dataframe
    :param pairlist: Pairlist used
    :param stake_currency: stake-currency - used to correctly name headers
    :param starting_balance: Starting balance
    :param results: Dataframe containing the backtest results
    :param skip_nan: Print "left open" open trades
    :return: List of Dicts containing the metrics per pair
    """

    tabular_data = []

    for pair in pairlist:
        result = results[results['pair'] == pair]
        if skip_nan and result['profit_abs'].isnull().all():
            continue

        tabular_data.append(_generate_result_line(result, starting_balance, pair))

    # Sort by total profit %:
    tabular_data = sorted(tabular_data, key=lambda k: k['profit_total_abs'], reverse=True)

    # Append Total
    tabular_data.append(_generate_result_line(results, starting_balance, 'TOTAL'))
    return tabular_data

def generate_tag_metrics(tag_type: str,
                         starting_balance: int,
                         results: DataFrame,
                         skip_nan: bool = False) -> List[Dict]:
    """
    Generates and returns a list of metrics for the given tag trades and the results dataframe
    :param starting_balance: Starting balance
    :param results: Dataframe containing the backtest results
    :param skip_nan: Print "left open" open trades
    :return: List of Dicts containing the metrics per pair
    """

    tabular_data = []

    if tag_type in results.columns:
        for tag, count in results[tag_type].value_counts().items():
            result = results[results[tag_type] == tag]
            if skip_nan and result['profit_abs'].isnull().all():
                continue

            tabular_data.append(_generate_result_line(result, starting_balance, tag))

        # Sort by total profit %:
        tabular_data = sorted(tabular_data, key=lambda k: k['profit_total_abs'], reverse=True)

        # Append Total
        tabular_data.append(_generate_result_line(results, starting_balance, 'TOTAL'))
        return tabular_data
    else:
        return []

def generate_exit_reason_stats(max_open_trades: int, results: DataFrame) -> List[Dict]:
    """
    Generate small table outlining Backtest results
    :param max_open_trades: Max_open_trades parameter
    :param results: Dataframe containing the backtest result for one strategy
    :return: List of Dicts containing the metrics per Sell reason
    """
    tabular_data = []

    for reason, count in results['exit_reason'].value_counts().items():
        result = results.loc[results['exit_reason'] == reason]

        profit_mean = result['profit_ratio'].mean()
        profit_sum = result['profit_ratio'].sum()
        profit_total = profit_sum / max_open_trades

        tabular_data.append(
            {
                'exit_reason': reason,
                'trades': count,
                'wins': len(result[result['profit_abs'] > 0]),
                'draws': len(result[result['profit_abs'] == 0]),
                'losses': len(result[result['profit_abs'] < 0]),
                'profit_mean': profit_mean,
                'profit_mean_pct': round(profit_mean * 100, 2),
                'profit_sum': profit_sum,
                'profit_sum_pct': round(profit_sum * 100, 2),
                'profit_total_abs': result['profit_abs'].sum(),
                'profit_total': profit_total,
                'profit_total_pct': round(profit_total * 100, 2),
            }
        )
    return tabular_data

def generate_strategy_comparison(bt_stats: Dict) -> List[Dict]:
    """
    Generate summary per strategy
    :param bt_stats: Dict of <Strategyname: DataFrame> containing results for all strategies
    :return: List of Dicts containing the metrics per Strategy
    """

    tabular_data = []
    for strategy, result in bt_stats.items():
        tabular_data.append(deepcopy(result['results_per_pair'][-1]))
        # Update "key" to strategy (results_per_pair has it as "Total").
        tabular_data[-1]['key'] = strategy
        tabular_data[-1]['max_drawdown_account'] = result['max_drawdown_account']
        tabular_data[-1]['max_drawdown_abs'] = round_coin_value(
            result['max_drawdown_abs'], result['stake_currency'], False)
    return tabular_data

def generate_edge_table(results: dict) -> str:
    floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', 'd', 'd')
    tabular_data = []
    headers = ['Pair', 'Stoploss', 'Win Rate', 'Risk Reward Ratio',
               'Required Risk Reward', 'Expectancy', 'Total Number of Trades',
               'Average Duration (min)']

    for result in results.items():
        if result[1].nb_trades > 0:
            tabular_data.append([
                result[0],
                result[1].stoploss,
                result[1].winrate,
                result[1].risk_reward_ratio,
                result[1].required_risk_reward,
                result[1].expectancy,
                result[1].nb_trades,
                round(result[1].avg_trade_duration)
            ])

    # Ignore type as floatfmt does allow tuples but mypy does not know that
    return tabulate(tabular_data, headers=headers,
                    floatfmt=floatfmt, tablefmt="orgtbl", stralign="right")

def _get_resample_from_period(period: str) -> str:
    if period == 'day':
        return '1d'
    if period == 'week':
        return '1w'
    if period == 'month':
        return '1M'
    raise ValueError(f"Period {period} is not supported.")

def generate_periodic_breakdown_stats(trade_list: List, period: str) -> List[Dict[str, Any]]:
    results = DataFrame.from_records(trade_list)
    if len(results) == 0:
        return []
    results['close_date'] = to_datetime(results['close_date'], utc=True)
    resample_period = _get_resample_from_period(period)
    resampled = results.resample(resample_period, on='close_date')
    stats = []
    for name, day in resampled:
        profit_abs = day['profit_abs'].sum().round(10)
        wins = sum(day['profit_abs'] > 0)
        draws = sum(day['profit_abs'] == 0)
        loses = sum(day['profit_abs'] < 0)
        stats.append(
            {
                'date': name.strftime('%d/%m/%Y'),
                'profit_abs': profit_abs,
                'wins': wins,
                'draws': draws,
                'loses': loses
            }
        )
    return stats

def generate_trading_stats(results: DataFrame) -> Dict[str, Any]:
    """ Generate overall trade statistics """
    if len(results) == 0:
        return {
            'wins': 0,
            'losses': 0,
            'draws': 0,
            'holding_avg': timedelta(),
            'winner_holding_avg': timedelta(),
            'loser_holding_avg': timedelta(),
        }

    winning_trades = results.loc[results['profit_ratio'] > 0]
    draw_trades = results.loc[results['profit_ratio'] == 0]
    losing_trades = results.loc[results['profit_ratio'] < 0]

    holding_avg = (timedelta(minutes=round(results['trade_duration'].mean()))
                   if not results.empty else timedelta())
    winner_holding_avg = (timedelta(minutes=round(winning_trades['trade_duration'].mean()))
                          if not winning_trades.empty else timedelta())
    loser_holding_avg = (timedelta(minutes=round(losing_trades['trade_duration'].mean()))
                         if not losing_trades.empty else timedelta())

    return {
        'wins': len(winning_trades),
        'losses': len(losing_trades),
        'draws': len(draw_trades),
        'holding_avg': holding_avg,
        'holding_avg_s': holding_avg.total_seconds(),
        'winner_holding_avg': winner_holding_avg,
        'winner_holding_avg_s': winner_holding_avg.total_seconds(),
        'loser_holding_avg': loser_holding_avg,
        'loser_holding_avg_s': loser_holding_avg.total_seconds(),
    }

def generate_daily_stats(results: DataFrame) -> Dict[str, Any]:
    """ Generate daily statistics """
    if len(results) == 0:
        return {
            'backtest_best_day': 0,
            'backtest_worst_day': 0,
            'backtest_best_day_abs': 0,
            'backtest_worst_day_abs': 0,
            'winning_days': 0,
            'draw_days': 0,
            'losing_days': 0,
            'daily_profit_list': [],
        }
    daily_profit_rel = results.resample('1d', on='close_date')['profit_ratio'].sum()
    daily_profit = results.resample('1d', on='close_date')['profit_abs'].sum().round(10)
    worst_rel = min(daily_profit_rel)
    best_rel = max(daily_profit_rel)
    worst = min(daily_profit)
    best = max(daily_profit)
    winning_days = sum(daily_profit > 0)
    draw_days = sum(daily_profit == 0)
    losing_days = sum(daily_profit < 0)
    daily_profit_list = [(str(idx.date()), val) for idx, val in daily_profit.items()]

    return {
        'backtest_best_day': best_rel,
        'backtest_worst_day': worst_rel,
        'backtest_best_day_abs': best,
        'backtest_worst_day_abs': worst,
        'winning_days': winning_days,
        'draw_days': draw_days,
        'losing_days': losing_days,
        'daily_profit': daily_profit_list,
    }

def generate_strategy_stats(pairlist: List[str],
                            strategy: str,
                            content: Dict[str, Any],
                            min_date: datetime, max_date: datetime,
                            market_change: float
                            ) -> Dict[str, Any]:
    """
    :param pairlist: List of pairs to backtest
    :param strategy: Strategy name
    :param content: Backtest result data in the format:
                    {'results: results, 'config: config}}.
    :param min_date: Backtest start date
    :param max_date: Backtest end date
    :param market_change: float indicating the market change
    :return: Dictionary containing results per strategy and a strategy summary.
    """
    results: Dict[str, DataFrame] = content['results']
    if not isinstance(results, DataFrame):
        return {}
    config = content['config']
    max_open_trades = min(config['max_open_trades'], len(pairlist))
    start_balance = config['dry_run_wallet']
    stake_currency = config['stake_currency']

    pair_results = generate_pair_metrics(pairlist, stake_currency=stake_currency,
                                         starting_balance=start_balance,
                                         results=results, skip_nan=False)

    enter_tag_results = generate_tag_metrics("enter_tag", starting_balance=start_balance,
                                             results=results, skip_nan=False)

    exit_reason_stats = generate_exit_reason_stats(max_open_trades=max_open_trades,
                                                   results=results)
    left_open_results = generate_pair_metrics(
        pairlist, stake_currency=stake_currency, starting_balance=start_balance,
        results=results.loc[results['exit_reason'] == 'force_exit'], skip_nan=True)

    daily_stats = generate_daily_stats(results)
    trade_stats = generate_trading_stats(results)
    best_pair = max([pair for pair in pair_results if pair['key'] != 'TOTAL'],
                    key=lambda x: x['profit_sum']) if len(pair_results) > 1 else None
    worst_pair = min([pair for pair in pair_results if pair['key'] != 'TOTAL'],
                     key=lambda x: x['profit_sum']) if len(pair_results) > 1 else None
    winning_profit = results.loc[results['profit_abs'] > 0, 'profit_abs'].sum()
    losing_profit = results.loc[results['profit_abs'] < 0, 'profit_abs'].sum()
    profit_factor = winning_profit / abs(losing_profit) if losing_profit else 0.0

    backtest_days = (max_date - min_date).days or 1
    strat_stats = {
        'trades': results.to_dict(orient='records'),
        'locks': [lock.to_json() for lock in content['locks']],
        'best_pair': best_pair,
        'worst_pair': worst_pair,
        'results_per_pair': pair_results,
        'results_per_enter_tag': enter_tag_results,
        'exit_reason_summary': exit_reason_stats,
        'left_open_trades': left_open_results,
        # 'days_breakdown_stats': days_breakdown_stats,

        'total_trades': len(results),
        'trade_count_long': len(results.loc[~results['is_short']]),
        'trade_count_short': len(results.loc[results['is_short']]),
        'total_volume': float(results['stake_amount'].sum()),
        'avg_stake_amount': results['stake_amount'].mean() if len(results) > 0 else 0,
        'profit_mean': results['profit_ratio'].mean() if len(results) > 0 else 0,
        'profit_median': results['profit_ratio'].median() if len(results) > 0 else 0,
        'profit_total': results['profit_abs'].sum() / start_balance,
        'profit_total_long': results.loc[~results['is_short'], 'profit_abs'].sum() / start_balance,
        'profit_total_short': results.loc[results['is_short'], 'profit_abs'].sum() / start_balance,
        'profit_total_abs': results['profit_abs'].sum(),
        'profit_total_long_abs': results.loc[~results['is_short'], 'profit_abs'].sum(),
        'profit_total_short_abs': results.loc[results['is_short'], 'profit_abs'].sum(),
        'cagr': calculate_cagr(backtest_days, start_balance, content['final_balance']),
        'profit_factor': profit_factor,
        'backtest_start': min_date.strftime(DATETIME_PRINT_FORMAT),
        'backtest_start_ts': int(min_date.timestamp() * 1000),
        'backtest_end': max_date.strftime(DATETIME_PRINT_FORMAT),
        'backtest_end_ts': int(max_date.timestamp() * 1000),
        'backtest_days': backtest_days,

        'backtest_run_start_ts': content['backtest_start_time'],
        'backtest_run_end_ts': content['backtest_end_time'],

        'trades_per_day': round(len(results) / backtest_days, 2),
        'market_change': market_change,
        'pairlist': pairlist,
        'stake_amount': config['stake_amount'],
        'stake_currency': config['stake_currency'],
        'stake_currency_decimals': decimals_per_coin(config['stake_currency']),
        'starting_balance': start_balance,
        'dry_run_wallet': start_balance,
        'final_balance': content['final_balance'],
        'rejected_signals': content['rejected_signals'],
        'timedout_entry_orders': content['timedout_entry_orders'],
        'timedout_exit_orders': content['timedout_exit_orders'],
        'canceled_trade_entries': content['canceled_trade_entries'],
        'canceled_entry_orders': content['canceled_entry_orders'],
        'replaced_entry_orders': content['replaced_entry_orders'],
        'max_open_trades': max_open_trades,
        'max_open_trades_setting': (config['max_open_trades']
                                    if config['max_open_trades'] != float('inf') else -1),
        'timeframe': config['timeframe'],
        'timeframe_detail': config.get('timeframe_detail', ''),
        'timerange': config.get('timerange', ''),
        'enable_protections': config.get('enable_protections', False),
        'strategy_name': strategy,
        # Parameters relevant for backtesting
        'stoploss': config['stoploss'],
        'trailing_stop': config.get('trailing_stop', False),
        'trailing_stop_positive': config.get('trailing_stop_positive'),
        'trailing_stop_positive_offset': config.get('trailing_stop_positive_offset', 0.0),
        'trailing_only_offset_is_reached': config.get('trailing_only_offset_is_reached', False),
        'use_custom_stoploss': config.get('use_custom_stoploss', False),
        'minimal_roi': config['minimal_roi'],
        'use_exit_signal': config['use_exit_signal'],
        'exit_profit_only': config['exit_profit_only'],
        'exit_profit_offset': config['exit_profit_offset'],
        'ignore_roi_if_entry_signal': config['ignore_roi_if_entry_signal'],
        **daily_stats,
        **trade_stats
    }

    try:
        max_drawdown_legacy, _, _, _, _, _ = calculate_max_drawdown(
            results, value_col='profit_ratio')
        (drawdown_abs, drawdown_start, drawdown_end, high_val, low_val,
         max_drawdown) = calculate_max_drawdown(
             results, value_col='profit_abs', starting_balance=start_balance)
        # max_relative_drawdown = Underwater
        (_, _, _, _, _, max_relative_drawdown) = calculate_max_drawdown(
             results, value_col='profit_abs', starting_balance=start_balance, relative=True)

        strat_stats.update({
            'max_drawdown': max_drawdown_legacy,  # Deprecated - do not use
            'max_drawdown_account': max_drawdown,
            'max_relative_drawdown': max_relative_drawdown,
            'max_drawdown_abs': drawdown_abs,
            'drawdown_start': drawdown_start.strftime(DATETIME_PRINT_FORMAT),
            'drawdown_start_ts': drawdown_start.timestamp() * 1000,
            'drawdown_end': drawdown_end.strftime(DATETIME_PRINT_FORMAT),
            'drawdown_end_ts': drawdown_end.timestamp() * 1000,

            'max_drawdown_low': low_val,
            'max_drawdown_high': high_val,
        })

        csum_min, csum_max = calculate_csum(results, start_balance)
        strat_stats.update({
            'csum_min': csum_min,
            'csum_max': csum_max
        })

    except ValueError:
        strat_stats.update({
            'max_drawdown': 0.0,
            'max_drawdown_account': 0.0,
            'max_relative_drawdown': 0.0,
            'max_drawdown_abs': 0.0,
            'max_drawdown_low': 0.0,
            'max_drawdown_high': 0.0,
            'drawdown_start': datetime(1970, 1, 1, tzinfo=timezone.utc),
            'drawdown_start_ts': 0,
            'drawdown_end': datetime(1970, 1, 1, tzinfo=timezone.utc),
            'drawdown_end_ts': 0,
            'csum_min': 0,
            'csum_max': 0
        })

    return strat_stats

def generate_backtest_stats(btdata: Dict[str, DataFrame],
                            all_results: Dict[str, Dict[str, Union[DataFrame, Dict]]],
                            min_date: datetime, max_date: datetime
                            ) -> Dict[str, Any]:
    """
    :param btdata: Backtest data
    :param all_results: backtest result - dictionary in the form:
                     { Strategy: {'results: results, 'config: config}}.
    :param min_date: Backtest start date
    :param max_date: Backtest end date
    :return: Dictionary containing results per strategy and a strategy summary.
    """
    result: Dict[str, Any] = {
        'metadata': {},
        'strategy': {},
        'strategy_comparison': [],
    }
    market_change = calculate_market_change(btdata, 'close')
    metadata = {}
    pairlist = list(btdata.keys())
    for strategy, content in all_results.items():
        strat_stats = generate_strategy_stats(pairlist, strategy, content,
                                              min_date, max_date, market_change=market_change)
        metadata[strategy] = {
            'run_id': content['run_id'],
            'backtest_start_time': content['backtest_start_time'],
        }
        result['strategy'][strategy] = strat_stats

    strategy_results = generate_strategy_comparison(bt_stats=result['strategy'])

    result['metadata'] = metadata
    result['strategy_comparison'] = strategy_results

    return result

###
# Start output section
###

def text_table_bt_results(pair_results: List[Dict[str, Any]], stake_currency: str) -> str:
    """
    Generates and returns a text table for the given backtest data and the results dataframe
    :param pair_results: List of Dictionaries - one entry per pair + final TOTAL row
    :param stake_currency: stake-currency - used to correctly name headers
    :return: pretty printed table with tabulate as string
    """

    headers = _get_line_header('Pair', stake_currency)
    floatfmt = _get_line_floatfmt(stake_currency)
    output = [[
        t['key'], t['trades'], t['profit_mean_pct'], t['profit_sum_pct'], t['profit_total_abs'],
        t['profit_total_pct'], t['duration_avg'],
        generate_wins_draws_losses(t['wins'], t['draws'], t['losses'])
    ] for t in pair_results]
    # Ignore type as floatfmt does allow tuples but mypy does not know that
    return tabulate(output, headers=headers,
                    floatfmt=floatfmt, tablefmt="orgtbl", stralign="right")

def text_table_exit_reason(exit_reason_stats: List[Dict[str, Any]], stake_currency: str) -> str:
    """
    Generate small table outlining Backtest results
    :param sell_reason_stats: Exit reason metrics
    :param stake_currency: Stakecurrency used
    :return: pretty printed table with tabulate as string
    """
    headers = [
        'Exit Reason',
        'Exits',
        'Win  Draws  Loss  Win%',
        'Avg Profit %',
        'Cum Profit %',
        f'Tot Profit {stake_currency}',
        'Tot Profit %',
    ]

    output = [[
        t.get('exit_reason', t.get('sell_reason')), t['trades'],
        generate_wins_draws_losses(t['wins'], t['draws'], t['losses']),
        t['profit_mean_pct'], t['profit_sum_pct'],
        round_coin_value(t['profit_total_abs'], stake_currency, False),
        t['profit_total_pct'],
    ] for t in exit_reason_stats]
    return tabulate(output, headers=headers, tablefmt="orgtbl", stralign="right")

def text_table_tags(tag_type: str, tag_results: List[Dict[str, Any]], stake_currency: str) -> str:
    """
    Generates and returns a text table for the given backtest data and the results dataframe
    :param pair_results: List of Dictionaries - one entry per pair + final TOTAL row
    :param stake_currency: stake-currency - used to correctly name headers
    :return: pretty printed table with tabulate as string
    """
    if (tag_type == "enter_tag"):
        headers = _get_line_header("TAG", stake_currency)
    else:
        headers = _get_line_header("TAG", stake_currency, 'Exits')
    floatfmt = _get_line_floatfmt(stake_currency)
    output = [
        [
            t['key'] if t['key'] is not None and len(
                t['key']) > 0 else "OTHER",
            t['trades'],
            t['profit_mean_pct'],
            t['profit_sum_pct'],
            t['profit_total_abs'],
            t['profit_total_pct'],
            t['duration_avg'],
            generate_wins_draws_losses(
                t['wins'],
                t['draws'],
                t['losses'])] for t in tag_results]
    # Ignore type as floatfmt does allow tuples but mypy does not know that
    return tabulate(output, headers=headers,
                    floatfmt=floatfmt, tablefmt="orgtbl", stralign="right")

def text_table_periodic_breakdown(days_breakdown_stats: List[Dict[str, Any]],
                                  stake_currency: str, period: str) -> str:
    """
    Generate small table with Backtest results by days
    :param days_breakdown_stats: Days breakdown metrics
    :param stake_currency: Stakecurrency used
    :return: pretty printed table with tabulate as string
    """
    headers = [
        period.capitalize(),
        f'Tot Profit {stake_currency}',
        'Wins',
        'Draws',
        'Losses',
    ]
    output = [[
        d['date'], round_coin_value(d['profit_abs'], stake_currency, False),
        d['wins'], d['draws'], d['loses'],
    ] for d in days_breakdown_stats]
    return tabulate(output, headers=headers, tablefmt="orgtbl", stralign="right")

def text_table_strategy(strategy_results, stake_currency: str) -> str:
    """
    Generate summary table per strategy
    :param strategy_results: Dict of <Strategyname: DataFrame> containing results for all strategies
    :param stake_currency: stake-currency - used to correctly name headers
    :return: pretty printed table with tabulate as string
    """
    floatfmt = _get_line_floatfmt(stake_currency)
    headers = _get_line_header('Strategy', stake_currency)
    # _get_line_header() is also used for per-pair summary. Per-pair drawdown is mostly useless
    # therefore we slip this column in only for strategy summary here.
    headers.append('Drawdown')

    # Align drawdown string on the center two space separator.
    if 'max_drawdown_account' in strategy_results[0]:
        drawdown = [f'{t["max_drawdown_account"] * 100:.2f}' for t in strategy_results]
    else:
        # Support for prior backtest results
        drawdown = [f'{t["max_drawdown_per"]:.2f}' for t in strategy_results]

    dd_pad_abs = max([len(t['max_drawdown_abs']) for t in strategy_results])
    dd_pad_per = max([len(dd) for dd in drawdown])
    drawdown = [f'{t["max_drawdown_abs"]:>{dd_pad_abs}} {stake_currency}  {dd:>{dd_pad_per}}%'
                for t, dd in zip(strategy_results, drawdown)]

    output = [[
        t['key'], t['trades'], t['profit_mean_pct'], t['profit_sum_pct'], t['profit_total_abs'],
        t['profit_total_pct'], t['duration_avg'],
        generate_wins_draws_losses(t['wins'], t['draws'], t['losses']), drawdown]
        for t, drawdown in zip(strategy_results, drawdown)]
    # Ignore type as floatfmt does allow tuples but mypy does not know that
    return tabulate(output, headers=headers,
                    floatfmt=floatfmt, tablefmt="orgtbl", stralign="right")

def text_table_add_metrics(strat_results: Dict) -> str:
    if len(strat_results['trades']) > 0:
        best_trade = max(strat_results['trades'], key=lambda x: x['profit_ratio'])
        worst_trade = min(strat_results['trades'], key=lambda x: x['profit_ratio'])

        short_metrics = [
            ('', ''),  # Empty line to improve readability
            ('Long / Short',
             f"{strat_results.get('trade_count_long', 'total_trades')} / "
             f"{strat_results.get('trade_count_short', 0)}"),
            ('Total profit Long %', f"{strat_results['profit_total_long']:.2%}"),
            ('Total profit Short %', f"{strat_results['profit_total_short']:.2%}"),
            ('Absolute profit Long', round_coin_value(strat_results['profit_total_long_abs'],
                                                      strat_results['stake_currency'])),
            ('Absolute profit Short', round_coin_value(strat_results['profit_total_short_abs'],
                                                       strat_results['stake_currency'])),
        ] if strat_results.get('trade_count_short', 0) > 0 else []

        drawdown_metrics = []
        if 'max_relative_drawdown' in strat_results:
            # Compatibility to show old hyperopt results
            drawdown_metrics.append(
                ('Max % of account underwater', f"{strat_results['max_relative_drawdown']:.2%}")
            )
        drawdown_metrics.extend([
            ('Absolute Drawdown (Account)', f"{strat_results['max_drawdown_account']:.2%}")
            if 'max_drawdown_account' in strat_results else (
                'Drawdown', f"{strat_results['max_drawdown']:.2%}"),
            ('Absolute Drawdown', round_coin_value(strat_results['max_drawdown_abs'],
                                                   strat_results['stake_currency'])),
            ('Drawdown high', round_coin_value(strat_results['max_drawdown_high'],
                                               strat_results['stake_currency'])),
            ('Drawdown low', round_coin_value(strat_results['max_drawdown_low'],
                                              strat_results['stake_currency'])),
            ('Drawdown Start', strat_results['drawdown_start']),
            ('Drawdown End', strat_results['drawdown_end']),
        ])

        entry_adjustment_metrics = [
            ('Canceled Trade Entries', strat_results.get('canceled_trade_entries', 'N/A')),
            ('Canceled Entry Orders', strat_results.get('canceled_entry_orders', 'N/A')),
            ('Replaced Entry Orders', strat_results.get('replaced_entry_orders', 'N/A')),
        ] if strat_results.get('canceled_entry_orders', 0) > 0 else []

        # Newly added fields should be ignored if they are missing in strat_results. hyperopt-show
        # command stores these results and newer version of freqtrade must be able to handle old
        # results with missing new fields.
        metrics = [
            ('Backtesting from', strat_results['backtest_start']),
            ('Backtesting to', strat_results['backtest_end']),
            ('Max open trades', strat_results['max_open_trades']),
            ('', ''),  # Empty line to improve readability
            ('Total/Daily Avg Trades',
                f"{strat_results['total_trades']} / {strat_results['trades_per_day']}"),

            ('Starting balance', round_coin_value(strat_results['starting_balance'],
                                                  strat_results['stake_currency'])),
            ('Final balance', round_coin_value(strat_results['final_balance'],
                                               strat_results['stake_currency'])),
            ('Absolute profit ', round_coin_value(strat_results['profit_total_abs'],
                                                  strat_results['stake_currency'])),
            ('Total profit %', f"{strat_results['profit_total']:.2%}"),
            ('CAGR %', f"{strat_results['cagr']:.2%}" if 'cagr' in strat_results else 'N/A'),
            ('Profit factor', f'{strat_results["profit_factor"]:.2f}' if 'profit_factor'
                              in strat_results else 'N/A'),
            ('Trades per day', strat_results['trades_per_day']),
            ('Avg. daily profit %',
             f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"),
            ('Avg. stake amount', round_coin_value(strat_results['avg_stake_amount'],
                                                   strat_results['stake_currency'])),
            ('Total trade volume', round_coin_value(strat_results['total_volume'],
                                                    strat_results['stake_currency'])),
            *short_metrics,
            ('', ''),  # Empty line to improve readability
            ('Best Pair', f"{strat_results['best_pair']['key']} "
                          f"{strat_results['best_pair']['profit_sum']:.2%}"),
            ('Worst Pair', f"{strat_results['worst_pair']['key']} "
                           f"{strat_results['worst_pair']['profit_sum']:.2%}"),
            ('Best trade', f"{best_trade['pair']} {best_trade['profit_ratio']:.2%}"),
            ('Worst trade', f"{worst_trade['pair']} "
                            f"{worst_trade['profit_ratio']:.2%}"),

            ('Best day', round_coin_value(strat_results['backtest_best_day_abs'],
                                          strat_results['stake_currency'])),
            ('Worst day', round_coin_value(strat_results['backtest_worst_day_abs'],
                                           strat_results['stake_currency'])),
            ('Days win/draw/lose', f"{strat_results['winning_days']} / "
                f"{strat_results['draw_days']} / {strat_results['losing_days']}"),
            ('Avg. Duration Winners', f"{strat_results['winner_holding_avg']}"),
            ('Avg. Duration Loser', f"{strat_results['loser_holding_avg']}"),
            ('Rejected Entry signals', strat_results.get('rejected_signals', 'N/A')),
            ('Entry/Exit Timeouts',
             f"{strat_results.get('timedout_entry_orders', 'N/A')} / "
             f"{strat_results.get('timedout_exit_orders', 'N/A')}"),
            *entry_adjustment_metrics,
            ('', ''),  # Empty line to improve readability

            ('Min balance', round_coin_value(strat_results['csum_min'],
                                             strat_results['stake_currency'])),
            ('Max balance', round_coin_value(strat_results['csum_max'],
                                             strat_results['stake_currency'])),

            *drawdown_metrics,
            ('Market change', f"{strat_results['market_change']:.2%}"),
        ]

        return tabulate(metrics, headers=["Metric", "Value"], tablefmt="orgtbl")
    else:
        start_balance = round_coin_value(strat_results['starting_balance'],
                                         strat_results['stake_currency'])
        stake_amount = round_coin_value(
            strat_results['stake_amount'], strat_results['stake_currency']
        ) if strat_results['stake_amount'] != UNLIMITED_STAKE_AMOUNT else 'unlimited'

        message = ("No trades made. "
                   f"Your starting balance was {start_balance}, "
                   f"and your stake was {stake_amount}."
                   )
        return message

def show_backtest_result(strategy: str, results: Dict[str, Any], stake_currency: str,
                         backtest_breakdown=[]):
    """
    Print results for one strategy
    """
    # Print results
    print(f"Result for strategy {strategy}")
    table = text_table_bt_results(results['results_per_pair'], stake_currency=stake_currency)
    if isinstance(table, str):
        print(' BACKTESTING REPORT '.center(len(table.splitlines()[0]), '='))
    print(table)

    if (results.get('results_per_enter_tag') is not None
            or results.get('results_per_buy_tag') is not None):
        # results_per_buy_tag is deprecated and should be removed 2 versions after short golive.
        table = text_table_tags(
            "enter_tag",
            results.get('results_per_enter_tag', results.get('results_per_buy_tag')),
            stake_currency=stake_currency)

        if isinstance(table, str) and len(table) > 0:
            print(' ENTER TAG STATS '.center(len(table.splitlines()[0]), '='))
        print(table)

    exit_reasons = results.get('exit_reason_summary', results.get('sell_reason_summary'))
    table = text_table_exit_reason(exit_reason_stats=exit_reasons,
                                   stake_currency=stake_currency)
    if isinstance(table, str) and len(table) > 0:
        print(' EXIT REASON STATS '.center(len(table.splitlines()[0]), '='))
    print(table)

    table = text_table_bt_results(results['left_open_trades'], stake_currency=stake_currency)
    if isinstance(table, str) and len(table) > 0:
        print(' LEFT OPEN TRADES REPORT '.center(len(table.splitlines()[0]), '='))
    print(table)

    for period in backtest_breakdown:
        days_breakdown_stats = generate_periodic_breakdown_stats(
            trade_list=results['trades'], period=period)
        table = text_table_periodic_breakdown(days_breakdown_stats=days_breakdown_stats,
                                              stake_currency=stake_currency, period=period)
        if isinstance(table, str) and len(table) > 0:
            print(f' {period.upper()} BREAKDOWN '.center(len(table.splitlines()[0]), '='))
        print(table)

    table = text_table_add_metrics(results)
    if isinstance(table, str) and len(table) > 0:
        print(' SUMMARY METRICS '.center(len(table.splitlines()[0]), '='))
    print(table)

    if isinstance(table, str) and len(table) > 0:
        print('=' * len(table.splitlines()[0]))

    print()

def show_backtest_results(config: Config, backtest_stats: Dict):
    stake_currency = config['stake_currency']

    for strategy, results in backtest_stats['strategy'].items():
        show_backtest_result(
            strategy, results, stake_currency,
            config.get('backtest_breakdown', []))

    if len(backtest_stats['strategy']) > 1:
        # Print Strategy summary table

        table = text_table_strategy(backtest_stats['strategy_comparison'], stake_currency)
        print(f"{results['backtest_start']} -> {results['backtest_end']} |"
              f" Max open trades : {results['max_open_trades']}")
        print(' STRATEGY SUMMARY '.center(len(table.splitlines()[0]), '='))
        print(table)
        print('=' * len(table.splitlines()[0]))
        print('\nFor more details, please look at the detail tables above')

def show_sorted_pairlist(config: Config, backtest_stats: Dict):
    if config.get('backtest_show_pair_list', False):
        for strategy, results in backtest_stats['strategy'].items():
            print(f"Pairs for Strategy {strategy}: \n[")
            for result in results['results_per_pair']:
                if result["key"] != 'TOTAL':
                    print(f'"{result["key"]}",  // {result["profit_mean"]:.2%}')
            print("]")


def tabung ( b, c):
    volume = 22/7 * b * c
    luas = 2*22/7*b*(b + c)
    return volume,luas
def balok ( a, b , c):
    volume = a * b * c
    return volume

def main():
    ma = input("masukkan yang ingin di pake rumus (tabung, balok): ")

    if ma == "tabung":

        b = float(input("masukkan jari"))
        c = float(input("masukkan tinggi"))
        volume, luas = tabung( b, c)
    elif ma == "balok":
        a = float(input("panjang : "))
        b = float(input("lebar : "))
        c = float(input("tinggi"))
        volume =balok (a, b, c)

    else:
        print("Tidak ada rumus.")
        return

    print(f"volume: {volume}")
    print(f"luas: {luas}")

if __name__ == "__main__":
    main()