import math
from freezegame.tile import Tile
from freezegame.auto_tiler import AutoTiler

class TileMap:
    def __init__(self, tile_width, tile_height, width, height, state, tile_set, image_region, group):
        self.tile_width = tile_width
        self.tile_height = tile_height

        self.width = width
        self.height = height

        self.state = state
        self.batch = self.state.batch
        self.group = group

        self.tileSet = tile_set
        self.imageRegion = image_region

        self.tiles = []
        self.autotiler = AutoTiler()
        for i in range(self.width):
            self.tiles.append([])
            for j in range(self.height):
                new_tile = None
                self.tiles[i].append(new_tile)

    def build_surrounding_walls(self):
        for i in range(self.width):
            for j in range(self.height):
                if i == 0 or i == self.width - 1 or j == 0 or j == self.height - 1:
                    new_tile = Tile(i * self.tile_width, j * self.tile_height, [0, 0, self.tile_width, self.tile_height],
                                    self.state, self.tileSet, self.imageRegion, self.batch, self.group)
                    self.tiles[i][j] = new_tile

    def fill(self):
        for i in range(self.width):
            for j in range(self.height):
                new_tile = Tile(i * self.tile_width, j * self.tile_height, [0, 0, self.tile_width, self.tile_height],
                                self.state, self.tileSet, self.imageRegion, self.batch, self.group)
                self.tiles[i][j] = new_tile

    def prep_for_pickle(self):
        self.state = None
        self.batch = None
        self.group = None
        for i in range(self.width):
            for j in range(self.height):
                if self.tiles[i][j] is not None:
                    self.tiles[i][j].prep_for_pickle()

    def restore_from_pickle(self, state, group):
        self.state = state
        self.batch = self.state.batch
        self.group = group
        for i in range(self.width):
            for j in range(self.height):
                if self.tiles[i][j] is not None:
                    self.tiles[i][j].restore_from_pickle(self.state, group)

    def update(self, dt, keys, state):
        pass

    def tile_coord_for_position(self, pos):
        x = int(math.floor(float(pos[0]) / float(self.tile_width)))
        y = int(math.floor(float(pos[1]) / float(self.tile_height)));
        return [x, y]

    def get_tile(self, coord):
        if not self.valid_tile(coord):
            return None
        return self.tiles[coord[0]][coord[1]]

    def get_tile_for_pos(self, pos):
        coord = self.tile_coord_for_position(pos)
        return self.get_tile(coord)

    def get_surrounding_tiles_by_pos(self, pos):
        coord = self.tile_coord_for_position(pos)
        surrounding_tiles = [self.get_tile([coord[0], coord[1] - 1]), self.get_tile([coord[0], coord[1] + 1]),
                             self.get_tile([coord[0] - 1, coord[1]]), self.get_tile([coord[0] + 1, coord[1]]),
                             self.get_tile([coord[0] - 1, coord[1] + 1]), self.get_tile([coord[0] + 1, coord[1] + 1]),
                             self.get_tile([coord[0] - 1, coord[1] - 1]), self.get_tile([coord[0] + 1, coord[1] - 1]),
                             self.get_tile([coord[0], coord[1]])]

        return surrounding_tiles

    def get_radius_two_surrounding_tiles_for_pos(self, pos):
        coord = self.tile_coord_for_position(pos)
        surrounding_tiles = [self.get_tile([coord[0], coord[1] - 2]), self.get_tile([coord[0], coord[1] - 1]),
                             self.get_tile([coord[0], coord[1] + 1]), self.get_tile([coord[0], coord[1] + 2]),
                             self.get_tile([coord[0] - 1, coord[1]]), self.get_tile([coord[0] - 2, coord[1]]),
                             self.get_tile([coord[0] + 1, coord[1]]), self.get_tile([coord[0] + 2, coord[1]]),
                             self.get_tile([coord[0] - 1, coord[1] + 1]), self.get_tile([coord[0] + 1, coord[1] + 1]),
                             self.get_tile([coord[0] - 1, coord[1] - 1]), self.get_tile([coord[0] + 1, coord[1] - 1]),
                             self.get_tile([coord[0], coord[1]])]

        return surrounding_tiles

    def remove_tile_for_pos(self, pos):
        coord = self.tile_coord_for_position(pos)
        self.remove_tile(*coord)

    def remove_tile(self, tile_x, tile_y):
        if self.tiles[tile_x][tile_y] is not None:
            if not self.tiles[tile_x][tile_y].invincible:
                self.tiles[tile_x][tile_y].sprite.delete()
                self.tiles[tile_x][tile_y] = None

    def valid_tile(self, coord):
        if coord[0] < 0:
            return False
        if coord[0] >= self.width:
            return False
        if coord[1] < 0:
            return False
        if coord[1] >= self.height:
            return False
        return True

    def make_tile(self, tile_x, tile_y):
        if self.valid_tile([tile_x, tile_y]):
            if self.tiles[tile_x][tile_y] is None:
                self.tiles[tile_x][tile_y] = Tile(tile_x * self.tile_width, tile_y * self.tile_height,
                                                [0, 0, self.tile_width, self.tile_height], self.state, self.tileSet,
                                                self.imageRegion, self.batch, self.group)

    def auto_tile(self):
        self.autotiler.auto_tile(self)

    def get_straight_path(self, start_pos, end_pos):
        [start_x, start_y] = self.tile_coord_for_position(start_pos)
        [x, y] = self.tile_coord_for_position(end_pos)
        path = []
        x0 = start_x + 0.5
        y0 = start_y + 0.5
        x1 = x + 0.5
        y1 = y + 0.5

        dx = abs(x1 - x0)
        dy = abs(y1 - y0)

        x = int(math.floor(x0))
        y = int(math.floor(y0))

        n = 1

        x_inc = 0
        y_inc = 0

        error = 0.0

        if dx == 0:
            x_inc = 0
            error = float('inf')
        elif x1 > x0:
            x_inc = 1
            n += int(math.floor(x1)) - x
            error = (math.floor(x0) + 1 - x0) * dy
        else:
            x_inc = -1
            n += x - int(math.floor(x1))
            error = (x0 - math.floor(x0)) * dy

        if dy == 0:
            y_inc = 0
            error = float('-inf')
        elif y1 > y0:
            y_inc = 1
            n += int(math.floor(y1)) - y
            error -= (math.floor(y0) + 1 - y0) * dx
        else:
            y_inc = -1
            n += y - int(math.floor(y1))
            error -= (y0 - math.floor(y0)) * dx

        while n > 0:
            n -= 1
            path.append([x, y])
            if self.get_tile([x, y]) is not None:
                return None
            if error > 0:
                y += y_inc
                error -= dx
            else:
                x += x_inc
                error += dy
        return path


from flask import Flask, render_template, request
import jsonify
import requests
import pickle
import numpy as np
import sklearn
from sklearn.preprocessing import StandardScaler
app = Flask(__name__)
model = pickle.load(open('heart_disease_random_forest_model.pkl', 'rb'))
@app.route('/',methods=['GET'])
def Home():
    return render_template('index.html')

#standard_to = StandardScaler()
@app.route("/predict", methods=['POST'])
def predict():
    #Fuel_Type_Diesel=0
    if request.method == 'POST':
        Age = int(request.form['Age'])
        Gender=request.form['sex']
        if(Gender=='Male'):
            Gender=1
        else:
            Gender=0
        cp = int(request.form['cp'])
        trestbps = int(request.form['trestbps'])
        chol = int(request.form['chol'])
        fbs = int(request.form['fbs'])
        restecg = int(request.form['restecg'])
        thalach = int(request.form['thalach'])
        exang = int(request.form['exang'])

        oldpeak=float(request.form['oldpeak'])

        slope=int(request.form['slope'])
        ca=int(request.form['slope'])
        thal=int(request.form['slope'])

        #Kms_Driven2=np.log(Kms_Driven)
        #Owner=int(request.form['Owner'])
        #Fuel_Type_Petrol=request.form['Fuel_Type_Petrol']
        #if(Fuel_Type_Petrol=='Petrol'):
        #        Fuel_Type_Petrol=1
        #        Fuel_Type_Diesel=0
        #else:
        #    Fuel_Type_Petrol=0
        #    Fuel_Type_Diesel=1
        #Year=2020-Year
        #Gender=request.form['Gender']
        #if(Gender=='Male'):
        #    Gender=1
        #else:
        #    Gender=0

        #Transmission_Mannual=request.form['Transmission_Mannual']
        #if(Transmission_Mannual=='Mannual'):
        #    Transmission_Mannual=1
        #else:
        #    Transmission_Mannual=0
        prediction=model.predict([[Age,sex,cp,tresttbps,chol,fbs,restecg,thalach,exang,oldspeak,slope,ca,thal]])
        output=round(prediction[0],2)
        if output==0:
            return render_template('index.html',prediction_texts="Patient does not have heart disease")
        elif output==1:
            return render_template('index.html',prediction_text="Patient has heart disease")
    else:
        return render_template('index.html')

if __name__=="__main__":
    app.run(debug=True)


from scr.main.services.note_service import Note_service
from scr.main.view.ui.user_interface import User_interface

class Note_list_template:

    def output(self):
        self._ui.output('\nNote list')
        notes = self._note_service.find_all()
        if notes:
            self._ui.output('\n'.join([f'ID: {note.id}; HEAD: {note.header}; CREATE DATE: {note.create_date.strftime("%Y-%m-%d %H:%M:%S")}' for note in notes]))
        else:
            self._ui.output("\nNo note found\n")

        self._ui.press_enter_to_continue()

    _ui = User_interface()
    _note_service = Note_service()


#!/usr/bin/env python3
import pika
import socket

'''
  Usage:
    Receives all messages transmitted from "c_emit_log_fanout.py"
    1) start up a couple of c_receive_logs_fanout.py sessions
    2) send a message

    > python3 c_emit_log_fanout.py <some message>

    Both receivers should see the emitted messages

  Demonstrates:
    * Publish Subscribe
    * Fanout exchange

  Monitoring:
    * to view the results with the RabbitMQ manager:
    <hostname>:15672 in browser

    where <hostname> is the results of your hostname command

'''

# Taken from Jamieson Becker
def get_ip():
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  try:
    # doesn't have to be reachable
    s.connect(('10.255.255.255', 1))
    IP = s.getsockname()[0]
  except:
    IP = '127.0.0.1'
  finally:
    s.close()
  return IP

# create a connection and a channel
credentials = pika.PlainCredentials('bob', 'dobbs')
parameters = pika.ConnectionParameters(get_ip(), 5672, '/', credentials)
connection = pika.BlockingConnection(parameters=parameters)
channel = connection.channel()

# create an exchange and bind it to an exclusive queue
channel.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='logs', queue=queue_name)

print(' [*] Waiting for logs. To exit press CTRL-C')

def callback(ch, method, properties, body):
  print(" [x] {!s}".format(body.decode('utf8')))

channel.basic_consume(callback,
    queue=queue_name,
    no_ack=True)
channel.start_consuming()


# -*- coding: utf-8 -*-
'''
Simple continuous beam analysis.
'''

from __future__ import division
from __future__ import print_function

__author__= "Luis C. Pérez Tato (LCPT) and Ana Ortega (AO_O)"
__copyright__= "Copyright 2021, LCPT and AO_O"
__license__= "GPL"
__version__= "3.0"
__email__= "l.pereztato@ciccp.es ana.ortega@ciccp.es"

import math
import geom
import xc
from solution import predefined_solutions
from model import predefined_spaces
from materials import typical_materials
from model.mesh import finit_el_model as fem

feProblem= xc.FEProblem()
preprocessor=  feProblem.getPreprocessor
nodes= preprocessor.getNodeHandler
# Problem type
modelSpace= predefined_spaces.StructuralMechanics2D(nodes)

# Geometry
spans= [3.0,3.0,3.0]

## Cross-section geometry.
b= 1.0 # section width.
h= 0.15 # section depth.

# Materials.
E= 2.0e10 # Young modulus.

A= b*h # Beam cross-section area.
I= 1/12.0*b*h**3 # Inertia of the beam section.
sry= 5/5.0 # Shear coefficient.
Ay= A/sry
nu= 0.3 # Poisson's ratio.
G= E/(2.0*(1+nu))
beam_mat= typical_materials.defElasticShearSection2d(preprocessor, "scc",A,E,G,I,alpha= Ay/A)

# Loads
vLoad= 10e3+3.75e3 # vertical load

points= preprocessor.getMultiBlockTopology.getPoints
lines= preprocessor.getMultiBlockTopology.getLines
x= 0
pt0= points.newPoint(geom.Pos3d(x,0,0))
beamPoints= []
beamLines= []
beamPoints.append(pt0)
for i, sp in enumerate(spans):
    x+= sp
    pt1= points.newPoint(geom.Pos3d(x,0,0))
    l= lines.newLine(pt0.tag,pt1.tag)
    l.nDiv= 8
    beamLines.append(l)
    beamPoints.append(pt1)
    pt0= pt1

# Mesh generation

## Geometric transformations
lin= modelSpace.newLinearCrdTransf("lin")

## Seed element
seedElemHandler= preprocessor.getElementHandler.seedElemHandler
seedElemHandler.dimElem= 2 # Bars defined in a two-dimensional space.
seedElemHandler.defaultMaterial= scc.name
seedElemHandler.defaultTransformation= lin.name
beam2d= seedElemHandler.newElement("ElasticBeam2d",xc.ID([0,0]))
beam2d.h= h

xcTotalSet= preprocessor.getSets.getSet("total")
xcTotalSet.genMesh(xc.meshDir.I)

## Constraints
constraints= preprocessor.getBoundaryCondHandler
for p in beamPoints:
    n= p.getNode()
    spc= constraints.newSPConstraint(n.tag,0,0.0) # Node A
    spc= constraints.newSPConstraint(n.tag,1,0.0)

# Load definition.
lp0= modelSpace.newLoadPattern(name= '0')

eleLoad= lp0.newElementalLoad("beam2d_uniform_load")
eleLoad.elementTags= xc.ID(xcTotalSet.getElementTags())
eleLoad.transComponent= -vLoad
# We add the load case to domain.
modelSpace.addLoadCaseToDomain(lp0.name)

# Solution
analysis= predefined_solutions.simple_static_linear(feProblem)
result= analysis.analyze(1)

#########################################################
# Graphic stuff.
from postprocess import output_handler
oh= output_handler.OutputHandler(modelSpace)

# oh.displayBlocks()
# oh.displayFEMesh()
# oh.displayLocalAxes()
oh.displayLoads()
oh.displayDispRot('uY', defFScale= 100.0)
oh.displayIntForcDiag(itemToDisp= 'Mz')
oh.displayIntForcDiag(itemToDisp= 'Qy')
oh.displayReactions()


import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_absolute_error

def getPoints(numOfPoints,std,degree,noise):
    x = np.linspace(0, 0.9, numOfPoints)
    eta, y = transformer(degree, noise, std, x)
    return x,eta,y

def transformer(degree, noise, std, x):
    eta = std * noise
    y = 2 * x ** degree + eta
    return eta, y

def plotPoints(x,y):
    plt.plot(x, y, '.', ms=5, label='Constructed Data')
    plt.show()

def fitPoly(x,y,deg):
    poly = PolynomialFeatures(degree=deg)
    X = poly.fit_transform(x[:, np.newaxis])
    lin = linear_model.LinearRegression()
    lin.fit(X, y)
    yPred = lin.predict(X)
    return yPred,lin,poly

def predictOut(lin,poly,yPred_in,y,degree):
    x_out=np.linspace(0.9,1, 15)
    noise = np.random.randn(15)
    eta, y_out = transformer(degree,noise,1,x_out)
    X_out = poly.transform(x_out[:, np.newaxis])
    yPred_out = lin.predict(X_out)
    return mean_absolute_error(y,yPred_in), mean_absolute_error(y_out,yPred_out), x_out, y_out, yPred_out

if __name__ == "__main__":
    numOfPoints = 100
    std = 1
    degree = 1
    x,eta,y = getPoints(numOfPoints,std, degree, np.random.randn())
    # plotPoints(x,y)
    yPred = fitPoly(x,y,2)
    # plotPoints(x,yPred)


import os.path
import structlog

my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "exercise.log")
print(path)

# Do not use a with construction in production code to pass the file to the logging.
# Here is it used to ensure the log file is properly closed without boilerplate
with open(path, "a+") as logfile:
    structlog.configure(
        logger_factory=structlog.PrintLoggerFactory(file=logfile),
    )

    # # create logger
    logger = structlog.getLogger("simpleLogger")

    # 'application' code
    logger.debug("debug message")
    logger.info("info message")
    logger.warning("warn message")
    logger.error("error message")
    logger.critical("critical message", action="create incident")


import FreeCAD as CAD
import numpy as np

from os import path
from math import degrees

import DapToolsMod as DT
if CAD.GuiUp:
    import FreeCADGui as CADGui
    from PySide import QtGui, QtCore
global Debug
Debug = False
# =============================================================================
class CommandDapAnimationC:
    if Debug:
        DT.Mess("CommandDapAnimationC-CLASS")
    #  -------------------------------------------------------------------------
    def GetResources(self):
        """Called by FreeCAD when 'CADGui.addCommand' is run in InitGui.py
        Returns a dictionary defining the icon, the menu text and the tooltip"""
        if Debug:
            DT.Mess("CommandDapAnimationC-GetResourcesC")

        return {
            "Pixmap": path.join(DT.getDapModulePath(), "icons", "Icon8n.png"),
            "MenuText": QtCore.QT_TRANSLATE_NOOP("DapAnimationAlias", "Animate solution"),
            "ToolTip": QtCore.QT_TRANSLATE_NOOP("DapAnimationAlias", "Animates the motion of the moving bodies"),
        }
    #  -------------------------------------------------------------------------
    def IsActive(self):
        """Determine if there are already some results stored in the solver object
        i.e. Determine if the animate command/icon must be active or greyed out"""
        if Debug:
            DT.Mess("CommandDapAnimationC-IsActive")

        # Look for the results valid flag in the DapSolver object
        activeContainer = DT.getActiveContainerObject()
        for groupMember in activeContainer.Group:
            if "DapSolver" in groupMember.Name:
                self.solverObj = groupMember
                return groupMember.DapResultsValid
        # Return False if we didn't find a DapSolver object at all
        return False
    #  -------------------------------------------------------------------------
    def Activated(self):
        """Called when the Animation command is run"""
        if Debug:
            DT.Mess("CommandDapAnimationC-Activated")

        # Get the identity of the DAP document
        # (which is the active document on entry)
        self.dapDocument = CAD.ActiveDocument

        # Find the ground object name in the container
        containerObj = DT.getActiveContainerObject()
        groundName = containerObj.groundBodyName

        # Set an existing "Animation" document active
        # or create it if it does not exist yet
        if "Animation" in CAD.listDocuments():
            CAD.setActiveDocument("Animation")
        else:
            CAD.newDocument("Animation")
        self.animationDocument = CAD.ActiveDocument

        # Add the ground object to the animation view (and forget about it)
        groundObj = self.dapDocument.findObjects(Name="^" + groundName + "$")[0]
        animObj = self.animationDocument.addObject("Part::FeaturePython", ("Ani_" + groundName))
        animObj.Shape = groundObj.Shape
        if CAD.GuiUp:
            ViewProviderDapAnimateC(animObj.ViewObject)

        # Generate the list of bodies to be animated and
        # create an object for each, with their shapes, in the animationDocument
        animationIndex = 0
        for bodyName in self.solverObj.BodyNames:
            bodyObj = self.dapDocument.findObjects(Name="^"+bodyName+"$")[0]

            animObj = self.animationDocument.addObject("Part::FeaturePython", ("Ani_"+bodyName))
            # Add the shape to the newly created object
            animObj.Shape = bodyObj.Shape
            # Instantiate the class to handle the Gui stuff
            if CAD.GuiUp:
                ViewProviderDapAnimateC(animObj.ViewObject)

        # Request the animation window zoom to be set to fit the entire system
        CADGui.SendMsgToActiveView("ViewFit")

        # Edit the parameters by calling the task dialog
        taskd = TaskPanelDapAnimateC(
            self.solverObj,
            self.dapDocument,
            self.animationDocument,
        )
        CADGui.Control.showDialog(taskd)
    #  -------------------------------------------------------------------------
    def __getstate__(self):
        if Debug:
            DT.Mess("CommandDapAnimC-__getstate__")
    #  -------------------------------------------------------------------------
    def __setstate__(self, state):
        if Debug:
            DT.Mess("CommandDapAnimC-__setstate__")
# =============================================================================
class ViewProviderDapAnimateC:
    """ A view provider for the DapAnimate container object """
    # -------------------------------------------------------------------------------------------------
    def __init__(self, vobj):
        vobj.Proxy = self
    # -------------------------------------------------------------------------------------------------
    def getIcon(self):
        icon_path = path.join(DT.getDapModulePath(), "Gui", "Resources", "icons", "Icon2n.png")
        return icon_path
    # -------------------------------------------------------------------------------------------------
    def attach(self, vobj):
        self.ViewObject = vobj
        self.Object = vobj.Object
        self.bubbles = None
    # -------------------------------------------------------------------------------------------------
    def updateData(self, obj, prop):
        return
    # -------------------------------------------------------------------------------------------------
    def onChanged(self, vobj, prop):
        return
    # -------------------------------------------------------------------------------------------------
    def doubleClicked(self, vobj):
        if not DT.getActiveAnalysis() == self.Object:
            if FreeCADGui.activeWorkbench().name() != 'DapWorkbench':
                FreeCADGui.activateWorkbench("DapWorkbench")
            DT.setActiveAnalysis(self.Object)
            return True
        return True
    # -------------------------------------------------------------------------------------------------
    def __getstate__(self):
        return None
    # -------------------------------------------------------------------------------------------------
    def __setstate__(self, state):
        return None
# =============================================================================
class TaskPanelDapAnimateC:
    """Taskpanel for Running an animation"""
    if Debug:
        DT.Mess("TaskPanelDapAnimateC-CLASS")
    #  -------------------------------------------------------------------------
    def __init__(
        self,
        solverObj,
        dapDocument,
        animationDocument,
    ):
        """Run on first instantiation of a TaskPanelDapAnimate class"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-__init__")

        # Here we get the list of objects from the animation document
        self.animationBodyObjects = CAD.ActiveDocument.Objects

        # Transfer the called parameters to the instance variables
        self.solverObj = solverObj
        self.dapDocument = dapDocument
        self.animationDocument = animationDocument

        # Set play back period to mid-range
        self.playBackPeriod = 100  # msec

        # Load the Dap Animate ui form
        uiPath = path.join(path.dirname(__file__), "TaskPanelDapAnimate.ui")
        self.form = CADGui.PySideUic.loadUi(uiPath)

        # Define callback functions when changes are made in the dialog
        self.form.horizontalSlider.valueChanged.connect(self.moveObjects)
        self.form.startButton.clicked.connect(self.playStart)
        self.form.stopButton.clicked.connect(self.stopStop)
        self.form.playSpeed.valueChanged.connect(self.changePlaySpeed)

        # Fetch the animation object for all the bodies and place in a list
        self.animationBodyObj = []
        for animationBodyName in self.solverObj.BodyNames:
            self.animationBodyObj.append(self.animationDocument.findObjects(Name="^Ani_"+animationBodyName+"$")[0])

        # Load the calculated values of positions/angles from the results file
        self.Positions = np.loadtxt(path.join(self.solverObj.Directory, "DapAnimation.csv"))
        self.nTimeSteps = len(self.Positions.T[0])

        # Positions matrix is:
        # timeValue : body1X body1Y body1phi : body2X body2Y body2phi : ....
        # next time tick

        # Shift all the values relative to the starting point of each body
        startTick = self.Positions[0, :]
        self.startX = []
        self.startY = []
        self.startPhi = []
        for animationIndex in range(len(self.solverObj.BodyNames)):
            self.startX.append(startTick[animationIndex * 3 + 1])
            self.startY.append(startTick[animationIndex * 3 + 2])
            self.startPhi.append(startTick[animationIndex * 3 + 3])
        for tick in range(self.nTimeSteps):
            thisTick = self.Positions[tick, :]
            for animationIndex in range(len(self.solverObj.BodyNames)):
                thisTick[animationIndex * 3 + 1] -= self.startX[animationIndex]
                thisTick[animationIndex * 3 + 2] -= self.startY[animationIndex]
                thisTick[animationIndex * 3 + 3] -= self.startPhi[animationIndex]
            self.Positions[tick, :] = thisTick

        # Set up the timer parameters
        self.timer = QtCore.QTimer()
        self.timer.setInterval(self.playBackPeriod)
        self.timer.timeout.connect(self.onTimerTimeout)  # callback function after each tick

        # Set up the values displayed on the dialog
        self.form.horizontalSlider.setRange(0, self.nTimeSteps - 1)
        self.form.timeStepLabel.setText("0.000s of {0:5.3f}s".format(self.solverObj.TimeLength))

    #  -------------------------------------------------------------------------
    def reject(self):
        """Run when we press the Close button
        Closes document and sets the active document
        back to the solver document"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-reject")

        CADGui.Control.closeDialog()
        CAD.closeDocument(self.animationDocument.Name)
        CAD.setActiveDocument(self.dapDocument.Name)
    #  -------------------------------------------------------------------------
    def getStandardButtons(self):
        """Set up button attributes for the dialog ui"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-getStandardButtons")
        return 0x00200000
    #  -------------------------------------------------------------------------
    def playStart(self):
        """Start the Qt timer when the play button is pressed"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-playStart")

        self.timer.start()
    #  -------------------------------------------------------------------------
    def stopStop(self):
        """Stop the Qt timer when the stop button is pressed"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-stopStop")

        self.timer.stop()
    #  -------------------------------------------------------------------------
    def onTimerTimeout(self):
        """Increment the tick position in the player, looping, if requested"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-onTimerTimeout")

        tickPosition = self.form.horizontalSlider.value()
        tickPosition += 1
        if tickPosition >= self.nTimeSteps:
            if self.form.loopCheckBox.isChecked():
                tickPosition: int = 0
            else:
                self.timer.stop()

        # Update the slider in the dialog
        self.form.horizontalSlider.setValue(tickPosition)
    #  -------------------------------------------------------------------------
    def changePlaySpeed(self, newSpeed):
        """Alter the playback period by a factor of 1/newSpeed"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-changePlaySpeed")

        self.timer.setInterval(self.playBackPeriod * (1.0 / newSpeed))
    #  -------------------------------------------------------------------------
    def moveObjects(self, tick):
        """Move all the bodies to their pose at this clock tick"""
        if Debug:
            DT.Mess("TaskPanelDapAnimateC-moveObjects")

        self.form.timeStepLabel.setText(
            "{0:5.3f}s of {1:5.3f}s".format(
                tick * self.solverObj.DeltaTime,
                self.solverObj.TimeLength
            )
        )

        thisTick = self.Positions[tick, :]
        for animationIndex in range(len(self.solverObj.BodyNames)):
            X = thisTick[animationIndex*3 + 1]
            Y = thisTick[animationIndex*3 + 2]
            Phi = thisTick[animationIndex*3 + 3]
            self.animationBodyObj[animationIndex].Placement = CAD.Placement(CAD.Vector(X, Y, 0.0),
                                                                            CAD.Rotation(CAD.Vector(0.0, 0.0, 1.0),degrees(Phi)),
                                                                            CAD.Vector(self.startX[animationIndex],
                                                                                self.startY[animationIndex],
                                                                                0.0))
    #  -------------------------------------------------------------------------
    def __getstate__(self):
        if Debug:
            DT.Mess("TaskPanelDapAnimationC-__getstate__")
    #  -------------------------------------------------------------------------
    def __setstate__(self, state):
        if Debug:
            DT.Mess("TaskPanelDapAnimationC-__setstate__")
# =============================================================================


n = 0
n = int(input())
num = 0
cnt = 0
if n >= 10:
    cnt = cnt + 45
    pass
else:
    print(int(((n * (n + 1)) / 2)))
    quit()

num = 10 ** (len(str(n))-1)
# print(num)

while n > 0 and num > 1:
    temp = n - num
    temp = temp+1
    temp = temp % 998244353
    cnt = cnt + (temp * (temp + 1)) // 2
    cnt = cnt % 998244353
    n = num - 1
    num = num // 10

print(int(cnt))


from collections import deque
branch_list = [0x1c6, 0x21f, 0x309, 0x21f, 0x309, 0x1c6, 0x309, 0x1c6, 0x21f]
true_take = [1, 0, 0, 0, 0, 1, 0, 1, 1]

BHT = [0 for _ in range(8)]

history_queue = deque(true_take[-3:])

for i in range(100):
    accuracy = 0
    prediction = []
    for j in range(len(true_take)):
        BHT_index = int("".join(map(str, list(history_queue))), 2)
        prediction.append(BHT[BHT_index] // 2)

        if BHT[BHT_index] // 2 == true_take[j]:
            accuracy += 1

        if true_take[j] == 1:
            if BHT[BHT_index] != 3:
                BHT[BHT_index] += 1
        if true_take[j] == 0:
            if BHT[BHT_index] != 0:
                BHT[BHT_index] -= 1

        history_queue.pop()
        history_queue.appendleft(true_take[j])

    print("Round " + str(i) + ":")
    print("BHT:")
    print(BHT)
    print("True take:")
    print(true_take)
    print("Prediction:")
    print(prediction)
    print("__________________")

    accuracy = accuracy / float(len(true_take))
    print(accuracy)


# 1021 회전하는 큐

import collections

N, M = map(int, input().split())

deque = collections.deque()
for i in range(1, N+1):
    deque.append(i)

lst = list(map(int, input().split()))
ans = 0

for x in lst:
    if deque[0] == x:
        deque.popleft()
    else:
        idx = deque.index(x)
        if idx < len(deque)-idx:
            for i in range(idx):
                deque.append(deque.popleft())
            ans += idx
        else:
            for i in range(len(deque)-idx):
                deque.appendleft(deque.pop())
            ans += (len(deque) - idx)
        deque.popleft()

print(ans)


import matplotlib.pyplot as plt
import numpy as np

def som(X_all, y_all, a, b, max_ep):
    cls, train_idx = np.unique(y_all, True)
    W = X_all[train_idx].astype(np.float64)
    X = np.array([x for i, x in enumerate(X_all) if i not in train_idx])
    y = np.array([y for i, y in enumerate(y_all) if i not in train_idx])
    hues = 'bo', 'go', 'ko', 'mo'
    dir = 'D:/LVQ'

    for i, c in enumerate(cls):
        x = X_all[y_all == c]
        plt.plot(x[:, 0], x[:, 1], hues[i])

    ep = 0

    plt.title('Data')
    plt.savefig('%s/0-0.png' % dir)

    plt.title('Bobot Awal')
    plt.plot(W[:, 0], W[:, 1], 'rX')
    plt.savefig('%s/0-1.png' % dir)
    plt.clf()

    while ep < max_ep:
        for i, x in enumerate(X):
            for i_, c in enumerate(cls):
                x_all = X_all[y_all == c]
                plt.plot(x_all[:, 0], x_all[:, 1], hues[i_])

            plt.title('Epoch: %d, data: %d' % (ep + 1, i + 1))
            plt.plot(W[:, 0], W[:, 1], 'rX')
            plt.plot(x[0], x[1], 'yD')
            plt.savefig('%s/%d-%da.png' % (dir, ep + 1, i + 1))
            plt.clf()

            d = [sum((w - x) ** 2) for w in W]
            min = np.argmin(d)
            s = 1 if y[i] == cls[min] else -1
            W[min] += s * a * (x - W[min])

            for i_, c in enumerate(cls):
                x_all = X_all[y_all == c]
                plt.plot(x_all[:, 0], x_all[:, 1], hues[i_])

            plt.title('Epoch: %d, data: %d' % (ep + 1, i + 1))
            plt.plot(W[:, 0], W[:, 1], 'rX')
            plt.savefig('%s/%d-%db.png' % (dir, ep + 1, i + 1))
            plt.clf()

        a *= b
        ep += 1

    return W

if __name__ == '__main__':
    x2 = np.array([[1.25, 1.25],
                   [1, 1],
                   [2, 1],
                   [1, 2],
                   [2, 2],
                   [3.25, 3.25],
                   [3, 3],
                   [4, 3],
                   [3, 4],
                   [4, 4]])

    x4 = np.array([[1.25, 3.25],
                   [1, 3],
                   [2, 3],
                   [1, 4],
                   [2, 4],
                   [3.25, 3.25],
                   [3, 3],
                   [4, 3],
                   [3, 4],
                   [4, 4],
                   [1.25, 1.25],
                   [1, 1],
                   [2, 1],
                   [1, 2],
                   [2, 2],
                   [3.25, 1.25],
                   [3, 1],
                   [4, 1],
                   [3, 2],
                   [4, 2]])

    y2 = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2])
    y4 = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4])

    R = 0
    a = .6
    b = .5
    w = som(x4, y4, a, b, 3)

    print(w)


# -*- coding: utf-8 -*-
# @Project:AID1810
# @Author:biabu
# @Date:2019/3/4 14:23
# @File_name:02_selenium_phantomjs.py
# @IDE:PyCharm

from selenium import webdriver
import time

# 1.创建浏览器对象
# driver = webdriver.PhantomJS()
driver = webdriver.Chrome()
# 2.利用浏览器对象的get方法发请求
driver.get('http://www.baidu.com')
# 3.获取屏幕截图
driver.save_screenshot("百度chrome.png")
time.sleep(10)
# 4.关闭浏览器
driver.quit()


import os
import argparse
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import backend as K
from ...lib.training import utils as trainutils

def main(
    patches_df_path,
    images_dir,
    min_threshold,
    base_model_name,
    x_col,
    y_col,
    epochs,
    batch_size,
    history_save_dir,
    model_save_dir,
    random_seed,
    rotation_range,
    width_shift_range,
    height_shift_range,
    zoom_range,
    horizontal_flip,
    vertical_flip,
    balanced_weights,
    previous_checkpoint,
    df_patches_val=""):

    aug_args = {
        "rotation_range": rotation_range,
        "width_shift_range": width_shift_range,
        "height_shift_range": height_shift_range,
        "zoom_range": zoom_range,
        "horizontal_flip": horizontal_flip,
        "vertical_flip": vertical_flip,
    }

    np.random.seed(random_seed)
    tf.set_random_seed(random_seed)

    model_path = os.path.join(
        model_save_dir,
        f"{base_model_name}_finetuned.h5",
    )
    folder, _ = os.path.split(model_path)
    os.makedirs(folder, exist_ok=True)

    patches_df = pd.read_csv(patches_df_path)
    patches_df = patches_df[~patches_df[y_col].isna()]
    patches_useful = patches_df[patches_df["Tissue"] > min_threshold]
    patches_useful = patches_df[patches_df["Artifact"] < 0.2]

    classes = sorted(patches_df[y_col].unique())
    print("Training with classes:", ", ".join(classes))

    train_df = patches_useful
    test_df = pd.read_csv(df_patches_val)

    model, history = trainutils.finetune_model(
        base_model_name,
        images_dir,
        train_df,
        test_df,
        classes,
        x_col,
        y_col,
        batch_size,
        epochs,
        balanced_weights,
        aug_args,
        random_seed,
        model_path,
        previous_checkpoint
    )

    history_path = os.path.join(
        history_save_dir,
        f"{base_model_name}_finetuned.csv",
    )

    model_path = os.path.join(
        model_save_dir,
        f"{base_model_name}_finetuned_end.h5",
    )

    trainutils.save_history(history, history_path)
    trainutils.save_model(model, model_path)
    K.clear_session()

if __name__ == "__main__":
    PARSER = argparse.ArgumentParser()
    PARSER.add_argument(
        "--patches_df_path",
        type=str,
        help="""\
        Ruta al archivo csv con los datos de los parches, indicando la cantidad
        de tejido, fondo y artefacto calculada para cada imagen.""",
        required=True,
    )
    PARSER.add_argument(
        "--images_dir",
        type=str,
        help="""\
        Directorio base donde se encuentran las imágenes.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--min_threshold",
        type=float,
        help="""\
        Umbral mínimo para el filtro de calidad.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--base_model_name",
        type=str,
        help="""\
        Nombre del modelo a usar en el entrenamiento. \
        """,
        choices=["inception-v3", "xception", "vgg16"],
        required=True,
    )
    PARSER.add_argument(
        "--x_col",
        type=str,
        help="""\
        Nombre de la columna del dataframe usada como input.\
        """,
        default="Filepath",
    )
    PARSER.add_argument(
        "--y_col",
        type=str,
        help="""\
        Nombre de la columna del dataframe usada como output.\
        """,
        default="Label",
    )
    PARSER.add_argument(
        "--epochs",
        type=int,
        help="""\
        Número de épocas de entrenamiento.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--batch_size",
        type=int,
        help="""\
        Tamaño de cada batch de entrenamiento.\
        """,
        default=32,
    )
    PARSER.add_argument(
        "--history_save_dir",
        type=str,
        help="""\
        Directorio donde se guardarán los historiales de entrenamiento.
        """,
        required=True,
    )
    PARSER.add_argument(
        "--model_save_dir",
        type=str,
        help="""\
        Directorio donde se guardarán los modelos ya entrenados.
        """,
        required=True,
    )
    PARSER.add_argument(
        "--random_seed",
        type=int,
        help="""\
        Semilla para obtener números aleatorios reproducibles.\
        """,
        default=0,
    )
    PARSER.add_argument(
        "--rotation_range",
        type=int,
        help="""\
        Rango de ángulo de rotación para data augmentation.\
        """,
        default=10,
    )
    PARSER.add_argument(
        "--width_shift_range",
        type=float,
        help="""\
        Rango de desplazamiento horizontal, entre 0 y 1, para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--height_shift_range",
        type=float,
        help="""\
        Rango de desplazamiento vertical, entre 0 y 1, para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--zoom_range",
        type=float,
        help="""\
        Rango de zoom para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--horizontal_flip",
        type=bool,
        help="""\
        True para voltear imágenes horizontalmente (data augmentation).\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--vertical_flip",
        type=bool,
        help="""\
        True para voltear imágenes verticalmente (data augmentation).\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--balanced_weights",
        type=bool,
        help="""\
        True para que se asigne pesos a las clases de tal forma de balancear el
        entrenamiento.\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--previous_checkpoint",
        type=str,
        help="""\
        Path con pesos del modelo a ajustar.\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--df_patches_val",
        type=str,
        help="""\
        DataFrame con los patches a utilizar como validación para cada modelo.\
        """,
        default=True,
    )
    FLAGS = PARSER.parse_args()

    main(
        FLAGS.patches_df_path,
        FLAGS.images_dir,
        FLAGS.min_threshold,
        FLAGS.base_model_name,
        FLAGS.x_col,
        FLAGS.y_col,
        FLAGS.epochs,
        FLAGS.batch_size,
        FLAGS.history_save_dir,
        FLAGS.model_save_dir,
        FLAGS.random_seed,
        FLAGS.rotation_range,
        FLAGS.width_shift_range,
        FLAGS.height_shift_range,
        FLAGS.zoom_range,
        FLAGS.horizontal_flip,
        FLAGS.vertical_flip,
        FLAGS.balanced_weights,
        FLAGS.previous_checkpoint,
        FLAGS.df_patches_val
    )


import json
import os
import sys

import falcon
import yaml
from django.core.wsgi import get_wsgi_application

from auth_service.utils.helper import validate_token
from clients.logger_client import LoggerClient
from clients.utils import convert_utc_into_ist

sys.path.append(os.pardir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'cricbett_db.settings'
get_wsgi_application()

from db.models import Match
from db.models import Player

class MatchService(object):
    """
    A Falcon service class that handles GET requests and filters a list of matches based on query parameters "match_type" and "match_status".
    GET /matches?&match_type=cricket&match_status=upcoming
    [
        {
            "match_name": "2nd ODI, IND v NZ",
            "match_status": "COMPLETED",
            "match_start_datetime": "2023-02-11T04:00:00Z",
            "match_end_datetime": null,
            "match_venue": "Raipur",
            "match_type": "CRICKET",
            "first_team": "INDIA",
            "second_team": "NEW ZEALAND",
            "match_id": 1
        }
    ]
    """

    def __init__(self, logger):
        """
        Initialize the MatchService class.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        Handles GET requests to the endpoint and filters the matches based on query parameters "match_type" and "match_status".
        If no query parameters are provided, it returns all the matches.

        :param req: Falcon request object.
        :param resp: Falcon response object.
        """
        try:
            match_type = req.params.get("match_type", "").upper()
            match_status = req.params.get("match_status", "").upper()

            matches = Match.objects.filter(
                match_type__contains=match_type, match_status__contains=match_status
            )
            response = []
            for match in matches:
                response.append(self.get_match_response(match))

            resp.status = falcon.HTTP_202
            resp.text = json.dumps(response)
            self.logger.info(
                f"MatchService: Successfully retrieved matches with match_type={match_type} and match_status={match_status}")
        except Exception as e:
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"MatchService: Failed to retrieve matches: {e}")

    @staticmethod
    def get_match_response(match):
        match_start_datetime = convert_utc_into_ist(str(match.match_start_datetime))
        return {
            "match_id": str(match.match_id),
            "match_name": str(match.match_name),
            "match_status": str(match.match_status),
            "match_start_datetime": str(match_start_datetime),
            "match_venue": str(match.match_venue),
            "match_type": str(match.match_type),
            "first_team": str(match.first_team),
            "second_team": str(match.second_team)
        }

class MyGameService(object):
    """
    This class is responsible for handling the requests for getting the bookings related to a player.
    GET /my_games?game_status=live&match_type=football
    """

    def __init__(self, logger):
        """
        Initializes the service with a logger.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        Handles the GET request for getting the bookings related to a player.
        """
        token = kwargs.get("token")
        match_type = req.params.get("match_type", "").upper()
        game_status = req.params.get("game_status", "").upper()

        player = Player.objects.filter(token__token_id=token).first()
        if not player:
            self.logger.error(f"MyGameService: Player with token {token} not found")
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": "Invalid token"})
            return

        player_booking_set = player.booking_set.filter(
            game__game_status__contains=game_status,
            game__match__match_type__contains=match_type
        )

        my_bookings = {
            "player_id": player.player_id,
            "player_phone": player.phone,
            "player_games": [
                self.get_response_template(player_booking) for player_booking in player_booking_set
            ]
        }

        resp.status = falcon.HTTP_202
        resp.text = json.dumps(my_bookings)

    @staticmethod
    def get_response_template(player_booking):
        """
        Creates the response template for the contest details.
        """
        if player_booking.game.game_type == "WIN_PREDICT":
            game_start_time = convert_utc_into_ist(str(player_booking.game.match.match_start_datetime))
        else:
            game_start_time = convert_utc_into_ist(str(player_booking.game.match.match_start_datetime), 30)
        return {
            "game_id": player_booking.game.game_id,
            "match_name": player_booking.game.match.match_name,
            "match_type": player_booking.game.match.match_type,
            "game_start_time": str(game_start_time),
            "game_type": player_booking.game.game_type,
            "game_status": player_booking.game.game_status,
            "team_won": player_booking.game.team_won,
            "player_bid_price": str(player_booking.player_bid_price),
            "player_bid_team": player_booking.player_bid_team,
            "player_bid_multiplier": str(player_booking.player_bid_multiplier),
            "player_won_price": str(player_booking.player_won_price),
            "is_player_won": player_booking.is_player_won
        }

class RetrieveGamesByMatchService(object):
    """
    This class handles GET requests to the endpoint and returns the details of the games in a match
    GET /retrieve_game_by_match/{match_id}
    {
    "playerDetails": {
        "name": null,
        "email": "",
        "phone": "8709996580"
    },
    "games": [
        {
            "game_type": "WIN_PREDICT",
            "game_status": "COMPLETED",
            "first_team_bid_multiplier": "1.50",
            "second_team_bid_multiplier": "2.00",
            "match": 1,
            "game_id": 1
        },
        {
            "game_type": "TOSS_PREDICT",
            "game_status": "COMPLETED",
            "first_team_bid_multiplier": "1.80",
            "second_team_bid_multiplier": "1.70",
            "match": 1,
            "game_id": 2
        }
    ]
}
    """

    def __init__(self, logger):
        """
        Initializes the service with a logger.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        This method handles GET requests to the endpoint and returns the details of the games in a match
        """
        try:
            # Get the match_id from the request path
            match_id = kwargs.get("match_id")
            if match_id is None:
                # Raise an error if match_id is not provided
                raise ValueError("Missing match_id in request path")

            # Check if match with the provided id exists
            if Match.objects.filter(match_id=match_id).exists():
                match = Match.objects.get(match_id=match_id)
            else:
                # Raise an error if match with the provided id does not exist
                raise Match.DoesNotExist("Match with id {} does not exist".format(match_id))

            # All games in the match
            games_in_match = match.game_set.all()

            # Retrieve user details using token
            token = kwargs.get("token")
            player = Player.objects.filter(token__token_id=token).first()
            if not player:
                self.logger.error(f"MyGameService: Player with token {token} not found")
                resp.status = falcon.HTTP_400
                resp.text = json.dumps({"error": "Invalid token"})
                return

            # Prepare the response
            response = {"playerDetails": {"name": player.name, "email": player.email, "phone": player.phone},
                        "games": []}
            for game in games_in_match:
                response["games"].append(self.get_upcoming_resp(game))

            # Return a successful response
            resp.status = falcon.HTTP_202
            resp.text = json.dumps(response)
            self.logger.info(f"GET request to RetrieveGamesByMatchService endpoint successfully processed")
        except ValueError as e:
            # Handle missing match_id error
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")
        except Match.DoesNotExist as e:
            # Handle non-existent match error
            resp.status = falcon.HTTP_404
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")
        except Exception as e:
            # Handle any other unexpected error
            resp.status = falcon.HTTP_500
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")

    @staticmethod
    def get_upcoming_resp(game):
        if game.game_type == "WIN_PREDICT":
            game_start_time = convert_utc_into_ist(str(game.match.match_start_datetime))
        else:
            game_start_time = convert_utc_into_ist(str(game.match.match_start_datetime), 30)
        return {
            "game_id": game.game_id,
            "game_type": str(game.game_type),
            "game_status": str(game.game_status),
            "game_start_time": str(game_start_time),
            "first_team_bid_multiplier": str(game.first_team_bid_multiplier),
            "second_team_bid_multiplier": str(game.second_team_bid_multiplier),
            "match_name": str(game.match.match_name)
        }

class HealthCheck(object):
    """
    HealthCheck class, it is a Falcon web framework's resource class.
    """

    def on_get(self, req, resp):
        """
        Handles GET requests to the endpoint
        """
        resp.status = falcon.HTTP_200
        resp.text = json.dumps("OK")

def initialize_and_start_service(cfg, logger):
    app = falcon.App()

    matchService = MatchService(logger=logger)
    app.add_route('/matches', matchService)

    myGameService = MyGameService(logger=logger)
    app.add_route('/my_games', myGameService)

    # GET /retrieve_game_by_match/{match_id}
    retrieveGamesByMatch = RetrieveGamesByMatchService(logger=logger)
    app.add_route('/retrieve_games_by_match/{match_id}', retrieveGamesByMatch)

    healthCheck = HealthCheck()
    app.add_route('/healthcheck', healthCheck)

    logger.info("Cricbett-Feeds API is live now!")

    return app

# Load the configuration file
config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "config/feeds_config.yaml")

# Open and read the configuration file into the config variable
with open(config_file, 'r') as cf:
    config = yaml.safe_load(cf)

# Setup LoggingClient by passing the config
logger_client = LoggerClient("cricbett-feeds", config)

# Initialize and start the service using the config
api = initialize_and_start_service(config, logger_client)


import sys
import os
import argparse
import atexit
import warnings
import random

import numpy as np
from  tqdm import tqdm
import pandas as pd
import tensorflow as tf
from tensorflow import keras

# sys.path.append(os.path.dirname(os.path.split(os.path.abspath(__file__))[0]))
from actor import Actor
from critic import  Critic
# from utils.ou import OrnsteinUhlenbeckProcess
from metrics import get_session_config, tf_summary
from logger import  Logger, colorize
from min_heap import MinHeap
from dataset import  CsvBuffer, Dataset
from memory_buffer import MemoryBuffer

# from utils.preprocessing import  StandardNumerify

warnings.filterwarnings(action='ignore',category=FutureWarning)
# print(colorize(os.path.dirname(os.path.split(os.path.abspath(__file__))[0]),'blue',True))
np.random.seed(2019)
tf.set_random_seed(2019)
random.seed(2019)

class TD3(object):
    """deep deterministic policy gradient
    """
    def __init__(self, n_state, n_action, a_bound, discount=0.99, tau=0.05, actor_lr=0.001, critic_lr=0.001, policy_freq=2,
                 exp_noise_std=0.1, noise_decay=0.9995, noise_decay_steps=1000, smooth_noise_std=0.1, clip= 0.2,
                 buffer_size=20000, save_interval= 5000, assess_interval= 20, logger=None, checkpoint_queen=None):
        #self.__dict__.update(locals())
        self.logger = logger
        self.logger.save_config(locals())
        self.n_action = n_action
        self.n_state = n_state
        self.a_bound = a_bound
        self.noise_std = exp_noise_std
        self.noise_decay = noise_decay
        self.noise_decay_steps = noise_decay_steps
        self.policy_freq = policy_freq
        self.smooth_noise_std = smooth_noise_std
        self.clip = clip
        self.discount = discount

        self.pointer = 0
        self.buffer = MemoryBuffer(buffer_size, with_per=True)
        self.save_interval = save_interval
        self.assess_interval = assess_interval
        self.actor = Actor(self.n_state, self.n_action, gamma=discount, lr=actor_lr, tau=tau)
        self.critic1 = Critic(self.n_state,self.n_action, gamma=discount, lr=critic_lr, tau=tau)
        self.critic2 = Critic(self.n_state,self.n_action, gamma=discount, lr=critic_lr, tau=tau)
        self.merge = self._merge_summary()
        self.ckpt_queen = checkpoint_queen
        self.prefix = self.__class__.__name__

    def _merge_summary(self):
        tf.summary.histogram('critic_output', self.critic1.model.output)
        tf.summary.histogram('actor_output', self.actor.model.output)
        tf.summary.histogram('critic_dense1',self.critic1.model.get_layer('l1').weights[0])
        tf.summary.histogram('actor_dense1',self.actor.model.get_layer('l1').weights[0])
        tf.summary.histogram('critic_dense2',self.critic1.model.get_layer('l2').weights[0])
        tf.summary.histogram('actor_dense2',self.actor.model.get_layer('l2').weights[0])
        return tf.summary.merge_all()

    def select_action(self,state):
        return self.actor.predict(state)

    def bellman_q_value(self, rewards, q_nexts, dones):
        """ Use the Bellman Equation to compute the critic target
        """
        q_target = np.zeros_like(rewards) #asarry( copy = False), array(cope=True)
        for i in range(rewards.shape[0]):
            if dones[i]:
                q_target[i] = rewards[i]
            else:
                q_target[i] = rewards[i] + self.discount * q_nexts[i]
        return q_target

    def memorize(self, state, action, reward, done, new_state):
        """ Store experience in memory buffer
        """
        if(self.buffer.with_per):
            q_val = reward
            q_val_t = self.critic1.target_predict(state,action)
            td_error = abs(q_val_t - q_val)[0]
            # print(td_error)
        else:
            td_error = 0
        state = state.reshape(-1)
        action = action.reshape(-1)
        self.buffer.memorize(state, action, reward, done, new_state, td_error)

    def sample_batch(self, batch_size):
        return self.buffer.sample_batch(batch_size)

    def update_actor(self, states):
        actions = self.actor.predict(states)
        grad_ys = self.critic1.gradients(states, actions)
        actor_output = self.actor.train(states, actions, grad_ys)
        self.actor.copy_weights()
        self.critic1.copy_weights()
        self.critic2.copy_weights()
        return grad_ys, actor_output

    def update_critic(self, states, actions, q_values):
        loss_names, loss_values = self.critic1.train_on_batch(states, actions, q_values)
        self.critic2.train_on_batch(states,actions, q_values)
        return loss_names, loss_values

    def save_weights(self,path):
        self.actor.save(path)
        self.critic1.save(path)
        self.critic2.save(path)

    def save_model(self,path, file):
        self.actor.model.save(os.path.join(path, self.prefix+'_actor_'+file+'.h5'))
        self.critic1.model.save(os.path.join(path, self.prefix+'_critic1_'+file+'.h5'))
        self.critic2.model.save(os.path.join(path, self.prefix+'_critic2_'+file+'.h5'))

    def checkpoint(self, path, step,  metric_value):
        signature = str(step)+'_'+ '{:.4}'.format(metric_value)
        to_delete, need_save = self.ckpt_queen.add((metric_value,signature))
        if to_delete:
            delete_actor = os.path.join(path, self.prefix+'_actor_'+to_delete[1]+'.h5')
            delete_critic1 = os.path.join(path,self.prefix+'_critic1_'+to_delete[1]+'.h5')
            delete_critic2 = os.path.join(path,self.prefix+'_critic2_'+to_delete[1]+'.h5')
            os.remove(delete_actor)
            os.remove(delete_critic1)
            os.remove(delete_critic2)
        if need_save:
            self.save_model(path, signature)

    def train(self, args, summary_writer, train_data=None, val_data=None, test_data=None):
        results = []
        max_val_rate =0
        val_data = np.asarray(val_data) # none will be array(None)
        # First, gather experience
        tqdm_e = tqdm(range(args.batchs), desc='score', leave=True, unit="epoch")
        if train_data is None:
            dataset = CsvBuffer(args.file_dir, args.reg_pattern, chunksize=args.batch_size)   # 100*(20+1)
            assert  dataset.is_buffer_available, 'neither train_data nor csv buffer is available'
        # noise = OrnsteinUhlenbeckProcess(size=self.n_action)
        else:
            dataset = Dataset(train_data, 1, shuffle=True)

        warm_up = 20 * args.batch_size
        for e in tqdm_e:
            batch_data = next(dataset)
            states, labels = batch_data[:,:-1], batch_data[:,-1].astype(int)

            a = self.select_action(states)  #(batch, n_action)
            a = np.clip(a + np.random.normal(0, self.noise_std, size=a.shape), self.a_bound[0], self.a_bound[1])
            llr = np.clip(np.log(a/(1-a) + 1e-6),-5,5)
            # rewards = np.where(labels==1, llr.ravel(), -llr.ravel())  #(batch,)
            rewards = np.where(labels==1, np.where(llr>0,llr.ravel(), 2*llr.ravel()), np.where(llr<0, -llr.ravel(),-2*llr.ravel())) #(batch,)
            # print(rewards)

            # a_ = self.actor.target_predict(next_states)
            # noise = np.clip(np.random.normal(0, self.smooth_noise_std), 0, self.clip)
            # a_ = a_ + noise
            # q_next1 = self.critic1.target_predict(new_states, a_)
            # q_next2 = self.critic2.target_predict(new_states,a_)
            # q_nexts = np.where(q_next1<q_next2, q_next1, q_next2)
            self.memorize(states, a, rewards, True, None)
            if e<warm_up:
                continue

            states, a, rewards, _, _, _ = self.sample_batch(args.batch_size)
            # print(states.shape, a.shape, rewards.shape)

            q_ = self.bellman_q_value(rewards=rewards, q_nexts=0, dones=[True]*rewards.shape[0]) #(batch,)

            loss_names, loss_values = self.update_critic(states,a, q_.reshape(-1,1))

            if e%self.policy_freq == 0 or e==warm_up:
                grad_ys, actor_output = self.update_actor(states)

            if ((e+1)%self.noise_decay_steps-1) == 0 or e==warm_up:
                self.noise_std *= self.noise_decay
                self.logger.log_tabular('noise', self.noise_std)
            if e%self.assess_interval == 0 or e == args.batchs -1 or e==warm_up:
                if val_data is not None:
                    val_pred= self.actor.predict(val_data[:,:-1])
                    val_y = val_data[:,-1]
                    # print(val_pred.shape,val_pred[:10])
                    # print(val_y.shape, val_y[:10])
                    val_rate, top_k = top_ratio_hit_rate(val_y.ravel(), val_pred.ravel())
                    self.logger.log_tabular('val_rate',val_rate)
                    self.logger.log_tabular('val_k',int(top_k))
                    self.checkpoint(args.model_path, e, val_rate)
                    max_val_rate = val_rate if val_rate>max_val_rate else max_val_rate
                if test_data is not None:
                    test_pred = self.actor.predict(test_data[:,:-1])
                    test_y = test_data[:,-1]
                    test_rate, top_k = top_ratio_hit_rate(test_y,test_pred.ravel())
                    self.logger.log_tabular('test_rate',test_rate)
                    self.logger.log_tabular('test_k',int(top_k))

            score = rewards.mean()
            summary_writer.add_summary(tf_summary(['mean-reward'],[score]), global_step =e )
            summary_writer.add_summary(tf_summary(loss_names,[loss_values]),global_step=e)
            merge = keras.backend.get_session().run(self.merge,feed_dict={
                self.critic1.model.input[0]:states,
                self.critic1.model.input[1]:a,
                self.actor.model.input:states})
            summary_writer.add_summary(merge,global_step=e)

            for name, val in zip(loss_names,[loss_values]):
                self.logger.log_tabular(name, val)

            self.logger.log_tabular('dQ/da','%.4f+%.4f'%(grad_ys.mean(), grad_ys.std())) # grad_ys (batch,act_dim)
            self.logger.log_tabular('aout','%.4f+%.4f'%(actor_output[0].mean(), actor_output[0].std()))
            self.logger.log_tabular('aloss','%.4f'%(actor_output[1]))
            self.logger.log_tabular('reward', '%.4f+%.4f'%(score, rewards.std()))
            self.logger.dump_tabular()
            tqdm_e.set_description("score: " + '{:.4f}'.format(score))
            tqdm_e.set_postfix(noise_std='{:.4}'.format(self.noise_std), max_val_rate='{:.4}'.format(max_val_rate),val_rate='{:.4}'.format(val_rate), top_k=top_k)
            tqdm_e.refresh()

        return results

if __name__ == '__main__':
    import sys
    import os
    import operator
    from datetime import datetime
    parser = argparse.ArgumentParser(description='Training parameters')
    parser.add_argument('--file_dir', type=str, default='../data/clean', help="folder contains train data")
    parser.add_argument('--reg_pattern', type=str, default=r'train_hnb.csv', help="pattern to filter files in file_dir")
    parser.add_argument('--batchs', type=int, default=500000, help="number of batchs to train")
    parser.add_argument('--batch_size', type=int, default=32)
    parser.add_argument('--type',type=str, default='td3')
    parser.add_argument('--model_path',type=str, default='../model/RL')
    args = parser.parse_args(sys.argv[1:])

    train_data = pd.read_pickle('../data/clean/train_bj_dl_107_woe_tail.pkl')
    val_data = pd.read_pickle('../data/clean/val_bj_dl_107_woe_tail.pkl')

    # demo_df  = pd.read_csv('../data/clean/train_hnb.csv',nrows=1)
    train_data = train_sampling(train_data, col='is_y2', method='down', pn_ratio=0.2)
    # train_data = train_sampling(train_data, col='is_y2', method='up', pn_ratio=0.5)
    pn_ratio = sum(train_data.is_y2==1)/train_data.shape[0]

    print(train_data.head())
    print(val_data.head())
    train_data = train_data.values
    np.random.shuffle(train_data)
    n_state= train_data.shape[1]-1
    n_action = 1
    print(colorize('pn-ratio={}'.format(pn_ratio),'blue',True))
    print(colorize('action_dim=%d, state_dim=%d'%(n_action,n_state), 'blue',True))
    print(colorize('train_shape={}, val_shape={}'.format(train_data.shape, val_data.shape),'blue',True))

    checkpoint_queen = MinHeap(max_size=5, compare_key=operator.itemgetter(0))
    logger = Logger(output_dir='../assets', output_fname='td3_per_epoch_log')

    config = get_config(frac=0.4, allow_growth=True, gpu="0")
    td3 = TD3(n_state=n_state, n_action=n_action, a_bound=[0.0001, 0.9999], logger=logger, checkpoint_queen=checkpoint_queen,
               actor_lr=0.001, critic_lr=0.001, policy_freq=4)

    summary_writer =  tf.summary.FileWriter('../assets', graph=tf.get_default_graph(), filename_suffix=datetime.now().strftime('_%m%d%H%M')+'_td3')
    atexit.register(summary_writer.close)
    # saver = tf.train.Saver(max_to_keep=5) # store_model

    with tf.Session(config=config) as sess:
        keras.backend.set_session(sess)
        sess.run(tf.global_variables_initializer())
        td3.train(args,summary_writer,train_data=train_data, val_data=val_data.values)


from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.interval import IntervalTrigger
from src.service import DataService

scheduler = BlockingScheduler()
@scheduler.scheduled_job(IntervalTrigger(hours=1))
def main():
    servicio = DataService()
    servicio.dataextraction()
    servicio.dataprocess()
    servicio.datawriter()

scheduler.start()


#!/usr/bin/env python3
import rospy
import tensorflow as tf

rospy.init_node("MPPI_DP_CONTROLLER")

rospy.loginfo("Set GPU")
if rospy.has_param("~gpu_idx"):
    gpu_idx = rospy.get_param("~gpu_idx")
    gpus = tf.config.list_physical_devices('GPU')
    rospy.loginfo(f"gpus: {gpus}")
    if len(gpus) > gpu_idx:
        rospy.loginfo(f"selected: {gpus[gpu_idx]}")
        tf.config.set_visible_devices(gpus[gpu_idx], 'GPU')
        #tf.config.experimental.set_memory_growth(gpus[gpu_idx], True)
    else:
        rospy.logerr("GPU index out of range")
rospy.loginfo("Done")

# Import after setting the GPU otherwise tensorflow complains.
from mppi_tf.scripts.src.controller import get_controller
from mppi_tf.scripts.src.cost import get_cost
from mppi_tf.scripts.src.model import get_model

from geometry_msgs.msg import Wrench, WrenchStamped, Twist, PoseStamped
from std_msgs.msg import Float32MultiArray, MultiArrayDimension
from nav_msgs.msg import Odometry
from rospy.numpy_msg import numpy_msg
from mppi_ros.msg import Transition
from mppi_ros.srv import UpdateModelParam, SaveRb, WriteWeights, WriteWeightsResponse, SetLogPath

from visualization_msgs.msg import Marker, MarkerArray
from geometry_msgs.msg import Point

from mppi_tf.scripts.src.misc.utile import dtype, npdtype

import numpy as np
import time as t
from datetime import datetime
import os

from scipy.spatial.transform import Rotation as R

def rotBtoI_np(quat):
    x = quat[0]
    y = quat[1]
    z = quat[2]
    w = quat[3]

    return np.array([
                        [1 - 2 * (y**2 + z**2),
                        2 * (x * y - z * w),
                        2 * (x * z + y * w)],
                        [2 * (x * y + z * w),
                        1 - 2 * (x**2 + z**2),
                        2 * (y * z - x * w)],
                        [2 * (x * z - y * w),
                        2 * (y * z + x * w),
                        1 - 2 * (x**2 + y**2)]
                    ])

def tItoB_np(euler):
        r = euler[0]
        p = euler[1]
        T = np.array([[1., 0., -np.sin(p)],
                      [0., np.cos(r), np.cos(p) * np.sin(r)],
                      [0., -np.sin(r), np.cos(p) * np.cos(r)]])
        return T

def quat_to_rot_np(quat_state):
    pos = quat_state[:3]
    quat = quat_state[3:7]
    vel = quat_state[-6:]
    r = R.from_quat(quat[:, 0])
    rot = r.as_matrix().reshape((9, 1))

    return np.concatenate([pos, rot, vel], axis=0)

class ContInput(object):
    def __init__(self, history, rot="quat"):
        self._states = np.zeros((history, 13, 1), dtype=npdtype)
        self._actions = np.zeros((history-1, 6, 1), dtype=npdtype)

        self._h_state = history
        self._h_action = history - 1
        self._rot = rot
        self._current_action = 0
        self._current_state = 0
        self._filled_state = False
        self._filled_action = False
        self._filled = False

    def add_state(self, state):
        if not self._filled_state:
            self._states[self._current_state] = state
            self._current_state += 1
            if self._current_state >= self._h_state:
                self._filled_state = True
        else:
            tmpState = self._states[1:]
            self._states = np.concatenate([tmpState, state[None, ...]], axis=0)

    def add_action(self, action):
        if self._h_action < 1:
            self._filled_action = True
            return

        if not self._filled_action:
            self._actions[self._current_action] = action
            self._current_action += 1
            if self._current_action >= self._h_action:
                self._filled_action = True
        else:
            tmpAct = self._actions[:-1]
            self._actions = np.concatenate([tmpAct, action[None, ...]], axis=0)

    def is_filled(self):
        return self._filled_action and self._filled_state

    def get_input(self):
        return self.pred_controller_input(self._states, self._actions)

    def pred_controller_input(self, lagged_state, lagged_action):
        if self._rot == "rot":
            lagged_state_rot = self.quat_to_rot(lagged_state)
        else:
            lagged_state_rot = lagged_state
        if self._h_action < 1:
            return (lagged_state_rot.astype(npdtype), None)
        return (lagged_state_rot.astype(npdtype), lagged_action.astype(npdtype))

    def get_last_state(self):
        if self._rot == "rot":
            lagged_state_rot = self.quat_to_rot(self._states)
        else:
            lagged_state_rot = self._states
        return lagged_state_rot[-1].astype(npdtype)

    def quat_to_rot(self, lagged_state):
        pos = lagged_state[:, :3]
        quat = lagged_state[:, 3:7]
        vel = lagged_state[:, -6:]
        r = R.from_quat(quat[:, :, 0])
        rot = r.as_matrix().reshape((-1, 9, 1))

        return np.concatenate([pos, rot, vel], axis=1)

class MPPINode(object):
    def __init__(self):
        # The action tensor that will be applied to the system.
        # currently we assume a 6DOF force tensor for AUVs.
        self._forces = np.zeros(6, dtype=npdtype)
        # Namespace for identify the vehicle.
        self._namespace = "rexrov2"
        # Flag indicating when the controller is connected to
        # ros and recieves odometry updates.
        self._initOdom = False
        # Variables to profile the controller during
        # its execution.
        self._elapsed = 0.
        self._steps = 0
        self._timeSteps = 0.
        # load the ros parameters and instanciate the
        # desired objects.
        self.load_ros_params()

        # indicates how many previous states
        # needs to be stored and be fed to the
        # model.
        self.lagged = 1
        if "history" in self._config:
            self.lagged = self._config['history']
        # Creates and object that will contain
        # the input state for the controller.
        # it alows to define the rotation representation
        # as well as the number of previous states to
        # maintain.
        self._cont_input = ContInput(self.lagged, self._modelConf['rot'])

        # If the internal model is a ML model
        # It will be trained every x steps.
        if "learnable" in self._modelConf:
            self._learnable = self._modelConf["learnable"]
        else:
            self._learnable = False

        # Logging of the controller's execution.
        if self._log:
            stamp = datetime.now().strftime("%Y.%m.%d-%H:%M:%S")
            path = 'graphs/python/'
            if self._dev:
                path = os.path.join(path, 'debug')
            self._logPath = os.path.join(self._logPath,
                                         path,
                                         self._modelConf['type'],
                                         "k" + str(self._samples.numpy()),
                                         "T" + str(self._horizon),
                                         "L" + str(self._lambda),
                                         stamp)
            if self._learnable:
                self.set_learner_path()

        rospy.loginfo("Setup Controller...")

        rospy.loginfo("Get cost")
        # Create the cost function object.
        self._cost = get_cost(
            self._task,
            self._lambda,
            self._gamma,
            self._upsilon,
            self._noise
        )

        rospy.loginfo("Get Model")
        # Create the model object.
        self._model = get_model(
            model_dict=self._modelConf,
            samples=self._samples,
            dt=self._dt,
            state_dim=self._stateDim,
            action_dim=self._actionDim,
            limMax=self._modelConf['limMax'],
            limMin=self._modelConf['limMin'],
            name=self._modelConf['type']
        )

        rospy.loginfo("Get controller")
        init_seq = np.zeros((self._horizon, self._actionDim, 1), dtype=npdtype)
        #init_seq[:, 2] = -263.
        # Create the MPPI controller object.
        self._controller = get_controller(
            model=self._model,
            cost=self._cost,
            k=self._samples,
            tau=self._horizon,
            sDim=self._stateDim,
            aDim=self._actionDim,
            lam=self._lambda,
            upsilon=self._upsilon,
            sigma=self._noise,
            initSeq=init_seq,
            normalizeCost=self._normCost,
            filterSeq=self._filterSeq,
            log=self._log,
            logPath=self._logPath,
            graphMode=self._graphMode,
            debug=self._dev,
            configDict=self._config,
            taskDict=self._task,
            modelDict=self._modelConf
        )

        # If graphMode is activate, the control
        # loop is traced and stored on the gpu
        # for faster inference.
        # if self._graphMode:
            # TODO: figure out why the tracing doesn't maintain the
            # computaitonal graph in memory before the first run of
            # the controller.
            ## USELESS FOR NOW FOR SOME REASON
            # start = t.perf_counter()
            # rospy.loginfo("Trace the tensorflow computational graph...")
            # self._controller.trace()
            # end = t.perf_counter()
            # rospy.loginfo("Tracing done in {:.4f} s".format(end-start))

        rospy.loginfo("Subscrive to odometrie topics...")
        self.init_subscribers()
        rospy.loginfo("Done")

        rospy.loginfo("Setup publisher to thruster topics...")
        self.init_publishers()
        rospy.loginfo("Done")

        # Setup a service that updates the model when new
        # parameters are recieved.
        if self._learnable:
            rospy.loginfo("Creating service for parameter update...")
            self._writeWeightsSrv = rospy.Service(
                "mppi/controller/write_weights",
                WriteWeights,
                self.write_weights
            )
        rospy.loginfo("Controller loaded.")

    def init_subscribers(self):
        # Subscribe to odometry topic
        self._odomTopicSub = rospy.Subscriber(
            "odom".
            format(self._uuvName),
            numpy_msg(Odometry),
            self.odometry_callback,
            queue_size=1)
        # Alows to dynamically set the goal in the
        # StaticCost object.
        # TODO: Get the right Goal for the right Cost
        self._setGoalSub = rospy.Subscriber(
            "mppi/setGoal",
            numpy_msg(PoseStamped),
            self.set_goal,
            queue_size=1
        )

    def init_publishers(self):
        # Create the action publisher object.
        # Iterates throught the message type
        # to know which publisher to instanciate.
        if self._thrusterMessage == "WrenchStamped":
            self._thrusterPublisher = rospy.Publisher(
                'thruster_input', WrenchStamped, queue_size=1
            )
            self._publisher_fct = self.publish_control_wrench_stamped

        elif self._thrusterMessage == "Wrench":
            self._thrusterPublisher = rospy.Publisher(
                'thruster_input', Wrench, queue_size=1
            )
            self._publisher_fct = self.publish_control_wrench

        elif self._thrusterMessage == "Twist":
            self._thrusterPublisher = rospy.Publisher(
                'thruster_input', Twist, queue_size=1
            )
            self._publisher_fct = self.publish_control_twist

        else:
            rospy.logerr(
                f"Failed to understand thruster message type\
                 expected |WrenchStamped|Wrench|Twist but\
                 got {self._thrusterMessage}"
            )
        # Publish transition (x_{t}, u_{t}, x_{t+1}) as observed
        # by the controller.
        self._transPub = rospy.Publisher(
            '/mppi/controller/transition',
            Transition,
            queue_size=1
        )

        # Publish the model generated trajectories so that they
        # can be rendered in rviz.
        self._trajsPub = rospy.Publisher(
            "/mppi/samples_traj/",
            MarkerArray,
            queue_size=10
        )

        # Publish obstacle in rviz.
        self._obsPub = rospy.Publisher(
            "mppi/obstacles/",
            MarkerArray,
            queue_size=10
        )

        # Publish cost representation in rviz.
        self._costPub = rospy.Publisher(
            "mppi/cost/",
            Marker,
            queue_size=10
        )

        # Publish the current action sequence
        self._seqPub = rospy.Publisher(
            "mppi/seq",
            Float32MultiArray,
            queue_size=10,
        )

    def load_ros_params(self):
        rospy.loginfo("loading param")
        if rospy.has_param("~model_name"):
            self._uuvName = rospy.get_param("~model_name")
            self._namespace = rospy.get_param("~model_name")
        else:
            rospy.logerr("Need to specify the model name to publish on")
            return

        if rospy.has_param("~samples"):
            self._samples = tf.Variable(rospy.get_param("~samples"))
        else:
            rospy.logerr("Need to set the number of samples to use")
            return

        if rospy.has_param("~horizon"):
            self._horizon = rospy.get_param("~horizon")
        else:
            rospy.logerr("Need to set the number of samples to use")
            return

        if rospy.has_param("~lambda"):
            self._lambda = rospy.get_param("~lambda")
        else:
            rospy.logerr("Need to set the number of samples to use")
            return

        if rospy.has_param("~alpha"):
            alpha = rospy.get_param("~alpha")
            if alpha > 1. or alpha < 0.:
                rospy.logerr("aplha needs to be between [0., lambda]")
                return
            self._gamma = self._lambda * ( 1 - alpha)
        else:
            rospy.logerr("Need to set the number of samples to use")
            return

        if rospy.has_param("~upsilon"):
            self._upsilon = rospy.get_param("~upsilon")
            if self._upsilon < 1.:
                rospy.logerr("Upsilon needs to be higher than 1.")
        else:
            rospy.logerr("Need to set the number of samples to use")
            return

        if rospy.has_param("~dt"):
            self._dt = rospy.get_param("~dt")
        else:
            rospy.logerr("Don't know the timestep.")
            return

        if rospy.has_param("~state_dim"):
            self._stateDim = rospy.get_param("~state_dim")
        else:
            rospy.logerr("Don't know the state dimensionality.")
            return

        if rospy.has_param("~action_dim"):
            self._actionDim = rospy.get_param("~action_dim")
        else:
            rospy.logerr("Don't know the actuator dimensionality.")
            return

        if rospy.has_param("~cost"):
            self._task = rospy.get_param("~cost")
        else:
            rospy.logerr("No cost function given.")
            return

        if rospy.has_param("~cost_norm"):
            self._normCost = rospy.get_param("~cost_norm")
        else:
            rospy.logwarn("Cost norm not given assuemd False")
            self._normCost = False

        if rospy.has_param("~model"):
            self._modelConf = rospy.get_param("~model")
        else:
            rospy.logerr("No internal model given.")
            return

        if rospy.has_param("~filter_seq"):
            self._filterSeq = rospy.get_param("~filter_seq")
        else:
            self._filterSeq = False

        if rospy.has_param("~config"):
            self._config = rospy.get_param("~config")
            if "noise" in self._config:
                self._noise = self._config['noise']
            else:
                rospy.logerr("No noise given in controller Config file")
                return
        else:
            rospy.logerr("No internal config given.")
            return

        if rospy.has_param("~log"):
            self._log = rospy.get_param("~log")
            if rospy.has_param("~log_path"):
                self._logPath = rospy.get_param("~log_path")
        else:
            rospy.logerr("No log flag given.")

        if rospy.has_param("~dev"):
            self._dev = rospy.get_param("~dev")
        else:
            rospy.logerr("No flag for dev mode given.")

        if rospy.has_param("~visu_samples"):
            self._visu_samples = rospy.get_param("~visu_samples")
        else:
            rospy.logwarn("No flag for visualisation mode given. Set to False")
            self._visu_samples = False

        if rospy.has_param("~odom_frame"):
            self._odom_frame = rospy.get_param("~odom_frame")
        else:
            rospy.logwarn("No odometry frame given, publishing of markers is not guarenteed.")
            self._odom_frame = "odom"

        if rospy.has_param("~graph_mode"):
            self._graphMode = rospy.get_param("~graph_mode")
        else:
            rospy.logerr("No flag for graph mode given.")

        if rospy.has_param("~thruster_message"):
            self._thrusterMessage = rospy.get_param("~thruster_message")
        else:
            rospy.logwarn("No thruster message type given, assumes WrenchStamped")
            self._thrusterMessage = "WrenchStamped"

    def publish_control_wrench(self, forces):
        if not self._initOdom:
            return

        forceMsg = Wrench()
        # Force
        forceMsg.force.x = forces[0]
        forceMsg.force.y = forces[1]
        forceMsg.force.z = forces[2]
        # Torque
        forceMsg.torque.x = forces[3]
        forceMsg.torque.y = forces[4]
        forceMsg.torque.z = forces[5]

        self._thrusterPublisher.publish(forceMsg)

    def publish_control_wrench_stamped(self, forces):
        if not self._initOdom:
            return

        forceMsg = WrenchStamped()
        forceMsg.header.stamp = rospy.Time.now()
        forceMsg.header.frame_id = f"{self._namespace}/base_link"
        # Force
        forceMsg.wrench.force.x = forces[0]
        forceMsg.wrench.force.y = forces[1]
        forceMsg.wrench.force.z = forces[2]
        # Torque
        forceMsg.wrench.torque.x = forces[3]
        forceMsg.wrench.torque.y = forces[4]
        forceMsg.wrench.torque.z = forces[5]

        self._thrusterPublisher.publish(forceMsg)

    def publish_control_twist(self, forces):
        if not self._initOdom:
            return

        #sign = np.sign(forces)
        #sign = sign - np.sign(self._prevForce)
        # Normalize forces vector.
        forces = forces / np.linalg.norm(forces)
        forceMsg = Twist()
        # Force
        forceMsg.linear.x = forces[0]
        forceMsg.linear.y = forces[1]
        forceMsg.linear.z = forces[2]
        # Torque
        forceMsg.angular.x = forces[3]
        forceMsg.angular.y = forces[4]
        forceMsg.angular.z = forces[5]

        self._prevForce = forces

        self._thrusterPublisher.publish(forceMsg)
        rospy.loginfo(f"Setting goal to \n {np.squeeze(self._controller._cost.get_goal())} \n Succesfull.")

        # Header
        transMsg = Transition()
        transMsg.header.stamp = rospy.Time.now()
        transMsg.header.frame_id = f"{self._namespace}/base_link"

        # Transition
        transMsg.x = x
        transMsg.u = u
        transMsg.xNext = xNext

        self._transPub.publish(transMsg)

    def call_controller(self, controller_input):
        start = t.perf_counter()
        self._forces, trajs, weights, seq = self._controller.next(controller_input)
        end = t.perf_counter()
        # disable controller for roll and pitch as there is non for falcon.
        #self._forces[3] = 0.
        #self._forces[4] = 0.
        # Normalize forces vector.

        self._elapsed += (end-start)
        self._timeSteps += 1
        self._steps += 1

        # If dev mode, don't publish the forces.
        if not self._dev:
            self._publisher_fct(self._forces)

        # Publish the generated trajectories
        # to rviz together with the weights.
        if self._visu_samples:
            #self.publish_expected(expected)
            self.publish_samples_traj(trajs, weights)
            self.publish_obstacles()
            self.publish_cost(state=controller_input[0][-1])
            self.publish_seq(seq)

        # Print the performances of the controller
        # every 10 steps. ~1/sec
        if self._steps % 10 == 0:
            rospy.loginfo("*"*5 + " MPPI Time stats " + "*"*5)
            rospy.loginfo("* Next step : {:.4f} (sec)".format(self._elapsed/self._timeSteps))
            self._elapsed = 0.
            self._timeSteps = 0

    def odometry_callback(self, msg):
        # If first call, we need to boot the controller
        # by initializing the controller input.
        if not self._initOdom:
            # First call
            self._prevTime = rospy.get_rostime()
            self._prevState  = self.update_odometry(msg)
            self._state = self._prevState.copy()
            self._cont_input.add_state(self._state.copy())
            self._cont_input.add_action(self._forces[..., None].copy())
            # When the controller input is filled we can start the controller.
            self._initOdom = self._cont_input.is_filled()
            self._first = True
            return

        else:
            # check if the elapsed time is
            # enough, to call the controller
            time = rospy.get_rostime()
            dt = time - self._prevTime
            if dt.to_sec() < self._dt:
                return

        # Get the current state.
        self._prevTime = time
        self._state = self.update_odometry(msg)

        # TODO: save the transition.
        self._controller.save(
            self._cont_input.get_input(),
            self._forces[..., None],
            self._state
        )

        # Send the data for the learner.
        # self.publish_transition(
        #     self._prevState,
        #     np.expand_dims(self._forces, -1),
        #     self._state
        # )

        # Add the current state to the controller input.
        self._cont_input.add_state(self._state.copy())
        # update previous state.
        self._prevState = self._state

        if self._first:
            rospy.loginfo("First call to the controller (suspicious tracing)!")
            if self._graphMode:
                self._controller.tracing = True

        self.call_controller(self._cont_input.get_input())
        if self._first:
            rospy.loginfo("First call to the controller finished!")
            self._first = False
            if self._graphMode:
                self._controller.tracing = False

        self._cont_input.add_action(self._forces[..., None].copy())

        if self._learnable:
            if self._steps % 50 == 0:
                self.update_model()

    def update_odometry(self, msg):

        """Odometry topic subscriber callback function."""
        # The frames of reference delivered by the odometry seems to be as
        # follows
        # position -> world frame
        # orientation -> world frame
        # linear velocity -> world frame
        # angular velocity -> world frame

        #if self._model._inertialFrameId != msg.header.frame_id:
        #    raise rospy.ROSException('The inertial frame ID used by the '
        #                             'vehicle model does not match the '
        #                             'odometry frame ID, vehicle=%s, odom=%s' %
        #                             (self._model._inertialFrameId,
        #                              msg.header.frame_id))

        # Update the velocity vector
        # Update the pose in the inertial frame
        state = np.zeros((13, 1), dtype=npdtype)
        state[0:3, :] = np.array([[msg.pose.pose.position.x],
                                  [msg.pose.pose.position.y],
                                  [msg.pose.pose.position.z]])

        # Using the (w, x, y, z) format for quaternions
        state[3:7, :] = np.array([[msg.pose.pose.orientation.x],
                                  [msg.pose.pose.orientation.y],
                                  [msg.pose.pose.orientation.z],
                                  [msg.pose.pose.orientation.w]])

        # Linear velocity on the INERTIAL frame
        linVel = np.array([msg.twist.twist.linear.x,
                           msg.twist.twist.linear.y,
                           msg.twist.twist.linear.z])
        # Transform linear velocity to the BODY frame
        rotItoB = rotBtoI_np(state[3:7, 0]).T

        linVel = np.expand_dims(np.dot(rotItoB, linVel), axis=-1)
        # Angular velocity in the INERTIAL frame
        angVel = np.array([msg.twist.twist.angular.x,
                           msg.twist.twist.angular.y,
                           msg.twist.twist.angular.z])
        # Transform angular velocity to BODY frame
        angVel = np.expand_dims(np.dot(rotItoB, angVel), axis=-1)
        # Store velocity vector
        state[7:13, :] = np.concatenate([linVel, angVel], axis=0)
        return state

    def write_weights(self, req):
        self._model.update_weights(req.weights)
        return WriteWeightsResponse(True)

    def update_model(self):
        rospy.loginfo("Updating parameter model")
        rospy.wait_for_service('/mppi/learner/update_model_params')
        try:
            start = t.perf_counter()
            updateModelSrv = rospy.ServiceProxy('/mppi/learner/update_model_params', UpdateModelParam)
            resp = updateModelSrv(train=True, save=self._log, step=self._steps)
            end = t.perf_counter()
            rospy.loginfo("Service replied in {:.4f} s".format(end-start))
        except rospy.ServiceException as e:
            print("Service call failed: %s"%e)

    def save_rb(self, file):
        rospy.loginfo("Creating client for save service..")
        rospy.wait_for_service('/mppi/learner/save_rb')
        try:
            saveRbSrv = rospy.ServiceProxy('/mppi/learner/save_rb', SaveRb)
            resp = saveRbSrv(file)
        except rospy.ServiceException as e:
            print("Service call failed: %s"%e)
        rospy.loginfo("Done")

    def set_learner_path(self):
        rospy.loginfo("Creating client for update service..")
        rospy.wait_for_service('/mppi/learner/set_log_path')
        try:
            setLogPath = rospy.ServiceProxy('/mppi/learner/set_log_path', SetLogPath)
            resp = setLogPath(self._logPath)
            print(resp)
        except rospy.ServiceException as e:
            print("Service call failed: %s"%e)
        rospy.loginfo("Done")

    def set_goal(self, msg):
        goal = np.zeros((13,1))
        goal[:3] = np.array(
            [[msg.pose.position.x],
             [msg.pose.position.y],
             [msg.pose.position.z]]
        )
        goal[3:7] = np.array(
            [[msg.pose.orientation.x],
             [msg.pose.orientation.y],
             [msg.pose.orientation.z],
             [msg.pose.orientation.w]]
        )
        self._controller.set_goal(goal)
        rospy.loginfo(f"Setting goal to \n {np.squeeze(self._controller._cost.get_goal())} \n Succesfull.")

    def populate_marker(self, traj, w, id):
        m = Marker()
        m.header.frame_id = self._odom_frame
        m.type = m.LINE_STRIP
        m.action = m.ADD
        m.id = id
        m.scale.x = 0.05
        m.scale.y = 0.05
        #m.color.a = w
        m.color.a = w
        m.color.g = 1.

        m.pose.orientation.w = 1.0
        m.pose.position.x = 0.0
        m.pose.position.y = 0.0
        m.pose.position.z = 0.0
        for t in traj:
            p = Point()
            p.x = t[0]
            p.y = t[1]
            p.z = t[2]
            m.points.append(p)
        return m

    def populate_expected_marker(self, traj):
        m = Marker()
        m.header.frame_id = self._odom_frame
        m.type = m.LINE_STRIP
        m.action = m.ADD
        m.id = 0
        m.scale.x = 0.05
        m.scale.y = 0.05
        m.color.a = 1.
        m.color.g = 0.
        m.color.r = 1.

        m.pose.orientation.w = 1.0
        m.pose.position.x = 0.0
        m.pose.position.y = 0.0
        m.pose.position.z = 0.0
        for t in traj:
            p = Point()
            p.x = t[0]
            p.y = t[1]
            p.z = t[2]
            m.points.append(p)
        return m

    def populate_marker_array(self, trajs, weights, nb_plots=100, expected=None):
        weights = (weights - np.min(weights))/np.max(weights)
        ind = np.argsort(-weights) # negate to get highest weight on first elements
        w = weights[ind]
        sort_trajs = trajs[ind]
        a = MarkerArray()
        for i in range(nb_plots):
            m = self.populate_marker(sort_trajs[i], w[i], i)
            a.markers.append(m)
        if expected is not None:
            m = self.populate_expected_marker(expected)
            a.markers.append(m)
        return a

    def publish_samples_traj(self, trajs, weights):
        nb_plots = 1000
        if trajs.shape[0] < nb_plots:
            nb_plots = trajs.shape[0]
        a = self.populate_marker_array(trajs, weights, nb_plots)
        self._trajsPub.publish(a)

    def publish_obstacles(self):
        obs = self._cost.get_obstacles()
        a = MarkerArray()
        for i, o in enumerate(obs):
            pc, q = o.get_pose()
            h, r = o.get_param()
            m = Marker()
            m.id = i
            m.header.frame_id = self._odom_frame
            m.type = m.CYLINDER
            m.action = m.ADD
            m.color.a = 1.
            m.color.r = 1.
            m.scale.x = 2.*r
            m.scale.y = 2.*r
            m.scale.z = h
            m.pose.position.x = pc[0]
            m.pose.position.y = pc[1]
            m.pose.position.z = pc[2]

            m.pose.orientation.x = q[0]
            m.pose.orientation.y = q[1]
            m.pose.orientation.z = q[2]
            m.pose.orientation.w = q[3]

            a.markers.append(m)

        self._obsPub.publish(a)

    def publish_cost(self, state):
        segments = self._cost.get_3D(state)
        m = Marker()
        m.id = 0
        m.header.frame_id = self._odom_frame
        m.type = m.LINE_STRIP
        m.action = m.ADD
        m.scale.x = 0.05
        m.scale.y = 0.05
        m.color.a = 1.
        m.color.r = 1.
        m.color.g = 0.5
        m.color.b = 0.0

        m.pose.orientation.w = 1.0
        m.pose.position.x = 0.0
        m.pose.position.y = 0.0
        m.pose.position.z = 0.0
        for t in segments:
            p = Point()
            p.x = t[0]
            p.y = t[1]
            p.z = t[2]
            m.points.append(p)
        self._costPub.publish(m)

    def publish_expected(self, traj):
        m = Marker()
        m.header.frame_id = self._odom_frame
        m.type = m.LINE_STRIP
        m.action = m.ADD
        m.id = 0
        m.scale.x = 0.05
        m.scale.y = 0.05
        m.color.a = 1.
        m.color.g = 0.
        m.color.r = 1.

        m.pose.orientation.w = 1.0
        m.pose.position.x = 0.0
        m.pose.position.y = 0.0
        m.pose.position.z = 0.0
        for t in traj:
            p = Point()
            p.x = t[0]
            p.y = t[1]
            p.z = t[2]
            m.points.append(p)
        self._expectPub.publish(m)

    def publish_seq(self, seq):
        msg = Float32MultiArray()
        msg.data = seq.reshape((-1))
        msg.layout.data_offset = 0
        msg.layout.dim = [MultiArrayDimension(), MultiArrayDimension()]

        # dim[0] is the vertical dimension of your matrix
        msg.layout.dim[0].label = "Tau"
        msg.layout.dim[0].size = self._horizon
        msg.layout.dim[0].stride = self._actionDim*self._horizon
        # dim[1] is the horizontal dimension of your matrix
        msg.layout.dim[1].label = "aDim"
        msg.layout.dim[1].size = self._actionDim
        msg.layout.dim[1].stride = self._actionDim

        self._seqPub.publish(msg)

if __name__ == "__main__":
    try:
        node = MPPINode()
        rospy.spin()
    except rospy.ROSInterruptException:
        print("Caught exception")
    print("Exiting")