import pandas as pd
import math
import numpy as np
from scipy import stats
import scipy.optimize
from scipy.optimize import OptimizeWarning
import warnings
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from matplotlib.dates import date2num
from datetime import datetime
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool
import matplotlib.pyplot as plt

class holder:
    1

# heiken Ashi candles

def heikenashi_helper(args):
    return heikenashi(*args)

def parallel_heikenashi(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(heikenashi_helper, job_args)

def heikenashi(HKA, periods):

    results = holder()

    dict = {}

    HAclose = HKA[['open','high','low','close']].sum(axis=1) / 4
    HAopen = HAclose.copy()
    HAopen.iloc[0] = HAclose.iloc[0]
    HAhigh = HAclose.copy()
    HAlow = HAclose.copy()

    for i in range(0, len(HKA)):
        HAopen.iloc[i] = (HAopen.iloc[i - 1] + HAclose.iloc[i - 1]) / 2

        HAhigh.iloc[i] = np.array([HKA.high.iloc[i]]).max()

        HAlow.iloc[i] = np.array([HKA.low.iloc[i]]).min()

    df = pd.concat((HAopen, HAhigh, HAlow, HAclose), axis=1)
    df.columns = [['open', 'high', 'close', 'low']]

    #df.index = df.index.droplevel(0)

    dict[periods[0]] = df

    results.candles = dict

    return results

def detrend(prices, method='difference'):
    # peram prices: dataframe OHLC currency data
    # peram method: method by which to detrend 'liner' or 'difference'
    # return: the detrended price series

    if method == 'difference':

        detrended = prices.close[1:] - prices.close[:-1].values

    elif method == 'linear':

        x = np.arange(0, len(prices))
        y = prices.close.values

        model = LinearRegression()

        model.fit(x.reshape(-1, 1), y.reshape(-1, 1))

        trend = model.predict(x.reshape(-1, 1))

        trend = trend.reshape((len(prices),))

        detrended = prices.close - trend
    else:
        print('you did not input a valid option')

    return detrended

# fourier series expression fitting function
def fseries(x, a0, a1, b1, w):
    f = a0 + a1 * np.cos(w * x) + b1 * np.sin(w * x)

    return f

# Sine series expression fitting function
def sseries(x, a0, b1, w):
    f = a0 + b1 * np.sin(w * x)

    return f

# Fourier series coefficient calculation function
def fourier_helper(args):
    return fourier(*args)

def parallel_fourier(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(fourier_helper, job_args)

def fourier(prices, periods, method='difference'):
    ""
    # param price: from OHLC Data
    # param periods: list of periods to determine coefficients i.e.,[1,3,5,7,]
    # param method: method to detrend data 'linear' or 'difference'
    # return: dictionary of dataframe containing coefficients for the periods
    ""
    results = holder()

    dict = {}
    # compute computation of the series
    plot = False

    detrended = detrend(prices, method)

    for i in range(0,len(periods)):  # loop the periods

        coeffs = []  # creat list for oefficients
        test = []

        for j in range(periods[i],len(prices)):  # shifting through the periods

            x = np.arange(0, periods[i],dtype=float)
            y = detrended.iloc[j - periods[i]:j].values.flatten()

            with warnings.catch_warnings():
                warnings.simplefilter('error',OptimizeWarning)

                try:

                    res = scipy.optimize.curve_fit(fseries, x, y)

                except (RuntimeError, OptimizeWarning):

                    res = np.empty((4, 4))
                    res[0, :] = np.NAN

                #except (KeyError):
                    #pass

            if plot == True:
                xt = np.linspace(0 , periods[i], 100)
                yt = fseries(xt, res[0][0], res[0][1], res[0][2], res[0][3])

                plt.plot(x, y)
                plt.plot(xt, yt, 'r')

                plt.show()

            coeffs = np.append(coeffs, res[0], axis=0)

        coeffs = np.array(coeffs, ).reshape(((len(coeffs) //  4, 4)))

        columns = ['a0', 'a1', 'b1', 'w']
        df = pd.DataFrame(columns=columns)

        #df.fillna(method='bfill')
        #print(df)

        coeffs = coeffs.flatten()
        a = coeffs[0::4]
        df['a0'] = a
        b = coeffs[1::4]
        df['a1'] = b
        c = coeffs[2::4]
        df['b1'] = c
        d = coeffs[3::4]
        df['w'] = d

        #print(df)
        #print(coeffs)

        dict[periods[i]] = df

    results.coeffs = dict

    return results

# sine series coefficient calculation function DATA but the array is dirfferent sizes
def sine_helper(args):
    return sine(*args)

def parallel_sine(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(sine_helper, job_args)

def sine(prices, periods, method='difference'):
    ""
    # param price: from OHLC Data
    # param periods: list of periods to determine coefficients i.e.,[1,3,5,7,]
    # param method: method to detrend data 'linear' or 'difference'
    # return: dictionary of dataframe containing coefficients for the periods
    ""
    results = holder()

    dict = {}
    # compute computation of the series
    plot = False

    detrended = detrend(prices, method)

    for i in range(0, len(periods)):  # loop the periods

        coeffs = []  # creat list for oefficients
        test = []

        for j in range(periods[i], len(prices)):  # shifting through the periods

            x = np.arange(0, periods[i],dtype=float)
            y = detrended.iloc[j - periods[i]:j].values.flatten()

            with warnings.catch_warnings():
                warnings.simplefilter('error')

                try:

                    res = scipy.optimize.curve_fit(sseries, x, y)

                except (RuntimeError):

                    res = np.empty((1, 3))
                    res[0, :] = np.NAN

            if plot == True:
                xt = np.linspace(0, periods[i], 100)
                yt = sseries(xt, res[0][0], res[0][1], res[0][2])

                plt.plot(x, y)
                plt.plot(xt, yt, 'r')

                plt.show()

            coeffs = np.append(coeffs, res[0], axis=0)

        coeffs = np.array(coeffs).reshape(((len(coeffs) // 3, 3 )))

        columns = ['a0','b1','w']
        df = pd.DataFrame(columns=columns)

        # df.fillna(method='bfill')

        coeffs = coeffs.flatten()
        a = coeffs[0::3]
        df['a0'] = a
        c = coeffs[1::3]
        df['b1'] = c
        d = coeffs[2::3]
        df['w'] = d
        dict[periods[i]] = df

    results.coeffs = dict

    return results

#stochastic Oscillator Function #

def stochastic_helper(args):
    return stochastic(*args)

def parallel_stochastic(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(stochastic_helper, job_args)

def stochastic(prices,periods):
    #param prices: price data
    #param periods: periods list to calculate function value
    #return: oscillator function values
    results = holder()
    close = {}

    for i in range(0, len(periods)):

        Ks = []

        for j in range(periods[i], len(prices)-periods[i]):

            C = prices.close.iloc[j]
            H = prices.high.iloc[j-periods[i]:j].all().max()
            L = prices.low.iloc[j - periods[i]:j].all().min()

            if H == L:
                K = 0
            else:
                K = 100*(C-L)/(H-L)
            Ks = np.append(Ks,K)
        Ks = Ks[0::1]

        columns = ['K','D']
        df = pd.DataFrame(columns=columns, index=prices.iloc[periods[i]+1:-periods[i]+1].index)
        df['K'] = list(Ks)
        a = list(df['K'].rolling(3).mean())
        df['D'] = a
        df = df.dropna()
        #print(df)

        close[periods[i]] = df

    results.close = close

    return results

#Williams Oscillator Function
def williams_helper(args):
    return williams(*args)

def parallel_williams(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(williams_helper, job_args)

def williams(prices,periods):
    #param prices: price data
    #param periods: list of periods
    #return; values of williams OSC funtions

    results = holder()
    close = {}

    for i in range(0,len(periods)):
        Rs = []
        for j in range(periods[i], len(prices)):

            C = prices.close.iloc[j]
            H = prices.high.iloc[j - periods[i]:j].max().all()
            L = prices.low.iloc[j - periods[i]:j].min().all()

            if H == L:
                R = 0
            else:
                R = -100 * (H - C) / (H - L)

            Rs = np.append(Rs,R)

        a = Rs[0::1]
        columns = ['R']
        df = pd.DataFrame(a, columns=columns)
        #df.columns = ['R']
        #df['R'] = list(a)
        close[periods[i]] = df

    results.close = close

    return results

# Williams Accumulation Distribution Line Function
def wadl_helper(args):
    return wadl(*args)

def parallel_wadl(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(wadl_helper, job_args)

def wadl(prices, periods):
    # param prices: dataframe of OHLC
    # param periods list periods to calculate function
    # return: williams accumulation ditribution lines

    results = holder()
    dict = {}

    for i in range(0, len(periods)):

        wad = []

        for j in range(periods[i], len(prices)):

            trh = np.array([prices.high.iloc[j], prices.close.iloc[j - 1]]).max()

            trl = np.array([prices.low.iloc[j], prices.close.iloc[j - 1]]).min()

            if prices.close.iloc[j].all() > prices.close.iloc[j - 1].all():

                pm = prices.close.iloc[j] - trl

            elif prices.close.iloc[j].all() < prices.close.iloc[j - 1].all():

                pm = prices.close.iloc[j] - trh

            elif prices.close.iloc[j].all() == prices.close.iloc[j - 1].all():

                pm = 0
            else:

                print('these things happen, keep up the good work')

            ad = pm * prices.volume.iloc[j]

            wad = np.append(wad, ad)

        w = wad[0::1]
        columns = ['close']
        wad = pd.DataFrame(columns=columns)#index=prices.iloc[periods[i]:-periods[i]].index)
        wad['close'] = w

        #wad.columns = [['close']]

        dict[periods[i]] = wad

    results.wadl = dict

    return results

# Data Resampling Function - changes candles
def ohlcresample(DataFrame, TimeFrame, column='ask'):
    # Param DataFrame: DataFrame containing data that we want to resample
    # param TmeFrame timeframe that we want for resampling
    # Param column which column we are resampling (buy or sell) default='sell'
    # return resampled OHCL data for the given timeframe

    resampled = holder()

    grouped = DataFrame

    if np.any(DataFrame.ask == True):

        if column == 'ask':
            sell = grouped['ask'].resample(TimeFrame).ohlc()
            volume = grouped['volume'].resample(TimeFrame).count()
            resampled = pd.DataFrame(sell)
            resampled['volume'] = volume

        elif column == 'bid':
            buy = grouped['bid'].resample(TimeFrame).ohlc()
            volume = grouped['volume'].resample(TimeFrame).count()
            resampled = pd.DataFrame(buy)
            resampled['volume'] = volume

        else:

            raise ValueError('bid or ask please')

    elif np.any(DataFrame.columns == 'close'):
        open = grouped['open'].resample(TimeFrame).ohlc()
        high = grouped['high'].resample(TimeFrame).ohlc()
        low = grouped['low'].resample(TimeFrame).ohlc()
        close = grouped['close'].resample(TimeFrame).count()
        volume = grouped['volume'].resample(TimeFrame).count()

        resampled = pd.DataFrame(open)
        resampled['high'] = high
        resampled['low'] = low
        resampled['close'] = close
        resampled['volume'] = volume

        #resampled = resampled.dropna()

    return resampled

# Momentum Function

def momentum_helper(args):
    return momentum(*args)

def parallel_momentum(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(momentum_helper, job_args)

def momentum(prices,periods):
    # param prices dataframe or OHLC
    # param periods list of periods to calculate funtion value
    # return momentum indicator

    results = holder()
    open = {}
    close = {}

    for i in range(0,len(periods)):

        open[periods[i]] = pd.DataFrame(prices.open.iloc[periods[i]:]-prices.open.iloc[:-periods[i]].values,
                                        index=prices.iloc[periods[i]:].index)

        close[periods[i]] = pd.DataFrame(prices.close.iloc[periods[i]:] - prices.close.iloc[:-periods[i]].values,
                                        index=prices.iloc[periods[i]:].index)

        open[periods[i]].columns = [['open']]
        close[periods[i]].columns = [['close']]

    results.open = open
    results.close = close

    return results

#Proc Function (Price Rate of Change)

def proc_helper(args):
    return proc(*args)

def parallel_proc(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(proc_helper, job_args)

def proc(prices,periods):

    #param prices: dataframe containing prices
    #param periods: periods to calculate Rrice rate of change
    #return: Price rate of change for indicated periods

    results = holder()
    proc = {}

    for i in range(0,len(periods)):

        proc[periods[i]] = pd.DataFrame((prices.close.iloc[periods[i]:]-prices.close.iloc[:-periods[i]].values)\
                                        /prices.close.iloc[:-periods[i]].values)

        proc[periods[i]].columns = ['close']

    results.proc = proc

    return results

#Accumulation Distribution Oscillator

def ado_helper(args):
    return ado(*args)

def parallel_ado(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(ado_helper, job_args)

def ado(prices,periods):

    #param prices: OHLC DATAFRAME
    #param periods: periods to compute indicator
    #return indicator values for given periods

    results = holder()
    accdist = {}

    for i in range(0,len(periods)):

        AD = []

        for j in range(periods[i],len(prices)-periods[i]):

            C = prices.close.iloc[j+1].all()
            H = prices.high.iloc[j-periods[i]:j].max().all()
            L = prices.low.iloc[j-periods[i]:j].min().all()
            V = prices.volume.iloc[j+1].all()

            if H==L:
                CLV = 0
            else:
                CLV= ((C-L)-(H-C))/(H-L)
            AD = np.append(AD,CLV*V)
        A = AD[0::1]
        columns = ['AD']

        AD = pd.DataFrame(columns=columns)
        AD['AD'] = A
        #AD.drop_duplicates(inplace=True)
        #AD.columns = [['AD']]

        accdist[periods[i]] = AD

    results.AD = accdist

    return results

#MACD - Moving Average Convergence Divergence

def macd_helper(args):
    return macd(*args)

def parallel_macd(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(macd_helper, job_args)

def macd(prices,periods):

    #param prices OHLC dataframe prices
    #param periods 1X2 array of EMA values
    results = holder()

    EMA1 = prices.close.ewm(span=periods[0]).mean()
    EMA2 = prices.close.ewm(span=periods[1]).mean()

    MACD = pd.DataFrame(EMA1 - EMA2)
    MACD.columns = [["L"]]

    SigMACD = MACD.rolling(3).mean()
    SigMACD.columns = [['SL']]

    results.line = MACD
    results.signal = SigMACD

    return results

#CCI (Commodity Channel Index)

def cci_helper(args):
    return cci(*args)

def parallel_cci(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(cci_helper, job_args)

def cci(prices,periods):

    #param prices: OHLC dataframe of price data
    #param periods: periods to compute indicator
    #retunr: CCI CCI for given periods

    results = holder()
    CCI = {}

    for i in range(0,len(periods)):

        MA = prices.close.rolling(periods[i]).mean()
        std = prices.close.rolling(periods[i]).std()

        D = (prices.close-MA)/std

        CCI[periods[i]] = pd.DataFrame((prices.close-MA)/(0.015*D))
        CCI[periods[i]].columns = [['close']]

    results.cci = CCI

    return results

# Bollinger Bands

def bollinger_helper(args):
    return bollinger(*args)

def parallel_bollinger(prices, periods, deviations):

    pool = ThreadPool()
    job_args = [(prices, periods, deviations)]
    pool.map(bollinger_helper, job_args)

def bollinger(prices,periods,deviations):
    #param prices: OHLC data
    #param periods: periods to computute bollinger abnds
    #param deviations: deviations to use when calculating bands (upper & lower)
    #return: bollinger bands

    results = holder()
    boll = {}

    for i in range(0, len(periods)):

        mid = prices.close.rolling(periods[i]).mean()
        std = prices.close.rolling(periods[i]).std()

        upper = mid+deviations*std
        lower = mid-deviations*std

        df = pd.concat((upper,mid,lower),axis=1)
        df.columns = [['upper','mid','lower']]

        boll[periods[i]] = df

    results.bands = boll

    return results

# Price Averages -DATA
def paverage_helper(args):
    return paverage(*args)

def parallel_paverage(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(paverage_helper, job_args)

def paverage(prices,periods):

    #param prices: price data
    #param periods list of epriods to calculate indicator values
    #return; average over the given periods

    results = holder()

    avs = {}

    for i in range(0,len(periods)):

        avs[periods[i]] = pd.DataFrame(prices[['open','high','low','close']].rolling(periods[i]).mean())

    results.avs = avs

    return results

# Slope functions
def slopes_helper(args):
    return slopes(*args)

def parallel_slopes(prices, periods):

    pool = ThreadPool()
    job_args = [(prices, periods)]
    pool.map(slopes_helper, job_args)

def slopes(prices,periods):

    #param: price data
    #param periods to get the indicaot values
    #return: slopes over given periods

    results = holder()
    slope = {}

    for i in range(0,len(periods)):

        ms = []

        for j in range(periods[i],len(prices)-periods[i]):

            y = prices.high.iloc[j-periods[i]:j].values.flatten()
            x = np.arange(0,len(y))

            res = stats.linregress(x,y=y)
            m = res.slope

            ms = np.append(ms,m)

        ms = pd.DataFrame(ms,index = prices.iloc[periods[i]:-periods[i]].index)

        slope[periods[i]] = ms

    results.slope = slope

    return results


import os
import numpy as np
from skimage.transform import warp, AffineTransform

import torch
import torch.utils.data as data
import torchvision.utils
from torchvision import transforms

class NYU_Depth_V2(data.Dataset):
    def __init__(self, train = True):
        if train == True:
            num_images = np.int(500 * 0.9)
        else:
            num_images = np.int(500 * 0.1)
        self.images = np.random.rand(num_images, 3,  228, 304) * 256
        self.depth = np.random.rand(num_images, 1, 480, 640)
        self.transform = transforms.Compose([
            transforms.Resize(size=(240,320), interpolation=1),
            transforms.CenterCrop(size=(228,304))
            ])

        return

    def __len__(self):
        if hasattr(self, 'images'):
            length = len(self.images)
            print("Length", length)

        return length

    def __getitem__(self, index):
        image = self.images[index]
        depth = self.depth[index]

        # The below call takes care of the image transformation. But one of the need is to get the data in the compatible format. The numpy array is not transformed using this logic
        #image_transformed = self.transform(image)

        return image, depth


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

from .data import get_data
from .model import Net

def train_mnist(args):
    use_cuda = torch.cuda.is_available()
    device = torch.device("cuda" if use_cuda else "cpu")

    train_loader, val_loader = get_data()

    model = Net().to(device)
    print(model)
    opt = optim.Adam(model.parameters(), lr=3e-4)

    cross_el_loss = nn.CrossEntropyLoss()
    l1_loss = nn.L1Loss()

    for epoch in range(args.epochs):
        # Train
        model.train()
        for batch_idx, data in enumerate(train_loader):
            img = data["img"].to(device)
            rand_num = data["rand_num"].to(device)
            cls_lbl = data["lbl"].to(device)
            sum_lbl = data["sum_lbl"].unsqueeze(dim=1).to(device)

            opt.zero_grad()
            cls_pred, sum_pred = model(img, rand_num)

            loss_cls = cross_el_loss(cls_pred, cls_lbl)
            loss_sum = l1_loss(sum_pred, sum_lbl)

            loss = loss_cls + loss_sum

            loss.backward()
            opt.step()

        print(f"Epoch: {epoch}, Train Cls loss: {loss_cls.item()}, Train Sum loss: {loss_sum.item()}, Train Total loss: {loss.item()}")

        # Eval
        model.eval()
        total_cls = 0
        correct_cls = 0
        total_sum = 0
        correct_sum = 0
        with torch.no_grad():
            for batch_idx, data in enumerate(val_loader):
                img = data["img"].to(device)
                rand_num = data["rand_num"].to(device)
                cls_lbl = data["lbl"].to(device)
                sum_lbl = data["sum_lbl"].unsqueeze(dim=1).to(device)

                cls_pred, sum_pred = model(img, rand_num)

                # Can be made better
                for idx, i in enumerate(cls_pred):
                    if torch.argmax(i) == cls_lbl[idx]:
                        correct_cls += 1
                    total_cls += 1

                # Can be made better
                for idx, i in enumerate(sum_pred):
                    p = sum_pred[idx][0].int()
                    l = sum_lbl[idx][0].int()
                    if (p == l):
                        correct_sum += 1
                    total_sum += 1

        print(f"Epoch: {epoch}, Test Cls accuracy: {correct_cls / total_cls}, Test Sum accuracy: {correct_sum / total_sum}")


import fileinput
import treelib

currentNode = None

AVAILABLE = 70000000
UPDATESIZE = 30000000

class FilesystemElement:
    def __init__(self, obj_type, size):
        self.obj_type = obj_type
        self.size = size
    def update_size(self, update):
        self.size += update

filesystem = treelib.Tree()

filesystem.create_node("/", "/", data=FilesystemElement("dir", 0))

def cd(command):
    global currentNode
    if command == "..":
        currentNode = filesystem.get_node(currentNode.bpointer)
    elif command == "/":
        currentNode = filesystem.get_node("/")
    else:
        identifier = currentNode.identifier + "_" + command
        if identifier in currentNode.fpointer:
            currentNode = filesystem.get_node(identifier)

def add_directory(properties):
    # create unique name with parent node _ new dir
    identifier = currentNode.identifier + "_" + properties
    node = treelib.Node(properties, identifier, data=FilesystemElement("dir", 0))
    filesystem.add_node(node, currentNode)

def add_file(properties):
    size, name = properties.split(" ")
    identifier = currentNode.identifier + "_" + name
    size = int(size)
    node = treelib.Node(name, identifier, data=FilesystemElement("file", size))
    filesystem.add_node(node, currentNode)
    update_tree(size)

def update_tree(size):
    currentNode.data.update_size(size)
    tempNode = currentNode
    while not tempNode.is_root():
        tempNode = filesystem.get_node(tempNode.bpointer)
        tempNode.data.update_size(size)

def sum_of_dir_smaller100000(tree_list):
    sum = 0
    for i in tree_list:
        if i.data.obj_type == "dir" and i.data.size < 100000:
            sum += i.data.size

    return sum

def find_appropriate_dir(tree_list, clear):
    temp = filesystem.get_node("/").data.size
    for i in tree_list:
        size = i.data.size
        if i.data.obj_type == "dir" and size > clear and size < temp:
            temp = size
    return temp

for line in fileinput.input("/home/gus/python/aoc-22/day7/input.txt"):
    line = line.rstrip()
    if line[0:4] == "$ cd":
        cd(line[5:])
    elif line[0:4] == "$ ls":
        ...
    elif line[0:3] == "dir":
        add_directory(line[4:])
    else:
        add_file(line)

filesystem.show(idhidden= False, data_property="size")

print(sum_of_dir_smaller100000(filesystem.all_nodes()))

used = filesystem.get_node("/").data.size
free = AVAILABLE - used
need = UPDATESIZE - free
print(f"space free:{free}")
print(f"need {need}")

print(f"Clear directory of size {find_appropriate_dir(filesystem.all_nodes(), need)}")


from lxml import objectify

from ebayapi import API, EbayError

EM = objectify.ElementMaker(annotate=False)

class ShoppingAPI(API):
    """
    Shopping API Request implementation.
    """

    def __init__(self, app_id, version, **config):
        super().__init__(app_id, version, **config)
        self.url = "http://open.api.ebay.com/shopping"

    def headers(self, call_name):
        headers = super(ShoppingAPI, self).headers(call_name)
        headers.update({
            "X-EBAY-API-VERSION": str(self.version),
            "X-EBAY-API-REQUEST-ENCODING": "XML"
        })
        return headers

    def parse(self, response):
        response = super().parse(response)
        if response['Ack'] == "Failure":
            raise EbayError(response['Errors']['ErrorClassification'], errors=response['Errors'])
        return response


import os
import pytest
import numpy
from firedrake import *

cwd = os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope='session')
def input():
   os.system("make -C " + cwd)

def swe_dam_break_2d():
   from firedrake_fluids.shallow_water import ShallowWater
   sw = ShallowWater(path=os.path.join(cwd, "swe_dam_break_2d.swml"))
   solution = sw.run()

   h = solution.split()[1]
   u = solution.split()[0]

   return h.vector().array(), u.vector().array()

def test_swe_dam_break_2d(input):
   h, u = swe_dam_break_2d()

   # x-component of Velocity
   assert(max(u[0::2]) <= 9.0)
   assert(max(u[0::2]) >= -2.0)
   # y-component of Velocity
   assert(max(u[1::2]) <= 6.0)
   assert(max(u[1::2]) >= -6.0)
   # Free surface
   assert(max(h) <= 5.0)
   assert(max(h) >= -4.0)

if __name__ == '__main__':
   pytest.main(os.path.abspath(__file__))


# -*- coding: utf-8 -*-
# @Time    : 2022/5/8 16:04
# @Author  : LiuYe
# @Email   : csu1704liuye@163.com | sy2113205@buaa.edu.cn
# @File    : data_loader.py
# @Software: PyCharm

# 目前需要处理的任务：
# 因为所有数据的文件名都是对应的，所以可以通过txt文件进行一一对应
# 1、图像超分任务：低分图像——高分图像
# 2、图像修复任务：缺损图像、缺损掩膜——修复图像

import os
import cv2
import albumentations as A
import numpy as np
import torch
from torch.utils.data import Dataset
from torchvision import transforms

def get_txt_from_directory(train_label_path, val_label_path, test_label_path):
    for file_path, text in zip((train_label_path, val_label_path, test_label_path), ('train', 'valid', 'test')):
        files = os.listdir(file_path)
        with open('./bjm_data/{}.txt'.format(text), 'w') as f:
            for i in files[: -1]:
                f.write(i + '\n')
            f.write(files[-1])

transform = A.Compose([
    A.HorizontalFlip(p=0.5),
    A.VerticalFlip(p=0.5),
    A.RandomRotate90(p=0.5),
    A.RandomCrop(128, 128),
])

class Super_Resolution_Dataset(Dataset):
    def __init__(self, low_resolution_image_path, raw_image_path, re_size,
                 data_txt, transformer=transform, down_scale=False, crop_size=False):
        self.raw_image_path = raw_image_path
        self.low_resolution_image_path = low_resolution_image_path
        self.re_size = re_size
        self.crop_size = crop_size
        self.data_txt = data_txt
        self.transform = transformer
        self.down_scale = down_scale
        with open(self.data_txt, 'r') as f:
            self.file_list = f.read().splitlines()

    def __len__(self):
        return len(self.file_list)

    def __getitem__(self, item):
        self.raw_image = cv2.imread(os.path.join(self.raw_image_path, self.file_list[item]))
        self.raw_image = cv2.cvtColor(self.raw_image, cv2.COLOR_BGR2RGB)
        self.raw_image = cv2.resize(self.raw_image, self.re_size)
        self.low_resolution_image = cv2.imread(os.path.join(self.low_resolution_image_path, self.file_list[item]))
        self.low_resolution_image = cv2.cvtColor(self.low_resolution_image, cv2.COLOR_BGR2RGB)
        self.low_resolution_image = cv2.resize(self.low_resolution_image, self.re_size)

        if self.transform is None:
            pass
        else:
            self.transformed = self.transform(image=self.raw_image, mask=self.low_resolution_image)
            self.raw_image, self.low_resolution_image = self.transformed['image'], self.transformed['mask']

        if self.down_scale:
            if self.crop_size:
                self.re_size = self.crop_size
            self.low_resolution_image = cv2.resize(self.low_resolution_image, (int(self.re_size[0] / 2 ** self.down_scale),
                                                                               int(self.re_size[1] / 2 ** self.down_scale)))

        self.raw_image, self.low_resolution_image = \
            transforms.ToTensor()(self.raw_image), transforms.ToTensor()(self.low_resolution_image)

        return self.low_resolution_image, self.raw_image

class Image_Reconstruction_Dataset(Dataset):
    def __init__(self, defective_image_path, defective_mask_path, raw_image_path, data_txt, transformer=transform):
        self.raw_image_path = raw_image_path
        self.defective_image_path = defective_image_path
        self.defective_mask_path = defective_mask_path
        self.data_txt = data_txt
        self.transform = transformer
        with open(self.data_txt, 'r') as f:
            self.file_list = f.read().splitlines()

    def __len__(self):
        return len(self.file_list)

    def __getitem__(self, item):
        self.raw_image = cv2.imread(os.path.join(self.raw_image_path, self.file_list[item]))
        self.raw_image = cv2.cvtColor(self.raw_image, cv2.COLOR_BGR2RGB)
        self.defective_image = cv2.imread(os.path.join(self.defective_image_path, self.file_list[item]))
        self.defective_image = cv2.cvtColor(self.defective_image, cv2.COLOR_BGR2RGB)
        self.defective_mask = cv2.imread(os.path.join(self.defective_mask_path, self.file_list[item]))
        self.defective_mask = cv2.cvtColor(self.defective_mask, cv2.COLOR_BGR2RGB)

        if self.transform is None:
            pass

        else:
            masks = [self.defective_image, self.defective_mask]
            self.transformed = self.transform(image=self.raw_image, masks=masks)
            self.raw_image = self.transformed['image']
            self.defective_image, self.defective_mask = self.transformed['masks']
            self.defective_mask = np.ones_like(self.defective_mask) - self.defective_mask
            self.raw_image, self.defective_image, self.defective_mask = \
                transforms.ToTensor()(self.raw_image), transforms.ToTensor()(self.defective_image), \
                transforms.ToTensor()(self.defective_mask)
            self.defective_mask = self.defective_mask[0:1, :, :]
            self.defective_image_mask = torch.cat([self.defective_image, self.defective_mask], dim=0)
        return self.defective_image_mask, self.raw_image


import os
import random
import boto3
import collections
from enum import Enum
from PIL import Image, ImageDraw, ImageFont
import tweepy
import json
from datetime import datetime, timedelta
import time
import re
import boto3

class State(Enum):
    INCORRECT_POSITION = 0
    CORRECT_POSITION = 1
    NOT_PRESENT = 2
    EMPTY = 3

colors = {
	State.INCORRECT_POSITION: "\x1b[43;30m",
	State.CORRECT_POSITION: "\x1b[42;30m",
	State.NOT_PRESENT: "\033[00m",
	State.EMPTY: "\033[00m"
}

image_colors = {
	State.INCORRECT_POSITION: "#c9b458",
	State.CORRECT_POSITION: "#6aaa64",
	State.NOT_PRESENT: "#86888a",
	State.EMPTY: "#d3d6da",
}

font = ImageFont.truetype('/var/task/package/fonts/HelveticaNeue Bold.ttf', 50)
letter_font = ImageFont.truetype('/var/task/package/fonts/HelveticaNeue Bold.ttf', 20)

SUCESS_MESSAGE = "{} {}! You got it in {}/6 tries!"
INVALID_MESSAGE = "❌ Invalid guess! Try again"
FAIL_MESSAGE = "Nice Try! Max tries exceeded, the word was {}"
GUESS_MESSAGE = "Guess {}/6:"
messages = {
    1: ["🎯", "GENIUS"],
    2: ["🧠", "MAGNIFICENT"],
    3: ["🔥", "IMPRESSIVE"],
    4: ["🏆", "GREAT"],
    5: ["🏅", "NOT BAD"],
    6: ["🤙", "PHEW"]
}

bot_user_id = "1501031219114516482"
s3 = boto3.client('s3')

def get_word_lists():
	solutions_file = open(os.path.join(os.path.dirname(__file__), "/var/task/package/data/solution_list.txt"), "r")
	solutions = solutions_file.read().splitlines()

	guesses_file = open(os.path.join(os.path.dirname(__file__), "/var/task/package/data/guess_list.txt"), "r")
	guesses = guesses_file.read().splitlines()
	guesses = guesses + solutions

	return solutions,guesses

def random_solution(solutions):
	return random.choice(solutions)

def handle_guesses(guesses, solution):
	output_map = {}
	letter_map = {}
	for guess in guesses:
		states = []
		# store pool of incorrect placements & counts
		pool = collections.Counter(s for s, g in zip(solution, guess) if s != g)

		for solution_char, guess_char in zip(solution, guess):
			if solution_char == guess_char:
				letter_map[guess_char] = State.CORRECT_POSITION
				states.append(State.CORRECT_POSITION)
			elif guess_char in solution and pool[guess_char] > 0:
				if guess_char not in letter_map or letter_map[guess_char] != State.CORRECT_POSITION:
					letter_map[guess_char] = State.INCORRECT_POSITION
				pool[guess_char] -= 1
				states.append(State.INCORRECT_POSITION)
			else:
				if guess_char not in letter_map:
					letter_map[guess_char] = State.NOT_PRESENT
				states.append(State.NOT_PRESENT)
		output_map[guess] = states

	return output_map, letter_map

def output(guesses, output_map, letter_map):
	for guess in guesses:
		string = ""
		for letter, state in zip(guess, output_map[guess]):
			string += colors[state] + " " + letter.upper() + " "
		string += colors[State.NOT_PRESENT]

def draw_image(guesses, output_map, letter_map):
	background = Image.new('RGBA', (700, 850), (255, 255, 255, 255))

	for y, guess in enumerate(guesses):
		for x, letter, state in zip(range(len(guess)), guess, output_map[guess]):
			draw_block(background, x, y, letter, state)

	for y in range(len(guesses), 6):
		for x in range(5):
			draw_block(background, x, y, None, State.EMPTY)

	alphabet = ["qwertyuiop","asdfghjkl","zxcvbnm"]
	for y, row in enumerate(alphabet):
		for x, letter in enumerate(row):
			state = letter_map[letter] if letter in letter_map else State.EMPTY
			draw_letter(background, x, y, letter, state)

	return background

def draw_letter(background, x, y, letter, state):
	size = (50, 65)
	spacing = 5
	font.size = 5
	side_spacing = {"x":77, "y":600}

	text_color = "black" if state == State.EMPTY else "white"

	color = image_colors[state]
	x_pos = side_spacing["x"] + (size[0] + spacing)*x
	y_pos = side_spacing["y"] + (size[1] + spacing)*y

	if(y == 1):
		x_pos += (size[0]+spacing)*0.5
	elif y==2:
		x_pos += (size[0]+spacing)*1.5
	block_pos = [x_pos, y_pos, x_pos + size[0], y_pos + size[1]]
	text_pos = (x_pos+size[0]/2,y_pos+size[1]/2)

	ImageDraw.Draw(background).rounded_rectangle(block_pos, fill=color, radius=6)
	ImageDraw.Draw(background).text(text_pos, letter.upper(), font=letter_font, anchor="mm", fill=text_color)

def draw_block(background, x, y, letter, state):
	side_spacing = {"x":130, "y":50}
	spacing = 10
	square_size = 80

	x_pos = side_spacing["x"] + (square_size + spacing)*x
	y_pos = side_spacing["y"] + (square_size + spacing)*y

	block_pos = [x_pos, y_pos, x_pos + square_size, y_pos + square_size]
	text_pos = (x_pos+square_size/2,y_pos+square_size/2)

	color = image_colors[state]

	if(letter):
		ImageDraw.Draw(background).rectangle(block_pos, fill=color)
		ImageDraw.Draw(background).text(text_pos, letter.upper(), font=font, anchor="mm")
	else:
		ImageDraw.Draw(background).rectangle(block_pos, outline=color, width=3)

def get_tweepy_client():
	client = tweepy.Client(
    	consumer_key=os.environ['CONSUMER_KEY'],
    	consumer_secret=os.environ['CONSUMER_KEY_SECRET'],
    	access_token=os.environ['ACCESS_TOKEN'],
    	access_token_secret=os.environ['ACCESS_TOKEN_SECRET'],
    	bearer_token=os.environ['BEARER_TOKEN']
	)

	auth = tweepy.OAuth1UserHandler(
	   os.environ['CONSUMER_KEY'], os.environ['CONSUMER_KEY_SECRET'],
	   os.environ['ACCESS_TOKEN'], os.environ['ACCESS_TOKEN_SECRET']
	)
	api = tweepy.API(auth)

	return client, api

def is_start_tweet(tweet, game_sessions):
	if "new game" not in tweet.text.lower():
		return False
	if str(tweet.author_id) not in game_sessions:
		return True
	session = game_sessions[str(tweet.author_id)]
	if session["new_game_id"] == str(tweet.id) or str(tweet.created_at) < session["created_at"]:
		return False

	return True

def is_guess_tweet(tweet, game_sessions):
	if str(tweet.author_id) not in game_sessions:
		return False
	session = game_sessions[str(tweet.author_id)]
	if(tweet.referenced_tweets is None):
		return False
	if(len(re.sub(r"(?:\@|https?\://)\S+", "", tweet.text).strip()) > 7):
		return False
	if(len(session["guesses"]) >= 6):
		return False

	is_referenced = False
	for referenced_tweet in tweet.referenced_tweets:
		if str(referenced_tweet.id) == session["latest_reply"]:
			is_referenced = True
	return is_referenced

def start_session(api, tweet, user, solution_list):
	message = "New Wordle game started. Start by replying with your first guess!"
	status = api.update_status(status=f"@{user.username} {message}", in_reply_to_status_id=str(tweet.id))
	session = {
		"author_id": str(tweet.author_id),
		"latest_reply": str(status.id),
		"guesses": [],
		"solution": random_solution(solution_list),
		"new_game_id": str(tweet.id),
		"created_at": str(tweet.created_at)
	}
	return session

def guess_response(api, message, tweet, user, image=None):
	response = None
	if(image):
		filename = f'/tmp/out_{tweet.id}.png'
		image.save(filename)
		response = api.update_status_with_media(status=f"@{user.username} {message}", filename=filename, in_reply_to_status_id=tweet.id)
		if os.path.exists(filename):
  			os.remove(filename)
	else:
		response = api.update_status(status=f"@{user.username} {message}", in_reply_to_status_id=tweet.id)
	return response.id

def get_since_time(delta_hours):
	date = datetime.utcnow()
	date = date - timedelta(hours=delta_hours)
	return date

def get_replies(client):
	query = f"-is:retweet (to:{bot_user_id} OR @wordle_io)"
	since_date = get_since_time(0.3)

	tweets = []
	users = {}
	for response in tweepy.Paginator(client.search_recent_tweets, query=query, start_time=since_date,
  			expansions=["author_id","referenced_tweets.id"], tweet_fields=["created_at"], user_fields=["username"], max_results=100):
		if not response.data:
			continue
		for user in response.includes['users']:
			users[user.id] = user
		for tweet in response.data:
			tweets.append(tweet)

	return [(tweet, users[tweet.author_id]) for tweet in tweets]

def valid_guess(guess, guess_list):
	return guess in guess_list

def get_game_sessions():
	try:
		obj = s3.get_object(
			Bucket=os.environ['S3_BUCKET'],
			Key=os.environ['GAME_SESSIONS_KEY']
		)
		sessions_json = obj['Body'].read()
		data = json.loads(sessions_json)
		return data
	except Exception as e:
		print("FATAL ERROR: Failed to load sessions: " + str(e))
		exit()

def store_game_sessions(game_sessions):
	sessions_string = json.dumps(game_sessions)
	s3.put_object(
		Bucket=os.environ['S3_BUCKET'],
    	Key=os.environ['GAME_SESSIONS_KEY'],
    	Body=str(sessions_string)
	)

def clear_old_sessions(game_sessions):
	clear_time = str(get_since_time(48))
	for user_id, session in game_sessions.copy().items():
		if(session["created_at"] < clear_time):
			game_sessions.pop(user_id)

def lambda_handler(event, context):
	solution_list, guess_list = get_word_lists()
	client, api = get_tweepy_client()
	game_sessions = get_game_sessions()
	update = False

	tweets = get_replies(client)
	if not tweets: return

	for tweet, user in tweets:

		print(str(tweet.id) + " " + str(user.username) + " " + tweet.text)

		user_id = str(user.id)
		if is_start_tweet(tweet, game_sessions):
			print(" => new game tweet")
			session = start_session(api, tweet, user, solution_list)
			game_sessions[user_id] = session
			update = True
		elif is_guess_tweet(tweet, game_sessions):
			print(" => new guess tweet")
			guess = re.sub(r"(?:\@|https?\://)\S+", "", tweet.text).strip().lower()
			session = game_sessions[user_id]
			update = True
			if len(guess) != 5 or not valid_guess(guess, guess_list):
				tweet_id = guess_response(api, INVALID_MESSAGE, tweet, user)
				session["latest_reply"] = str(tweet_id)
				game_sessions[user_id] = session
				continue

			session["guesses"].append(guess)
			guesses = session["guesses"]

			output_map, letter_map = handle_guesses(guesses, session["solution"])
			image = draw_image(guesses, output_map, letter_map)

			guess_count = len(guesses)
			message = ""
			game_over = False
			if(guess == session["solution"]):
				message = SUCESS_MESSAGE.format(messages[guess_count][0], messages[guess_count][1], guess_count)
				game_over = True
			elif guess_count >= 6:
				message = FAIL_MESSAGE.format(session["solution"])
				game_over = True
			else:
				message = GUESS_MESSAGE.format(guess_count)

			tweet_id = guess_response(api, message, tweet, user, image)
			session["latest_reply"] = str(tweet_id)
			game_sessions[user_id] = session

	if update:
		clear_old_sessions(game_sessions)
		store_game_sessions(game_sessions)


'''
'''
from django.db import models
from ckeditor.fields import RichTextField

class HelpSection(models.Model):
    title = models.CharField(max_length=150)
    slug = models.SlugField(unique=True)
    ref = models.CharField(max_length=300, null=True, blank=True)
    content = RichTextField()
    order_by = models.IntegerField(default=0)
    help_section = models.ForeignKey('HelpSection', null=True, blank=True)

    created_at = models.DateTimeField(auto_now_add=True, editable=False)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return '%s - %s' % (self.title, self.slug)


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# import the dataset
df = pd.read_csv("normalised.csv")
def fit_poly(x, y, degree):
    """
    Fit a polynomial function to the data.

    Args:
    x: independent variable data
    y: dependent variable data
    degree: degree of the polynomial function to fit

    Returns:
    popt: coefficients of the polynomial fit
    pcov: covariance matrix of the fit
    """
    popt, pcov = curve_fit(lambda x, *p: np.polyval(p, x), x, y, p0=np.ones(degree + 1))
    return popt, pcov
# create a subset of the data with only CO2 and GDP columns
df_subset = df[['CO2', 'GDP']]

# define the independent and dependent variables
x = df_subset['GDP']
y = df_subset['CO2']

# fit a polynomial function of degree 2 to the data
popt, pcov = fit_poly(x, y, degree=2)

# plot the original data and the fitted function
plt.scatter(x, y, label='Data')
plt.plot(x, np.polyval(popt, x), 'r-', label='Fit')
plt.xlabel('GDP')
plt.ylabel('CO2')
plt.legend()
plt.show()
# predict CO2 level in 2030
future_year = 2030
predicted_gdp = df_subset['GDP'].max() + 0.1  # assume 10% GDP growth
predicted_co2 = np.polyval(popt, predicted_gdp)

# print the predicted CO2 level
print(f"Predicted CO2 level in {future_year}: {predicted_co2:.2f} metric tons per capita")


"""
licenses_exporter: A prometheus client to export lsmon & lmutil licenses
Tonin 2018. University of Cordoba
"""

import traceback
import subprocess
from prometheus_client import Gauge, start_http_server, REGISTRY, PROCESS_COLLECTOR, PLATFORM_COLLECTOR, GC_COLLECTOR
from selenium import webdriver
from datetime import datetime
import time
import sys
import os
import re
import ruamel.yaml as yaml
import requests
import pandas as pd
import socket

#unregister default metrics
REGISTRY.unregister(PROCESS_COLLECTOR)
REGISTRY.unregister(PLATFORM_COLLECTOR)
REGISTRY.unregister(GC_COLLECTOR)

#Licenses & config file
CONFIG_FILE = 'config.yml'
WRITEHTML = False
DEBUG = False
TRACE = False
VERBOSE = False
SUMMARY = True
if DEBUG: VERBOSE = True

driver = None

def appendFeature(feature_list,feature):
	if feature.name == "NULL":
		return
	else:
		feature_list.append(feature)

def isWindows():
	ret = True if os.name == 'nt' else False
	return ret

def isDocker():
	path = '/proc/self/cgroup'
	return (
		os.path.exists('/.dockerenv') or
		os.path.isfile(path) and any('docker' in line for line in open(path))
	)

def isNan(num):
	return num != num

def value(row,label):
	if type(label) is int:
		return row[int(label)]
	else:
		return row[label]

def trace(label,msg):
	print("TRACE:",label," ",msg)

class User(object):
	def __init__(self, name):
		self.name = name
		self.hostName = None
		self.device = None
		self.date = None

	def printUser(self):
		print("\t",self.name," ",self.hostName," ",self.device," ",self.date)

	def printUserToError(self):
		print("\t",self.name," ",self.hostName," ",self.device," ",self.date, file=sys.stderr)

class Feature(object):
	def __init__(self, name, app, parent):
		self.name = name
		self.maxLicenses = 0
		self.inUse = 0
		self.app = app
		self.parent = parent
		self.userList = []

		#Vemos si tenemos translaciones de etiquetes de features
		try:
			dummy = parent.features['translate']
			self.translatable = True
		except:
			self.translatable = False
			return

		#Realizamos la traduccion del self.name
		if parent.features['translate']['at_stage'] == 1:
			self.translate()

	def translate(self):
			r = re.search(self.parent.features['translate']['search'],self.name)
			if r is not None:
				#Depuramos
				if DEBUG:
					print("DEBUG: Translating feature: ",self.name)
				self.name = self.parent.features['translate']['translations'][r.group('feature_name')] + " " + r.group('feature_suffix')
			else:
				#Si no encontramos traslacion debemos marcarla para borrar
				self.name = "NULL"

	def isUsing(self):
		if self.inUse > 0.0:
			return True
		else:
			return False

	def printFeature(self):
		if not VERBOSE:
			return
		print("app=",self.app," feature=",self.name," max=",self.maxLicenses," current=",self.inUse)
		for user in self.userList:
			user.printUser()

class App(object):
	def __init__(self, parent, argsDict):
		self.parent = parent
		for key,value in argsDict.items():
			setattr(self,key,value)
		#Hacemos lista los strings separados por comas
		try:
			self.features['include'] =  str(self.features['include']).split(",")
		except:
			pass
		try:
			self.users['url']['index'] = str(self.users['url']['index']).split(",")
		except:
			pass
		try:
			self.label['item'] = self.label['item'].split(",")
		except:
			pass

		self.featureList = []
		if(self.type == 'lsmon'):
			self.parse = self.parseLsmon
		elif(self.type == 'lmutil'):
			self.parse = self.parseLmutil
		elif(self.type == 'rlmutil'):
			self.parse = self.parseRlmutil
		elif(self.type == 'web'):
			self.parse = self.parseWeb
		elif(self.type == 'webtable'):
			self.parse = self.parseWebTable
		elif(self.type == 'webtablejs'):
			self.parse = self.parseWebTableJs
		elif(self.type == 'rawsocket'):
			self.parse = self.parseRawSocket
		self.online = False
		driver = None

	def df_parse_features(self,feature_tbl):
		has_features = False
		if DEBUG: print("DEBUG: features_to_include: ",self.features['include'])
		if not feature_tbl.empty:
			#Hemos encontrado cosas
			for index,row in feature_tbl.iterrows():
				if TRACE: trace(self.name,"En bucle iterrows de df_parse_features")
				if not isNan(row[self.features['label']['name']]):
					if TRACE: trace(self.name,"not isNan en  df_parse_features")
					#No siempre tiene que estar product definido, lo ponemos en un try
					try:
						if self.product['include'] is not None:
							if not str(self.product['include']) in str(row[self.product['label']]):
								continue
					except:
						pass
					if DEBUG: print("DEBUG: row[self.feature_label_name: ",row[self.features['label']['name']])
					if row[self.features['label']['name']] in self.features['include'] or self.features['include'][0] == 'ALL':
						if DEBUG:
							print("DEBUG: ",row[self.features['label']['name']]," Total: ",row[self.features['label']['total']]," Usadas: ",row[self.features['label']['used']])
						self.online = True
						feature = Feature(row[self.features['label']['name']],self.name,self)
						appendFeature(self.featureList,feature)
						feature.maxLicenses = float(row[self.features['label']['total']])
						feature.inUse = float(row[self.features['label']['used']])
						if isNan(feature.inUse):
							feature.inUse = 0;
						if self.used_as_free:
							feature.inUse = feature.maxLicenses - feature.inUse
						has_features = True
		return has_features

	def df_parse_users(self,users_tbl,current_feat):
		if not users_tbl.empty:
			for index,row in users_tbl.iterrows():
				if index == self.users['table']['skip_header']:
					continue
				if self.users['table']['method'] == 'search':
					#TODO: En base a codemeter solo sacamos info del hostname, ya lo iremos ampliando
					for feat in self.featureList:
						if feat.name in row[self.users['label']['featurename']]:
							user = User(value(row,self.users['label']['username'])) if self.users['label']['username'] is not None else "None"
							feat.userList.append(user)
							user.hostName = value(row,self.users['label']['hostname']) if self.users['label']['hostname'] is not None else "None"
							user.date = value(row,self.users['label']['date']) if self.users['label']['date'] is not None else "None"
				if self.users['table']['method'] == 'index':
					user = User(value(row,self.users['label']['username']) if self.users['label']['username'] is not None else "None")
					current_feat.userList.append(user)
					user.hostName = value(row,self.users['label']['hostname']) if self.users['label']['hostname'] is not None else "None"
					user.date = value(row,self.users['label']['date']) if self.users['label']['date'] is not None else "None"

	def parseWebFeaturesUrl(self):
		url_range  = self.features['url']['index'] if self.features['url']['index'] is not None else 2
		for i in range(1,url_range):
			if TRACE: trace(self.name," En bucle parseweburl")
			#Componemos la url
			if url_range == 2:
				url = self.features['url']['prefix']
			else:
				url = self.features['url']['prefix'] + str(i) + self.features['url']['suffix']
			if DEBUG: print("URL: ",url)
		return url

	def parseWebUsersUrl(self,i):
		passFeature = False
		#Me salto los features que no se esten usando
		for current_feat in self.featureList:
			if current_feat.name == self.features['include'][self.users['url']['index'].index(i)]:
				if current_feat.isUsing() is False:
					passFeature = True
				else:
					break
		if passFeature:
			return None,None
		if self.users['url']['suffix'] is not None:
			url = self.users['url']['prefix'] + str(i) + self.users['url']['suffix']
		else:
			url = self.users['url']['prefix']
		return current_feat,url

	def parseWebTableJs(self):
		if TRACE: trace(self.name," Entrando en parseWebJS")
		self.featureList = []
		self.online = False

		#Parse features
		url = self.parseWebFeaturesUrl()
		driver = self.parent.driver
		try:
			driver.get(url)
		except Exception as exc:
			#Si se produce una excepcion retornamos
			print("Excepcion en driver.get de pwtJs")
			print("URL: ",url)
			print("Exception: ",exc)
			return
		try:
			table = driver.find_element("id",self.features['js']['id'])
		except Exception as exc:
			print("Excepción en driver.find de PwtJS")
			print("Exception: ",exc)
			return
		try:
			table_html = table.get_attribute(self.features['js']['attr'])
		except Exception as exc:
			print("Excepción en table.get_attribute de PwtJS")
			print("Exception: ",exc)
			return
		try:
			feature_tbl = pd.read_html(table_html)[0]
		except Exception as exc:
			print("Excepcion en read_html de pwtJs")
			print("Exception: ",exc)
			return
		if self.features['js']['iloc'] is not None:
			feature_tbl.columns = feature_tbl.iloc[int(self.features['js']['iloc'])]
			feature_tbl.drop([int(self.features['js']['iloc'])],inplace=True)
		has_features = self.df_parse_features(feature_tbl)
		if DEBUG: print("Has features: ",has_features)
		if not has_features:
			if DEBUG: print("Salgo por not has features")
			return
		#Parse users
		#Lo meto todo en un try por si falla
		try:
			if has_features and self.users['monitor']:
				for i in self.users['url']['index']:
					current_feat,url = self.parseWebUsersUrl(i)
					if url is not None:
						driver.get(url)
						table = driver.find_element("id",self.users['js']['id'])
						table_html = table.get_attribute(self.users['js']['attr'])
						users_tbl = pd.read_html(table_html)[0]
						if self.users['js']['iloc'] is not None:
							users_tbl.columns = users_tbl.iloc[int(self.users['js']['iloc'])]
							users_tbl.drop([int(self.users['js']['iloc'])],inplace=True)
						self.df_parse_users(users_tbl,current_feat)
		except Exception as exc:
			print("Excepcion en parse users de pwtJs")
			print("Exception: ",exc)
			return

	def parseWebTable(self):
		if TRACE: trace(self.name," Entrando en parseWebTable")
		self.featureList = []
		self.online = False

		url = self.parseWebFeaturesUrl()
		#Aquí puede fallar, controlamos el error
		try:
			all_feature_tables = pd.read_html(url)
		except Exception as exc:
			print("Excepción en pd.read_html (features) de parseWebTable")
			print("Excepción: ",exc)
			return

		feature_tbl = all_feature_tables[self.features['table']['index']]
		#monitorizamos las licencias
		has_features = self.df_parse_features(feature_tbl)
		#monitorizamos los usuarios:
		if has_features and self.users['monitor']:
			for i in self.users['url']['index']:
				current_feat,url = self.parseWebUsersUrl(i)
				if url is not None:
					try:
						all_users_table = pd.read_html(url)
					except Exception as exc:
						print("Excepción en pd.read_html (users) de parseWebTable")
						print("Excepción: ",exc)
					return
					users_tbl = all_users_table[self.users['table']['index']]
					self.df_parse_users(users_tbl,current_feat)

	def parseWeb(self):
		if TRACE: trace(self.name," Entrando en parseweb")
		self.featureList = []
		self.online = False

		url = self.parseWebFeaturesUrl()
		if DEBUG: print("URL: ",self.name," ",url)
		#Realizamos el request
		try:
			Response = requests.get(url)
		except Exception as exc:
			print("Excepción en request.get  de parseWeb")
			print("Excepción: ",exc)
			return
		if TRACE: print("TRACE: ",self.name," parseweb despues de request")
		content = Response.content

		if WRITEHTML:
			name = str(i) + ".web"
			file = open(name,"wb")
			file.write(content)
			file.close()
			print("DEBUGURL: ",self.name," ",url)
			print("DEBUGREGEX: ",self.match_exist)

		#Vemos si existe algo para este parametro
		match = re.findall(self.features['match']['exist'], str(content), re.MULTILINE)
		if DEBUG: print("PARSEWEBMATCH: ",self.name," ",match)
		if match:
			if TRACE: trace(self.name,"En if match parseweb")
			feature = Feature(match[0],self.name,self)
			self.online = True
			appendFeature(self.featureList,feature)
			#Existe luego leemos el numero total de licencias y las que estan en uso
			total = re.findall(self.features['match']['total'], str(content), re.MULTILINE)
			inUse = re.findall(self.features['match']['used'], str(content), re.MULTILINE)
			#Tenemos que comprobar que efectivamente hay alguien usándolo, si no, no podemos leer el total de licencias
			try:
				feature.maxLicenses = float(total[0])
				feature.inUse = float(inUse[0])
			except:
				return
			if self.used_as_free:
				feature.inUse = feature.maxLicenses - feature.inUse
				if DEBUG:
					print("Total ",feature.name,": ",feature.maxLicenses)
					print("Inuse ",feature.name,": ",feature.inUse)
			else:
				if DEBUG: print("DEBUG: ",self.name," ",i,"nomatch. Pattern ",self.features['match']['exist'])

	def parseLsmon(self):
		self.featureList = []
		self.online = False
		p = subprocess.Popen([self.parent.LSMONCMD,self.license_server],stdin=subprocess.PIPE,stdout=subprocess.PIPE,universal_newlines=True)
		output = p.stdout
		p.stdin.close()
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					if 'Feature name' in line:
						aux = line.split(":",1)[1][1:-3].replace('"','')
						if aux in self.features['include'] or self.features['include'][0] == "ALL":
							feature = Feature(aux, self.name,self)
							self.online = True
							appendFeature(self.featureList,feature)
						else:
							feature = None
					if 'Maximum concurrent user' in line and feature:
						feature.maxLicenses = float(line.split(":",1)[1][1:])
					if 'Unreserved tokens in use' in line and feature:
						feature.inUse = float(line.split(":",1)[1][1:])
					if  'Feature version' in line and feature:
						feature.name = feature.name + line.split(":",1)[1][1:].strip('"')
						if feature.translatable:
							if self.features['translate']['at_stage'] == 2:
								feature.translate()
					if 'User name' in line and feature and self.users['monitor']:
						user = User(line.split(":",1)[1][1:])
						feature.userList.append(user)
					if 'Host name' in line and feature and self.users['monitor']:
						user.hostName =  line.split(":",1)[1][1:]

	def parseLmutil(self):
		self.featureList = []
		self.online = False
		feature = None
		output = subprocess.getstatusoutput(self.parent.LMUTILCMD + ' ' + self.license_server)
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					if 'Users of' in line:
						r = re.search('Users of (.*):  \(Total of (.*)licenses? issued;  Total of (.*) licenses? in use\)',line)
						if r is not None:
							if r.group(1) in self.features['include'] or self.features['include'][0] == "ALL":
								feature = Feature(r.group(1), self.name,self)
								self.online = True
								feature.maxLicenses = float(r.group(2))
								feature.inUse = float(r.group(3))
								appendFeature(self.featureList,feature)
							else:
								feature = None
					if ', start' in line and feature and self.users['monitor']:
						r = re.search('^\s+(.*) (.*) (.*) \((.*)\) \((.*)/(.*) (.*)\), start (.*)',line)
						user = User(r.group(1))
						user.hostName = r.group(2)
						user.device = r.group(3)
						user.date = r.group(8)
						feature.userList.append(user)
	def parseRlmutil(self):
		self.featureList = []
		self.online = False
		output = subprocess.getstatusoutput(self.parent.RLMUTILCMD + ' ' + self.license_server)
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					feature = None
					if any(label in line for label in self.label['item']):
						feat_name = line.strip().split(" ")[0]
					#monitor features
					if self.label['count'] in line:
						r = re.search('.+count: (.*), (.*) inuse: (.*),',line)
						if r is not None:
							if r.group(1) in self.features['include'] or self.features['include'][0] == "ALL":
									feature = Feature(feat_name, self.name,self)
									self.online = True
									feature.maxLicenses = float(r.group(1))
									feature.inUse = float(r.group(3))
									appendFeature(self.featureList,feature)
							else:
									feature = None
					#monitor users
					if 'handle' in line  and self.users['monitor']:
						r = re.search('^\s+(.*) (.*): (.*)@(.*) (.*) at (.*)  \(handle.*',line)
						user = User(r.group(3))
						user.hostName = r.group(4)
						user.device = r.group(4)
						user.date = r.group(6)
						#tenemos que averiguar a que feature se refiere
						for feat in self.featureList:
							if r.group(1) == feat.name:
								feat.userList.append(user)
	def parseRawSocket(self):
		self.featureList = []
		self.online = False
		if TRACE: trace(self.name,"En parseRawSocket")
		try:
			host = socket.gethostbyname(self.license_server)
		except Exception as exc:
			print("Excepción en gethostbyname  de parRawSocket")
			print("Excepción: ",exc)
			return
		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		sock.settimeout(self.timeout)
		try:
			if DEBUG:
				print("Conectando a ",host,":",self.license_port)
			sock.connect((host, self.license_port))
			if DEBUG:
				print("Conectado a ",host,":",self.license_port)
			if hasattr(self,'connect_only'):
				pass
			else:
				a = sock.recv(self.recv_bytes)
			feature = Feature(self.name,self.name,self)
			self.online = True
			feature.maxLicenses = 999
			feature.inUse = 888
			appendFeature(self.featureList,feature)
		except Exception as exc:
			print("Excepción en connect de parRawSocket")
			print("Excepción: ",exc)
			pass
		sock.close()

	def printFeatures(self):
		for feature in self.featureList:
			feature.printFeature()
		if self.featureList:
			return True
		else:
			return False

	def updateMetric(self):
		self.parse()
		self.parent.license_server_status.labels(app=self.name,fqdn=self.license_server,
												master='true',port='port',
												version='version').set(self.online)
		for feature in self.featureList:
			self.parent.license_feature_issued.labels(app=feature.app,name=feature.name).set(feature.maxLicenses)
			self.parent.license_feature_used.labels(app=feature.app,name=feature.name).set(feature.inUse)
			for user in feature.userList:
				try:
					self.parent.license_feature_used_users.labels(app=feature.app,name=feature.name,user=user.name,
																host=user.hostName,device=user.device).set(1)
				except Exception as exc:
					print("Excepción en updateMetric de updateMetric")
					print("Excepción: ",exc)
					print("Error en used_users.label", file=sys.stderr)
					user.printUserToError()

class Apps(object):
	def __init__(self,cfgFile):
		self.appList = []
		self.name = "Apps"
		with open(cfgFile, 'r') as yamlFile:
			self.cfg = yaml.safe_load(yamlFile)
		for appCfg in self.cfg['licenses']:
			if self.cfg['onlythis'] is None:
				if not appCfg['skip']:
					app = App(self, appCfg)
					self.appList.append(app)
			else:
				if isinstance(self.cfg['onlythis'],str):
					self.cfg['onlythis'] = self.cfg['onlythis'].split(",")
				if appCfg['name'] in self.cfg['onlythis']:
					app = App(self, appCfg)
					self.appList.append(app)

		self.license_feature_used = Gauge('license_feature_used','number of licenses used',['app','name'])
		self.license_feature_issued = Gauge('license_feature_issued','max number of licenses',['app','name'])
		self.license_feature_used_users = Gauge('license_feature_used_users','license used by user',['app','name','user','host','device'])
		self.license_server_status = Gauge('license_server_status','status of the license server',['app','fqdn','master','port','version'])
		self.PORT = self.cfg['config']['port']
		self.SLEEP = self.cfg['config']['sleep']
		self.LSMONCMD = self.cfg['config']['lsmon_cmd'] if not isWindows() else self.cfg['config']['lsmon_cmd'].replace('/','\\')
		self.LMUTILCMD = self.cfg['config']['lmutil_cmd'] if not isWindows() else self.cfg['config']['lmutil_cmd'].replace('/','\\')
		self.RLMUTILCMD = self.cfg['config']['rlmutil_cmd'] if not isWindows() else self.cfg['config']['rlmutil_cmd'].replace('/','\\')
		self.WEBDRIVER_TYPE = self.cfg['config']['webdriver']['type']
		self.WEBDRIVER_URL = self.cfg['config']['webdriver']['private-url'] if  isDocker() else self.cfg['config']['webdriver']['public-url']

		if TRACE: trace(self.name,"Despues de crear objetos prometheus")
		if self.WEBDRIVER_TYPE == 'local':
			self.driver = webdriver.Chrome()
		elif self.WEBDRIVER_TYPE == 'remote':
			driver_options = webdriver.ChromeOptions()
			self.driver = webdriver.Remote(
				command_executor=f"{self.WEBDRIVER_URL}",
				options=driver_options
			)
			self.driver.set_page_load_timeout(10)
		if TRACE: trace(self.name,"Saliendo de Apps")

	def parse(self):
		for app in self.appList:
			app.parse()

	def printApps(self):
		totalOnline = 0
		totalOffline = 0
		for app in self.appList:
			if app.printFeatures():
				totalOnline = totalOnline + 1
			else:
				totalOffline = totalOffline + 1
		if SUMMARY:
			now = datetime.now()
			dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
			print(dt_string," TOTAL ONLINE: ",totalOnline," TOTAL OFFLINE: ",totalOffline)

	def updateMetric(self):
		self.license_feature_used_users._metrics.clear()
		for app in self.appList:
			app.updateMetric()

if __name__ == '__main__':
	try:
		if TRACE: trace("MAIN ","Antes de Apps")
		apps = Apps(CONFIG_FILE)
	except Exception as exc:
		print("Excepción en configuración: ",exc)
		exit(1)
	start_http_server(apps.PORT)
	while True:
			try:
				if TRACE: trace("MAIN ","Antes de apps.updateMetric")
				apps.updateMetric()
			except Exception as exc:
				print("EXCEPCION NO CONTROLADA: ",exc),
				print(traceback.format_exc())
			if VERBOSE or SUMMARY:
				apps.printApps()
			sys.stdout.flush()
			time.sleep(apps.SLEEP)


# //////////////////// logger ////////////////////

#shows only WARNING, ERROR and CRITICAL and not INFO or DEBUG
#DEBUG do NOT goes in the logging.log file
import logging
import os

def logger():

    log_file = os.path.join("__pycache__", "logging.log")
    logging.basicConfig(filename=log_file, filemode='w', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.ERROR)
    logger.addHandler(console_handler)

# //////////////////// logger ////////////////////


# -*- coding: utf-8 -*-
from __future__ import absolute_import
import base64
from io import BytesIO
from PIL import Image
from splash.tests.test_proxy import BaseHtmlProxyTest
from .test_execute import BaseLuaRenderTest

class OnRequestTest(BaseLuaRenderTest, BaseHtmlProxyTest):
    def test_request_log(self):
        resp = self.request_lua("""
        function main(splash)
            local urls = {}
            local requests = {}
            splash:on_request(function(request)
                requests[#requests+1] = request.info
                urls[#urls+1] = request.url
            end)
            splash:go(splash.args.url)
            return requests, urls
        end
        """, {'url': self.mockurl("show-image")})
        self.assertStatusCode(resp, 200)
        requests, urls = resp.json()

        # FIXME: it should return lists, and indices should be integer
        self.assertIn("show-image", urls['1'])
        self.assertIn("slow.gif", urls['2'])

        self.assertEqual(requests['1']['method'], 'GET')
        self.assertEqual(requests['1']['url'], urls['1'])

    def test_abort_request(self):
        resp = self.request_lua("""
        function main(splash)
            splash:on_request(function(request)
                if string.find(request.url, "gif") ~= nil then
                    request:abort()
                end
            end)
            splash:go(splash.args.url)
            return {har=splash:har(), png=splash:png()}
        end
        """, {'url': self.mockurl("show-image")})
        self.assertStatusCode(resp, 200)
        data = resp.json()

        # the rendered image is not black (gif is not rendered)
        img = Image.open(BytesIO(base64.b64decode(data['png'])))
        self.assertEqual((255, 255, 255, 255), img.getpixel((10, 10)))

        # gif file is not in HAR log
        urls = [e['request']['url'] for e in data['har']['log']['entries']]
        self.assertTrue(any('show-image' in url for url in urls), urls)
        self.assertFalse(any('.gif' in url for url in urls), urls)

    def test_set_url(self):
        url = self.mockurl("http-redirect?code=302")
        new_url = self.mockurl("jsrender")
        resp = self.request_lua("""
        function main(splash)
            splash:on_request(function(request)
                if request.url == splash.args.url then
                    request:set_url(splash.args.new_url)
                end
            end)
            splash:go(splash.args.url)
            return splash:html()
        end
        """, {'url': url, 'new_url': new_url})
        self.assertStatusCode(resp, 200)
        self.assertIn('After', resp.content)

    def test_set_proxy(self):
        proxy_port = self.ts.mock_proxy_port
        resp = self.request_lua("""
        function main(splash)
            assert(splash:go(splash.args.url))
            local html_1 = splash:html()

            splash:on_request(function(request)
                request:set_proxy{
                    host="0.0.0.0",
                    port=splash.args.proxy_port
                }
            end)

            assert(splash:go(splash.args.url))
            local html_2 = splash:html()
            return html_1, html_2
        end
        """, {'url': self.mockurl("jsrender"), 'proxy_port': proxy_port})
        self.assertStatusCode(resp, 200)
        html_1, html_2 = resp.json()
        self.assertNotProxied(html_1)
        self.assertProxied(html_2)

    def test_request_outside_callback(self):
        resp = self.request_lua("""
        function main(splash)
            local req = nil
            splash:on_request(function(request)
                req = request
            end)
            assert(splash:go(splash.args.url))
            req:abort()
            return "ok"
        end
        """, {'url': self.mockurl("jsrender")})
        self.assertStatusCode(resp, 400)
        self.assertErrorLineNumber(resp, 8)
        self.assertIn("request is used outside a callback", resp.content)

    def test_set_header(self):
        resp = self.request_lua("""
        function main(splash)
            splash:on_request(function(request)
                request:set_header("User-Agent", "Mozilla")
                request:set_header{name="Custom-header", value="some-val"}
            end)
            splash:go(splash.args.url)
            return splash:html()
        end
        """, {'url': self.mockurl("getrequest")})
        self.assertStatusCode(resp, 200)

        self.assertIn("'custom-header': 'some-val'", resp.text)
        self.assertIn("'user-agent': 'Mozilla'", resp.text)


"""
Association Scientifique pour la Geologie et ses Applications (ASGA)

Copyright (c) 2020 ASGA and Universite de Lorraine. All Rights Reserved.

 Author: Capucine Legentil - capucine.legentil@univ-lorraine.fr

 """
from lib_data_structure.Mesh import Mesh
import gmsh

def open_gmsh_file(file_path):
    """
    Open mesh file with gmsh
    @param file_path: absolute path
    """
    gmsh.initialize([])
    gmsh.open(file_path)

def get_triangle_tags(global_mesh_filepath):
    """
    Read the region tags that are used in a mesh
    @param global_mesh_filepath: path to the mesh file
    @return: list of region tags
    """
    gmsh.initialize([])
    gmsh.open(global_mesh_filepath)
    l_tuple_tags = gmsh.model.getEntities(dim=2)
    l_tags = [tuple[1] for tuple in l_tuple_tags]
    gmsh.finalize()

    return l_tags

def global_mesh(global_mesh_file, l_regions=[]):
    """
    Create a Mesh object that represents the initial global mesh
    @param global_mesh_file: path to the initial mesh file
    @param l_regions: list that contains tags of materials of the initial mesh
    @return: return the Mesh object
    """
    global_mesh = Mesh(global_mesh_file, l_regions)
    return global_mesh

def find_local_vertices(global_mesh, local_vertices, trgl_id):
    """
    Add vertices of a triangle in the list of vertices to keep in the new mesh file
    @param global_mesh: Mesh object that represents the initial global mesh
    @param local_vertices: list of vertex indexes to keep in the new mesh (indexes from the initial mesh)
    @param trgl_id: triangle index
    """
    triangle = global_mesh.l_triangles_[trgl_id - 1]
    for vertex_id in triangle.l_trgl_vertices_idx_:
        if vertex_id not in local_vertices:
            local_vertices.append(vertex_id)

def find_local_edges(global_mesh, local_edges, trgl_id):
    """
    Add edges of a triangle in the list of edges to keep in the new mesh file
    @param global_mesh: Mesh object that represents the initial global mesh
    @param local_edges: list of edge indexes to keep in the new mesh (indexes from the initial mesh)
    @param trgl_id: triangle index
    """
    l_couple_vrtx = [(1, 2), (2, 0), (0, 1)]
    triangle = global_mesh.l_triangles_[trgl_id - 1]

    for tuple in l_couple_vrtx:
        endpoints = triangle.l_trgl_vertices_idx_[tuple[0]], triangle.l_trgl_vertices_idx_[tuple[1]]
        endpoints = sorted(endpoints)
        # if endpoints not in local_edges:
        local_edges.append(endpoints)

def tag_reg_boundary_edges(local_edges, l_trgl_id, global_mesh):
    """
    Clean the list of edge indexes to keep in the new mesh and return the list of edge tags in the same order
    @param local_edges: list of edge indexes to keep in the new mesh (indexes from the initial mesh)
    @param l_trgl_id: list of triangle indexes of the new mesh (indexes from the initial mesh)
    @param global_mesh: Mesh object that represents the initial global mesh
    @return: l_tag: list of edge tag in the same order than l_clean_local_edges
             l_clean_local_edges: list of edge indexes to keep in the new mesh without duplicates
    """
    l_tag_global_mesh = global_mesh.tag_region_boundary_edges_
    l_tag = []
    l_clean_local_edges = []
    for edge in range(len(local_edges)):
        if local_edges[edge] not in l_clean_local_edges:
            l_clean_local_edges.append(local_edges[edge])
            triangle_id_l = edge // 3
            triangle = l_trgl_id[triangle_id_l]
            edge_global_id = (triangle - 1) * 3 + edge % 3

            l_tag.append(l_tag_global_mesh[edge_global_id])
    return l_tag, l_clean_local_edges

def find_local_vertices_and_edges(global_mesh, l_trgl_id):
    """
    Create the lists of indexes of vertices and edges to keep in the new mesh
    @param global_mesh: Mesh object that represents the initial global mesh
    @param l_trgl_id: list of triangle indexes of the new mesh (indexes from the initial mesh)
    @return: local_vertices: list of vertex indexes to keep in the new mesh (indexes from the initial mesh)
             l_clean_local_edges: list of edge indexes to keep in the new mesh without duplicates
             l_tag: list of edge tag in the same order than l_clean_local_edges
    """
    local_vertices = []
    local_edges = []

    for trgl_id in l_trgl_id:
        find_local_vertices(global_mesh, local_vertices, trgl_id)
        find_local_edges(global_mesh, local_edges, trgl_id)

    l_tag, l_clean_local_edges = tag_reg_boundary_edges(local_edges, l_trgl_id, global_mesh)
    return local_vertices, l_clean_local_edges, l_tag

def write_header(file_initial_mesh, file_new_mesh, local_l_vertices):
    """
    Write the header of the 2d .mesh file
    @param file_initial_mesh: initial mesh file opened in reading mode
    @param file_new_mesh: new mesh file opened in writing mode
    @param local_l_vertices: list of vertex indexes to keep in the new mesh (indexes from the initial mesh)
    @return: vertices_number: number of vertices in the new mesh
    """
    line = file_initial_mesh.readline()

    while "Dimension" not in line:
        file_new_mesh.write(line)
        line = file_initial_mesh.readline()

    file_new_mesh.write("Dimension")
    file_new_mesh.write(" 2\n\n")  # impose 2D
    line = file_initial_mesh.readline()

    ## "Vertices"
    while "Vertices" not in line:
        line = file_initial_mesh.readline()
        file_new_mesh.write(line)

    ## Number of vertices
    line = file_initial_mesh.readline()
    vertices_number = len(local_l_vertices)
    file_new_mesh.write(str(vertices_number) + " \n")

    return vertices_number

def write_vertices(local_vertices, file_init_mesh, file_new_mesh):
    """
    Write vertices in the new mesh file and return the list of sorted vertices (by indexes)
    @param local_vertices: list of vertex indexes (index from the .mesh file)
    @param file_init_mesh: initial mesh file opened in reading mode
    @param file_new_mesh: new mesh file opened in writing mode
    @return: list of vertex sorted by their indexes
    """
    sort_local_vertices = sorted(local_vertices)
    vertex_id_read = 0

    for vertex_id in sort_local_vertices:
        id_diff = vertex_id - vertex_id_read
        for j in range(id_diff):
            line = file_init_mesh.readline()
        split_line = line.split()

        if len(split_line) > 3:
            line = " ".join(split_line[:3]) + "\n"
        else:
            line = " ".join(split_line) + "\n"
        file_new_mesh.write(line)

        vertex_id_read = vertex_id

    return sort_local_vertices

def write_edges(local_edges, sort_local_vertices, l_edge_tag, file_new_mesh):
    """
    Write edges in the new mesh file
    @param local_edges: list of edge indexes to keep in the new mesh
    @param sort_local_vertices: list of sorted vertex indexes (in ascending order) to keep in the new mesh
    @param l_edge_tag: list of edge tag in the same order than local_edges
    @param file_new_mesh: new mesh file opened in writing mode
    """
    file_new_mesh.write("Edges\n")
    file_new_mesh.write(str(len(local_edges)) + "\n")

    id = 0
    for tuple in local_edges:
        first_end_point_id = sort_local_vertices.index(tuple[0]) + 1
        second_end_point_id = sort_local_vertices.index(tuple[1]) + 1
        edge_tag = l_edge_tag[id]
        file_new_mesh.write(
            str(first_end_point_id) + " " + str(second_end_point_id) + " " + str(edge_tag) + "\n")
        id += 1

def write_triangles(l_triangles, sort_local_vertices, file_initial_mesh, file_new_mesh):
    """
    Write triangles in the new mesh file
    @param l_triangles: list of triangle indexes of the new mesh
    @param sort_local_vertices: list of sorted vertex indexes (in ascending order) to keep in the new mesh
    @param file_initial_mesh: initial mesh file opened in reading mode
    @param file_new_mesh: new mesh file opened in writing mode
    """
    file_initial_mesh.readline()
    file_new_mesh.write("Triangles\n")
    file_new_mesh.write(str(len(l_triangles)) + "\n")

    sort_local_triangles = sorted(l_triangles)
    triangle_id_read = 0

    for triangle_id in sort_local_triangles:
        id_diff = triangle_id - triangle_id_read
        for j in range(id_diff):
            line = file_initial_mesh.readline()

        split_line = line.split(" ")

        for vrtx_id in split_line:
            if vrtx_id == "" or "\n" in vrtx_id:
                pass
            else:
                split_line[split_line.index(vrtx_id)] = str(sort_local_vertices.index(int(vrtx_id)) + 1)

        line = " ".join(split_line)
        file_new_mesh.write(line)
        triangle_id_read = triangle_id

def write_local_mesh(filepath_initial_mesh, filepath_new_mesh, l_triangles, l_triangles_gmsh, l_regions):
    """
    Write the mesh file of the new mesh (from a list of triangle of a initial mesh)
    @param filepath_initial_mesh: path to initial mesh file
    @param filepath_new_mesh: path to new mesh file
    @param l_triangles: list of triangle indexes of the new mesh
    @param l_triangles_gmsh: list of triangle indexes of the new mesh (gmsh indexes)
    @param l_regions: list that contains tags of materials of the initial mesh
    """
    file_init_mesh = open(filepath_initial_mesh, "r")
    file_new_mesh = open(filepath_new_mesh, "w")

    mesh = global_mesh(filepath_initial_mesh, l_regions)
    if not l_triangles:
        l_triangles = [i for i in range(1, len(mesh.l_triangles_) + 1)]

    local_vertices, local_edges, l_tag = find_local_vertices_and_edges(mesh, l_triangles_gmsh)

    write_header(file_init_mesh, file_new_mesh, local_vertices)

    # Vertices
    sort_local_vertices = write_vertices(local_vertices, file_init_mesh, file_new_mesh)

    # Corners
    # RequiredVertices
    # RequiredEdges

    # Edges
    line = file_init_mesh.readline()
    while "Edges" not in line:
        line = file_init_mesh.readline()
    write_edges(local_edges, sort_local_vertices, l_tag, file_new_mesh)

    # Triangles
    line = file_init_mesh.readline()
    while "Triangles" not in line:
        line = file_init_mesh.readline()
    write_triangles(l_triangles, sort_local_vertices, file_init_mesh, file_new_mesh)

    file_new_mesh.write("End")
    file_init_mesh.close()
    file_new_mesh.close()

def build_l_triangles(global_mesh_filepath, l_region_id):
    """
    Create lists of all triangles that are in the inner region and in outer region
    @param global_mesh_filepath: Path to initial mesh file
    @param l_region_id: list that contains tags of materials in inner and outer regions
    @return: l_inner_triangles: list of triangle indexes of the inner region
             l_inner_triangles_gmsh_order: list of triangle indexes of the inner region with the gmsh indexes
             l_triangles_other: list of triangle indexes of the outer region
             l_triangles_other_gmsh_order: list of triangle indexes of the outer region with the gmsh indexes
    """
    open_gmsh_file(global_mesh_filepath)
    array_dim_global, array_trgl_global_idx, array_vertex_global_idx = gmsh.model.mesh.getElements(dim=2, tag=-1)
    l_sort_trgl_global_idx = sorted(list(array_trgl_global_idx[0]))
    l_trgl_global_idx = list(array_trgl_global_idx[0])
    l_inner_triangles = []
    l_inner_triangles_gmsh_order = []
    l_outer_triangles = l_sort_trgl_global_idx.copy()
    l_outer_triangles_gmsh = l_trgl_global_idx.copy()

    for region_id in l_region_id:
        array_dim_region, array_trgl_region_idx, array_vertex_region_idx = gmsh.model.mesh.getElements(dim=2,
                                                                                tag=region_id)

        l_trgl_region_idx = list(array_trgl_region_idx[0])

        for trgl_id in l_trgl_region_idx:
            l_outer_triangles.remove(trgl_id)
            l_outer_triangles_gmsh.remove(trgl_id)

        l_triangles_reg = [l_sort_trgl_global_idx.index(reg_trgl) + 1 for reg_trgl in l_trgl_region_idx]
        l_inner_triangles += l_triangles_reg

        l_triangles_reg_gmsh = [l_trgl_global_idx.index(reg_trgl) + 1 for reg_trgl in l_trgl_region_idx]
        l_inner_triangles_gmsh_order += l_triangles_reg_gmsh

    l_triangles_other = [l_sort_trgl_global_idx.index(reg_trgl) + 1 for reg_trgl in l_outer_triangles]
    l_triangles_other_gmsh_order = [l_trgl_global_idx.index(reg_trgl) + 1 for reg_trgl in l_outer_triangles_gmsh]

    gmsh.finalize()

    return l_inner_triangles, l_inner_triangles_gmsh_order, l_triangles_other, l_triangles_other_gmsh_order

def build_2_local_meshes(filepath_initial_mesh, filepath_inner_region, filepath_outer_region, l_regions):
    """
    Create two sub-meshes that represent the inner (modified region) and outer region
    @param filepath_initial_mesh: path to initial mesh file
    @param filepath_inner_region: Path to mesh file of the inner region
    @param filepath_outer_region: Path to mesh file of the outer region
    @param l_regions: list that contains tags of materials in inner and outer regions
    """
    l_inner_region = l_regions[0]
    l_inner_trgl, l_triangles_gmsh, l_outer_trgl, l_outer_triangles_gmsh_order = build_l_triangles(
        filepath_initial_mesh, l_inner_region)
    write_local_mesh(filepath_initial_mesh, filepath_inner_region, l_inner_trgl, l_triangles_gmsh, l_regions)
    write_local_mesh(filepath_initial_mesh, filepath_outer_region, l_outer_trgl, l_outer_triangles_gmsh_order,
                     l_regions)

def merge(mesh_reg1, mesh_reg2, output_file):
    """
    Merge two sub-parts (iner and outer parts) of the mesh
    @param mesh_reg1:first mesh sub-part file path
    @param mesh_reg2:second mesh sub-part file path
    @param output_file: path to global mesh that contains the two sub-parts
    """
    open_gmsh_file(mesh_reg1)
    gmsh.merge(mesh_reg2)

    gmsh.model.mesh.removeDuplicateNodes()
    gmsh.write(output_file)

if __name__ == '__main__':
    filepath_to_read = "/home/legentil/Documents/Data/_2D/Simple_Models/A1/surf1/Code_Test/ext_line/region/curve1_cut.o.mesh"
    filepath_to_write_cut = "/home/legentil/Documents/Data/_2D/Simple_Models/A1/surf1/Code_Test/ext_line/region/mesh_regcut.mesh"
    filepath_to_write_other = "/home/legentil/Documents/Data/_2D/Simple_Models/A1/surf1/Code_Test/ext_line/region/mesh_regother.mesh"
    filepath_final = "/home/legentil/Documents/Data/_2D/Simple_Models/A1/surf1/Code_Test/ext_line/region/mesh_merge.mesh"
    l_regions = [[1, 3], [4]]
    build_2_local_meshes(filepath_to_read, filepath_to_write_cut, filepath_to_write_other, l_regions)

    merge("C:/Users/legentil1.UL/Downloads/test.msh", "C:/Users/legentil1.UL/Downloads/test2.msh",
          "C:/Users/legentil1.UL/Downloads/test_merge.msh")


#!/usr/bin/env python3

import sys
import cv2

import json
result = {}

img = cv2.imread(sys.argv[1], cv2.IMREAD_COLOR)
meta = json.loads(sys.stdin.read())

for d in meta:
    tl = (int(d["tl_x"]), int(d["tl_y"]))
    br = (int(d["br_x"]), int(d["br_y"]))
    cv2.rectangle(img, tl, br, color=(255,255,255), thickness=3)

cv2.imwrite("output.jpg", img)


# -*- coding:utf-8 -*-
"""
Created on 18/11/29 下午10:21.

Author: Ruizhang1993 (zhang1rui4@foxmail.com)
"""
import math
import torch
import torch.nn as nn

class CustomedLSTMCell(nn.Module):

    def __init__(self, input_size, hidden_size, bias=True):
        super(CustomedLSTMCell, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.bias = bias

        self.i2h = nn.Linear(input_size, 4 * hidden_size, bias=bias)
        self.h2h = nn.Linear(hidden_size, 4 * hidden_size, bias=bias)
        self.reset_parameters()

    def reset_parameters(self):
        std = 1.0 / math.sqrt(self.hidden_size)
        for w in self.parameters():
            w.data.uniform_(-std, std)

    def forward(self, x, hidden):
        h, c = hidden

        # Linear mappings
        preact = self.i2h(x)+self.h2h(h)

        # activations
        gates = preact[:, : 3* self.hidden_size].sigmoid()
        g_t = preact[:, 3 * self.hidden_size:].tanh()
        i_t = gates[:, :self.hidden_size]
        f_t = gates[:, self.hidden_size: 2* self.hidden_size]
        o_t = gates[:, -self.hidden_size:]

        c_t = torch.mul(c, f_t)
        c_t = c_t + torch.mul(i_t, g_t)
        h_t = torch.mul(o_t, c_t.tanh())

        return h_t, (h_t, c_t)

class CustomedLSTM(nn.Module):

    def __init__(self, input_size, hidden_size, n_layers, bias=True):
        super(CustomedLSTM, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.bias = bias
        self.n_layers = n_layers

        self.cells = nn.ModuleList(
            [CustomedLSTMCell(input_size, hidden_size, bias)])
        self.cells.extend([CustomedLSTMCell(input_size + hidden_size, hidden_size, bias) for _ in range(1, n_layers)])

    def forward(self, x, hidden):

        h, c = hidden

        hs, cs = [], []
        for i in range(self.n_layers):
            if i == 0:
                o_, (h_, c_) = self.cells[i](x, (h[i], c[i]))
            else:
                inp_ = torch.cat([x, o_], -1)
                o_, (h_, c_) = self.cells[i](inp_, (h[i], c[i]))
            hs.append(h_)
            cs.append(c_)

        o = o_
        h = torch.stack(hs)
        c = torch.stack(cs)

        return o, (h, c)


from django.urls import path
from django.conf.urls import url, include

from rest_framework.routers import DefaultRouter

from .views import user_views, thread_views, forum_category_views, forum_views, report_views, notification_views, private_message_views, post_views, forum_settings_views
router = DefaultRouter()
router.register(r'users', user_views.UserViewSet)
router.register(r'forum/categories', forum_category_views.ForumCategoryViewSet)
router.register(r'forum', forum_views.ForumViewSet)
router.register(r'thread', thread_views.ThreadViewSet)
router.register(r'posts', post_views.PostViewSet)
router.register(r'reports', report_views.ReportViewSet)
router.register(r'private_messages', private_message_views.PrivateMessageViewSet)
router.register(r'notifications', notification_views.NotificationsViewSet, base_name='notifications')
#router.register(r'search/posts', views.PostSearchView, base_name="post-search")
router.register(r'search/threads', thread_views.ThreadSearchView, base_name="thread-search")
router.register(r'search/users', user_views.UserSearchView, base_name="user-search")
urlpatterns = [
    path('', include(router.urls)),
    path('settings/', forum_settings_views.ForumSettings.as_view())
]


import numpy as np
import pandas as pd
import pickle

import os

from sklearn.preprocessing import StandardScaler, MinMaxScaler

from sklearn.linear_model import ElasticNet
from sklearn.model_selection import GridSearchCV, ShuffleSplit
from sklearn.metrics import r2_score, make_scorer

path_data = "/cobrain/groups/ml_group/data/HCP/cleaned_data/"

with open(path_data + "mean_mesh_labels", 'rb') as f:
    mean_labels = pickle.load(f)

with open(path_data + "subjects_log_jac", 'rb') as f:
    log_jac = pickle.load(f)

with open(path_data + "subjects_thinkness", 'rb') as f:
    thinkness = pickle.load(f)

with open(path_data + "subjects_mesh_area", 'rb') as f:
    mesh_area = pickle.load(f)

targets_name = ['clustering', 'rich_club', 'betweenness', 'closeness',  'degree_centrality', 'eigenvector']

targets_data = []
for name in targets_name:
    with open(path_data + name, 'rb') as f:
        targets_data  += [pickle.load(f)]

print(np.array(targets_data).shape)

cv = ShuffleSplit(test_size=0.2)

elastic_param = {'alpha': [1e-10, 1e-7, 1e-5, 1e-3, 0.1, 1.0, 5, 10, 20, 50, 70, 100,],
                  'l1_ratio': [1e-10, 1e-7, 1e-3, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
                'max_iter':[1000,10000]}

path_res = '/home/ayagoz/connec/results/'

thinkness = thinkness.reshape(789,-1)
log_jac = log_jac.reshape(789,-1)
mesh_area = mesh_area.reshape(789,-1)

X = np.concatenate([thinkness, log_jac, mesh_area], axis = -1)

cv = ShuffleSplit(test_size=0.2)

from sklearn.model_selection import cross_val_score

elastic = ElasticNet()

for tr, ts in cv.split(X):
    X_train, X_test = X[tr], X[ts]
    y_train, y_test = targets_data[0][tr], targets_data[0][ts]
    elastic = ElasticNet()
    elastic.fit(X_train, y_train)
    y_pred = elastic.predict(X_test)
    print(r2_score(y_test, y_pred))