# - [ML_master.py](file:///C:/Local/Work/ML_Name/Code/Test/ML_master.py)

 # - [ML_Amazon_product_adviser_chat_bot.md](file:///C:/Local/Work/ML_Name/Note/ML_Amazon_product/ML_Amazon_product_adviser_chat_bot.md)

# https://github.com/Jcharis/Streamlit_DataScience_Apps/tree/master/NLP_App_with_Streamlit_Python

# !------------------------------------------------------------------------->
#  Synopsis :
#     Master doc to Running the streamlit based web UI
#  Documentation :
#     ML_Amazon_product_adviser_chat_bot.md
# !------------------------------------------------------------------------->

"""
# App: NLP App with Streamlit (NLPiffy)
Author: [Jesse E.Agbe(JCharis)](https://github.com/Jcharis))\n
Source: [Github](https://github.com/Jcharis/Streamlit_DataScience_Apps/)
Credits: Streamlit Team,Marc Skov Madsen(For Awesome-streamlit gallery)
Description
This is a Natural Language Processing(NLP) Based App useful for basic NLP concepts such as follows;
+ Tokenization & Lemmatization using Spacy
+ Named Entity Recognition(NER) using SpaCy
+ Sentiment Analysis using TextBlob
+ Document/Text Summarization using Gensim/Sumy
This is built with Streamlit Framework, an awesome framework for building ML and NLP tools.
Purpose
To perform basic and useful NLP task with Streamlit,Spacy,Textblob and Gensim/Sumy
"""
# Core Pkgs

from PIL import Image
import streamlit as st
import os

# NLP Pkgs
from textblob import TextBlob
import spacy
from gensim.summarization import summarize

# Sumy Summary Pkg
from sumy.parsers.plaintext import PlaintextParser
from sumy.nlp.tokenizers import Tokenizer
from sumy.summarizers.lex_rank import LexRankSummarizer

import name_nationality as nn
import name_entity_reco as ner
import ML_amazon_best_seller as best_seller
from newspaper import Article
import urllib.request
import itertools as it
import sys
import collections
import numpy as np

from bs4 import BeautifulSoup
import requests
import re
import nltk
import spacy
import streamlit as st
# NLP Pkgs

# Sumy Summary Pkg

# Function for Sumy Summarization
def sumy_summarizer(docx):
    parser = PlaintextParser.from_string(docx, Tokenizer("english"))
    lex_summarizer = LexRankSummarizer()
    summary = lex_summarizer(parser.document, 3)
    summary_list = [str(sentence) for sentence in summary]
    result = ' '.join(summary_list)
    return result

# Function to Analyse Tokens and Lemma

@st.cache
def text_analyzer(my_text):
    nlp = spacy.load('en')
    docx = nlp(my_text)
    # tokens = [ token.text for token in docx]
    allData = [('"Token":{},\n"Lemma":{}'.format(
        token.text, token.lemma_))for token in docx]
    return allData

# Function For Extracting Entities

@st.cache
def entity_analyzer(my_text):
    nlp = spacy.load('en')
    docx = nlp(my_text)
    tokens = [token.text for token in docx]
    entities = [(entity.text, entity.label_)for entity in docx.ents]
    allData = ['"Token":{},\n"Entities":{}'.format(tokens, entities)]
    return allData

# C:\Local\Work\Web\Note\nlp-word-cloud.jpg

@st.cache
def name_nationality(my_text):
    return(0)

def main():
    """ NLP Based App with Streamlit """
    # see  ML_Master.md
    # Title
    st.title("Jian's work ")

    # sidbar title image
    image = Image.open('C:/Local/Work/ML_Name/Code/Lib/my_nlp-word-cloud.jpg')
    st.sidebar.image(image, caption='NLP Cloud',
                     use_column_width=True)
    st.sidebar.subheader("Natural Language Processing On the Go..")
    st.markdown("""
    	# Description
    	+ This is a Natural Language Processing(NLP) Based App useful for basic NLP task
    	Tokenization,NER,Sentiment,Summarization : See
    	""")

    # Name Nationality
    if st.sidebar.checkbox("Name Nationality Recongition"):
        st.subheader("Enter your names, seperated by , ")
        message = st.text_area("Enter Name", "Type Here ..")
        if st.button("Analyze"):
            nlp_name = nn.name_nationality(message)
            st.json(nlp_name)

    # Name entity recognition
    if st.sidebar.checkbox("Name Entity Recongition"):
        st.subheader("Enter your website ")
        message = st.text_area(
            "Input:  article web link;\n  Output : person's names in article\n Highlight the person's name in the article\n Example : https://finance.yahoo.com/news/why-us-china-relations-are-worsening-on-almost-every-front-213714768.html")
        if st.button("Analyze"):
            nlp_text = ner.Get_html_text(message)
            #nlp_text = nlp_text.replace("University ", "**University** ")
            (nlp_text, person_name_all) = ner.get_person_name(nlp_text)
            st.write(person_name_all)
            st.markdown(nlp_text)

    # Amazon Best seller
    # Give a search lis
    if st.sidebar.checkbox("Amazon best seller list "):
                st.subheader("Enter your product search item ")
                message = st.text_area("Enter Name", "Type Here ..")
                if st.button("Analyze"):
                    best_seller.ML_amazon_best_seller(message)
                    #st.json(nlp_name)

    # give a product ID : download Amazon Product Information
    # see  ML_Master.md
    import bs_lib
    if st.sidebar.checkbox("Amazon Product"):
        st.subheader("Enter your product ID ")
        message = st.text_area(
            "ID: eg. B079K4TVPG")
        if st.button("Analyze"):
            amazon_product_dict = bs_lib.get_amazon_product_info(message)
            st.write(amazon_product_dict)

    #
    st.sidebar.subheader("About App")
    st.sidebar.text("NLP with Streamlit")
    st.sidebar.info("Cudos to the Streamlit Team")

    st.sidebar.subheader("By")
    st.sidebar.text("Jian Tang")

if __name__ == '__main__':
    main()


n = int(input())
s = input()
i = 0
count = 0

while i < len(s):
    if not (s[i] == 'A'):
        i+=1
        continue

    i+=1
    if not i < len(s):
        break
    if not (s[i] == 'B'):
        continue

    i+=1
    if not i < len(s):
        break
    if not (s[i] == 'C'):
        continue

    i+=1
    count+=1

print(count)


import array
import codecs
import datetime
import os

from .errors import DecodingError, CompletionCodeError
from .msgs import constants
from .utils import bcd_search, chunks, py3_array_tobytes
from .fields import FruTypeLengthString

codecs.register(bcd_search)

class Fru(object):
    def __init__(self):
        self.write_length = 16

    def get_fru_inventory_area_info(self, fru_id=0):
        rsp = self.send_message_with_name('GetFruInventoryAreaInfo',
                                          fru_id=fru_id)
        return rsp.area_size

    def write_fru_data(self, data, offset=0, fru_id=0):
        for chunk in chunks(data, self.write_length):
            write_rsp = self.send_message_with_name('WriteFruData',
                                                    fru_id=fru_id,
                                                    offset=offset,
                                                    data=chunk)

            # check if device wrote the same number of bytes sent
            if write_rsp.count_written != len(chunk):
                raise Exception('sent {:} bytes but device wrote {:} bytes'
                                .format(len(chunk), write_rsp.count_written))

            offset += len(chunk)

    def read_fru_data(self, offset=None, count=None, fru_id=0):
        req_size = 32
        data = array.array('B')

        # first check for maximum area size
        if offset is None:
            area_size = self.get_fru_inventory_area_info(fru_id)
            off = 0
        else:
            area_size = offset + count
            off = offset

        while off < area_size:
            if (off + req_size) > area_size:
                req_size = area_size - off

            try:
                rsp = self.send_message_with_name('ReadFruData', fru_id=fru_id,
                                                  offset=off, count=req_size)
            except CompletionCodeError as ex:
                if ex.cc in (constants.CC_CANT_RET_NUM_REQ_BYTES,
                             constants.CC_REQ_DATA_FIELD_EXCEED,
                             constants.CC_PARAM_OUT_OF_RANGE):
                    req_size -= 2
                    if req_size <= 0:
                        raise
                    continue
                else:
                    raise

            data.extend(rsp.data)
            off += rsp.count

        return py3_array_tobytes(data)

    def read_fru_data_full(self, fru_id=0):
        return self.read_fru_data(fru_id=fru_id)

    def get_fru_inventory_header(self, fru_id=0):
        data = self.read_fru_data(offset=0, count=8, fru_id=fru_id)
        return InventoryCommonHeader(data)

    def _read_fru_area(self, offset, fru_id=0):
        # read the area header
        data = self.read_fru_data(offset=offset, count=5, fru_id=fru_id)
        # get the whole area data
        count = data[1] * 8
        return self.read_fru_data(offset=offset, count=count, fru_id=fru_id)

    def get_fru_chassis_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.chassis_info_area_offset,
                                   fru_id=fru_id)
        return InventoryChassisInfoArea(data)

    def get_fru_board_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.board_info_area_offset,
                                   fru_id=fru_id)
        return InventoryBoardInfoArea(data)

    def get_fru_product_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)
        data = self._read_fru_area(offset=header.product_info_area_offset,
                                   fru_id=fru_id)
        return InventoryProductInfoArea(data)

    def get_fru_multirecord_area(self, fru_id=0):
        header = self.get_fru_inventory_header(fru_id=fru_id)

        # we have to determine the length of the area first
        offset = header.multirecord_area_offset
        count = 0

        while True:
            # read the header
            data = self.read_fru_data(offset=offset, count=5)
            end_of_list = bool(data[1] & 0x80)
            length = data[2]
            count += length + 5
            offset += length + 5
            if end_of_list:
                break

        # now read the full area
        offset = header.multirecord_area_offset
        data = self.read_fru_data(offset=offset, count=count)
        return InventoryMultiRecordArea(data)

    def get_fru_inventory(self, fru_id=0):
        """
        Get the full parsed FRU inventory data.
        """
        fru = FruInventory()
        header = self.get_fru_inventory_header(fru_id=fru_id)

        if header.chassis_info_area_offset:
            fru.chassis_info_area = self.get_fru_chassis_area(fru_id=fru_id)

        if header.board_info_area_offset:
            fru.board_info_area = self.get_fru_board_area(fru_id=fru_id)

        if header.product_info_area_offset:
            fru.product_info_area = self.get_fru_product_area(fru_id=fru_id)

        if header.multirecord_area_offset:
            fru.multirecord_area = self.get_fru_multirecord_area(fru_id=fru_id)

        return fru

def get_fru_inventory_from_file(filename):
    try:
        file = open(filename, "rb")
    except IOError:
        print('Error open file "%s"' % filename)

    ################################
    # get file size
    file_size = os.stat(filename).st_size
    file_data = file.read(file_size)
    data = array.array('B', file_data)
    file.close()
    return FruInventory(data)

CUSTOM_FIELD_END = 0xc1

def _decode_custom_fields(data):
    offset = 0
    fields = []
    while data[offset] != CUSTOM_FIELD_END:
        field = FruTypeLengthString(data, offset)
        fields.append(field)
        offset += field.length + 1
    return fields

class FruData(object):
    def __init__(self, data=None):
        if data:
            if isinstance(data, str):
                data = [ord(c) for c in data]
            self.data = data
            if hasattr(self, '_from_data'):
                self._from_data(data)

class InventoryCommonHeader(FruData):
    def _from_data(self, data):
        if len(data) != 8:
            raise DecodingError('InventoryCommonHeader length != 8')
        self.format_version = data[0] & 0x0f
        self.internal_use_area_offset = data[1] * 8 or None
        self.chassis_info_area_offset = data[2] * 8 or None
        self.board_info_area_offset = data[3] * 8 or None
        self.product_info_area_offset = data[4] * 8 or None
        self.multirecord_area_offset = data[5] * 8 or None
        if sum(data) % 256 != 0:
            raise DecodingError('InventoryCommonHeader checksum failed')

class CommonInfoArea(FruData):
    def _from_data(self, data):
        self.format_version = data[0] & 0x0f
        if self.format_version != 1:
            raise DecodingError('unsupported format version (%d)' %
                                self.format_version)
        self.length = data[1] * 8
        if sum(data[:self.length]) % 256 != 0:
            raise DecodingError('checksum failed')

class InventoryChassisInfoArea(CommonInfoArea):
    TYPE_OTHER = 1
    TYPE_UNKNOWN = 2
    TYPE_DESKTOP = 3
    TYPE_LOW_PROFILE_DESKTOP = 4
    TYPE_PIZZA_BOX = 5
    TYPE_MINI_TOWER = 6
    TYPE_TOWER = 7
    TYPE_PORTABLE = 8
    TYPE_LAPTOP = 9
    TYPE_NOTEBOOK = 10
    TYPE_HAND_HELD = 11
    TYPE_DOCKING_STATION = 12
    TYPE_ALL_IN_ONE = 13
    TYPE_SUB_NOTEBOOK = 14
    TYPE_SPACE_SAVING = 15
    TYPE_LUNCH_BOX = 16
    TYPE_MAIN_SERVER_CHASSIS = 17
    TYPE_EXPANSION_CHASSIS = 18
    TYPE_SUB_CHASSIS = 19
    TYPE_BUS_EXPANSION_CHASSIS = 20
    TYPE_PERIPHERAL_CHASSIS = 21
    TYPE_RAID_CHASSIS = 22
    TYPE_RACK_MOUNT_CHASSIS = 23

    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.type = data[2]
        offset = 3
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.custom_chassis_info = _decode_custom_fields(data[offset:])

class InventoryBoardInfoArea(CommonInfoArea):
    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.language_code = data[2]
        minutes = data[5] << 16 | data[4] << 8 | data[3]
        self.mfg_date = (datetime.datetime(1996, 1, 1)
                         + datetime.timedelta(minutes=minutes))
        offset = 6
        self.manufacturer = FruTypeLengthString(data, offset)
        offset += self.manufacturer.length + 1
        self.product_name = FruTypeLengthString(data, offset)
        offset += self.product_name.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.fru_file_id = FruTypeLengthString(data, offset, True)
        offset += self.fru_file_id.length + 1
        self.custom_mfg_info = _decode_custom_fields(data[offset:])

class InventoryProductInfoArea(CommonInfoArea):
    def _from_data(self, data):
        CommonInfoArea._from_data(self, data)
        self.language_code = data[2]
        offset = 3
        self.manufacturer = FruTypeLengthString(data, offset)
        offset += self.manufacturer.length + 1
        self.name = FruTypeLengthString(data, offset)
        offset += self.name.length + 1
        self.part_number = FruTypeLengthString(data, offset)
        offset += self.part_number.length + 1
        self.version = FruTypeLengthString(data, offset)
        offset += self.version.length + 1
        self.serial_number = FruTypeLengthString(data, offset, True)
        offset += self.serial_number.length + 1
        self.asset_tag = FruTypeLengthString(data, offset)
        offset += self.asset_tag.length + 1
        self.fru_file_id = FruTypeLengthString(data, offset, True)
        offset += self.fru_file_id.length + 1
        self.custom_mfg_info = list()
        self.custom_mfg_info = _decode_custom_fields(data[offset:])

class FruDataMultiRecord(FruData):
    TYPE_POWER_SUPPLY_INFORMATION = 0
    TYPE_DC_OUTPUT = 1
    TYPE_DC_LOAD = 2
    TYPE_MANAGEMENT_ACCESS_RECORD = 3
    TYPE_BASE_COMPATIBILITY_RECORD = 4
    TYPE_EXTENDED_COMPATIBILITY_RECORD = 5
    TYPE_OEM = list(range(0x0c, 0x100))
    TYPE_OEM_PICMG = 0xc0

    def __str__(self):
        return '%02x: %s' % (self.record_type_id,
                             ' '.join('%02x' % b for b in self.raw))

    def _from_data(self, data):
        if len(data) < 5:
            raise DecodingError('data too short')
        self.record_type_id = data[0]
        self.format_version = data[1] & 0x0f
        self.end_of_list = bool(data[1] & 0x80)
        self.length = data[2]
        if sum(data[:5]) % 256 != 0:
            raise DecodingError('FruDataMultiRecord header checksum failed')
        self.raw = data[5:5+self.length]
        if (sum(self.raw) + data[3]) % 256 != 0:
            raise DecodingError('FruDataMultiRecord record checksum failed')

    @staticmethod
    def create_from_record_id(data):
        if data[0] == FruDataMultiRecord.TYPE_OEM_PICMG:
            return FruPicmgRecord.create_from_record_id(data)
        else:
            return FruDataUnknown(data)

class FruDataUnknown(FruDataMultiRecord):
    """This class is used to indicate undecoded picmg record."""

    pass

class FruPicmgRecord(FruDataMultiRecord):
    PICMG_RECORD_ID_BACKPLANE_PTP_CONNECTIVITY = 0x04
    PICMG_RECORD_ID_ADDRESS_TABLE = 0x10
    PICMG_RECORD_ID_SHELF_POWER_DISTRIBUTION = 0x11
    PICMG_RECORD_ID_SHMC_ACTIVATION_MANAGEMENT = 0x12
    PICMG_RECORD_ID_SHMC_IP_CONNECTION = 0x13
    PICMG_RECORD_ID_BOARD_PTP_CONNECTIVITY = 0x14
    PICMG_RECORD_ID_RADIAL_IPMB0_LINK_MAPPING = 0x15
    PICMG_RECORD_ID_MODULE_CURRENT_REQUIREMENTS = 0x16
    PICMG_RECORD_ID_CARRIER_ACTIVATION_MANAGEMENT = 0x17
    PICMG_RECORD_ID_CARRIER_PTP_CONNECTIVITY = 0x18
    PICMG_RECORD_ID_AMC_PTP_CONNECTIVITY = 0x19
    PICMG_RECORD_ID_CARRIER_INFORMATION = 0x1a
    PICMG_RECORD_ID_MTCA_FRU_INFORMATION_PARTITION = 0x20
    PICMG_RECORD_ID_MTCA_CARRIER_MANAGER_IP_LINK = 0x21
    PICMG_RECORD_ID_MTCA_CARRIER_INFORMATION = 0x22
    PICMG_RECORD_ID_MTCA_SHELF_INFORMATION = 0x23
    PICMG_RECORD_ID_MTCA_SHELF_MANAGER_IP_LINK = 0x24
    PICMG_RECORD_ID_MTCA_CARRIER_POWER_POLICY = 0x25
    PICMG_RECORD_ID_MTCA_CARRIER_ACTIVATION_AND_POWER = 0x26
    PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY = 0x27
    PICMG_RECORD_ID_MTCA_FAN_GEOGRAPHY = 0x28
    PICMG_RECORD_ID_OEM_MODULE_DESCRIPTION = 0x29
    PICMG_RECORD_ID_CARRIER_CLOCK_PTP_CONNECTIVITY = 0x2C
    PICMG_RECORD_ID_CLOCK_CONFIGURATION = 0x2d
    PICMG_RECORD_ID_ZONE_3_INTERFACE_COMPATIBILITY = 0x30
    PICMG_RECORD_ID_CARRIER_BUSED_CONNECTIVITY = 0x31
    PICMG_RECORD_ID_ZONE_3_INTERFACE_DOCUMENTATION = 0x32

    def __init__(self, data):
        FruDataMultiRecord.__init__(self, data)

    @staticmethod
    def create_from_record_id(data):
        picmg_record = FruPicmgRecord(data)
        if picmg_record.picmg_record_type_id ==\
                FruPicmgRecord.PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY:
            return FruPicmgPowerModuleCapabilityRecord(data)

        return FruPicmgRecord(data)

    def _from_data(self, data):
        if len(data) < 10:
            raise DecodingError('data too short')
        data = array.array('B', data)
        FruDataMultiRecord._from_data(self, data)
        self.manufacturer_id = \
            data[5] | data[6] << 8 | data[7] << 16
        self.picmg_record_type_id = data[8]
        self.format_version = data[9]

class FruPicmgPowerModuleCapabilityRecord(FruPicmgRecord):
    def _from_data(self, data):
        if len(data) < 12:
            raise DecodingError('data too short')
        FruPicmgRecord._from_data(self, data)
        maximum_current_output = data[10] | data[11] << 8
        self.maximum_current_output = float(maximum_current_output/10)

class InventoryMultiRecordArea(object):
    def __init__(self, data):
        if data:
            self._from_data(data)

    def _from_data(self, data):
        self.records = list()
        offset = 0
        while True:
            record = FruDataMultiRecord.create_from_record_id(data[offset:])
            self.records.append(record)
            offset += record.length + 5
            if record.end_of_list:
                break

class FruInventory(object):
    def __init__(self, data=None):
        self.chassis_info_area = None
        self.board_info_area = None
        self.product_info_area = None
        self.multirecord_area = None

        if data:
            self._from_data(data)

    def _from_data(self, data):
        self.raw = data
        self.common_header = InventoryCommonHeader(data[:8])

        if self.common_header.chassis_info_area_offset:
            self.chassis_info_area = InventoryChassisInfoArea(
                data[self.common_header.chassis_info_area_offset:])

        if self.common_header.board_info_area_offset:
            self.board_info_area = InventoryBoardInfoArea(
                data[self.common_header.board_info_area_offset:])

        if self.common_header.product_info_area_offset:
            self.product_info_area = InventoryProductInfoArea(
                data[self.common_header.product_info_area_offset:])

        if self.common_header.multirecord_area_offset:
            self.multirecord_area = InventoryMultiRecordArea(
                data[self.common_header.multirecord_area_offset:])


import utils.displayStandards as dsp
from . import scattering_factors as scatf
import numpy as np
from math import pi

__all__=['structure_factor3D','plot_structure3D','get_miller3D',
        'get_pendulossung']

#2D for factors
ai = 1/np.array([0.1,0.25,0.26,0.27,1.5])**2
fj = lambda q,j,eps:eps*(np.pi/ai[j])*np.exp(-(np.pi*q)**2/ai[j])

def structure_factor3D(pattern,lat_vec,hkl=None,hklMax=10,sym=1,v=''):
    '''Computes structure factor in 3D from :
    - `pattern` : Nx4 array - N atoms with each row : fractional coordinates and Za
    - `lat_vec` : 3x3 array - reciprocal lattice vectors (2*pi/a convention)
    - `hkl`     : list of 3 miller indices h,k,l each as 3Ndarray
    - `hklMax`  : int - max miller index in each direction from -hklMax to hklMax
    '''
    #unpack
    if not hkl : hkl = get_miller3D(hklMax,sym)
    hx,ky,lz = hkl
    # print('rearranging h,k,l so h[(hi,k,l)]=hi')
    hx,ky,lz = np.transpose(hx,[1,0,2]),np.transpose(ky,[1,0,2]),np.transpose(lz,[1,0,2])
    hkl = [hx,ky,lz]
    ra,fa = pattern[:,:3],pattern[:,3]
    atoms = list(np.array(np.unique(fa),dtype=int));#print(atoms)
    # get scattering factor
    b1,b2,b3 = lat_vec
    k_x,k_y,k_z = hx*b1[0]+ky*b2[0]+lz*b3[0],hx*b1[1]+ky*b2[1]+lz*b3[1],hx*b1[2]+ky*b2[2]+lz*b3[2]
    q = np.sqrt(k_x**2+k_y**2+k_z**2)/(2*pi)
    q,fq = scatf.get_elec_atomic_factors(atoms,q)
    if 'q' in v:qmax=q.max();print('qmax=%.4f A^-1\nmax_res=%.4f A' %(qmax,1/qmax))
    #structure factor
    Fhkl,n_atoms = np.zeros(hx.shape,dtype=complex),len(atoms)
    for i,atom in zip(range(n_atoms),atoms):
        F_i = np.zeros(hx.shape,dtype=complex)
        idx = fa==atom
        for ri in ra[idx,:]:
            # print(ri)
            # print(ri,np.exp(-2*pi*1J*(ri[0]*hx+ri[1]*ky+ri[2]*lz)))
            F_i += np.exp(-2*pi*1J*(ri[0]*hx+ri[1]*ky+ri[2]*lz))
        Fhkl += F_i*fq[i]

    # cs=dsp.getCs('Spectral',n_atoms)
    # plts=[[q.flatten(),fq[i].flatten(),[cs[i],'+'],atom] for i,atom in enumerate(atoms)]
    # dsp.stddisp(plts,lw=2)
    return hkl,Fhkl

def structure_factor2D(pattern,lat_vec,hk=None,hkMax=10,sym=1,v=0,eps=1):
    '''get structure factor
    - pattern : atomic positions in real space (fractional coordinates)
    - lat_vec : reciprocal lattice vectors (2pi/a convention)
    '''
    #unpack
    if not hk : hl = get_miller2D(hkMax,sym)
    hx,ky = hl
    hx,ky = hx.T,ky.T
    hl = [hx,ky]
    ra,fa = pattern[:,:2],pattern[:,2]
    atoms = list(np.array(np.unique(fa),dtype=int));#print(atoms)
    #scattering factor
    b1,b2 = lat_vec
    k_x,k_y = hx*b1[0]+ky*b2[0],hx*b1[1]+ky*b2[1]
    q = np.sqrt(k_x**2+k_y**2)/(2*pi)
    fq = [fj(q,Za,eps) for Za in atoms]
    if v : qmax=q.max();print('qmax=%.4f A^-1\nmax_res=%.4f A' %(qmax,1/qmax))
    #compute structure factor
    Fhl,n_atoms = np.zeros(hx.shape,dtype=complex),len(atoms)
    for i,atom in zip(range(n_atoms),atoms):
        F_i = np.zeros(hx.shape,dtype=complex)
        idx = fa==atom
        for ri in ra[idx,:]:
            F_i += np.exp(2*pi*1J*(ri[0]*hx+ri[1]*ky))
        Fhl += F_i*fq[i]
    return hl,Fhl

###
def get_pendulossung(name='Si',miller=[0,0,0],keV=200,opt='p'):
    ''' give the theorertical 2-beam approximation Pendullosung thickness
    - `name`    : compound
    - `miller`  : [h,k,l]
    - `keV`     : wavelength (keV)
    RETURN
    - xi : Pendullosung thickness (A)
    '''
    # compute structure factor
    from crystals import Crystal
    crys = Crystal.from_database(name)
    lat_vec  = crys.reciprocal_vectors
    pattern  = np.array([list(a.coords_fractional)+[a.atomic_number] for a in crys.atoms])
    hkl,Fhkl = structure_factor3D(pattern,lat_vec,hklMax=max(miller),sym=0,v='')
    ax,by,cz = crys.lattice_parameters[:3]
    Vcell    = crys.volume
    # compute Pendullosung
    h,k,l = miller
    Ug,K  = np.abs(Fhkl[h,k,l])/Vcell,1/scatf.wavelength(keV)
    xi  = K/Ug
    if 'p' in opt:
        print(green+"\tPendullosung thickness "+name+'[%d%d%d]' %(h,k,l)+black)
        print('%-5s= %.2f\n%-5s= %.2f\n%-5s= %.2f'%('K',K,'Ug',Ug,'xi',xi))
    return xi

##########################################################################
###def : display
##########################################################################
def plot_structure3D(hkl,Fhkl,log=0,**kwargs):
    '''scatter plot of the intensity'''
    hx,ky,lz = hkl
    hx,ky,lz = hx.flatten(),ky.flatten(),lz.flatten()
    S        = np.abs(Fhkl.flatten())**2
    if log : S = np.log10(S+1)
    N = hx.max()
    lims = [0,N,0,N,0,N]
    dsp.stddisp(scat=[hx,ky,lz,S],rc='3d',xylims=lims,**kwargs)

def plot2Dcutplane(Shkl,n='100',title='auto',**kwargs):
    '''Not working for arbitrary cut yet '''
    N = Shkl.shape[0]
    if title=='auto' : title='Silicon([%s]) $S_{hk}$' %n
    if   n=='100' : Scut = Shkl[0,:,:]
    elif n=='110' : Scut = Shkl[np.identity(N,dtype=bool),:]
    dsp.stddisp(im=Scut,imOpt='c',legOpt=0,title=title,**kwargs)

def plot1Dcutline(Shkl,u='001',lat_vec=None,dopt='fq',**kwargs):
    '''
    u : str cutline
    dopt:f(fe(q)),q(q units)
    '''
    N,labx = Shkl.shape[0],'$index$'
    ql = np.arange(N)
    if u == '001' :
        Scut = Shkl[0,0,:]
    else :
        Scut = Shkl[0,0,:]
    plts = [[ql,Scut,'bs-','$S_{%s}$' %u]]
    if 'q' in dopt or 'f' in dopt :
        b1,b2,b3 = lat_vec
        ql *= b3[2]/(2*pi)
        labx = '$q(A^{-1})$'
    if 'f' in dopt:
        #k_x,k_y,k_z = hx*b1[0]+ky*b2[0]+lz*b3[0],hx*b1[1]+ky*b2[1]+lz*b3[1],hx*b1[2]+ky*b2[2]+lz*b3[2]
        #q = np.sqrt(k_x**2+k_y**2+k_z**2)/(2*pi)
        qz = np.linspace(0,N,1000)*b3[2]/(2*pi)
        qz,fq = scatf.get_elec_atomic_factors([14],qz)
        plts += [[qz,64*fq[0]**2,'g--','$64f_e^2$'],[qz,32*fq[0]**2,'c--','$32f_e^2$']]
    dsp.stddisp(plts,labs=[labx,'$S_q(A^2)$'],**kwargs)

##########################################################################
##### def: misc
def get_miller3D(hklMax=10,sym=1):
    '''hklMax : Number of Beams such that Fourier components = 2^(N+1) - 1'''
    Nhkl = range(-hklMax*sym,hklMax+1)
    hkl = np.meshgrid(Nhkl,Nhkl,Nhkl)
    return hkl
def get_miller2D(hkMax=10,sym=1):
    Nhk = range(-hkMax*sym,hkMax+1)
    hk = np.meshgrid(Nhk,Nhk)
    return hk

##########################################################################
#### def : test
##########################################################################
def _test_structure_factor2D(N=5):
    pptype,a,b,angle='p1',50,50,90      #A
    pattern = np.array([[0.5,0.5,1]])

    p1=pg.Wallpaper(pptype,a,b,angle,pattern=pattern,gen=False,pOpt='')
    b1,b2 = p1.get_reciprocal_lattice_2D()

    hl = np.arange(-2**N+1,2**N)
    h,l = np.meshgrid(hl,hl)
    Fhl = get_structure_factor2D(pattern,h,l,[b1,b2])

    qx,qy = (h*b1[0]+l*b2[0])/(2*pi),(h*b1[1]+l*b2[1])/(2*pi)
    fig,(axM,axP) = create_fig('12',pad=0.5,rc='12')
    axM.pcolor(np.abs(Fhl)**2);
    axP.pcolor(qx,qy,np.abs(Fhl)**2);
    #axP.pcolor(kx,ky,np.angle(Fhl));
    fig.show()
    return h,l,qx,qy,Fhl

def _test_structure_factor3D(N=5,sym=False,**kwargs):
    from crystals import Crystal
    Si = Crystal.from_database('Si'); #vol     = Si.volume
    lat_vec = Si.reciprocal_vectors
    rj      = np.array([a.coords_fractional for a in Si.atoms])
    pattern = np.concatenate((rj,14*np.ones((rj.shape[0],1))),axis=1)
    hkl,Fhkl  = structure_factor3D(pattern,lat_vec,hklMax=N,sym=sym)
    Shkl = np.abs(Fhkl)**2
    #plot_structure3D(hkl,Fhkl,name=figpath+'Si_Shkl.png',opt='s',cmap='jet',ms=50,title='Si $c=log_{10}(S+1)$',view=[9,-72])
    Shkl = np.log10(Shkl+1)
    plot2Dcutplane(Shkl,n='100',name=figpath+'Si_S100.png',**kwargs)
    plot2Dcutplane(Shkl,n='110',name=figpath+'Si_S110.png',**kwargs)
    #plot1Dcutline(Shkl,u='001',dopt='')
    return hkl,Fhkl

if __name__ == "__main__" :
    figpath=get_figpath(__file__,"/figures/")
    plt.close('all')
    #hk,Fhk = _test_structure_factor2D(N=8)
    #hkl,Fhkl = _test_structure_factor3D(N=4,opt='p',cmap='jet')


import time
import gym
import random
from IPython.display import clear_output
import numpy as np

env = gym.make("FrozenLake-v0")

action_column_size = env.action_space.n
observation_column_size = env.observation_space.n

q_table = np.zeros((observation_column_size, action_column_size))

num_ep = 10000
num_step = 100

discount_rate = 0.99
learning_rate = 0.1
exploration_rate = 1
max_exp_rate = 1
min_exp_rate = 0.01
exp_rate_decay = 0.001

all_ep_reward = []

def time_step(episodes, steps, exp_rate):
    for episode in range(episodes):
        state = env.reset()
        done = False
        current_ep_reward = 0

        for step in range(steps):
            exploration_rate_threshold = random.uniform(0, 1)
            if exploration_rate_threshold > exp_rate:
                action = np.argmax(q_table[state,:])
            else:
                action = env.action_space.sample()

            new_state, reward, done, info = env.step(action)

            q_table[state, action] = q_table[state, action] * (1 - learning_rate) + \
                                     learning_rate * (reward + discount_rate * np.max(q_table[new_state, :]))

            state = new_state
            current_ep_reward += reward

            if done == True:
                break

        exp_rate = min_exp_rate + \
                           (max_exp_rate - min_exp_rate) * np.exp(-exp_rate_decay*episode)

        all_ep_reward.append(current_ep_reward)

time_step(num_ep, num_step, exploration_rate)

rewards_per_thousand_episodes = np.split(np.array(all_ep_reward),num_ep/1000)
count = 1000

print("-------------Average reward per thousand episodes-------------\n")
for r in rewards_per_thousand_episodes:
    print(count, ": ", str(sum(r/1000)))
    count += 1000
print(q_table)


#!/usr/bin/env python3

import re
from filelist import *
from unittest import TestCase

class TestFilelist(TestCase):
  def test_ensure_full_paths(self):
    self.assertEqual(
      ensure_full_paths(['/a/b/c/d/e', '/a/b/c/f']),
      set([
        '/',
        '/a',
        '/a/b',
        '/a/b/c',
        '/a/b/c/d',
        '/a/b/c/f',
        '/a/b/c/d/e',
      ]),
    )
    self.assertEqual(
      ensure_full_paths(['a/b/c/d/e', 'a/b/c/f']),
      set([
        'a',
        'a/b',
        'a/b/c',
        'a/b/c/d',
        'a/b/c/f',
        'a/b/c/d/e',
      ]),
    )

  def test_detect_regex_exprs(self):
    self.assertEqual(
      detect_regex_exprs([
        'a',
        '#comment',
        '~b',
        '',
        'c',
      ]),
      (
        set(['a', 'c']),
        set([re.compile('b')]),
      ),
    )

  def test_match_in(self):
    S = ['/a/b/c/d', '/a/b/', '/', '/a/b/c/e']
    S_re = [re.compile('test$')]
    self.assertEqual(
      match_in(
        S, S_re, '/a/test',
      ), 1,
      'regex catch',
    )
    self.assertEqual(
      match_in(
        S, S_re, '/a/test2',
      ), 3,
      'parent is /',
    )
    self.assertEqual(
      match_in(
        S, S_re, '/a/b/c',
      ), 2,
      'parent is /a/b/',
    )
    self.assertEqual(
      match_in(
        S, S_re, '/a/b/c/d',
      ), 1,
      'appears in S',
    )
    self.assertEqual(
      match_in(
        S, S_re, 'a/b/c/d/e',
      ), 5,
      'No recursive parent',
    )
    self.assertEqual(
      match_in(
        S, S_re, '/a/b/c/e/f',
      ), 2,
      'Direct parent',
    )
    self.assertEqual(
      match_in(
        S, S_re, '/a/b/c/e/f/g',
      ), 5,
      'parent is /a/b',
    )


import random

NOMBRE_MIN = 1
NOMBRE_MAX = 10
NB_QUESTIONS = 4

# Posez la question à l'utilisateur : Calculez : 1(nombr aléatoire) + 5(nombre alétoire) =
# 1 et 5 sont des nombres aléatoires qu'ils faudra définir
# Créez une fonction poser_question(): qui ne prend pas de paramètres, on utilise nombre min et nombre max directement dans le corps de la fonction
# Tirez au sort vos 2 nombres a et b. Vous allez devoir demander la réponse à l'utilisateur, coonvertir la réponse en int, et tester si c'est bien égal à a + b
# pas de cas d'erreurs, faites simple et afficher réponse correcte ou incorrecte

# 2 : Posez plusieurs questions à l'user, posez 4 questions en bouclant, rajouter un print en annonçant le numéro de la question (question n°1 sur 4)

# 3 : Ajouter la gestion d'un nombre de points. nb_points = 0, et à chaque fois que vous donnez une bonne réponse, vous aurez plus 1 point, et à la fin
# afficher votre note est par exemple 2/4
# incrémenter le nb_points dans la boucle for, meilleure implémentation que de passer par une variable globale

# 4 : Rajoutez la note, si 4/4 => Excellent
# si 0/4 => révisez vos Maths !
# inferieur ou superieur à la moyenne donc calculez la moyenne qui est le nombre de questions/2 il va donc falloir convertir en int() pour éviter les floats
# donc int(NB_Questions/2)
# si > à la moyenne, on affiche "Pas mal"
# < moyenne on affiche "Peut mieux faire"

def poser_question():

    a = random.randint(NOMBRE_MIN, NOMBRE_MAX)
    b = random.randint(NOMBRE_MIN, NOMBRE_MAX)
    o = random.randint(0, 1)
    # si on tombe sur 0, ça sera une addition
    # si on tombe sur 1, ça sera une multiplication
    operateur_str = "+"
    if o == 1:
        operateur_str = "*"
    reponse_user = input(f"Calculez : {a} {operateur_str} {b} = ")
    reponse_user_convert = int(reponse_user)
    calcul = a + b
    if o == 1:
        calcul = a * b
    if reponse_user_convert == calcul:
        return True
    return False

nb_points = 0
for i in range(0, NB_QUESTIONS):
        print(f"Question n°{i + 1} sur {NB_QUESTIONS}")
        # la ligne du dessous sous entend if pose_question() == True:
        if poser_question():
            print("Correct !")
            nb_points += 1
        else:
            print('Incorrect.')
        print()

print(f"Votre note est {nb_points} / {NB_QUESTIONS}")

moyenne = int(NB_QUESTIONS / 2)

if nb_points == NB_QUESTIONS:
    print("Excellent !")
elif nb_points == 0:
    print("Révisez vos Maths !")
elif nb_points > moyenne:
    print("Pas mal !")
else:
    print("Peut mieux faire.")


# 有N个数, 两两一组, 要挑出 N/2 组 pair, 希望 Max Pair Sum 是最小。
# 我本来在想, 会不会是 binary search 去挑答案, 但想想不太对
# 偷看 Desription 的 Hint 提到 sort() 及太大的数要怎么降。
# 想到品设系他们第1名到第20名用 S型的方式分配。
#  1  2  3  4  5  6  7  8  9 10
# 20 19 18 17 16 15 14 13 12 11
#
class Solution:
    def minPairSum(self, nums: List[int]) -> int:
        nums.sort()
        N = len(nums)
        ans = 0
        for i in range(N//2):
            now = nums[i] + nums[N-1-i]
            ans = max(now, ans)
        return ans


from pyad import *
from treelib import Node, Tree
import pyad.adquery, pyad.adsearch, pyad.adcomputer, pyad.adbase, pyad.adcontainer, pyad.addomain, pyad.adgroup, pyad.aduser, pyad.pyad

def get_aduser(name: str=None) -> pyad.aduser.ADUser:
    """
    Function to get a pyad.ADUser object from a string

    Args:
        name (str, optional): String of the searched user. Defaults to None.

    Raises:
        Exception: Exception when user can not be resolved in AD

    Returns:
        pyad.ADUser: ADUser Object matching to given string.
    """
    query: pyad.adquery.ADQuery= pyad.adquery.ADQuery()
    query.execute_query(
        attributes=["name"],
        where_clause=f"SamAccountName = '{name}'"
    )
    name = query.get_single_result()["name"]
    try:
        user = pyad.aduser.ADUser.from_cn(name)
    except:
        raise Exception("User not found")
    return user

def get_groups(user: pyad.aduser.ADUser=None) -> list:
    """
    Function to get all groups of a user

    Args:
        user (pyad.ADUser, optional): ADUser object to get the memberships from. Defaults to None.

    Raises:
        Exception: Exception when user is not an pyad.ADUser object

    Returns:
        list: list of all distinguishedNames the user is a member of
    """
    try:
        return user.get_attribute(attribute="memberOf")
    except:
        raise Exception("User is no PYAD user object")

def get_adgroup(name: str=None) -> pyad.adgroup.ADGroup:
    """
    Get a specified group by its name

    Args:
        name (str, optional): Name of the group. Defaults to None.

    Raises:
        Exception: When group can not be resolbved

    Returns:
        pyad.ADGroup: Group matching to name
    """
    try:
        group = pyad.adgroup.ADGroup.from_dn(name)
    except:
        raise Exception("Group not found")
    return group

def create_tree(tree: Tree=Tree(), parent: Node=None, ad_object=None) -> Tree:
    """
    Generate a hierarchical tree a given ad_object is member of.

    Args:
        tree (Tree, optional): Tree object for recursion, leave empty! Defaults to Tree().
        parent (Node, optional): Parent for recursion, leave empty! Defaults to None.
        ad_object (pyad.ADObject, optional): ADObject, should be root element. Defaults to None.

    Returns:
        treelib.Tree: Hierarchical tree of memberships
    """

    # Root Element
    if parent is None:
        name: str = "".join(ad_object.get_attribute("SamAccountName"))
        tree.create_node(data=name, identifier=name, tag=name)
        parent = name

    memberOf: list = ad_object.get_attribute(attribute="memberOf")
    for membership in memberOf:
        group: pyad.adgroup.ADGroup = get_adgroup(membership)
        name: str = "".join(group.get_attribute("SamAccountName"))

        # Duplicate identifier prevention
        id: str = name
        i: int = 1
        while tree.get_node(id) is not None:
            id += f" (DUPLICATE {i})"
            i += 1

        tree.create_node(data=name, identifier=id, parent=parent, tag=id)

        # Check if child nodes have groups and start recursion
        if group.get_attribute("memberOf") is not []:
            tree = create_tree(tree=tree, parent=id, ad_object=group)
    return tree


from haversine import haversine
from airports import airport, yourCordinates
from localeparser import *
from colorama import Fore, Back, Style

yc = yourCordinates()

# should be EWR or LGA
def fastlyDistance():
    fastlyLocation = fastly(requests.get("https://tile.openstreetmap.org").headers["X-served-by"], True)

    # lat, long
    air = airport(fastlyLocation[0])

    return {"provider": "Fastly \t \t \t \t", "airport": fastlyLocation[0], "distance": haversine(air[0], air[1], yc[0], yc[1])}

def cloudflareDistance():
    cloudflareLocation = cloudflare(requests.get("https://www.cloudflare.com").headers["Cf-ray"])

    air = airport(cloudflareLocation[0])

    return {"provider": "Cloudflare \t \t \t", "airport": cloudflareLocation[0], "distance": haversine(air[0], air[1], yc[0], yc[1])}

def cloudflareFreeDistance():
    cloudflareLocation = cloudflare(requests.get("https://check-host.net").headers["Cf-ray"])

    air = airport(cloudflareLocation[0])

    return {"provider": "Cloudflare (free) \t \t", "airport": cloudflareLocation[0], "distance": haversine(air[0], air[1], yc[0], yc[1])}

def cloudfrontDistance():
    cloudfrontLocation = cloudfront(requests.get("https://desmos.com").headers["x-amz-cf-pop"])
    air = airport(cloudfrontLocation[0])

    return {"provider": "CloudFront \t \t \t", "airport": cloudfrontLocation[0], "distance": haversine(air[0], air[1], yc[0], yc[1])}

def cacheFlyDistance():
    cacheFlyLocation = cacheFly(requests.get("https://www.cachefly.com").headers["x-cf1"])
    air = airport(cacheFlyLocation[0])

    return {"provider": "CacheFly \t \t \t", "airport": cacheFlyLocation[0], "distance": haversine(air[0], air[1], yc[0], yc[1])}

def fancyPrintResults():
    finalArray = []
    finalArray.append(fastlyDistance())
    finalArray.append(cloudflareDistance())
    finalArray.append(cloudflareFreeDistance())
    finalArray.append(cloudfrontDistance())
    finalArray.append(cacheFlyDistance())

    for x in finalArray:
        if x["distance"] >= 0 and x["distance"] < 50:
            print(Fore.CYAN + x["provider"] + " " + str(round(x["distance"])) + "km from you (via " + x["airport"] + ")")
            print(Style.RESET_ALL)
        elif x["distance"] >= 50 and x["distance"] < 100:
            print(Fore.BLUE + x["provider"] + " " + str(round(x["distance"])) + "km from you (via " + x["airport"] + ")")
            print(Style.RESET_ALL)
        elif x["distance"] >= 100 and x["distance"] < 300:
            print(Fore.GREEN + x["provider"] + " " + str(round(x["distance"])) + "km from you (via " + x["airport"] + ")")
            print(Style.RESET_ALL)
        else:
            print(Fore.RED + x["provider"] + " " + str(round(x["distance"])) + "km from you (via " + x["airport"] + ")")
            print(Style.RESET_ALL)


#0. 导入需要的包和模块
from PyQt5.Qt import *
import  sys

#1.创建一个应用程序对象
app=QApplication(sys.argv)

#2.控件的操作
#2.1 创建控件
window=QWidget()
#2.2 设置控件
window.setWindowTitle("")
window.resize(500,500)

text=QTextEdit(window)
#字符设置

tcf=QTextCharFormat()
tcf.setFontFamily("宋体")
tcf.setFontPointSize(20)
tcf.setFontCapitalization(QFont.Capitalize)                 #设置字体大小写，首字母大小写  QFont.MixedCase 这是正常的文本呈现选项，不应用大写更改。  QFont.AllUppercase 这会改变要以全大写类型呈现的文本。  QFont.AllLowercase 这会改变要以全小写类型呈现的文本。  QFont.SmallCaps 这会改变要以小型大写字母呈现的文本。  QFont.Capitalize 这会将要呈现的文本更改为每个单词的第一个字符作为大写字符。

tcf2=QTextCharFormat()
tcf2.setFontItalic(True)

text.setCurrentCharFormat(tcf)
text.mergeCurrentCharFormat(tcf2)       #合并格式，把第二个格式也合并过去

#2.3 显示控件
window.show()

#3. 应用程序执行，进入消息循环
sys.exit(app.exec_())


# -*- coding: utf-8 -*-
"""
Created on Tue Jul 10 09:41:14 2023

@author: zodyac

Signal for Three Methods pattern

Characteristics
- Rising Three Methods
    - First candlestick is a big bullish candle, followed by three smaller bodied bearish candlesticks and one final big bullish candle
    - Three bearish candles are normally contained in the range of the first bullish cnadle
    - Final bullish candle has a close higher than the first candles high
- Falling Three Methods
    - First candlestick is a big bearish candle, followed by three smaller bodied bullish candlesticks and one final big bearish candle
    - Three bullish candles are normally contained in the range of the first bearish cnadle
    - Final bearish candle has a close lower than the first candles low

Reasoning
- Market Psychology
    - Stabilizes price through correction or consolidation as traders close out of positions following a big bear/bull candle
Nuances
- Rare signal
- Rarely useful when used on its own

"""

from array_util import add_column
from chart_util import signal_chart
from data_import import mass_import
from performance import performance
from rounding_util import rounding

def signal(data, open_column, high_column, low_column, close_column, buy_column, sell_column) :

    data = add_column(data, 5)

    for i in range(len(data)) :
        try :
            # Bullish Pattern
            if data[i, close_column] > data[i, open_column] and \
                data[i, close_column] > data[i- 4, high_column] and \
                data[i, low_column] < data[i - 1, low_column] and \
                data[i - 1, close_column] < data[i - 4, close_column] and \
                data[i - 1, low_column] > data[i - 4, low_column] and \
                data[i - 2, close_column] < data[i - 4, close_column] and \
                data[i - 2, low_column] > data[i - 4, low_column] and \
                data[i - 3, close_column] < data[i - 4, close_column] and \
                data[i - 3, low_column] > data[i - 4, low_column] and \
                data[i - 4, close_column] > data [i - 4, open_column] :

                    data[i + 1, buy_column] = 1

            # Bearish Pattern
            if data[i, close_column] < data[i, open_column] and \
                data[i, close_column] < data[i- 4, low_column] and \
                data[i, high_column] > data[i - 1, high_column] and \
                data[i - 1, close_column] > data[i - 4, close_column] and \
                data[i - 1, high_column] < data[i - 4, high_column] and \
                data[i - 2, close_column] > data[i - 4, close_column] and \
                data[i - 2, high_column] < data[i - 4, high_column] and \
                data[i - 3, close_column] > data[i - 4, close_column] and \
                data[i - 3, high_column] < data[i - 4, high_column] and \
                data[i - 4, close_column] < data [i - 4, open_column] :

                    data[i + 1, sell_column] = -1

        except IndexError :
            pass

    return data

# Choose an Asset
pair = 0 # EURUSD

# Time frame
horizon = "H1"

# Importing the asset as an array
my_data = mass_import(pair, horizon)
my_data = rounding(my_data, 5)

# Calling the Signal Function
min_body = 10
my_data = signal(my_data, 0, 1, 2, 3, 4, 5)

# Charting the latest 150 Signals
signal_chart(my_data, 0, 4, 5, window = 200)

# Get Performance Metrics
performance(my_data, 0, 4, 5, 6, 7, 8)


import sys
from time import gmtime, strftime
import service
import unittest
import logging
import os
from datetime import datetime
from dateutil.relativedelta import relativedelta

UNITTEST_CALENDAR = 'unittest-calendar'
SERVER = 'http://localhost:5984'

class GCalendarTest(unittest.TestCase):
  def setUp(self):
    self.calendarListFd = service.GCalendarList()
    self.calendarFd = service.GCalendar(UNITTEST_CALENDAR)
    self.assertTrue(self.calendarListFd.exists(UNITTEST_CALENDAR))

  '''
  def tearDown(self):
    self.calendarListFd.delete(UNITTEST_CALENDAR)
    self.assertFalse(self.calendarListFd.exists(UNITTEST_CALENDAR))
    pass
  '''

  def test_existing_calendar(self):
    self.assertIsNotNone(service.GCalendarList().exists("Menu"))

  def test_create_event(self):
    all_day_event = {
      'summary': 'New Appointment',
      'location': 'Somewhere',
      'start': {
        'date': strftime("%Y-%m-%d", gmtime())
        #'dateTime': strftime("%Y-%m-%d %H:%M:%S", gmtime())
      },
      'end': {
        'date': strftime("%Y-%m-%d", gmtime())
        #'dateTime': strftime("%Y-%m-%d %H:%M:%S", gmtime())
      },
      'attendees': [
        {
          'email': 'raymund.rimando@gmail.com',
        }
      ]
    }
    event = {
      'summary': 'New Appointment',
      'location': 'Somewhere',
      'start': {
        'dateTime': strftime("%Y-%m-%d %H:%M:%S", gmtime())
      },
      'end': {
        'dateTime': strftime("%Y-%m-%d %H:%M:%S", gmtime())
      },
      'attendees': [
        {
          'email': 'raymund.rimando@gmail.com',
        }
      ]
    }

    self.calendarFd.insert_event(all_day_event)
    #eventFd = service.GEvents()
    self.assertTrue(True)

class ShoppingListCreator(unittest.TestCase):
  def test_create_shopping_list_from_calendar(self):
    self.assertIsNotNone({})

if __name__ == '__main__':
  logging.basicConfig(filename='%s/test.log' % os.environ['LOG_DIR'], level=logging.DEBUG)
  sys.exit(unittest.main())


# 98962 Pedro Pereira
def eh_tabuleiro(tab):  # 2.1.1
    # eh_tabuleiro: universal -> booleano
    """
    Valida se o tab (tabuleiro) colocado e valido
    Esta funcao devolve false se nao for na forma:
    (x,x,x),(x,x,x),(x,x,x)
    sendo "x" = 1 (X), -1 (O) ou 0 (Vazio)
    Retorna:
        True/False
    """
    hipoteses = (-1, 0, 1)
    if not (isinstance(tab, tuple) and len(tab) == 3):
        return False
    tuplo1, tuplo2, tuplo3 = tab[0], tab[1], tab[2]
    if not (type(tuplo1) == tuple and type(tuplo2) == tuple and type(tuplo3) == tuple):
        return False
    if not (len(tuplo1) == 3 and len(tuplo2) == 3 and len(tuplo3) == 3):
        return False
    for i in range(len(tuplo1)):
        if not (
            tuplo1[i] in hipoteses and tuplo2[i] in hipoteses and tuplo3[i] in hipoteses
        ):
            return False
    return True

def tup_tem_tipo(tup, tipo):
    # tup_tem_tipo: tuple x integer -> boolean / NoneType
    # (tuplo X tipo -> True/None)
    """
    Recebe um tuplo e um tipo em forma de int,
    e verifica se esse int esta presente no tuplo
    Devolve True se for verificado e None se nao.
    Funcao auxiliar.
    Retorna:
        True / None
    """
    for x in tup:
        if x == tipo:
            return True

def eh_difi(dific):
    # eh_difi: string -> boolean / NoneType (dificuldade -> False/None)
    """
    Recebe uma string e verifica se ela e igual as predefenidas
    (basico, normal ou perfeito)
    Funcao auxiliar.
    Retorna:
        False/None
    """
    if dific != "basico" and dific != "normal" and dific != "perfeito":
        return False

def eh_tipo(tipo):
    # eh_tipo: integer -> boolean / NoneType (tipo -> False/None)
    """
    Recebe um integer e verifica o seu tipo, e se e 1, 0 ou -1
    Funcao auxiliar.
    Retorna:
        False/None
    """
    if type(tipo) != int or tipo < -1 or tipo > 1 or tipo == 0:
        return False

def eh_posicao(posi):  # 2.1.2
    # eh_posicao: universal -> boolean (posicao -> True/False)
    """
    Recebe um integer e verifica o seu tipo,
    e se pertence ao intervalo de [1,9] devolvendo entao True/False
    Retorna:
        True/False
    """
    x = True if type(posi) == int and posi >= 1 and posi <= 9 else False
    return x

def contrar_tipo(tipo):
    # contrar_tipo: integer -> integer (tipo -> tipo contrario)
    """
    Recebe um integer e devolve o seu simetrico.
    Como esta funcao apenas sera utilizada com os inteiros 1 e -1,
    foi simplificada desta forma
    funcao auxiliar
    Retorna:
        simetrico do argumento
    """
    if tipo == 1:
        return -1
    if tipo == -1:
        return 1

def obter_coluna(tab, colun):  # 2.1.3
    # obter_coluna: tabuleiro X integer -> vector
    # (tabuleiro X numero de coluna -> vector)
    """
    Recebe um tabuleiro e um inteiro. Valida o tabuleiro
    e o inteiro(tem de ser entre [1,3]).
    Retorna com a coluna correspondente ao inteiro introduzido
    indo da esquerda para a direita
    ValueError:
        se algum dos argumentos nao for valido
    """
    if type(colun) != int or colun < 1 or colun > 3 or (eh_tabuleiro(tab) == False):
        raise ValueError("obter_coluna: algum dos argumentos e invalido")
    else:
        colun = colun - 1
        tupColun = (tab[0][colun], tab[1][colun], tab[2][colun])
        return tupColun

def obter_linha(tab, lin):  # 2.1.4
    # obter_linha: tuple X integer -> vector
    # (tabuleiro X numero de linha -> vector)
    """
    Recebe um tabuleiro e um inteiro. Valida o tabuleiro
    e o inteiro(tem de ser entre [1,3]).
    Retorna com a linha correspondente ao inteiro introduzido
    indo de cima para baixo
    ValueError:
        se algum dos argumentos nao for valido
    """
    if type(lin) != int or lin < 1 or lin > 3 or eh_tabuleiro(tab) == False:
        raise ValueError("obter_linha: algum dos argumentos e invalido")
    else:
        lin = lin - 1
        tupLin = (tab[lin][0], tab[lin][1], tab[lin][2])
        return tupLin

def obter_diagonal(tab, diag):  # 2.1.5
    # obter_diagonal: tuple X integer -> vector
    # (tabuleiro X numero da diagonal -> vector)
    """
    Recebe um tabuleiro e um inteiro. Valida o tabuleiro e
    o inteiro(tem de ser entre [1,2]).
    Retorna com a diagonal correspondente ao inteiro
    introduzido sendo 1 a diagonal a que vai das posicoes 1 a 9
    e 2 a diagonal que vai de 3 a 7
    ValueError:
        se algum dos argumentos nao for valido
    """
    if type(diag) != int or diag < 1 or diag > 2 or eh_tabuleiro(tab) == False:
        raise ValueError("obter_diagonal: algum dos argumentos e invalido")
    else:
        if diag == 1:
            digEsqDir = (tab[0][0], tab[1][1], tab[2][2])
            return digEsqDir
        else:
            digDirEsq = (tab[2][0], tab[1][1], tab[0][2])
            return digDirEsq

def tabuleiro_str(tab):  # 2.1.6
    # tabueliro_str: tabuleiro -> cadeia de carateres
    """
    Recebe um tabuleiro. Valida o tabuleiro.
    Transforma o tabuleiro numa string.
    Nesta funcao foi optado pela criacao da funcao
    tendo em conta ao tabuleiro dado.
    A funcao possui um ciclo que percorre o tablueiro e coloca um 'X'
    quando deteta um 1 e 'O' quando deteta um -1.
    A mesma tambem coloca um espaco em branco se for 0 e um '|'
    sempre que o mesmo acaba de percorrer as posicoes 1 e 2 de cada linha
    ValueError:
        se o argumento nao for valido
    """
    if eh_tabuleiro(tab) == False:
        raise ValueError("tabuleiro_str: o argumento e invalido")
    resul = ""
    for i in range(0, len(tab)):
        for j in range(0, len(tab[i])):
            if tab[i][j] == 1:
                resul = resul + (" X ")
            elif tab[i][j] == 0:
                resul = resul + ("   ")
            elif tab[i][j] == -1:
                resul = resul + (" O ")
            if j == 0 or j == 1:
                resul = resul + ("|")
        if i != 2:
            resul = resul + ("\n-----------\n")

    return resul

def eh_posicao_livre(tab, posi):  # 2.2.1
    # eh_posicao_livre: tabuleiro X posicao -> boolean
    """
    Recebe e valida um tabuleiro e uma posisao.
    A funcao verifica se a posisao colocada esta ou nao ocupada (True/False)
    Verificando entre que numeros ou seja, que linha e que esse mesmo numero
    esta presente, utiliza-se simples opercoes aritmeticas
    e verifica se nessa mesma posicao, esta um zero ou seja, uma casa livre
    ValueError:
        se algum dos argumentos nao for valido
    """
    if eh_tabuleiro(tab) == False or eh_posicao(posi) != True:
        raise ValueError("eh_posicao_livre: algum dos argumentos e invalido")
    elif posi <= 3:
        if tab[0][posi - 1] == 0:
            return True
    elif posi <= 6:
        if tab[1][posi - 4] == 0:
            return True
    elif posi <= 9:
        if tab[2][posi - 7] == 0:
            return True
    return False

def obter_posicoes_livres(tab):  # 2.2.2
    # obter_posicoes_livre: tabuleiro -> vector
    """
    A funcao recebe um tabuleiro. Com 2 ciclos "for" que ira passar
    por todos os valores do tablueiro.
    Se o valor da posicao for 0, essa mesma posicao sera colocada num tuplo.
    Retorna:
        Tuplo com todas as posicoes livre no tabuleiro colocado no argumento
    ValueError:
        Se o argumento nao for valido
    """
    if eh_tabuleiro(tab) == False:
        raise ValueError("obter_posicoes_livres: o argumento e invalido")
    pot = ()
    for i in range(0, len(tab)):
        for j in range(0, len(tab[i])):
            if tab[i][j] == 0:
                if i == 0:
                    pot = pot + (j + 1,)
                if i == 1:
                    pot = pot + (j + 4,)
                if i == 2:
                    pot = pot + (j + 7,)
    return pot

def jogador_ganhador(tab):  # 2.2.3
    # jogador_ganhador: tabuleiro -> integer
    """
    Recebe um tabuleiro. E utilizado 2 ciclos while,
    um para as linhas e colunas,e outro para as diagonais.
    Verifica se existe um 3 em linha e se existir,
    retorna com tipo do jogador que ganhou.
    Se o jogo ainda nao tiver terminado, retorna com 0
    Retorna:
        O jogador que, naquele tabuleiro, ganhou o jogo
    ValueError:
        Se o argumento nao for valido
    """
    if eh_tabuleiro(tab) == False:
        raise ValueError("jogador_ganhador: o argumento e invalido")
    count = 1
    while count <= 3:
        lin = obter_linha(tab, count)
        col = obter_coluna(tab, count)
        if (lin[0] == 1 or lin[0] == -1) and lin[0] == lin[1] and (lin[1] == lin[2]):
            return lin[0]
        if (col[0] == 1 or col[0] == -1) and col[0] == col[1] and (col[1] == col[2]):
            return col[0]
        count += 1
    count = 1
    while count <= 2:
        dig = obter_diagonal(tab, count)
        if (dig[0] == 1 or dig[0] == -1) and dig[0] == dig[1] and (dig[1] == dig[2]):
            return dig[0]
        count += 1
    return 0

def marcar_posicao(tab, tipo, posi):  # 2.2.4
    # marcar_posicao: tabuleiro X integer X posicao -> tabuleiro
    """
    Valida os argumentos introduzidos.
    Esta funcao verifica em que linha a poiscao entroduzida se localiza.
    Se ela estiver na primeira linha, a posicao tem de estar
    entre os valores [1,3].
    E utilizado uma lista, que possui os valores de cada linha do tabuleiro.
    E entao modificado o 0 prensente nessa posicao com o tipo selecionado.
    Retorna:
        Um tabuleiro que foi alterado com o tipo introduzido nos argumentos,
        na posicao igualmente aprensentada
    ValueError:
        Se algum dos argumentos nao for valido
    """
    if (
        eh_tabuleiro(tab) == False
        or eh_tipo(tipo) == False
        or eh_posicao(posi) == False
        or eh_posicao_livre(tab, posi) == False
    ):
        raise ValueError("marcar_posicao: algum dos argumentos e invalido")
    if posi <= 3:
        poteTab = list(tab[0])
        poteTab[posi - 1] = tipo
        poteTab = tuple(poteTab)
        tab = (poteTab, tab[1], tab[2])
    elif posi <= 6:
        poteTab = list(tab[1])
        poteTab[posi - 4] = tipo
        poteTab = tuple(poteTab)
        tab = (tab[0], poteTab, tab[2])
    else:
        poteTab = list(tab[2])
        poteTab[posi - 7] = tipo
        poteTab = tuple(poteTab)
        tab = (tab[0], tab[1], poteTab)
    return tab

def escolher_posicao_manual(tab):  # 2.3.1
    # escolher_posicao_manual: tabuleiro -> posicao
    """
    Valida os argumentos introduzidos.
    Retorna:
        posicao escolhida
    ValueError:
        Se o tabuleiro for invalido
        Se a posisao colocada nao for valida
        ou se a casa escolhida nao for livre
    """
    if eh_tabuleiro(tab) == False:
        raise ValueError("escolher_posicao_manual: o argumento e invalido")
    posi = eval(input("Turno do jogador. Escolha uma posicao livre: "))
    if eh_posicao(posi) != True or eh_posicao_livre(tab, posi) != True:
        raise ValueError("escolher_posicao_manual: a posicao introduzida e invalida")
    return posi

def escolher_posicao_auto_12(tab, tipo):
    # escolher_posicao_auto_12: tabuleiro X tipo -> posicao
    """
    Esta funcao serve para retornar os criterios 1 e 2.
    A funcao esta dividida em 2 partes: 1(ataque) e 2(defesa)
    Dentro dessas duas partes, existem as linhas, colunas e diagonais
    A funcao verifica se e possivel criar / defender um 3 em linha
    Retorna:
        posicao que impede/cria 3 em linha
    """
    pote = 0
    posi = 0
    posi1 = 1
    j = 1
    l = 1
    contr = contrar_tipo(tipo)
    for i in tab:
        poteTab = list(i)
        if pote == 1:
            posi = 3
            posi1 = 2
        elif pote == 2:
            posi = 6
            posi1 = 3
        if (
            eh_posicao_livre(tab, posi + 1) == True
            or eh_posicao_livre(tab, posi + 2) == True
            or eh_posicao_livre(tab, posi + 3) == True
        ):  # 1 linhas ataque
            if (
                poteTab[0] == tipo
                and poteTab[0] == poteTab[1]
                and eh_posicao_livre(tab, posi + 3) == True
            ):
                return posi + 3
            elif (
                poteTab[1] == tipo
                and poteTab[1] == poteTab[2]
                and eh_posicao_livre(tab, posi + 1) == True
            ):
                return posi + 1
            elif (
                poteTab[2] == tipo
                and poteTab[0] == poteTab[2]
                and eh_posicao_livre(tab, posi + 2) == True
            ):
                return posi + 2
        if (
            eh_posicao_livre(tab, posi1) == True
            or eh_posicao_livre(tab, posi1 + 3) == True
            or eh_posicao_livre(tab, posi1 + 6) == True
        ):  # 1 coluna ataque
            poteTab1 = obter_coluna(tab, pote + 1)
            if (
                poteTab1[0] == tipo
                and poteTab1[0] == poteTab1[1]
                and eh_posicao_livre(tab, posi1 + 6) == True
            ):
                return posi1 + 6
            elif (
                poteTab1[1] == tipo
                and poteTab1[1] == poteTab1[2]
                and eh_posicao_livre(tab, posi1) == True
            ):
                return posi1
            elif (
                poteTab1[2] == tipo
                and poteTab1[0] == poteTab1[2]
                and eh_posicao_livre(tab, posi1 + 3) == True
            ):
                return posi1 + 3
        if (
            eh_posicao_livre(tab, 1) == True
            or eh_posicao_livre(tab, 5) == True
            or eh_posicao_livre(tab, 9) == True
            or eh_posicao_livre(tab, 3) == True
            or eh_posicao_livre(tab, 7) == True
        ):
            # 1 diagonal ataque
            while j <= 2:
                dig = obter_diagonal(tab, j)
                if dig[0] == tipo and dig[0] == dig[1]:
                    if j == 1 and eh_posicao_livre(tab, 9) == True:
                        return 9
                    elif j == 2 and eh_posicao_livre(tab, 3) == True:
                        return 3
                if dig[1] == tipo and dig[1] == dig[2]:
                    if j == 1 and eh_posicao_livre(tab, 1) == True:
                        return 1
                    elif j == 2 and eh_posicao_livre(tab, 7) == True:
                        return 7
                if (
                    dig[2] == tipo
                    and dig[0] == dig[2]
                    and eh_posicao_livre(tab, 5) == True
                ):
                    return 5
                j += 1
        pote += 1
    pote = 0
    posi = 0
    posi1 = 1
    j = 1
    l = 1
    for k in tab:
        poteTab = list(k)
        if pote == 1:
            posi = 3
            posi1 = 2
        elif pote == 2:
            posi = 6
            posi1 = 3
        if (
            eh_posicao_livre(tab, posi + 1) == True
            or eh_posicao_livre(tab, posi + 2) == True
            or eh_posicao_livre(tab, posi + 3) == True
        ):  # 2 linhas defesa
            if poteTab[0] == contr and poteTab[0] == poteTab[1]:
                return posi + 3
            if poteTab[1] == contr and poteTab[1] == poteTab[2]:
                return posi + 1
            if poteTab[2] == contr and poteTab[0] == poteTab[2]:
                return posi + 2
        if (
            eh_posicao_livre(tab, 1) == True
            or eh_posicao_livre(tab, 5) == True
            or eh_posicao_livre(tab, 9) == True
            or eh_posicao_livre(tab, 3) == True
            or eh_posicao_livre(tab, 7) == True
        ):
            # 2 diagonal defesa
            while l <= 2:
                dig = obter_diagonal(tab, l)
                if (
                    dig[0] == contr
                    and dig[0] == dig[1]
                    and eh_posicao_livre(tab, 9) == True
                    and eh_posicao_livre(tab, 3) == True
                ):
                    if l == 1:
                        return 9
                    else:
                        return 3
                if (
                    dig[1] == contr
                    and dig[1] == dig[2]
                    and eh_posicao_livre(tab, 1) == True
                    and eh_posicao_livre(tab, 7) == True
                ):
                    if l == 1:
                        return 1
                    else:
                        return 7
                if (
                    dig[2] == contr
                    and dig[0] == dig[2]
                    and eh_posicao_livre(tab, 5) == True
                ):
                    return 5
                l += 1
        if (
            eh_posicao_livre(tab, posi1) == True
            or eh_posicao_livre(tab, posi1 + 3) == True
            or eh_posicao_livre(tab, posi1 + 6) == True
        ):  # 2 coluna defesa
            poteTab1 = obter_coluna(tab, pote + 1)
            if (
                poteTab1[0] == contr
                and poteTab1[1] == contr
                and eh_posicao_livre(tab, posi1 + 6) == True
            ):
                return posi1 + 6
            if (
                poteTab1[1] == contr
                and poteTab1[1] == poteTab1[2]
                and eh_posicao_livre(tab, posi1) == True
            ):
                return posi1
            if (
                poteTab1[2] == contr
                and poteTab1[0] == poteTab1[2]
                and eh_posicao_livre(tab, posi1 + 3) == True
            ):
                return posi1 + 3
        pote += 1
    return False

def obter_3_criterio(tab, tipo):
    dig1 = obter_diagonal(tab, 1)  # 3
    dig2 = obter_diagonal(tab, 2)
    linha1 = obter_linha(tab, 1)
    linha2 = obter_linha(tab, 2)
    linha3 = obter_linha(tab, 3)
    i = 1
    tupote = ()
    while i <= 3:
        colunas = obter_coluna(tab, i)
        if (
            tup_tem_tipo(colunas, tipo) == True
            and tup_tem_tipo(colunas, contrar_tipo(tipo)) != True
        ):
            # coluna x linha 1
            if (
                eh_posicao_livre(tab, i) == True
                and tup_tem_tipo(linha1, tipo) == True
                and tup_tem_tipo(linha1, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (i,)
            # coluna x linha 2
            if (
                eh_posicao_livre(tab, i + 3) == True
                and tup_tem_tipo(linha2, tipo) == True
                and tup_tem_tipo(linha2, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (i + 3,)
            # coluna x linha 3
            if (
                eh_posicao_livre(tab, i + 6) == True
                and tup_tem_tipo(linha3, tipo) == True
                and tup_tem_tipo(linha3, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (i + 6,)
            # diagonais
            if (
                i == 1
                and eh_posicao_livre(tab, 1) == True
                and tup_tem_tipo(dig1, tipo) == True
                and tup_tem_tipo(dig1, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (1,)
            if (
                i == 1
                and eh_posicao_livre(tab, 7) == True
                and tup_tem_tipo(dig2, tipo) == True
                and tup_tem_tipo(dig2, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (7,)
            if (
                i == 2
                and eh_posicao_livre(tab, 5) == True
                and (
                    tup_tem_tipo(dig1, tipo) == True or tup_tem_tipo(dig2, tipo) == True
                )
                and tup_tem_tipo(dig1, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (5,)
            if (
                i == 3
                and eh_posicao_livre(tab, 3) == True
                and tup_tem_tipo(dig2, tipo) == True
                and tup_tem_tipo(dig2, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (3,)
            if (
                i == 3
                and eh_posicao_livre(tab, 9) == True
                and tup_tem_tipo(dig1, tipo) == True
                and tup_tem_tipo(dig1, contrar_tipo(tipo)) != True
            ):
                tupote = tupote + (9,)
        i += 1
    tupote = list(tupote)
    tupote.sort()
    return tupote

def obter_dois_linha(tab, tipo):
    # obter_dois_linha: tabuleiro X tipo -> posicao
    """
    Esta funcao serve para retornar o criterio 4.
    A funcao esta dividida em 2 partes: 1(diagonais) e 2(linhas e colunas)
    Utilizando lincolun, um tuplo constituido por outros tuplos
    de todas as linhas e colunas,verifica se e possivel a criacao de um 2 em
    linha para impedir a biforcacao inimiga.
    Se a defesa a essa posicao criar uma nova biforcacao,
    nao funcao nao a deve retornar
    Retorna:
        posicao que cria um 2 em linha
    """
    i = 1
    pote = 1
    dig = (obter_diagonal(tab, 1), obter_diagonal(tab, 2))
    lincolun = (
        obter_linha(tab, 1),
        obter_linha(tab, 2),
        obter_linha(tab, 3),
        obter_coluna(tab, 1),
        obter_coluna(tab, 2),
        obter_coluna(tab, 3),
    )
    tupote = ()
    for h in dig:
        if h[0] == tipo and h[1] == 0 and h[2] == 0:
            tupote = tupote + (5,)
        if h[0] == 0 and h[1] == tipo and h[2] == 0:
            if i == 1:
                tupote = tupote + (2,)
            if i == 2:
                tupote = tupote + (7,)
        if h[0] == 0 and h[1] == 0 and h[2] == tipo:
            tupote = tupote + (5,)
        i += 1
    for j in lincolun:
        if j[0] == tipo and j[1] == 0 and j[2] == 0:
            if pote == 1:
                tupote = tupote + (3,)
            if pote == 2 or pote == 5:
                tupote = tupote + (5,)
            if pote == 3 or pote == 6:
                tupote = tupote + (9,)
            if pote == 4:
                tupote = tupote + (4,)
        if j[0] == 0 and j[1] == tipo and j[2] == 0:
            if pote == 1 or pote == 4:
                tupote = tupote + (1,)
            if pote == 2:
                tupote = tupote + (2,)
            if pote == 3 or pote == 6:
                tupote = tupote + (9,)
        if j[0] == 0 and j[1] == 0 and j[2] == tipo:
            if pote == 1 or pote == 4:
                tupote = tupote + (1,)
            if pote == 2 or pote == 5:
                tupote = tupote + (5,)
            if pote == 3:
                tupote = tupote + (8,)
            if pote == 4 or pote == 6:
                tupote = tupote + (3,)
        pote += 1
    tupotelist = list(tupote)
    tupotelist.sort()
    if len(obter_3_criterio(tab, contrar_tipo(tipo))) == 1:
        return tupotelist[0]
    if len(obter_3_criterio(tab, contrar_tipo(tipo))) > 1:
        pote = 0
        for i in tupotelist:
            while pote < len(tupotelist):
                potab = tab
                potab = marcar_posicao(potab, tipo, tupotelist[pote])
                if len(obter_3_criterio(potab, contrar_tipo(tipo))) < len(
                    obter_3_criterio(tab, contrar_tipo(tipo))
                ):
                    return tupotelist[pote]
                pote += 1
    return tupotelist[0]

def escolher_posicao_auto_78(tab, tipo):
    # escolher_posicao_auto_78: tabuleiro X tipo -> posicao
    """
    Esta funcao serve para retornar os criterios 7 e 8.
    A funcao esta dividida em 2 partes: criterio 7 e criterio 8.
    Na primeira parte, e utilizada um loop "while" que verifica se
    algum canto se encontra livre.
    Na segunda parte, a funcao verifica se alguma posicao que nao
    e o meio nem os cantos se encontra livre.
    Retorna:
        posicao livre dos cantos / posicao livre de 2, 4, 6 ou 8
    """
    cont = 1
    while eh_posicao(cont) == True:  # 7
        if eh_posicao_livre(tab, cont) == True:
            return cont
        if cont == 1 or cont == 7:
            cont += 2
        else:
            cont += 4
    if eh_posicao_livre(tab, 2) == True:  # 8
        return 2
    elif eh_posicao_livre(tab, 4) == True:  # 8
        return 4
    elif eh_posicao_livre(tab, 6) == True:  # 8
        return 6
    elif eh_posicao_livre(tab, 8) == True:
        return 8
    return False

def escolher_posicao_auto(tab, tipo, dific):  # 2.3.2
    # escolher_posicao_auto: tabuleiro X tipo X cad. caracteres -> posicao
    """
    Esta funcao recebe um tabuleiro, o tipo que joga (X ou O) e dependendo
    de uma dificuldade, ira escolher uma posicao tendo em conta aos criterios
    associados.
    A mesma esta dividida em 3:
    dificuldade basica (criterios 5,7 e 8)
    dificuldade normal (criterios 1,2,5,6,7,8)
    dificuldade perfeita (criterios 1,2,3,4,5,6,7,8)
    Retorna:
        posicao que melhor se adequa ao tabuleiro tendo em conta a dificuldade
    """
    if eh_difi(dific) == False or eh_tabuleiro(tab) == False or eh_tipo(tipo) == False:
        raise ValueError("escolher_posicao_auto: algum dos argumentos e invalido")
    if dific == "basico":  # basico
        if eh_posicao_livre(tab, 5) == True:  # 5
            return 5
        if escolher_posicao_auto_78(tab, tipo) != False:  # 7,8
            return escolher_posicao_auto_78(tab, tipo)
    if dific == "normal":  # normal
        if escolher_posicao_auto_12(tab, tipo) != False:  # 1,2
            return escolher_posicao_auto_12(tab, tipo)
        if eh_posicao_livre(tab, 5) == True:  # 5
            return 5
        if tab[0][0] == contrar_tipo(tipo) and eh_posicao_livre(tab, 9) == True:  # 6
            return 9
        if tab[0][2] == contrar_tipo(tipo) and eh_posicao_livre(tab, 7) == True:
            return 7
        if tab[2][0] == contrar_tipo(tipo) and eh_posicao_livre(tab, 3) == True:
            return 3
        if tab[2][2] == contrar_tipo(tipo) and eh_posicao_livre(tab, 1) == True:
            return 1
        if escolher_posicao_auto_78(tab, tipo) != False:  # 7,8
            return escolher_posicao_auto_78(tab, tipo)
    if dific == "perfeito":  # perfeito
        if escolher_posicao_auto_12(tab, tipo) != False:  # 1,2
            return escolher_posicao_auto_12(tab, tipo)
        if len(obter_3_criterio(tab, tipo)) != 0:  # 3
            return (obter_3_criterio(tab, tipo))[0]
        if len(obter_3_criterio(tab, contrar_tipo(tipo))) != 0:
            return obter_dois_linha(tab, tipo)  # 4
        if eh_posicao_livre(tab, 5) == True:  # 5
            return 5
        if tab[0][0] == contrar_tipo(tipo) and eh_posicao_livre(tab, 9) == True:  # 6
            return 9
        if tab[0][2] == contrar_tipo(tipo) and eh_posicao_livre(tab, 7) == True:
            return 7
        if tab[2][0] == contrar_tipo(tipo) and eh_posicao_livre(tab, 7) == True:
            return 3
        if tab[2][2] == contrar_tipo(tipo) and eh_posicao_livre(tab, 1) == True:
            return 1
        if escolher_posicao_auto_78(tab, tipo) != False:  # 7,8
            return escolher_posicao_auto_78(tab, tipo)

def eh_terminado(tab):
    # escolher_posicao_auto: tabuleiro X tipo X cad. caracteres -> posicao
    """
    A funcao recebe um tablueiro e, utilizando a funcao jogador_ganhador e
    a escolher_posicao_auto_78, devolve em string o significado do inteiro.
    Se o jogador vencedor for 1, devolve X. Se for -1, devolve O e se for 0,
    devolve Empate
    Retorna:
        Representacao em string do resultado do jogo quando terminado
    Funcao auxiliar
    """
    if jogador_ganhador(tab) == 0:
        return "EMPATE"
    elif jogador_ganhador(tab) == 1:
        return "X"
    elif jogador_ganhador(tab) == -1:
        return "O"

def jogo_do_galo(tipo, dific):
    # jogo_do_galo: cad. caracteres X cad. caracteres -> posicao
    """
    Esta funcao recebe duas cadeias de caracteres.
    A primeira, sendo o tipo representada em forma de string,
    e mudada para integer.
    A segunda, e a dificuldade escolhida pelo utilizador.
    A funcao e dividida em 2, se o tipo for 'X' ou '0'
    Foi assim escolhido pois, no jogo, o 'X' comeca a jogar
    Foi introduzido tambem um ciclo 'while'.
    E importante explicar o uso de while i < 4:
    Em ambas as partes desta funcao, a primeira jogada e sempre fora
    do while. Num jogo, o maximo par de jogadas possivel e 4
    ate chegar ao empate.
    Retorna:
        jogo funcional do jogo do galo
    """
    tab = ((0, 0, 0), (0, 0, 0), (0, 0, 0))
    i = 0
    if tipo == "X":
        print("Bem-vindo ao JOGO DO GALO.\nO jogador joga com 'X'.")
        tipo = 1
        tab = marcar_posicao(tab, tipo, escolher_posicao_manual(tab))
        print(tabuleiro_str(tab))
        while i < 4:
            tab = marcar_posicao(
                tab,
                contrar_tipo(tipo),
                escolher_posicao_auto(tab, contrar_tipo(tipo), dific),
            )
            if dific == "basico":
                print("Turno do computador (basico):")
            elif dific == "normal":
                print("Turno do computador (normal):")
            elif dific == "perfeito":
                print("Turno do computador (perfeito):")
            print(tabuleiro_str(tab))
            if jogador_ganhador(tab) != 0:
                return eh_terminado(tab)
            tab = marcar_posicao(tab, tipo, escolher_posicao_manual(tab))
            print(tabuleiro_str(tab))
            if jogador_ganhador(tab) != 0:
                return eh_terminado(tab)
            i += 1
        return eh_terminado(tab)
    if tipo == "O":
        print("Bem-vindo ao JOGO DO GALO.\nO jogador joga com 'O'.")
        tipo = -1
        tab = marcar_posicao(
            tab,
            contrar_tipo(tipo),
            escolher_posicao_auto(tab, contrar_tipo(tipo), dific),
        )
        if dific == "basico":
            print("Turno do computador (basico):")
        elif dific == "normal":
            print("Turno do computador (normal):")
        elif dific == "perfeito":
            print("Turno do computador (perfeito):")
        print(tabuleiro_str(tab))
        while i < 4:
            tab = marcar_posicao(tab, tipo, escolher_posicao_manual(tab))
            print(tabuleiro_str(tab))
            if jogador_ganhador(tab) != 0:
                return eh_terminado(tab)
            tab = marcar_posicao(
                tab,
                contrar_tipo(tipo),
                escolher_posicao_auto(tab, contrar_tipo(tipo), dific),
            )
            if dific == "basico":
                print("Turno do computador (basico):")
            elif dific == "normal":
                print("Turno do computador (normal):")
            elif dific == "perfeito":
                print("Turno do computador (perfeito):")
            print(tabuleiro_str(tab))
            if jogador_ganhador(tab) != 0:
                return eh_terminado(tab)
            i += 1
        return eh_terminado(tab)

tab = ((False, False, 0), (0, 0, 0), (0, 0, 0))
print(eh_tabuleiro(tab))


"""This file simulates power spectra which one parameter varying."""

import numpy as np

from fooof.sim import *

import sys
sys.path.append('../bratios')
from settings import *
from paths import DATA_PATHS as dp

###################################################################################################
###################################################################################################

def main():

    #################### Center Frequency ####################

    # Theta Band
    cf_theta_step = Stepper(THETA_BAND[0], THETA_BAND[1], CF_INC)
    cf_iter_theta = param_iter([cf_theta_step, PW_DEF, BW_DEF])
    cf_theta_fs, cf_theta_ps, cf_theta_syns = \
        gen_group_power_spectra(len(cf_theta_step), FREQ_RANGE, AP_DEF, cf_iter_theta)
    cf_theta_save = [cf_theta_ps, cf_theta_syns]
    cf_theta_save_final = np.empty(len(cf_theta_save), dtype=object)
    cf_theta_save_final[:] = cf_theta_save
    np.save(dp.make_file_path(dp.sims_single, 'cf_theta'), cf_theta_save_final)

    # Alpha Band
    cf_alpha_step = Stepper(ALPHA_BAND[0], ALPHA_BAND[1], CF_INC)
    cf_iter_alpha = param_iter([cf_alpha_step, PW_DEF, BW_DEF])
    cf_alpha_fs, cf_alpha_ps, cf_alpha_syns = \
        gen_group_power_spectra(len(cf_alpha_step), FREQ_RANGE, AP_DEF, cf_iter_alpha)
    cf_alpha_save = [cf_alpha_ps, cf_alpha_syns]
    cf_alpha_save_final = np.empty(len(cf_alpha_save), dtype=object)
    cf_alpha_save_final[:] = cf_alpha_save
    np.save(dp.make_file_path(dp.sims_single, 'cf_alpha'), cf_alpha_save_final)

    # Beta Band
    cf_beta_step = Stepper(BETA_BAND[0], BETA_BAND[1], CF_INC)
    cf_iter_beta = param_iter([cf_beta_step, PW_DEF, BW_DEF])
    cf_beta_fs, cf_beta_ps, cf_beta_syns = \
        gen_group_power_spectra(len(cf_beta_step), FREQ_RANGE, AP_DEF, cf_iter_beta)
    cf_beta_save = [cf_beta_ps, cf_beta_syns]
    cf_beta_save_final = np.empty(len(cf_beta_save), dtype=object)
    cf_beta_save_final[:] = cf_beta_save
    np.save(dp.make_file_path(dp.sims_single, 'cf_beta'), cf_beta_save_final)

    #################### Power ####################

    # Theta Band
    pw_theta_step = Stepper(0, PW_END, PW_INC)
    pw_iter_theta = param_iter([np.mean(THETA_BAND), pw_theta_step, BW_DEF])
    pw_theta_fs, pw_theta_ps, pw_theta_syns = \
        gen_group_power_spectra(len(pw_theta_step), FREQ_RANGE, AP_DEF, pw_iter_theta)
    pw_theta_save = [pw_theta_ps, pw_theta_syns]
    pw_theta_save_final = np.empty(len(pw_theta_save), dtype=object)
    pw_theta_save_final[:] = pw_theta_save
    np.save(dp.make_file_path(dp.sims_single, 'pw_theta'), pw_theta_save_final)

    # Alpha Band
    pw_alpha_step = Stepper(0, PW_END, PW_INC)
    pw_iter_alpha = param_iter([np.mean(ALPHA_BAND), pw_alpha_step, BW_DEF])
    pw_alpha_fs, pw_alpha_ps, pw_alpha_syns = \
        gen_group_power_spectra(len(pw_alpha_step), FREQ_RANGE, AP_DEF, pw_iter_alpha)
    pw_alpha_save = [pw_alpha_ps, pw_alpha_syns]
    pw_alpha_save_final = np.empty(len(pw_alpha_save), dtype=object)
    pw_alpha_save_final[:] = pw_alpha_save
    np.save(dp.make_file_path(dp.sims_single, 'pw_alpha'), pw_alpha_save_final)

    # Off Band
    pw_beta_step = Stepper(0, PW_END, PW_INC)
    pw_iter_beta = param_iter([np.mean(BETA_BAND), pw_beta_step, BW_DEF])
    pw_beta_fs, pw_beta_ps, pw_beta_syns = \
        gen_group_power_spectra(len(pw_beta_step), FREQ_RANGE, AP_DEF, pw_iter_beta)
    pw_beta_save = [pw_beta_ps, pw_beta_syns]
    pw_beta_save_final = np.empty(len(pw_beta_save), dtype=object)
    pw_beta_save_final[:] = pw_beta_save
    np.save(dp.make_file_path(dp.sims_single, 'pw_beta'), pw_beta_save_final)

    ##################### Band Width ####################

    # Theta Band
    bw_theta_step = Stepper(.5, BW_END, BW_INC)
    bw_iter_theta = param_iter([np.mean(THETA_BAND), PW_DEF, bw_theta_step])
    bw_theta_fs, bw_theta_ps, bw_theta_syns = \
        gen_group_power_spectra(len(bw_theta_step), FREQ_RANGE, AP_DEF, bw_iter_theta)
    bw_theta_save = [bw_theta_ps, bw_theta_syns]
    bw_theta_save_final = np.empty(len(bw_theta_save),dtype=object)
    bw_theta_save_final[:] = bw_theta_save
    np.save(dp.make_file_path(dp.sims_single, 'bw_theta'), bw_theta_save_final)

    # Alpha Band
    bw_alpha_step = Stepper(.5, BW_END, BW_INC)
    bw_iter_alpha = param_iter([np.mean(ALPHA_BAND), PW_DEF, bw_alpha_step])
    bw_alpha_fs, bw_alpha_ps, bw_alpha_syns = \
        gen_group_power_spectra(len(bw_alpha_step), FREQ_RANGE, AP_DEF, bw_iter_alpha)
    bw_alpha_save = [bw_alpha_ps, bw_alpha_syns]
    bw_alpha_save_final = np.empty(len(bw_alpha_save), dtype=object)
    bw_alpha_save_final[:] = bw_alpha_save
    np.save(dp.make_file_path(dp.sims_single, 'bw_alpha'), bw_alpha_save_final)

    # Beta Band
    bw_beta_step = Stepper(.5, BW_END, BW_INC)
    bw_iter_beta = param_iter([np.mean(BETA_BAND), PW_DEF, bw_beta_step])
    bw_beta_fs, bw_beta_ps, bw_beta_syns = \
        gen_group_power_spectra(len(bw_beta_step), FREQ_RANGE, AP_DEF, bw_iter_beta)
    bw_beta_save = [bw_beta_ps, bw_beta_syns]
    bw_beta_save_final = np.empty(len(bw_beta_save), dtype=object)
    bw_beta_save_final[:] = bw_beta_save
    np.save(dp.make_file_path(dp.sims_single, 'bw_beta'), bw_beta_save_final)

    #################### Exponent ####################

    exp_step = Stepper(EXP_START, EXP_END, EXP_INC)
    exp_iter = param_iter([0, exp_step])
    exp_fs, exp_ps, exp_syns = \
        gen_group_power_spectra(len(exp_step), FREQ_RANGE, exp_iter, [])
    exp_save = [exp_ps, exp_syns]
    exp_save_final = np.empty(len(exp_save), dtype=object)
    exp_save_final[:] = exp_save
    np.save(dp.make_file_path(dp.sims_single, 'exp_data'), exp_save_final)

    #################### Offset ####################

    off_step = Stepper(OFF_START, OFF_END, OFF_INC)
    off_iter = param_iter([off_step, 0])
    off_fs, off_ps, off_syns = \
        gen_group_power_spectra(len(off_step), FREQ_RANGE, off_iter, [], nlvs=0)
    off_save = [off_ps, off_syns]
    off_save_final = np.empty(len(off_save), dtype=object)
    off_save_final[:] = off_save
    np.save(dp.make_file_path(dp.sims_single, 'offset_data'), off_save_final)

    #################### Rotation ####################

#     rot_save = []
#     vals = []
#     freqs, ps, _ = gen_group_power_spectra(50, [1, 50], [0, 1], [])
#     for curr_ps in ps:
#         curr_ps_array = []
#         rot_step = Stepper(ROT_FREQS[0], ROT_FREQS[1], ROT_INC)

#         #TODO change rot freq
#         for delta in rot_step:
#             r_ps = rotate_spectrum(freqs, curr_ps, delta, 20)
#             curr_ps_array.append(r_ps)
#         vals.append(curr_ps_array)
#     rot_save.append((freqs, vals))
#     np.save(dp.make_file_path(dp.sims_single, 'rot_data'), rot_save)

    #################### No Oscillations - 1/f changes ####################

    f_step = Stepper(EXP_START, EXP_END, EXP_INC)
    f_iter = param_iter([OFF_DEF, f_step])
    f_fs, f_ps, f_syns = \
        gen_group_power_spectra(len(f_step), FREQ_RANGE, f_iter, [], nlvs=0)
    f_save = [f_ps, f_syns]
    f_save_final = np.empty(len(f_save), dtype=object)
    f_save_final[:] = f_save
    np.save(dp.make_file_path(dp.sims_single, '1f_data'), f_save_final)

    #################### Shifting Alpha ####################
    a_step = Stepper(ALPHA_BAND[0], ALPHA_BAND[1], CF_INC)
    a_iter = param_iter([ a_step, PW_DEF, BW_DEF, CF_LOW_DEF, PW_DEF, BW_DEF, CF_HIGH_DEF, PW_DEF, BW_DEF])
    a_fs, a_ps, a_syns = \
        gen_group_power_spectra(len(a_step), FREQ_RANGE, AP_DEF, a_iter, nlvs=0)
    a_save = [a_ps, a_syns]
    a_save_final = np.empty(len(a_save), dtype=object)
    a_save_final[:] = a_save
    np.save(dp.make_file_path(dp.sims_single, 'shifting_alpha'), a_save_final)

if __name__ == "__main__":
    main()


import os

import argparse
import logging
import torch
from torch.utils.data import DataLoader
from pytorch_msssim import ssim

from datasets.dataset import LocVisVC
from models.alexnet import SiameseAlexNet
from transforms.display_model import gamma_EOTF
from transforms.pu2_encode import pu2_encode

def rgb2gray(image):
    # shape (b, 3, h, w)
    result = 0.2989 * image[:, 0, :, :] + 0.5870 * image[:, 1, :, :] + 0.1140 * image[:, 2, :, :]
    return result.unsqueeze(1)

def PSNR(pred, label, max_val=255):
    mse = torch.mean((pred - label) ** 2)
    return 10 * torch.log10(max_val ** 2 / mse)

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--batch_size", type=int, default=32)
    parser.add_argument("--device", type=int, default=0)
    parser.add_argument("--lr", type=float, default=1e-5)
    parser.add_argument("--gamma", type=float, default=0.9)
    parser.add_argument("--epochs", type=int, default=10)
    parser.add_argument("--log_interval", type=int, default=100)
    parser.add_argument("--save_interval", type=int, default=10)
    parser.add_argument("--save_dir", type=str, default="checkpoints")
    parser.add_argument("--dataset_dir", type=str, default="dataset")
    args = parser.parse_args()
    return args

def train(model, dataloader, criterion, optimizer, device, log_interval, epoch):
    model.train()
    for batch_index, data in enumerate(dataloader):
        optimizer.zero_grad()
        reference = data["reference"].to(device)
        distortion = data["distortion"].to(device)
        label = data["label"].to(device)
        lumin = data["lumin"].to(device)
        ppd = data["ppd"].to(device)
        n = data["n"].to(device)
        likelihood = data["likelihood"].to(device)

        reference = gamma_EOTF(reference, lumin)
        distortion = gamma_EOTF(distortion, lumin)
        ref_lumin = rgb2gray(reference)
        dis_lumin = rgb2gray(distortion)
        ref_ratio = pu2_encode(ref_lumin) / (ref_lumin + 1e-8)
        dis_ratio = pu2_encode(dis_lumin) / (dis_lumin + 1e-8)
        reference = reference * ref_ratio
        distortion = distortion * dis_ratio

        pred = model(reference, distortion, ppd)
        loss = criterion(pred, label)
        loss.backward()
        optimizer.step()
        if (batch_index + 1) % log_interval == 0:
            print(f"Epoch {epoch + 1}, Batch {batch_index + 1}, Loss {loss.item()}, PSNR {PSNR(pred, label).item()}, SSIM {ssim(pred, label).item()}")

def test(model, dataloader, criterion, device, epoch):
    model.eval()
    total_loss = 0
    total_psnr = 0
    total_ssim = 0
    with torch.no_grad():
        for batch_index, data in enumerate(dataloader):
            reference = data["reference"].to(device)
            distortion = data["distortion"].to(device)
            label = data["label"].to(device)
            lumin = data["lumin"].to(device)
            ppd = data["ppd"].to(device)
            n = data["n"].to(device)
            likelihood = data["likelihood"].to(device)

            reference = gamma_EOTF(reference, lumin)
            distortion = gamma_EOTF(distortion, lumin)
            ref_lumin = rgb2gray(reference)
            dis_lumin = rgb2gray(distortion)
            ref_ratio = pu2_encode(ref_lumin) / (ref_lumin + 1e-8)
            dis_ratio = pu2_encode(dis_lumin) / (dis_lumin + 1e-8)
            reference = reference * ref_ratio
            distortion = distortion * dis_ratio
            pred = model(reference, distortion, ppd)
            loss = criterion(pred, label)

            total_loss += loss.item()
            total_psnr += PSNR(pred, label).item()
            total_ssim += ssim(pred, label).item()
        print(f"Epoch {epoch + 1}, Test Loss {total_loss / (batch_index + 1)} PSNR {total_psnr / (batch_index + 1)} SSIM {total_ssim / (batch_index + 1)}")

def main(args):
    if not os.path.exists(args.save_dir):
        os.makedirs(args.save_dir)
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
    device = f"cuda:{args.device}" if args.device != -1 else "cpu"
    train_dataset = LocVisVC("dataset", is_training=True)
    test_dataset = LocVisVC("dataset", is_training=False)
    train_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=0)
    test_loader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, num_workers=0)
    model = SiameseAlexNet().to(device)
    optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=args.gamma)
    criterion = torch.nn.MSELoss()
    for epoch in range(args.epochs):
        train(model, train_loader, criterion, optimizer, device, args.log_interval, epoch)
        test(model, test_loader, criterion, device, epoch)
        scheduler.step()
        if (epoch + 1) % args.save_interval == 0:
            torch.save(model.state_dict(), os.path.join(args.save_dir, f"model_{epoch + 1}.pth"))

if __name__ == "__main__":
    args = parse_args()
    main(args)


# nb: discord has more than this, but I'm only filling out as much in these structs as i'm using.
from __future__ import annotations

from typing import Any, List, Literal, Never, Optional, Union
import msgspec

from enum import IntEnum

# Interactions.
class InteractionType(IntEnum):
    PING = 1
    APPLICATION_COMMAND = 2

class BaseInteraction(msgspec.Struct, kw_only=True, tag_field="type"):
    id: str

class PingInteraction(BaseInteraction, tag=InteractionType.PING.value):
    pass

class ApplicationCommandInteraction(BaseInteraction, tag=InteractionType.APPLICATION_COMMAND.value):
    guild_id: str  # we don't support DMs. So this will always be a value.
    data: Union[ChatInputApplicationCommandData, MessageApplicationCommandData]

AnyInteraction = Union[PingInteraction, ApplicationCommandInteraction]

class ApplicationCommandType(IntEnum):
    CHAT_INPUT = 1
    # USER = 2  (not used)
    MESSAGE = 3

class BaseApplicationCommandData(msgspec.Struct, kw_only=True, tag_field="type"):
    id: str
    name: str

class ChatInputApplicationCommandData(BaseApplicationCommandData, tag=ApplicationCommandType.CHAT_INPUT.value):
    pass

class MessageApplicationCommandData(BaseApplicationCommandData, tag=ApplicationCommandType.MESSAGE.value):
    target_id: str
    resolved: Optional[Resolved] = None

class DiscordMessage(msgspec.Struct):
    id: str
    channel_id: str
    attachments: List[DiscordAttachment]

class DiscordAttachment(msgspec.Struct, kw_only=True):
    id: str
    filename: str
    content_type: Optional[str] = None
    size: int
    url: str
    proxy_url: str

class Resolved(msgspec.Struct):
    messages: Optional[dict[str, DiscordMessage]] = None

class InteractionCallbackType(IntEnum):
    PONG = 1
    CHANNEL_MESSAGE_WITH_SOURCE = 4

class InteractionResponse(msgspec.Struct, kw_only=True, tag_field="type"):
    data: Optional[Any]

class PongInteractionResponse(InteractionResponse, tag=InteractionCallbackType.PONG.value):
    data: None = None

NOT_EPHEMERAL = 0
EPHEMERAL = 1 << 6

class InteractionMessage(msgspec.Struct):
    content: str
    flags: int

class MessageInteractionResponse(InteractionResponse, tag=InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE.value):
    data: InteractionMessage

class ApplicationCommandType(IntEnum):
    CHAT_INPUT = 1
    USER = 2
    MESSAGE = 3

class ApplicationCommand(msgspec.Struct):
    name: str
    description: Optional[str] = None
    type: ApplicationCommandType = ApplicationCommandType.CHAT_INPUT
    default_member_permissions: str = "0"
    dm_permission: bool = False


from django.db import models
from apps.db.models import BaseModel
# Create your models here.

class OrderInfo(BaseModel):
    """订单模型类"""
    PAY_METHOD_CHOICES = (
        (1,"货到付款"),
        (2,"微信支付"),
        (3,"支付宝"),
        (4,"银联支付"),
    )

    ORDER_STATUS_CHOICES = (
        (1,"待支付"),
        (2,"待发货"),
        (3,"待收货"),
        (4,"待评论"),
        (5,"已完成"),
    )

    order_id = models.IntegerField(primary_key=True,verbose_name="订单id",help_text="订单id")
    user = models.ForeignKey("user.User", on_delete=models.CASCADE, verbose_name="用户id", help_text="用户id")
    addr = models.ForeignKey("user.Address", on_delete=models.CASCADE, verbose_name="地址id", help_text="地址id")
    pay_meihod = models.SmallIntegerField(choices=PAY_METHOD_CHOICES,default=3,verbose_name="支付方式",help_text="支付方式")
    total_count = models.IntegerField(default=1,verbose_name="商品数量",help_text="商品数量")
    total_price = models.FloatField(verbose_name="支付金额",help_text="支付金额")
    transit_price = models.FloatField(verbose_name="运费",help_text="运费")
    order_status = models.SmallIntegerField(default=1,choices=ORDER_STATUS_CHOICES,verbose_name="支付状态",help_text="支付状态")
    trade_no = models.CharField(max_length=120,verbose_name="支付编码",help_text="支付编码")

    class Meta:
        db_table = "db_order_info"
        verbose_name = "订单"
        verbose_name_plural = verbose_name

class OrderGoods(BaseModel):
    """订单商品模型类"""
    order = models.ForeignKey("OrderInfo",on_delete=models.CASCADE)
    sku = models.ForeignKey("goods.GoodsSKU", on_delete=models.CASCADE)
    count = models.IntegerField(default=1,verbose_name="商品数量",help_text="商品数量")
    price = models.FloatField(verbose_name="商品价格",help_text="商品价格")
    comment = models.CharField(max_length=250,verbose_name="评论")

    class Meta:
        db_table = "db_order_goods"
        verbose_name = "订单商品"
        verbose_name_plural = verbose_name


#£¡/usr/bin/env python
#-*- coding:utf-8 -*-
# author: qiuxiang
# datetime: 2018/10/31 20:23
# software: PyCharm
# project: adminset
from django.urls import path
from navi import views

urlpatterns = [
    path('', views.index, name='navi'),
    path('add/', views.add, name='add'),
    path('manage/', views.manage, name='manage'),
    path('delete/', views.delete, name='delete'),
    path('edit/', views.edit, name='edit'),
    path('save/', views.save, name='save'),
]


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# import tools.DataFrame_preprocess
# import FinanceDataReader as fdr

pd.set_option('display.max_seq_items', None)
pd.set_option('display.max_rows', None)

# Using data from csv file
path = '/workspace/AI-Trade_/datas/AAPL.csv'
dataframe = pd.read_csv(path, index_col='Date', parse_dates=['Date'])

# Using data from FinanceDataReader
# fdr.DataReader(Stock code, time spans)
# dataframe = fdr.DataReader('293490', '2020')

# When using option 'inplace', original dataframe is modified.
# Filling missing value(NaN, inf, -inf)

dataframe['daily_return'] = dataframe['Adj Close'].pct_change()

# replace infinity value to null value.
dataframe.replace([np.inf, -np.inf], np.nan, inplace=True)
dataframe.fillna(method='pad', inplace=True)
dataframe.fillna(method='bfill', inplace=True)

# DataFrame_preprocess.del_NaN_padbfill(dataframe)
# ^same function with above three lines

# print rows that have NaN or infinity value least 1
print(dataframe[dataframe.isin([np.nan, np.inf, -np.inf]).any(1)])

# dataframe.fillna(method='pad')  # forward filling
# dataframe.fillna(method='bfill') # backward filling

print(dataframe.head())

price_dataframe = dataframe.loc[:, ['Adj Close']].copy()
return_dataframe = dataframe.loc[:, ['daily_return']].copy()

# print(price_dataframe)
price_dataframe.plot(figsize=(16, 9), title='Adj Close')
plt.savefig('./plots/Adj_Close.png')

# print(return_dataframe)
return_dataframe.plot(figsize=(16, 9), title='return')
plt.savefig('./plots/return.png')