import os

import eidolon
from eidolon import vec3, color, enum, first, fillList, Camera2DView, DrawContourMixin, DrawLineMixin, PolyHandle2D

from ..ui import QtWidgets, QtCore, Qt, Ui_Measure2DView, Ui_MeasureObjProp
from .SegmentPlugin import triangulateContour, generateContoursFromMask
from .PlotPlugin import TimePlotWidget
import itertools

# names of parameters for the measurement data file
DatafileParams=enum('name','title','srcimage','tracksrc','trackdata')

# types of measurements
MeasureType=enum('point','line','contour')

# extension of measurement files
measureExt='.measure'

defaultNumNodes=16 # default number of contour nodes
defaultColor=color(1,0,0) # default handle colour

# default colours for points
PointColors=(color(1,0,0),color(0,1,0),color(0,0,1),color(1,1,0),color(1,0,1),color(0,1,1),color(1,1,1))

def calculateLength(measure,objs):
    return [v[0].distTo(v[1]) for v in measure.values]

def calculateDisplacement(measure,objs):
    return [measure.values[0][0].distTo(v[0]) for v in measure.values]

def calculateCircumference(measure,objs):
    results=[]
    for v in measure.values:
        results.append(sum(a.distTo(b) for a,b in eidolon.successive(v,cyclic=True)))

    return results

def calculateArea(measure,objs):
    results=[]
    for v in measure.values:
        triinds=triangulateContour(v,True)
        results.append(sum(v[a].triArea(v[b],v[c]) for a,b,c in triinds))

    return results

def calculateImageVolume(measure,objs):
    area=calculateArea(measure,objs)
    img=first(o for o in objs if isinstance(o,eidolon.ImageSceneObject))
    if img:
        area*=img.getVoxelSize().z()

    return area

# List of metric calculation functions to apply to specific measurement types, values are (description, MeasureType, function)
# The function should accept two arguments, a Measurement object and a list of objects representing the main image object followed
# by secondary objects. The Measurement object is expected to be on one of the planes of the main image, and the secondary
# objects are assumed to be the secondary visible objects in a 2D view.
MetricFuncs=enum(
    ('length','Length',MeasureType._line,calculateLength),
    ('disp','Displacement',MeasureType._point,calculateDisplacement),
    ('circum','Circumference',MeasureType._contour,calculateCircumference),
    ('area','Area',MeasureType._contour,calculateArea),
    #('volume','Volume',MeasureType._contour,calculateImageVolume),
    doc='Types of metrics to apply to measurements over time'
)

class Measurement(object):
    def __init__(self,name,mtype,col=(1,1,1),timesteps=[],values=[]):
        self.name=name
        self.mtype=mtype
        self.col=color(*col)
        self.timesteps=list(timesteps)
        self.values=[list(itertools.starmap(vec3,v)) for v in values] # list of lists, store values as vec3

        assert len(self.values)==len(self.timesteps)
        assert all(len(v)==len(self.values[0]) for v in self.values)
        assert mtype in MeasureType

    def clone(self):
        return Measurement(self.name,self.mtype,self.col,self.timesteps,self.values)

    def setHandlePoints(self,handle,timestep,margin=0):
        curtimeind=eidolon.minmaxIndices(abs(ts-timestep) for ts in self.timesteps)[0]
        assert 0<=curtimeind<len(self.values)

        for i,n in enumerate(self.values[curtimeind]):
            handle.setNode(i,n)

        handle.col=self.col

    def setHandleVisible(self,handle,timestep,margin):
        handle.setVisible(handle.isVisible() and (not margin or min(abs(ts-timestep) for ts in self.timesteps)<=margin))

    def updateValue(self,handle,timestep):
        curtimeind=eidolon.minmaxIndices(abs(ts-timestep) for ts in self.timesteps)[0]
        assert 0<=curtimeind<len(self.values)
        nodes=handle.getNodes()

        if nodes!=self.values[curtimeind]: # if the nodes are changed, update
            self.values[curtimeind]=nodes
            return True
        else:
            return False

    def addTimestep(self,timestep,values):
        self.timesteps.append(timestep)
        self.values.append(list(values))

        # resort timestep and values
        sortinds=eidolon.sortIndices(self.timesteps)
        self.timesteps=eidolon.indexList(sortinds,self.timesteps)
        self.values=eidolon.indexList(sortinds,self.values)

    def setTimesteps(self,timesteps,copyFirstValues=True):
        self.timesteps=timesteps
        if copyFirstValues or len(timesteps)!=len(self.values):
            self.values=[list(self.values[0]) for ii in timesteps]

    def __repr__(self):
        col=tuple(self.col)
        values=[list(map(tuple,v)) for v in self.values]
        return repr((self.name,self.mtype,col,self.timesteps,values))

class MeasureSceneObject(eidolon.DatafileSceneObject):
    def __init__(self,name,filename,plugin,**kwargs):
        filename=eidolon.ensureExt(filename,measureExt)
        datamap={
            DatafileParams.name: name,
            DatafileParams.title: name,
            DatafileParams.srcimage:'',
            DatafileParams.tracksrc:'',
            DatafileParams.trackdata:''
        }

        eidolon.DatafileSceneObject.__init__(self,name,filename,datamap,plugin,**kwargs)

    def getWidget(self):
        '''Get the docked widget for this object, or None if the user hasn't created one.'''
        return self.plugin.getObjectWidget(self)

    def getObjectNames(self):
        return [n for n in self.datamap if n not in DatafileParams]

    def addObject(self,sceneobj):
        basename=sceneobj.name or sceneobj.mtype
        sceneobj.name=eidolon.uniqueStr(basename,[sceneobj.mtype]+self.getObjectNames())
        self.datamap[sceneobj.name]=sceneobj
        return sceneobj.name

    def enumObjects(self):
        for name,val in self.datamap.items():
            if name not in DatafileParams:
                yield val

    def clearObjects(self):
        for n in list(self.datamap):
            if n not in DatafileParams:
                self.datamap.pop(n)

class MeasurePropertyWidget(QtWidgets.QWidget,Ui_MeasureObjProp):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self,parent)
        self.setupUi(self)

class Measure2DWidget(QtWidgets.QWidget,Ui_Measure2DView):
    def __init__(self,parent=None):
        QtWidgets.QWidget.__init__(self,parent)
        self.setupUi(self)

class LabelPolyHandle2D(PolyHandle2D):
    def __init__(self,widg2D,pts,isClosed=False,col=color(1,0,0,1),etype=None,radius=None):
        PolyHandle2D.__init__(self,widg2D,pts,isClosed,col,etype,radius)
        self.label=None

    def setVisible(self,isVisible):
        PolyHandle2D.setVisible(self,isVisible)
        if self.label:
            self.label.setVisible(isVisible and self.isActive())

    def updatePositions(self):
        PolyHandle2D.updatePositions(self)

        if self.isVisible():
            self.label.setPosition(self.widg2D.getOrthoPosition(eidolon.avg(self.pts)))

            if len(self.pts)==2:
                text='Len: %g'%self.pts[0].distTo(self.pts[1])
            else:
                circ=sum(a.distTo(b) for a,b in eidolon.successive(self.pts,cyclic=True))
                triinds=triangulateContour(self.pts,True)
                area=sum(self.pts[a].triArea(self.pts[b],self.pts[c]) for a,b,c in triinds)

                text='Circ: %g\nArea:%g'%(circ,area)
                self.label.setHAlign(eidolon.H_CENTER)
                self.label.setVAlign(eidolon.V_CENTER)

            self.label.setText(text)

    def updateRepr(self):
        PolyHandle2D.updateRepr(self)

        if not self.label:
            self.label=self.widg2D.createFigure('label',eidolon.FT_TEXT)
            self.label.setTextHeight(20)
            self.label.setOverlay(True)
            self.label.setVisible(False)

        self.figs.append(self.label)

class MeasurementView(DrawLineMixin,DrawContourMixin,Camera2DView):

    measurementChanged=QtCore.pyqtSignal(int)

    def __init__(self,mgr,camera,parent=None):
        Camera2DView.__init__(self,mgr,camera,parent)
        DrawLineMixin.__init__(self)
        DrawContourMixin.__init__(self,defaultNumNodes)

        self.plugin=self.mgr.getPlugin('Measure')
        self.handlecol=defaultColor
        self.handleradius=5.0
        self.planeMargin=eidolon.Handle2D.defaultPlaneMargin

        self.lastUpdateTime=-1.0

        self.sceneobj=None

        self.handleNames={} # index -> Measurement object for each index in self.handles which is a measuring handle (not all handles are such)

        self.uiobj=Measure2DWidget()
        self.uiobj.measureBox.setParent(None)
        self.mainLayout.addWidget(self.uiobj.measureBox)

        self.uiobj.numCtrlBox.setValue(self.numNodes)
        self.uiobj.numCtrlBox.valueChanged.connect(self.setNumNodes)

        self.uiobj.cloneButton.clicked.connect(self._cloneObject)
        self.uiobj.delButton.clicked.connect(self._deleteObject)
        self.uiobj.saveButton.clicked.connect(self.save)
        self.uiobj.setPlaneButton.clicked.connect(self._setObjectPlane)
        self.uiobj.setStartButton.clicked.connect(self._setStartTime)
        self.uiobj.copyStepsButton.clicked.connect(self._copySteps)
        self.uiobj.trackButton.clicked.connect(self._motionTrack)

        self.uiobj.addPointButton.clicked.connect(self._addPointButton)
        self.uiobj.addLineButton.clicked.connect(self._addLineButton)
        self.uiobj.addContourButton.clicked.connect(self._addContourButton)

        self.uiobj.show3DBox.clicked.connect(lambda:self.setVisible3D(self.isVisible3D()))

        self.uiobj.objectList.itemSelectionChanged.connect(self._selectObject)

        self.measurementChanged.connect(lambda i:self.updateSceneObject())

        eidolon.setCollapsibleGroupbox(self.uiobj.measureBox,True)

#       self.uiobj.trackGroup.setVisible(False) # TODO: hide the track box until figured out how to track without close coupling

    def setSceneObject(self,sceneobj):
        self.sceneobj=sceneobj

        for i,ind in enumerate(sorted(self.handleNames)): # remove objects only, leave other handles alone
            self.removeHandle(ind-i)

        self.handleNames={}

        for mobj in tuple(self.sceneobj.enumObjects()):
            if isinstance(mobj,tuple):
                mobj=Measurement(*mobj)

            self.addMeasurement(mobj)

        self.setActiveObject('') # select nothing

    def updateSceneObject(self):
        if self.sceneobj:
            self.sceneobj.clearObjects()
            for i,v in self.handleNames.items():
                self.sceneobj.addObject(v)

    def save(self):
        if self.sceneobj:
            self.updateSceneObject()

            if not os.path.isfile(self.sceneobj.filename):
                self.sceneobj.filename=eidolon.ensureExt(self.sceneobj.plugin.getFilename(False),measureExt)
            self.sceneobj.save()

    def setNumNodes(self,n):
        if n>=4:
            self.numNodes=n
            with eidolon.signalBlocker(self.uiobj.numCtrlBox):
                self.uiobj.numCtrlBox.setValue(n)

        self._repaintDelay()

    def addMeasurement(self,mobj):
        '''Add the Measurement object `mobj' to the list of measurements and create an appropriate handle.'''
        if mobj.mtype==MeasureType.point:
            h=eidolon.PointHandle2D(self,mobj.values[0][0],mobj.col)
        elif mobj.mtype==MeasureType.line:
            h=LabelPolyHandle2D(self,mobj.values[0][:2],False,mobj.col,eidolon.ElemType.Line1NL,self.handleradius)
        elif mobj.mtype==MeasureType.contour:
            h=LabelPolyHandle2D(self,mobj.values[0],True,mobj.col,eidolon.ElemType.Line1PCR,self.handleradius)

        i=len(self.handles)
        self.addHandle(h)
        self.handleNames[i]=mobj
        self.measurementChanged.emit(i)

    def createMeasurement(self,mtype,col,values,name=None,timesteps=None):
        '''Create and add a new Measurement object of type `mtype', color `col', with points `values'.'''

        existingnames=list(map(first,MeasureType))+[n.name for n in self.handleNames.values()] # ensures names are unique and always numbered
        name=eidolon.uniqueStr(name or mtype,existingnames)
        timesteps=[self.mgr.timestep] if timesteps==None else timesteps
        col=col or self.handlecol
        if not isinstance(values[0],list):
            values=[values]

        mobj=Measurement(name,mtype,col,timesteps,values)
        self.addMeasurement(mobj)
        self.setActiveObject(mobj.name)

        return mobj

    def getMeasurement(self,i):
        return self.handleNames[i]

    def addPoint(self,point,col=None,name=None,timestep=None):
        return self.createMeasurement(MeasureType.point,col,[point],name,timestep)

    def addLine(self,start,end,col=None,name=None,timestep=None):
        return self.createMeasurement(MeasureType.line,col,[start,end],name,timestep)

    def addContour(self,nodes,col=None,name=None,timestep=None):
        return self.createMeasurement(MeasureType.contour,col,nodes,name,timestep)

    def setActiveObject(self,name):
        for i,v in self.handleNames.items():
            self.handles[i].setActive(v.name==name)

        listitem=first(self.uiobj.objectList.findItems(name+' @ ',Qt.MatchStartsWith))
        if listitem:
            with eidolon.signalBlocker(self.uiobj.objectList):
                self.uiobj.objectList.setCurrentItem(listitem)

        self._repaintDelay()

    def handleSelected(self,handle):
        self.setActiveObject(self.handleNames[self.handles.index(handle)].name)

    def getActiveIndex(self):
        return first(i for i in self.handleNames if i<len(self.handles) and self.handles[i].isActive())

    def removeHandle(self,index):
        if index!=None:
            for i in sorted(self.handleNames.keys()):
                if i==index: # remove the entry for this handle
                    self.handleNames.pop(index)
                elif i>index: # move entries indexed above this handle down 1
                    self.handleNames[i-1]=self.handleNames.pop(i)

            Camera2DView.removeHandle(self,index)

    def removeHandles(self):
        Camera2DView.removeHandles(self)
        self.handleNames={}

    def updateView(self):
        self.fillLineFig()
        self.fillContourFig()

        handles=sorted(self.handleNames.items())

        # fill the handles list, selecting the active handle
        objects=['%s @ %.2f->%.2f (%s)'%(mobj.name,mobj.timesteps[0],mobj.timesteps[-1],mobj.mtype) for i,mobj in handles]
        selected=self.getActiveIndex()
        fillList(self.uiobj.objectList,objects,selected if selected!=None else -1,None,True)

        curtime=self.mgr.timestep
        rep=self.mgr.findObject(self.sourceName)
        tslist=rep.getTimestepList() if rep else []
        tsmargin=eidolon.avgspan(tslist)/2 if len(tslist)>=2 else 0
        #mintimeind=minmaxIndices(abs(ts-curtime) for ts in tslist)[0] if rep else -1

        # set the handle for each measurement object to the data for the current timestep
        if curtime!=self.lastUpdateTime:
            self.lastUpdateTime=curtime
            for i,mobj in handles:
                mobj.setHandlePoints(self.handles[i],curtime,tsmargin)

        Camera2DView.updateView(self)

        for i,mobj in handles:
            mobj.setHandleVisible(self.handles[i],curtime,tsmargin)

        fillList(self.uiobj.trackDataBox,sorted(list(self.plugin.trackSrcs)))

    def mousePress(self,e):
        if DrawLineMixin.drawMousePress(self,e) or DrawContourMixin.drawMousePress(self,e):
            return

        Camera2DView.mousePress(self,e)

    def mouseRelease(self,e):
        self.uiobj.addContourButton.setStyleSheet('')
        self.uiobj.addLineButton.setStyleSheet('')

        if DrawLineMixin.drawMouseRelease(self,e):
            self.addLine(self.lineStart,self.lineEnd)
            self._repaintDelay()
        elif DrawContourMixin.drawMouseRelease(self,e):
            self.addContour(self.contour)
            self._repaintDelay()
        else:
            i=self.getActiveIndex()
            if i!=None and self.handles[i].isVisible():
                if self.handleNames[i].updateValue(self.handles[i],self.mgr.timestep):
                    self.measurementChanged.emit(i)

            Camera2DView.mouseRelease(self,e)

    def mouseDrag(self,e,dx,dy):
        if DrawLineMixin.drawMouseDrag(self,e,dx,dy) or DrawContourMixin.drawMouseDrag(self,e,dx,dy):
            self._repaintDelay()
        else:
            Camera2DView.mouseDrag(self,e,dx,dy)

    def isVisible3D(self):
        return self.uiobj.show3DBox.isChecked()

    def setVisible3D(self,isVisible):
        eidolon.setChecked(isVisible,self.uiobj.show3DBox)

        for i in self.handleNames:
            self.handles[i].setVisible3D(isVisible)

        self.mgr.repaint(False)

    def _selectObject(self):
        if self.uiobj.objectList.currentItem():
            text=str(self.uiobj.objectList.currentItem().text())
            self.setActiveObject(text.split('@')[0].strip())

    def _addPointButton(self):
        p=self.getWorldPosition(0.5,0.5,False)
        self.addPoint(p,self.handlecol)

    def _addLineButton(self):
        if not self.drawingContour:
            self.startLineDraw()
            self.uiobj.addLineButton.setStyleSheet('border: 1px solid rgb(255,0,0);')

    def _addContourButton(self):
        if not self.drawingLine:
            self.startContourDraw()
            self.uiobj.addContourButton.setStyleSheet('border: 1px solid rgb(255,0,0);')

    def _deleteObject(self):
        self.removeHandle(self.getActiveIndex())

    def _setObjectPlane(self):
        i=self.getActiveIndex()
        if i!=None:
#           h=self.handles[i]
#           nodes=h.getNodes()
#           for n in range(len(nodes)):
#               x,y,_=self.getScreenPosition(nodes[n])
#               h.setNode(n,self.getWorldPosition(x,y))
#
#           if self.handleNames[i].updateValue(h,self.mgr.timestep):
#               self.measurementChanged.emit(i)

            m=self.handleNames[i]

            for ts in m.values:
                for j,n in enumerate(ts):
                    x,y,_=self.getScreenPosition(n)
                    ts[j]=self.getWorldPosition(x,y)

            self.measurementChanged.emit(i)
            self._repaintDelay()

    def _setStartTime(self):
        i=self.getActiveIndex()
        if i!=None:
            m=self.handleNames[i]
            m.timesteps=[self.mgr.timestep]
            m.values=[m.values[0]]
            self.measurementChanged.emit(i)

    def _cloneObject(self):
        i=self.getActiveIndex()
        if i!=None:
            #m=self.handleNames[i].clone()
            #m.name=uniqueStr(m.mtype,[n.name for n in self.handleNames.values()]) # ensure name uniqueness
            #self.addMeasurement(m)
            m=self.handleNames[i]
            self.createMeasurement(m.mtype,m.col,m.values,None,m.timesteps)

    def _copySteps(self):
        i=self.getActiveIndex()
        rep=self.mgr.findObject(self.sourceName)
        if i!=None and rep!=None:
            m=self.handleNames[i]
            m.setTimesteps(rep.getTimestepList())
            self.measurementChanged.emit(i)

    def _motionTrack(self):
        i=self.getActiveIndex()
        rep=self.mgr.findObject(self.sourceName)
        trackdata=str(self.uiobj.trackDataBox.currentText())

        if not trackdata:
            self.mgr.showMsg('No source for motion track data','No Track Data')
        elif i!=None and rep!=None:
            m=self.handleNames[i]
            m.timesteps=rep.getTimestepList()

            result=self.plugin.trackSrcs[trackdata](trackdata,m.values[0])
            m.values=[]

            for ts in m.timesteps:
                _,pts=min((abs(ts-t),p) for t,p in result.items())
                m.values.append(pts)

            self.measurementChanged.emit(i)

class MeasurementPlotWidget(TimePlotWidget):
    def __init__(self,plugin,parent=None):
        TimePlotWidget.__init__(self,plugin,parent)
        self.measureCache={} # maps (measurement name, metric name) to (is visible, timestep,line data) tuples
        self.setObjectName('Measurement Plot')

    def isLineVisible(self,measure,metric):
        k=(measure.name,metric)
        return k in self.measureCache and self.measureCache[k][0]

    def setLineVisible(self,measure,metric,isVisible):
        k=(measure.name,metric)
        if k in self.measureCache:
            self.measureCache[k]=(isVisible,measure.timesteps,self.measureCache[k][-1])
            self.updatePlot()

    def setMeasurement(self,measure,metric,data):
        self.measureCache[(measure.name,metric)]=(True,measure.timesteps,data)
        self.updatePlot()

    def updatePlot(self):
        @self.plugin.mgr.callThreadSafe
        def _update():
            data=[]
            timesteps=[]
            labels=[]

            for mname,metric in self.measureCache:
                isVis,timestep,linedata=self.measureCache[(mname,metric)]
                if isVis:
                    labels.append('%s (%s)'%(mname,MetricFuncs[metric][0]))
                    timesteps.append(timestep)
                    data.append(linedata)

            self.setData(data,timesteps,labels)
            self.repaint()

class MeasureSplitView(QtWidgets.QSplitter):
    def __init__(self,mgr,camera,parent=None):
        QtWidgets.QSplitter.__init__(self)
        self.mgr=mgr
        self.setOrientation(Qt.Horizontal)
        self.setChildrenCollapsible(True)
        self.measure=MeasurementView(mgr,camera,self)

        self.measure.measurementChanged.connect(self.updateMeasurement)

        self.plotwidg=QtWidgets.QWidget(self)
        self.plotLayout=QtWidgets.QVBoxLayout(self.plotwidg)

        self.plot=MeasurementPlotWidget(mgr.getPlugin('Plot'),self.plotwidg)

        self.plotctrls=QtWidgets.QGroupBox('Choose Plot Measurements',self.plotwidg)
        self.plotCtrlLayout=QtWidgets.QHBoxLayout(self.plotctrls)

        self.chooseMenu=QtWidgets.QMenu(self)
        self.plotChooseButton=QtWidgets.QToolButton(self.plotctrls)
        self.plotChooseButton.setText('Choose Measurements')
        self.plotChooseButton.setMenu(self.chooseMenu)
        self.plotChooseButton.setPopupMode(QtWidgets.QToolButton.InstantPopup)

        self.plotCtrlLayout.addWidget(self.plotChooseButton)

        self.plotLayout.addWidget(self.plot)
        self.plotLayout.addWidget(self.plotctrls)

    def setSceneObject(self,sceneobj):
        self.measure.setSceneObject(sceneobj)

    def parentClosed(self,e):
        self.measure.parentClosed(e)
        self.plot.parentClosed(e)

    def fillChooseMenu(self):
        def _addAction(measure,metric):
            '''Use a subroutine to ensure `measure' and `metric' are fresh variables for each call to connect().'''
            action=self.chooseMenu.addAction('%s (%s)'%(measure.name,MetricFuncs[metric][0]))
            action.setCheckable(True)
            action.setChecked(self.plot.isLineVisible(measure,metric))
            action.toggled.connect(lambda b:self.setLineVisible(measure,metric,b))

        self.chooseMenu.clear()
        for m in self.measure.sceneobj.enumObjects():
            for mf in MetricFuncs:
                if mf[2]==m.mtype:
                    _addAction(m,mf[0])

    @eidolon.taskmethod('Calculating Plot')
    def setMeasurement(self,measure,metric,objs,task):
        linedata=MetricFuncs[metric][2](measure,objs)
        self.plot.setMeasurement(measure,metric,linedata)
        return linedata

    def setLineVisible(self,measure,metric,isVisible):
        if isVisible and (measure.name,metric) not in self.plot.measureCache:
            objs=[self.mgr.findObject(n).parent for n in self.measure.getObjectNames() if n]
            f=self.setMeasurement(measure,metric,objs)
            #self.mgr.checkFutureResult(f)
        else:
            self.plot.setLineVisible(measure,metric,isVisible)

    def updateMeasurement(self,i):
        self.fillChooseMenu()
        m=self.measure.getMeasurement(i)
        objs=[self.mgr.findObject(n).parent for n in self.measure.getObjectNames() if n]

        for k in list(self.plot.measureCache):
            if k[0]==m.name:
                if not self.plot.measureCache[k][0]:
                    self.plot.measureCache.pop(k)
                else:
                    self.setMeasurement(m,k[1],objs)

class MeasurePlugin(eidolon.ScenePlugin):
    def __init__(self):
        eidolon.ScenePlugin.__init__(self,'Measure')
        self.dockmap={}
        # maps source name/directory to function accepting (name, points list) and returns mapping from timesteps to list of points tracked to that time
        self.trackSrcs={}

    def init(self,plugid,win,mgr):
        eidolon.ScenePlugin.init(self,plugid,win,mgr)
        if win:
            win.addMenuItem('Create','NewMeasure'+str(plugid),'&Measurement Object',self._createMeasure)
            win.addMenuItem('Import','ImportMeasure'+str(plugid),'&Measurements',self._importMeasure)

        if mgr.conf.hasValue('args','--measure'):
            @eidolon.taskroutine('Loading Measurement File(s)')
            def _loadTask(filenames,task=None):
                for f in filenames:
                    obj=self.loadObject(f)
                    self.mgr.addSceneObject(obj)

            self.mgr.runTasks(_loadTask(mgr.conf.get('args','--measure').split(',')))

    def _importMeasure(self):
        filename=self.getFilename()
        if filename:
            obj=self.loadObject(filename)
            self.mgr.addSceneObject(obj)

    def _createMeasure(self):
        obj=self.createMeasurementObject('','Measurement')
        self.mgr.addSceneObject(obj)

    def getMenu(self,obj):
        return [obj.getName(),'Show Measurement View'],self.objectMenuItem

    def getFilename(self,isOpen=True):
        return self.mgr.win.chooseFileDialog('Choose Measurement filename',filterstr='Measurement Files (*%s)'%measureExt,isOpen=isOpen)

    def getObjectWidget(self,obj):
        return first(w for w in self.win.dockWidgets if id(w)==self.dockmap.get(obj.getName(),-1))

    def objectMenuItem(self,obj,item):
        if item=='Show Measurement View':
            self.mgr.addFuncTask(lambda:obj.createRepr(None))

    def createObjPropBox(self,obj):
        prop=MeasurePropertyWidget()

        prop.createContButton.clicked.connect(lambda:self._createContoursButton(prop,obj))
        prop.showButton.clicked.connect(lambda:self.mgr.addFuncTask(lambda:obj.createRepr(None)))
        prop.srcBox.activated.connect(lambda i:obj.set(DatafileParams.srcimage,str(prop.srcBox.itemText(i))))

        return prop

    def updateObjPropBox(self,obj,prop):
        if not prop.isVisible():
            return

        prop.ctrlsBox.setValue(defaultNumNodes)

        imgnames=[o.getName() for o in self.mgr.objs if isinstance(o,eidolon.ImageSceneObject)]

        eidolon.fillTable(obj.getPropTuples(),prop.propTable)
        eidolon.fillList(prop.srcBox,imgnames,obj.get(DatafileParams.srcimage))

        eidolon.fillList(prop.maskImgBox,imgnames)

    def acceptFile(self,filename):
        return eidolon.splitPathExt(filename)[2].lower() == measureExt

    def checkFileOverwrite(self,obj,dirpath,name=None):
        outfile=os.path.join(dirpath,name or obj.getName())+measureExt
        if os.path.exists(outfile):
            return [outfile]
        else:
            return []

    def renameObjFiles(self,obj,oldname,overwrite=False):
        assert isinstance(obj,eidolon.SceneObject) and obj.plugin==self
        if os.path.isfile(obj.filename):
            obj.filename=eidolon.renameFile(obj.filename,obj.getName(),overwriteFile=overwrite)

    def getObjFiles(self,obj):
        return [obj.filename] if obj.filename else []

    def copyObjFiles(self,obj,sdir,overwrite=False):
        assert os.path.isfile(obj.filename),'Nonexistent filename: %r'%obj.filename

        newfilename=os.path.join(sdir,os.path.basename(obj.filename))
        if not overwrite and os.path.exists(newfilename):
            raise IOError('File already exists: %r'%newfilename)

        obj.filename=newfilename
        obj.save()

    def getScriptCode(self,obj,**kwargs):
        configSection=kwargs.get('configSection',False)
        namemap=kwargs.get('namemap',{})
        convertpath=kwargs['convertPath']
        script=''
        args={'varname':namemap[obj], 'objname':obj.name}

        if not configSection:
            args['filename']=convertpath(obj.filename)
            script+='%(varname)s = Measure.loadObject(%(filename)s,%(objname)r)\n'

        return eidolon.setStrIndent(script % args).strip()+'\n'

    def createMeasurementObject(self,filename,name):
        return MeasureSceneObject(name,filename,self)

    @eidolon.taskmethod('Creating Segmentation View')
    def createRepr(self,obj,reprtype,refine=0,task=None,**kwargs):
        sobj=self.mgr.findObject(obj.get(DatafileParams.srcimage))

        # make a representation of the source object visible if one doesn't already exist
        if isinstance(sobj,eidolon.ImageSceneObject) and not len(sobj.reprs):
            isEmpty=first(self.mgr.enumSceneObjectReprs())==None
            r=sobj.createRepr(eidolon.ReprType._imgtimestack if sobj.isTimeDependent else eidolon.ReprType._imgstack)
            self.mgr.addSceneObjectRepr(r)
            if isEmpty:
                self.mgr.setCameraSeeAll()
                self.mgr.repaint()

        return self.getMeasurementDock(obj)

    def getMeasurementDock(self,obj,w=400,h=400):
        @self.mgr.proxyThreadSafe
        def createWidget():
            widg=self.mgr.create2DView(obj.get(DatafileParams.name),MeasureSplitView)#MeasurementView)
            self.dockmap[obj.getName()]=id(widg)
            widg.setSceneObject(obj)
            return widg

        if self.win:
            self.win.sync()
            widg=first(d for d in self.win.dockWidgets if id(d)==self.dockmap.get(obj.getName(),-1))
            return widg or createWidget()

    def loadObject(self,filename,name=None,**kwargs):
        obj=self.createMeasurementObject(filename,name or eidolon.splitPathExt(filename)[1])
        obj.load()
        return obj

    def saveObject(self,obj,path,overwrite=False,setFilenames=False,**kwargs):
        if not isinstance(obj,MeasureSceneObject) or not isinstance(obj.plugin,MeasurePlugin):
            raise ValueError('Can only save measurement objects with MeasurePlugin')

        if os.path.isdir(path):
            path=os.path.join(path,eidolon.getValidFilename(obj.getName()))

        path=eidolon.ensureExt(path,measureExt)
        oldpath=obj.filename
        obj.filename=path
        obj.save()

        if not setFilenames: # set the filename back to the original if we're not supposed to change it
            obj.filename=oldpath

        return path

    def addTrackSource(self,name,func):
        '''
        Add the tracking source for the name/directory `name'. The `func' callable must accept 2 arguments, the name
        it was keyed to and a list of vec3 points, and return a dict mapping timesteps to the motion tracked data
        at that time.
        '''
        self.trackSrcs[name]=func

    def removeTrackSource(self,name_or_func):
        '''Remove all tracking sources using the given name or function.'''
        for n,f in list(self.trackSrcs.items()):
            if name_or_func in (n,f):
                del self.trackSrcs[n]

    @eidolon.taskmethod('Add segmentations from mask image')
    def addMaskSegmentations(self,obj,mask,numctrls,innerseg,minSegSize=100,refine=2,task=None):
        contours=generateContoursFromMask(mask.images,numctrls,innerseg,minSegSize,2,task)

        for ts,nodes in contours:
            mobj=Measurement('contour',MeasureType.contour,defaultColor,[ts],[nodes])
            obj.addObject(mobj)

        widg=obj.getWidget()
        if widg:
            self.mgr.callThreadSafe(widg.setSceneObject,obj)

    def _createContoursButton(self,prop,obj):
        maskname=str(prop.maskImgBox.currentText())
        numctrls=prop.ctrlsBox.value()
        innerseg=prop.innerContBox.isChecked()
        mask=self.findObject(maskname)

        f=self.addMaskSegmentations(obj,mask,numctrls,innerseg)
        self.mgr.checkFutureResult(f)

eidolon.addPlugin(MeasurePlugin())


# -*- coding: utf-8 -*-

import os
import sys
from glob import glob
import numpy as np
from skimage import io, transform
import joblib
import pandas as pd

def load_square_image(img_name, target_shape):
    img = io.imread(img_name)

    channels = 3
    greater_side = max(img.shape[:2])
    smaller_side = min(img.shape[:2])

    new_img = np.zeros((greater_side, greater_side, channels)).astype('uint8')
    new_img[:,:,:] = 255

    start = int((greater_side/2) - (smaller_side//2))
    end = start + smaller_side

    max_side = np.argmax(img.shape)

    if max_side == 0: #vertical
        new_img[:,start:end,0] = img
    elif max_side == 1: #horizontal
        new_img[start:end,:,0] = img

    for c in range(2):
        new_img[:,:,c+1] = new_img[:,:,0]

    new_img = transform.resize(new_img, target_shape, preserve_range=True) / 255.0

    return new_img

if len(sys.argv) != 3:
    print('Usage: python 01_create_dataset.py <data_dir> <image_side>')
    exit(1)

base_dir = sys.argv[1]
img_side = int(sys.argv[2])

shape = (img_side, img_side, 3)

#plankton datasets
datasets = dict()

datasets['furg'] = os.path.join(base_dir, 'furg')
datasets['laps'] = os.path.join(base_dir, 'laps_nobg_100')
datasets['ndsb'] = os.path.join(base_dir, 'ndsb')
datasets['japan'] = os.path.join(base_dir, 'LRoot_japan_dataset_review_jul2018')

for dataset, path in datasets.items():
    classes = sorted(glob(path + '/*'))

    label_names = []
    y_tmp = []
    X_tmp = []

    for i, c in enumerate(classes):
        if os.path.isdir(c):
            print(i, c)
            label_names.append(os.path.basename(c))

            files_in_class = sorted(glob(c + '/*.*'))

            for f in files_in_class:
                img = load_square_image(f, shape)
                X_tmp.append(img)
                y_tmp.append(i)

    np.save(os.path.join(base_dir, 'X_%s.npy' % dataset), np.array(X_tmp))
    np.save(os.path.join(base_dir, 'y_%s.npy' % dataset), np.array(y_tmp).astype('uint8'))
    joblib.dump(label_names, os.path.join(base_dir, 'label_names_%s.pkl' % dataset))


import numpy as np

def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))

def int_to_onehot(y, num_labels):

    ary = np.zeros((y.shape[0], num_labels))

    for i, val in enumerate(y):
        ary[i, val] = 1

    return ary

class NeuralNetMLP:

    def __init__(self, num_features, num_hidden, num_classes, random_seed=123):
        super().__init__()

        self.num_classes = num_classes

        rng = np.random.RandomState(random_seed)

        self.weight_h = rng.normal(
            loc=0.0,
            scale=0.1,
            size=(num_hidden, num_features)
        )

        self.bias_h = np.zeros(num_hidden)

        # Output
        self.weight_out = rng.normal(
            loc=0.0,
            scale=0.1,
            size=(num_classes, num_hidden)
        )

        self.bias_out = np.zeros(num_classes)

    def forward(self, X):

        z_h = np.dot(X, np.transpose(self.weight_h)) + self.bias_h
        a_h = sigmoid(z_h)

        z_out = np.dot(a_h, np.transpose(self.weight_out)) + self.bias_out
        a_out = sigmoid(z_out)

        return a_h, a_out

    def backward(self, X: np.ndarray, activation_hidden, activation_output, y: np.ndarray):

        # Part One
        y_onehot = int_to_onehot(y, self.num_classes)

        d_loss__d_a_out = 2.0 * (activation_output - y_onehot) / y.shape[0]

        d_a_out__d_z_out = activation_output * (1.0 - activation_output)

        delta_out = d_loss__d_a_out * d_a_out__d_z_out

        d_z_out__dw_out = activation_hidden

        d_loss__dw_out = np.dot(np.transpose(delta_out), d_z_out__dw_out)
        d_loss__db_out = np.sum(delta_out, axis=0)

        # Part Two

        d_z_out__a_h = self.weight_out

        d_loss__a_h = np.dot(delta_out, d_z_out__a_h)

        d_a_h__d_z_h = activation_hidden * (1.0 - activation_hidden)

        d_z_h__d_w_h = X

        d_loss__d_w_h = np.dot(
            np.transpose((d_loss__a_h * d_a_h__d_z_h)),
            d_z_h__d_w_h
        )

        d_loss__d_b_h = np.sum((d_loss__a_h * d_a_h__d_z_h), axis=0)

        return (d_loss__dw_out, d_loss__db_out, d_loss__d_w_h, d_loss__d_b_h)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from flask import Flask, render_template, request, template_rendered
from xgboost import XGBRegressor
from sklearn import linear_model

app=Flask(__name__)

@app.route('/')
def web1():
   return render_template("index.html")
@app.route('/',methods=['POST'])
def web2():
   m=request.form['name']
   m=int(m)
   c=request.form['b']
   c=int(c)
   k={'AREA':[m],'BHK':[c]}
   df2=pd.DataFrame(k)
   l=request.form['se']
   f=l+".csv"

   data=pd.read_csv(f)
   #print(data)
   #print(data.values)
   New={'AREA':data['Area'],'BHK':data['bhk'],'PRICE':data['Price']}
   df1=pd.DataFrame(New)

   #print(df1)
   Y=df1['PRICE']
   X=df1.drop(['PRICE'],axis=1)

   X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=0.2, random_state=2)
   #print(X.shape,X_train.shape,X_test.shape)
   model=XGBRegressor()
   model.fit(X_train,Y_train)

   model2=linear_model.LinearRegression()
   model2.fit(X_train,Y_train)

   ka=model.predict(X_train)
   t=model.predict(df2)
   plt.scatter(Y_train,ka)
   plt.xlabel("actual_value")
   plt.ylabel("predicted_value")
   plt.title("graph for testing data")
   t=int(t)
   e=model2.predict(df2)
   e=int(e)
   minim=min(t,e)
   maxim=max(t,e)

   return render_template("web2.html",name=minim,name2=maxim,city=l,d=c,z=m)

if __name__ == '__main__':

   app.run(debug=True,port=5001)


from player import Player # Uses Player as foundation

class Bot(Player):

    def calc_hand_hidden(self): # To show user potential total of dealer
        sum = 0

        hand_copy = list(self.hand)
        hand_copy.pop(0)

        non_aces = [card for card in hand_copy if card.val != 1]
        aces = [card for card in hand_copy if card.val == 1]

        for card in non_aces:
            if card.val >= 10:
                sum += 10
            else:
                sum += card.val

        aces_len = len(aces)

        sum += aces_len

        for card in aces:
            if sum <= 11:
                sum += 10

        return sum

    def show_hand_hidden(self): # To show user one card

        hand_string = ""

        first_iteration = True

        for card in self.hand:

            if first_iteration:
                hand_string += "?, "
                first_iteration = False
                continue

            hand_string += card.__str__()
            hand_string += ", "

        return hand_string


#! /usr/bin/env python
# -*- coding:utf-8 -*-

################################################################
#
# Class 07: 1-D Euler system of equations
# Solve equation using the Roe scheme
# Author: P. S. Volpiani
# Date: 01/08/2020
#
################################################################

#import os, sys
import numpy as np
from numpy import *
import matplotlib.pyplot as plt

from matplotlib import rc
rc('font', family='serif')
rc('lines', linewidth=1.5)
rc('font', size=14)
#plt.rc('legend',**{'fontsize':11})

######################################################################
#             Solving 1-D Euler system of equations
#                     using the Roe scheme
#
#             dq_i/dt + df_i/dx = 0, for x \in [a,b]
#
# This code solves the Sod's shock tube problem (IC=1)
#
# t=0                                 t=tEnd
# Density                             Density
#   ****************|                 *********\
#                   |                           \
#                   |                            \
#                   |                             ****|
#                   |                                 |
#                   |                                 ****|
#                   ***************                       ***********
#
# Domain cells (I{i}) reference:
#
#                |           |   u(i)    |           |
#                |  u(i-1)   |___________|           |
#                |___________|           |   u(i+1)  |
#                |           |           |___________|
#             ...|-----0-----|-----0-----|-----0-----|...
#                |    i-1    |     i     |    i+1    |
#                |-         +|-         +|-         +|
#              i-3/2       i-1/2       i+1/2       i+3/2
#
######################################################################

#def func_cons2prim(q,gamma):
#    # Primitive variables
#    r=q[0];
#    u=q[1]/r;
#    E=q[2]/r;
#    p=(gamma-1.)*r*(E-0.5*u**2);
#
#    return (r,u,p)

#def func_prim2cons(r,u,p,gamma):
#    # Conservative variables
#    q0=r;
#    q1=r*u;
#    q2=p/(gamma-1.)+0.5*r*u**2;
#    q =np.array([ q0, q1, q2 ]);
#
#    return (q)

def func_flux(q,gamma):
    # Primitive variables
    r=q[0];
    u=q[1]/r;
    E=q[2]/r;
    p=(gamma-1.)*r*(E-0.5*u**2);

    # Flux vector
    F0 = np.array(r*u)
    F1 = np.array(r*u**2+p)
    F2 = np.array(u*(r*E+p))
    flux=np.array([ F0, F1, F2 ])

    return (flux)

def flux_roe(q,dx,gamma,a,nx):

    # Compute primitive variables and enthalpy
    r=q[0];
    u=q[1]/r;
    E=q[2]/r;
    p=(gamma-1.)*r*(E-0.5*u**2);
    htot = gamma/(gamma-1)*p/r+0.5*u**2

    # Initialize Roe flux
    Phi=np.zeros((3,nx-1))

    for j in range (0,nx-1):

        # Compute Roe averages
        R=sqrt(r[j+1]/r[j]);                          # R_{j+1/2}
        rmoy=R*r[j];                                  # {hat rho}_{j+1/2}
        umoy=(R*u[j+1]+u[j])/(R+1);                   # {hat U}_{j+1/2}
        hmoy=(R*htot[j+1]+htot[j])/(R+1);             # {hat H}_{j+1/2}
        amoy=sqrt((gamma-1.0)*(hmoy-0.5*umoy*umoy));  # {hat a}_{j+1/2}

        # Auxiliary variables used to compute P_{j+1/2}^{-1}
        alph1=(gamma-1)*umoy*umoy/(2*amoy*amoy);
        alph2=(gamma-1)/(amoy*amoy);

        # Compute vector (W_{j+1}-W_j)
        wdif = q[:,j+1]-q[:,j];

        # Compute matrix P^{-1}_{j+1/2}
        Pinv = np.array([[0.5*(alph1+umoy/amoy), -0.5*(alph2*umoy+1/amoy),  alph2/2],
                        [1-alph1,                alph2*umoy,                -alph2 ],
                        [0.5*(alph1-umoy/amoy),  -0.5*(alph2*umoy-1/amoy),  alph2/2]]);

        # Compute matrix P_{j+1/2}
        P    = np.array([[ 1,              1,              1              ],
                        [umoy-amoy,        umoy,           umoy+amoy      ],
                        [hmoy-amoy*umoy,   0.5*umoy*umoy,  hmoy+amoy*umoy ]]);

        # Compute matrix Lambda_{j+1/2}
        lamb = np.array([[ abs(umoy-amoy),  0,              0                 ],
                        [0,                 abs(umoy),      0                 ],
                        [0,                 0,              abs(umoy+amoy)    ]]);

        # Compute Roe matrix |A_{j+1/2}|
        A=np.dot(P,lamb)
        A=np.dot(A,Pinv)

        # Compute |A_{j+1/2}| (W_{j+1}-W_j)
        Phi[:,j]=np.dot(A,wdif)

    #==============================================================
    # Compute Phi=(F(W_{j+1}+F(W_j))/2-|A_{j+1/2}| (W_{j+1}-W_j)/2
    #==============================================================
    F = func_flux(q,gamma);
    Phi=0.5*(F[:,0:nx-1]+F[:,1:nx])-0.5*Phi

    dF = (Phi[:,1:-1]-Phi[:,0:-2])

    return (dF)

# Parameters
CFL    = 0.50               # Courant Number
gamma  = 1.4                # Ratio of specific heats
ncells = 400                # Number of cells
x_ini =0.; x_fin = 1.       # Limits of computational domain
dx = (x_fin-x_ini)/ncells   # Step size
nx = ncells+1               # Number of points
x = np.linspace(x_ini+dx/2.,x_fin,nx) # Mesh

# Build IC
r0 = zeros(nx)
u0 = zeros(nx)
p0 = zeros(nx)
halfcells = int(ncells/2)

IC = 1 # 6 IC cases are available
if IC == 1:
    print ("Configuration 1, Sod's Problem")
    p0[:halfcells] = 1.0  ; p0[halfcells:] = 0.1;
    u0[:halfcells] = 0.0  ; u0[halfcells:] = 0.0;
    r0[:halfcells] = 1.0  ; r0[halfcells:] = 0.125;
    tEnd = 0.20;
elif IC== 2:
    print ("Configuration 2, Left Expansion and right strong shock")
    p0[:halfcells] = 1000.; p0[halfcells:] = 0.1;
    u0[:halfcells] = 0.0  ; u0[halfcells:] = 0.0;
    r0[:halfcells] = 3.0  ; r0[halfcells:] = 0.2;
    tEnd = 0.01;
elif IC == 3:
    print ("Configuration 3, Right Expansion and left strong shock")
    p0[:halfcells] = 7.   ; p0[halfcells:] = 10.;
    u0[:halfcells] = 0.0  ; u0[halfcells:] = 0.0;
    r0[:halfcells] = 1.0  ; r0[halfcells:] = 1.0;
    tEnd = 0.10;
elif IC == 4:
    print ("Configuration 4, Shocktube problem of G.A. Sod, JCP 27:1, 1978")
    p0[:halfcells] = 1.0  ; p0[halfcells:] = 0.1;
    u0[:halfcells] = 0.75 ; u0[halfcells:] = 0.0;
    r0[:halfcells] = 1.0  ; r0[halfcells:] = 0.125;
    tEnd = 0.17;
elif IC == 5:
    print ("Configuration 5, Lax test case: M. Arora and P.L. Roe: JCP 132:3-11, 1997")
    p0[:halfcells] = 3.528; p0[halfcells:] = 0.571;
    u0[:halfcells] = 0.698; u0[halfcells:] = 0.0;
    r0[:halfcells] = 0.445; r0[halfcells:] = 0.5;
    tEnd = 0.15;
elif IC == 6:
    print ("Configuration 6, Mach = 3 test case: M. Arora and P.L. Roe: JCP 132:3-11, 1997")
    p0[:halfcells] = 10.33; p0[halfcells:] = 1.0;
    u0[:halfcells] = 0.92 ; u0[halfcells:] = 3.55;
    r0[:halfcells] = 3.857; r0[halfcells:] = 1.0;
    tEnd = 0.09;

E0 = p0/((gamma-1.)*r0)+0.5*u0**2 # Total Energy density
a0 = sqrt(gamma*p0/r0)            # Speed of sound
q  = np.array([r0,r0*u0,r0*E0])   # Vector of conserved variables

if (False):
    fig = plt.subplots()
    ax1 = plt.subplot(4, 1, 1)
    #plt.title('Lax-Wendroff scheme')
    plt.plot(x, r0, 'k-')
    plt.ylabel('$rho$',fontsize=18)
    plt.tick_params(axis='x',bottom=False,labelbottom=False)
    plt.grid(True)

    ax2 = plt.subplot(4, 1, 2)
    plt.plot(x, u0, 'r-')
    plt.ylabel('$U$',fontsize=18)
    plt.tick_params(axis='x',bottom=False,labelbottom=False)
    plt.grid(True)

    ax3 = plt.subplot(4, 1, 3)
    plt.plot(x, p0, 'b-')
    plt.ylabel('$P$',fontsize=18)
    plt.tick_params(axis='x',bottom=False,labelbottom=False)
    plt.grid(True)

    ax4 = plt.subplot(4, 1, 4)
    plt.plot(x, E0, 'g-')
    plt.ylabel('$E$',fontsize=18)
    plt.grid(True)
    plt.xlim(x_ini,x_fin)
    plt.xlabel('x',fontsize=18)
    plt.subplots_adjust(left=0.2)
    plt.subplots_adjust(bottom=0.15)
    plt.subplots_adjust(top=0.95)

    plt.show()

# Solver loop
t  = 0
it = 0
a  = a0
dt=CFL*dx/max(abs(u0)+a0)         # Using the system's largest eigenvalue

while t < tEnd:

    q0 = q.copy();
    dF = flux_roe(q0,dx,gamma,a,nx);

    q[:,1:-2] = q0[:,1:-2]-dt/dx*dF;
    q[:,0]=q0[:,0]; q[:,-1]=q0[:,-1]; # Dirichlet BCs

    # Compute primary variables
    rho=q[0];
    u=q[1]/rho;
    E=q[2]/rho;
    p=(gamma-1.)*rho*(E-0.5*u**2);
    a=sqrt(gamma*p/rho);
    if min(p)<0: print ('negative pressure found!')

    # Update/correct time step
    dt=CFL*dx/max(abs(u)+a);

    # Update time and iteration counter
    t=t+dt; it=it+1;

    # Plot solution
    if it%40 == 0:
        print (it)
        fig,axes = plt.subplots(nrows=4, ncols=1)
        plt.subplot(4, 1, 1)
        #plt.title('Roe scheme')
        plt.plot(x, rho, 'k-')
        plt.ylabel('$rho$',fontsize=16)
        plt.tick_params(axis='x',bottom=False,labelbottom=False)
        plt.grid(True)

        plt.subplot(4, 1, 2)
        plt.plot(x, u, 'r-')
        plt.ylabel('$U$',fontsize=16)
        plt.tick_params(axis='x',bottom=False,labelbottom=False)
        plt.grid(True)

        plt.subplot(4, 1, 3)
        plt.plot(x, p, 'b-')
        plt.ylabel('$p$',fontsize=16)
        plt.tick_params(axis='x',bottom=False,labelbottom=False)
        plt.grid(True)

        plt.subplot(4, 1, 4)
        plt.plot(x, E, 'g-')
        plt.ylabel('$E$',fontsize=16)
        plt.grid(True)
        plt.xlim(x_ini,x_fin)
        plt.xlabel('x',fontsize=16)
        plt.subplots_adjust(left=0.2)
        plt.subplots_adjust(bottom=0.15)
        plt.subplots_adjust(top=0.95)
        plt.show()
        fig.savefig("fig_Sod_Roe_it"+str(it)+".pdf", dpi=300)


"""
The math quiz program

Write a program that asks the answer for a mathematical expression, checks whether the user is right or wrong,
and then responds with a message accordingly.
"""

right_answer = 357 / 7
user_answer = int(input("What is 357 divided by 7? "))

if user_answer == right_answer:
    print("Well done, that's right!")
else:
    print("Eeeeh nope.")


import pandas as pd
import numpy as np
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Oct  7 20:41:28 2019

@author: Amruta Abhyankar NJITID-aa2348
"""
import pandas as pd
data1 = pd.read_csv("AAPL.csv")
data2 = pd.read_csv("AMZN.csv")
data3 = pd.read_csv("FB.csv")
data4 = pd.read_csv("GOOG.csv")
data5 = pd.read_csv("IBM.csv")
data6 = pd.read_csv("MSFT.csv")

print('Apple Dividend')
#Dividend Calculation for AAPL#
data1['CloseRatio']=data1['Close'].div(data1['Close'].shift(1))
data1['AdjCloseRatio']=data1['Adj Close'].div(data1['Adj Close'].shift(1))
data1['Dividend']=(data1['CloseRatio']-data1['AdjCloseRatio'])*(data1['Close'])
aapl_Dividend=data1[['Date','Dividend']].copy()
aapl_Dividend = aapl_Dividend[aapl_Dividend['Dividend']>0.000000000]
print(aapl_Dividend)

print('Amazon Dividend')
#Dividend Calculation for AMZN#
data2['CloseRatio']=data2['Close'].div(data2['Close'].shift(1))
data2['AdjCloseRatio']=data2['Adj Close'].div(data2['Adj Close'].shift(1))
data2['Dividend']=(data2['CloseRatio']-data2['AdjCloseRatio'])*(data2['Close'])
amzn_Dividend=data2[['Date','Dividend']].copy()
amzn_Dividend = amzn_Dividend[amzn_Dividend['Dividend']>0.000000000]
print(amzn_Dividend)

print('Facebook Dividend')
#Dividend Calculation for FB#
data3['CloseRatio']=data3['Close'].div(data3['Close'].shift(1))
data3['AdjCloseRatio']=data3['Adj Close'].div(data3['Adj Close'].shift(1))
data3['Dividend']=(data3['CloseRatio']-data3['AdjCloseRatio'])*(data3['Close'])
fb_Dividend=data3[['Date','Dividend']].copy()
fb_Dividend = fb_Dividend[fb_Dividend['Dividend']>0.000000000]
print(fb_Dividend)

print('Google Dividend')
#Dividend Calculation for GOOG#
data4['CloseRatio']=data4['Close'].div(data4['Close'].shift(1))
data4['AdjCloseRatio']=data4['Adj Close'].div(data4['Adj Close'].shift(1))
data4['Dividend']=(data4['CloseRatio']-data4['AdjCloseRatio'])*(data4['Close'])
goog_Dividend=data4[['Date','Dividend']].copy()
goog_Dividend = goog_Dividend[goog_Dividend['Dividend']>0.00000000000000]
print(goog_Dividend)

print('IBM Dividend')
#Dividend Calculation for IBM#
data5['CloseRatio']=data5['Close'].div(data5['Close'].shift(1))
data5['AdjCloseRatio']=data5['Adj Close'].div(data5['Adj Close'].shift(1))
data5['Dividend']=(data5['CloseRatio']-data5['AdjCloseRatio'])*(data5['Close'])
ibm_Dividend=data5[['Date','Dividend']].copy()
ibm_Dividend = ibm_Dividend[ibm_Dividend['Dividend']>0.000000000]
print(ibm_Dividend)

print('MicrSoft Dividend')
#Dividend Calculation for MSFT#
data6['CloseRatio']=data6['Close'].div(data6['Close'].shift(1))
data6['AdjCloseRatio']=data6['Adj Close'].div(data6['Adj Close'].shift(1))
data6['Dividend']=(data6['CloseRatio']-data6['AdjCloseRatio'])*(data6['Close'])
msft_Dividend=data6[['Date','Dividend']].copy()
msft_Dividend = msft_Dividend[msft_Dividend['Dividend']>0.000000000]
print(msft_Dividend)


def solution(babbling):
    answer = 0
    check = ["aya","ye","woo","ma"]
    for item in babbling:
        tmp = 0
        for c in check:
            if c in item:
                tmp += len(c)

        if tmp == len(item):
            answer += 1
    return answer


#!/usr/bin/env python

import os
from vtkmodules.vtkCommonCore import (
    vtkIdList,
    vtkPoints,
)
from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid
from vtkmodules.vtkIOXML import (
    vtkXMLUnstructuredGridReader,
    vtkXMLUnstructuredGridWriter,
)
from vtkmodules.util.misc import vtkGetTempDir

VTK_TEMP_DIR = vtkGetTempDir()
filename = VTK_TEMP_DIR + '/TestCellArray.vtu'

ugrid = vtkUnstructuredGrid()
pts = vtkPoints()
ugrid.SetPoints(pts)
ugrid.Allocate(10)

for i in range(10):
  pts.InsertNextPoint(i, i, i)
  ids = [i]
  ugrid.InsertNextCell(1, 1, ids) # a vertex

writer = vtkXMLUnstructuredGridWriter()
writer.SetInputDataObject(ugrid)
writer.SetFileName(filename)
writer.Write()

reader = vtkXMLUnstructuredGridReader()
reader.SetFileName(filename)
reader.Update()

readergrid = reader.GetOutput()
copygrid = readergrid.NewInstance()

copygrid.DeepCopy(readergrid)

pts = copygrid.GetPoints()
#o.SetPoints(pts)

pt = [1, 2, 3]

idlist = vtkIdList()
idlist.SetNumberOfIds(1)

for i in range(5):
  newpt = [10+i, 10+i, 10+i]
  pts.InsertNextPoint(newpt)
  iii = [copygrid.GetNumberOfPoints()-1]
  copygrid.InsertNextCell(1, 1, iii)
  copygrid.GetCellPoints(copygrid.GetNumberOfCells()-1, idlist)

if copygrid.GetNumberOfPoints() != 15 or copygrid.GetNumberOfCells() != 15:
  print ("ERROR: incorrect number of points and or cells")
  import sys
  sys.exit(1)

count = 0
ci = copygrid.NewCellIterator()
# Now we verify that each vertex has the proper point (the cell id should be the point id)
while ci.IsDoneWithTraversal() == False:
  id = ci.GetCellId()
  ids = ci.GetPointIds()
  copygrid.GetCellPoints(id, idlist)
  if ids.GetId(0) != idlist.GetId(0) or idlist.GetId(0) != count:
    print ("ERROR: incorrect cell points ", count, id, ids.GetId(0), idlist.GetId(0))
    import sys
    sys.exit(1)

  count = count+1
  ci.GoToNextCell()

ci.UnRegister(None)
ci = None

os.remove(filename)


import fire
import torch

from _path_init import manage_package_logging
from vision_base.utils.builder import build
from vision_base.utils.utils import cfg_from_file, update_cfg
from vision_base.networks.utils.utils import load_models

print('CUDA available: {}'.format(torch.cuda.is_available()))

def main(config:str="config/config.py",
        gpu:int=0,
        checkpoint_path:str="retinanet_79.pth",
        split_to_test:str='validation',
        **kwargs):
    # Read Config
    cfg = cfg_from_file(config)
    cfg = update_cfg(cfg, **kwargs)

    # Force GPU selection in command line
    cfg.trainer.gpu = gpu
    torch.cuda.set_device(cfg.trainer.gpu)

    manage_package_logging()

    # Set up dataset and dataloader
    if split_to_test == 'training':
        dataset = build(**cfg.train_dataset)
    elif split_to_test == 'test':
        dataset = build(**cfg.test_dataset)
    else:
        dataset = build(**cfg.val_dataset)

    # Create the model
    meta_arch = build(**cfg.meta_arch)
    meta_arch = meta_arch.cuda()

    load_models(checkpoint_path, meta_arch, map_location=f'cuda:{gpu}', strict=False)
    meta_arch.eval()

    if 'evaluate_hook' in cfg.trainer:
        evaluate_hook = build(result_path_split='validation', **cfg.trainer.evaluate_hook)
        print("Found evaluate function")
    else:
        raise KeyError("evaluate_hook not found in Config")

    # Run evaluation
    evaluate_hook(meta_arch, dataset)
    print('finish')

if __name__ == '__main__':
    fire.Fire(main)


# -*- coding: utf-8 -*-
"""
useful functions including data pre-processing, cost funcions, and 6 ML functions in Table 1
"""

import numpy as np
import csv

##### data pre-processing, aggregated in preprocessing() #####
def load_csv_data(data_path, sub_sample=False):
    """Loads data and returns y (class labels), tX (features) and ids (event ids)"""
    y = np.genfromtxt(data_path, delimiter=",", skip_header=1, dtype=str, usecols=1)
    x = np.genfromtxt(data_path, delimiter=",", skip_header=1)
    ids = x[:, 0].astype(np.int)
    input_data = x[:, 2:]  # 22 is "PRI_jet_num" categorial column

    # convert class labels from strings to binary (0,1)
    yb = np.ones(len(y))
    yb[np.where(y == "b")] = 0  # set backgroud "b" to 0

    # sub-sample
    if sub_sample:
        yb = yb[::50]  # take one every 50 records
        input_data = input_data[::50]
        ids = ids[::50]

    return yb, input_data, ids

def fillna_with_mean(tx):
    """
    replace the missing value with mean value of each feature.
    Args:
        tx: numpy array of shape (N,D), N is the number of samples, D is number of features
    Returns:
        numpy array numpy array of shape (N,D), with missing values replaced with mean.
    """
    for feature in range(tx.shape[1]):
        row_indices = np.where(tx[:, feature] == -999.0)[0]
        clean_data = [x for x in tx[:, feature] if x != -999.0]
        tx[row_indices, feature] = np.mean(clean_data)
    return tx

def get_dummy(x, col=22):
    """
    one-hot encode the categorial feature in x. In this case, it's the 23rd column (index=22)
    Args:
        x: numpy array of shape (N,D), N is the number of samples, D is number of features
    Returns:
        dummies: numpy array of shape (N,d), one-hot encoded with d categories
    """
    target = x[:, col].astype(int)
    dummies = np.zeros((target.size, target.max() + 1))
    dummies[np.arange(target.size), target] = 1
    return dummies

def build_poly(x, degree):
    """polynomial basis functions for input data, for j = 1 up to j = degree.
    Args:
        x: numpy array of shape (N,D), N is the number of samples, D is number of features
        degree: the largest power
    Returns:
        output: augmented data with polynomials
    """
    x = np.delete(x, 22, 1)  # firstly drop the categorical column 22
    output = np.copy(x)
    for i in range(1, degree):
        output = np.concatenate((output, np.power(x, i + 1)), axis=1)
    return output

def add_interactions(x):
    """create all interaction features of x
    Args:
        x: numpy array of shape (N,D), N is the number of samples, D is number of features
    Returns:
        output: augmented data with interation terms
    """
    x = np.delete(x, 22, 1)  # firstly drop the categorical column 22
    output = np.copy(x)
    for i in range(x.shape[1] - 1):
        for j in range(i + 1, x.shape[1]):
            combi = np.multiply(x[:, i], x[:, j])
            output = np.c_[output, combi]
    return output

def standardization(x, test=False, mean=None, std=None):
    """z-score standardization
    Args:
        x: numpy array of shape (N,D), N is the number of samples, D is number of features
        test: a flag to decide whether standardization is performed on testing set.
              If True, mean and std must be given
    Returns:
        x: standardized data, mean at 0 and std at 1
        mean: mean of each column of training set, stored for future use on testing set
        std: std of each column of training set, stored for future use on testing set
    """
    # for training set:
    if not test:
        mean = x.mean(axis=0)
        std = x.std(axis=0)
    x = (x - mean) / std
    return x, mean, std

def make_x(x, dummies):
    """
    concatenate x, dummies, and a column of ones to make final x.
    Notice that dummy variables don't need to be standardized.
    """
    return np.concatenate((x, dummies, np.ones(len(x)).reshape((-1, 1))), axis=1)

def preprocessing(
    x, dummies, test=False, mean=None, std=None, poly=True, degree=10, interaction=False
):
    """
    A function to aggregate all data preprocessing steps.
    If poly=True, degree must be given
    If test=True, mean and std must be given
    """
    x = fillna_with_mean(x)
    if poly and interaction:
        x_poly = build_poly(x, degree=degree)
        x_interaction = add_interactions(x)
        x = np.c_[x_poly, x_interaction]
    elif poly and not interaction:
        x = build_poly(x, degree=degree)
    elif not poly and interaction:
        x = add_interactions(x)
    else:
        x = np.delete(x, 22, 1)

    x_stand, x_mean, x_std = standardization(x, test=test, mean=mean, std=std)
    final_x = make_x(x_stand, dummies)
    return final_x, x_mean, x_std

def split_data(x, y, ratio, seed=1):
    """
    split the dataset into training and validation set, based on the split ratio.
    Args:
        ratio: scalar in [0,1]
        seed: integer
    Returns:
        x_tr: numpy array containing the train data.
        x_te: numpy array containing the validation data.
        y_tr: numpy array containing the train labels.
        y_te: numpy array containing the validation labels.
    """
    # set seed
    np.random.seed(seed)
    shuffle_indices = np.random.permutation(np.arange(len(x)))
    cut = int(np.floor(ratio * len(x)))
    x_tr = x[shuffle_indices[:cut]]
    x_te = x[shuffle_indices[cut:]]
    y_tr = y[shuffle_indices[:cut]]
    y_te = y[shuffle_indices[cut:]]
    return (x_tr, x_te, y_tr, y_te)

def create_csv_submission(ids, y_pred, name):
    """
    Creates an output file in .csv format for submission to Kaggle or AIcrowd
    Arguments: ids (event ids associated with each prediction)
               y_pred (predicted class labels)
               name (string name of .csv output file to be created)
    """
    with open(name, "w") as csvfile:
        fieldnames = ["Id", "Prediction"]
        writer = csv.DictWriter(csvfile, delimiter=",", fieldnames=fieldnames)
        writer.writeheader()
        for r1, r2 in zip(ids, y_pred):
            writer.writerow({"Id": int(r1), "Prediction": int(r2)})

#### costs ####
def compute_loss(y, tx, w, method="MSE"):
    """Calculate the loss using either MSE or MAE.
    Args:
        y: shape=(N, )
        tx: shape=(N, D)
        w: shape=(D,). The vector of model parameters.
    """
    if method == "MSE":
        loss = 0.5 * np.square((y - tx @ w)).mean()  # 0.5 to be consistent with lecture
    elif method == "MAE":
        loss = np.abs((y - tx @ w)).mean()
    else:
        raise Exception("method {} not implemented!".format(method))
    return loss

def sigmoid(x):
    """sigmoid function"""
    return 1 / (1 + np.exp(-x))

def compute_logistic_loss(y, tx, w):
    """Log-loss for logistic regression"""
    p = sigmoid(tx @ w)
    loss = -1 / len(y) * np.sum((1 - y) * np.log(1 - p) + y * np.log(p))
    return loss

##### gradient #####
def compute_gradient(y, tx, w, lambda_=0):
    """Computes the gradient at w."""
    return -1 / len(y) * (tx.T @ (y - tx @ w)) + 2 * lambda_ * w

def compute_logistic_gradient(y, tx, w, lambda_=0):
    """Gradient for logistic loss"""
    p = sigmoid(tx @ w)
    return -1 / len(y) * tx.T @ (y - p) + 2 * lambda_ * w

##### mini-batch #####
def batch_iter(y, tx, batch_size=1, num_batches=100, shuffle=True):
    """
    Generate a minibatch iterator for a dataset.
    Data can be randomly shuffled to avoid ordering in the original data messing with the randomness of the minibatches.
    batch_size: must be 1 according to task description
    num_batches: can be changed freely
    """
    data_size = len(y)
    if shuffle:
        shuffle_indices = np.random.permutation(np.arange(data_size))
        shuffled_y = y[shuffle_indices]
        shuffled_tx = tx[shuffle_indices]
    else:
        shuffled_y = y
        shuffled_tx = tx
    for batch_num in range(num_batches):
        start_index = batch_num * batch_size
        end_index = min((batch_num + 1) * batch_size, data_size)
        if start_index < end_index:
            yield shuffled_y[start_index:end_index], shuffled_tx[start_index:end_index]

##### (stochastic) gradient descent #####
def gradient_descent(
    y, tx, initial_w, max_iters=100, gamma=0.1, decay=0, lambda_=0, logistic=False
):
    """
    The Gradient Descent (GD) algorithm.
    Return the last recorded loss and weights
    """
    # Define parameters to store w and loss
    ws = [initial_w]
    losses = [
        compute_logistic_loss(y, tx, initial_w)
        if logistic
        else compute_loss(y, tx, initial_w)
    ]
    w = initial_w
    if logistic:
        for n_iter in range(max_iters):
            grad = compute_logistic_gradient(y, tx, w, lambda_=lambda_)
            w = w - gamma * grad
            loss = compute_logistic_loss(y, tx, w)
            gamma = (
                gamma * 1 / (1 + decay * n_iter)
            )  # add a Time-Based Learning Rate decay
            # store w and loss
            ws.append(w)
            losses.append(loss)
    else:
        for n_iter in range(max_iters):
            grad = compute_gradient(y, tx, w, lambda_=lambda_)
            w = w - gamma * grad
            loss = compute_loss(y, tx, w)
            gamma = (
                gamma * 1 / (1 + decay * n_iter)
            )  # add a Time-Based Learning Rate decay
            # store w and loss
            ws.append(w)
            losses.append(loss)
    return (ws[-1], losses[-1])

def stochastic_gradient_descent(
    y, tx, initial_w, max_iters=100, gamma=0.1, decay=0, lambda_=0, logistic=False
):
    """
    The Stochastic Gradient Descent algorithm (SGD)
    Return the last recorded loss and weights
    """
    # Define parameters to store w and loss
    ws = [initial_w]
    losses = [
        compute_logistic_loss(y, tx, initial_w)
        if logistic
        else compute_loss(y, tx, initial_w)
    ]
    w = initial_w
    # different method if is logistic reg
    if logistic:
        for n_iter in range(max_iters):
            for minibatch_y, minibatch_tx in batch_iter(
                y, tx, shuffle=True
            ):  # from from helpers import batch_iter
                grad = compute_logistic_gradient(
                    minibatch_y, minibatch_tx, w, lambda_=lambda_
                )
                w = w - gamma * grad
            loss = compute_logistic_loss(y, tx, w)
            gamma = (
                gamma * 1 / (1 + decay * n_iter)
            )  # add a Time-Based Learning Rate decay
            ws.append(w)
            losses.append(loss)
    else:
        for n_iter in range(max_iters):
            for minibatch_y, minibatch_tx in batch_iter(
                y, tx, shuffle=True
            ):  # from from helpers import batch_iter
                grad = compute_gradient(minibatch_y, minibatch_tx, w, lambda_=lambda_)
                w = w - gamma * grad
            loss = compute_loss(y, tx, w)
            gamma = (
                gamma * 1 / (1 + decay * n_iter)
            )  # add a Time-Based Learning Rate decay
            ws.append(w)
            losses.append(loss)
    return (ws[-1], losses[-1])

########## 6 ML functions in Table 1 ##########
###############################################

def mean_squared_error_gd(
    y, tx, initial_w, max_iters=100, gamma=0.1, decay=0, lambda_=0
):
    """
    Linear regression using gradient descent
    """
    return gradient_descent(
        y,
        tx,
        initial_w,
        max_iters=max_iters,
        gamma=gamma,
        decay=decay,
        lambda_=lambda_,
        logistic=False,
    )

def mean_squared_error_sgd(
    y, tx, initial_w, max_iters=100, gamma=0.1, decay=0, lambda_=0
):
    """
    Linear regression using stochastic gradient descent (mini-batch-size 1)
    """
    return stochastic_gradient_descent(
        y,
        tx,
        initial_w,
        max_iters=max_iters,
        gamma=gamma,
        decay=decay,
        lambda_=lambda_,
        logistic=False,
    )

def least_squares(y, tx):
    """
    Least squares regression using normal equations
    """
    try:
        w = np.linalg.solve(tx.T @ tx, tx.T @ y)
    # for numerically unstable while not singular tx.T@tx
    except np.linalg.linalg.LinAlgError:
        w = np.linalg.lstsq(tx.T @ tx, tx.T @ y)[0]
    mse = compute_loss(y, tx, w)
    return w, mse

def ridge_regression(y, tx, lambda_):
    """
    Ridge regression using normal equations
    """
    N = tx.shape[0]
    D = tx.shape[1]
    w = np.linalg.solve((tx.T @ tx + 2 * lambda_ * N * np.identity(D)), tx.T @ y)
    mse = compute_loss(y, tx, w)
    return w, mse

def logistic_regression(y, tx, initial_w, max_iters=100, gamma=0.1, decay=0):
    """
    Logistic regression using gradient descent
    """
    return gradient_descent(
        y,
        tx,
        initial_w,
        max_iters=max_iters,
        gamma=gamma,
        decay=decay,
        lambda_=0,
        logistic=True,
    )

def reg_logistic_regression(
    y, tx, lambda_, initial_w, max_iters=100, gamma=0.1, decay=0
):
    """
    Regularized logistic regression using gradient descent
    """
    return gradient_descent(
        y,
        tx,
        initial_w,
        max_iters=max_iters,
        gamma=gamma,
        decay=decay,
        lambda_=lambda_,
        logistic=True,
    )


# adapted from: https://github.com/pytorch/examples/blob/master/mnist/main.py
import argparse
import torch as pt
import torch.nn as nn
import torch.nn.functional as nnf
import torch.optim as optim
from utils import get_data_loaders

class MnistCNN(nn.Module):
    def __init__(self):
        super(MnistCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5, 1)
        self.conv2 = nn.Conv2d(20, 50, 5, 1)
        self.fc1 = nn.Linear(4 * 4 * 50, 500)
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x):
        x = nnf.relu(self.conv1(x))
        x = nnf.max_pool2d(x, 2, 2)
        x = nnf.relu(self.conv2(x))
        x = nnf.max_pool2d(x, 2, 2)
        x = x.view(-1, 4 * 4 * 50)
        x = nnf.relu(self.fc1(x))
        x = self.fc2(x)
        return nnf.log_softmax(x, dim=1)

def train(args, model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = nnf.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % args.log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))

def test(args, model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with pt.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += nnf.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)

    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

def main():
    # Training settings
    parser = argparse.ArgumentParser(description='Pypt MNIST Example')
    parser.add_argument('--batch-size', type=int, default=64)
    parser.add_argument('--test-batch-size', type=int, default=1000)
    parser.add_argument('--epochs', type=int, default=10)
    parser.add_argument('--lr', type=float, default=0.01)
    parser.add_argument('--momentum', type=float, default=0.5)
    parser.add_argument('--no-cuda', action='store_true', default=False)
    parser.add_argument('--seed', type=int, default=1)
    parser.add_argument('--log-interval', type=int, default=60)
    parser.add_argument('--fashion', action='store_true', default=False)
    parser.add_argument('--save-dir', type=str, default=None)
    args = parser.parse_args()
    use_cuda = not args.no_cuda and pt.cuda.is_available()

    pt.manual_seed(args.seed)

    device = pt.device("cuda" if use_cuda else "cpu")

    train_loader, test_loader = get_data_loaders(use_cuda, args, fashion=args.fashion)

    model = MnistCNN().to(device)
    optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)

    for epoch in range(1, args.epochs + 1):
        train(args, model, device, train_loader, optimizer, epoch)
        test(args, model, device, test_loader)

    if args.save_dir is not None:
        pt.save(model.state_dict(), "softmax_mnist_cnn{}.pt".format('_fashion' if args.fashion else ''))

if __name__ == '__main__':
    main()


# countries.append("nz")
# c=countries[index]
# countries[i]= "Berlins"
# if("nz" in countries)
# countries.insert(index,"ce")
# countries.pop(index)
# r=nap(func,list)
    #print(list(r))
# countries.xvssdf??("canada")
# countries[1:3]= ["nz","bulgary"]
    #del(countries[3])
def main():

    country=input("What country should I add to my list: ")
    countries=["canada","australia","combodia","laos","china"]

    while (country in countries ):
        print("already in list")
        country=input("try another one")

    countries.append(country)

    print(countries)

if __name__== "__main__":
    main()


import discord
from discord.ext import commands

import discordSuperUtils

bot = commands.Bot(command_prefix="-", intents=discord.Intents.all())
LevelingManager = discordSuperUtils.LevelingManager(bot, award_role=True)
ImageManager = (
    discordSuperUtils.ImageManager()
)  # LevelingManager uses ImageManager to create the rank command.

@bot.event
async def on_ready():
    database = discordSuperUtils.DatabaseManager.connect(...)
    await LevelingManager.connect_to_database(database, ["xp", "roles", "role_list"])

    print("Leveling manager is ready.", bot.user)

@LevelingManager.event()
async def on_level_up(message, member_data, roles):
    await message.reply(
        f"You are now level {await member_data.level()}"
        + (f", you have received the {roles[0]}" f" role." if roles else "")
    )

@bot.command()
async def rank(ctx, member: discord.Member = None):
    mem_obj = member if member else ctx.author
    member_data = await LevelingManager.get_account(mem_obj)

    if not member_data:
        await ctx.send(f"I am still creating your account! please wait a few seconds.")
        return

    guild_leaderboard = await LevelingManager.get_leaderboard(ctx.guild)
    member = [x for x in guild_leaderboard if x.member == mem_obj]
    member_rank = guild_leaderboard.index(member[0]) + 1 if member else -1

    image = await ImageManager.create_leveling_profile(
        member=mem_obj,
        member_account=member_data,
        background=discordSuperUtils.Backgrounds.GALAXY,
        # name_color=(255, 255, 255),
        # rank_color=(127, 255, 0),
        # level_color=(255, 255, 255),
        # xp_color=(255, 255, 255),
        # bar_outline_color=(255, 255, 255),
        # bar_fill_color=(127, 255, 0),
        # bar_blank_color=(72, 75, 78),
        # profile_outline_color=(100, 100, 100),
        rank=member_rank,
        font_path=None,
        outline=5,
    )
    await ctx.send(file=image)

@bot.command()
async def set_roles(ctx, interval: int, *roles: discord.Role):
    await LevelingManager.set_interval(ctx.guild, interval)
    await LevelingManager.set_roles(ctx.guild, roles)

    await ctx.send(
        f"Successfully set the interval to {interval} and role list to {', '.join(role.name for role in roles)}"
    )

@bot.command()
async def leaderboard(ctx):
    guild_leaderboard = await LevelingManager.get_leaderboard(ctx.guild)
    formatted_leaderboard = [
        f"Member: {x.member}, XP: {await x.xp()}" for x in guild_leaderboard
    ]

    await discordSuperUtils.PageManager(
        ctx,
        discordSuperUtils.generate_embeds(
            formatted_leaderboard,
            title="Leveling Leaderboard",
            fields=25,
            description=f"Leaderboard of {ctx.guild}",
        ),
    ).run()

bot.run("token")


"""
12. Escreva uma função que imprime um tablado de tamanho 20x10, contendo um personagem ‘#’, que
deverá ser controlado pela entrada dos caracteres WASD. O personagem inicia no centro do
trabalho - posição (10, 10). O código deve controlar a posição (linha x coluna) do personagem e
alterá-la conforme os caracteres WASD forem informados. Note que, ao imprimir o tablado, é
necessário considerar a posição em que se encontra o personagem para imprimí-lo na posição
adequada. O código deve impedir que o personagem seja movido além dos limites do tablado. De
forma geral, o programa consiste em:
1. Ler caractere do teclado (W-A-S-D ou Q);
a. Cada um dos caracteres WASD corresponde à uma direção;
b. O caractere Q (“quit”) deve encerrar o programa.
2. De acordo com o caractere informado (WASD), deve alterar (adicionar/subtrair) a
linha/coluna correspondente, de forma a reposicionar o personagem;
a. W: linha -= 1, S: linha += 1, A: coluna -= 1, D: coluna += 1
3. Reimprimir o tablado após cada entrada, conforme exemplo abaixo. Considerar a posição
em que deve ser impresso o caractere do personagem (‘#’).

Notas: Fiz uma adição em que se o "personagem" ultrapassar a caixar, ele será teleportado para o outro lado da caixa
"""

def moveAMove():
    command = 0
    x = 5
    y = 10
    linhas = 12
    colunas = 22
    while command != 'q':
        print("     Move A Move")
        for i in range(linhas): #Printando a caixa
            if i == 0: #Topo
                print('╔', end = "")
                for j in range(colunas):
                    print("═", end="")
                print("╗")
            elif i == linhas - 1: #Chao
                print('╚', end = "")
                for j in range(colunas):
                    print("═", end="")
                print("╝")
            else:
                print("║", end="")  #Meiuca
                for j in range(colunas):
                    if i == x and y == j:
                        print("#", end="")
                    else:
                        print(" ", end="")
                print("║")
        print("Teclas: A⇦ W⇧ D⇨ S⇩")
        command = (input(""))
        for i in range(len(command)):  #Controles
            if command[i] == 'w':
                x -= 1
                if x - 1 < 0:
                    x = 10
            if command[i] == 'a':
                y -= 1
                if y - 1 < -1:
                    y = 21
            if command[i] == 's':
                x += 1
                if x + 1 > 11:
                    x = 1
            if command[i] == 'd':
                y += 1
                if y + 1 > 22:
                    y = 0

        print("\033c", end="") #Limpar a tela
def main():
    moveAMove()

main()


import numpy as np
from scipy.optimize import fmin_l_bfgs_b, NonlinearConstraint, minimize, Bounds, fmin_cobyla
from sklearn import gaussian_process as gp
import warnings
from scipy.stats import norm
from matplotlib import pyplot as plt

DOMAIN = np.array([[0, 10]])  # restrict \theta in [0, 10]
SAFETY_THRESHOLD = 4  # threshold, upper bound of SA
SEED = 0

""" Solution """

warnings.filterwarnings("ignore", category=RuntimeWarning)
warnings.filterwarnings("ignore", category=UserWarning)
class BO_algo():
    def __init__(self):
        """Initializes the algorithm with a parameter configuration. """

        self.beta = 4
        self.beta_v = 4
        self.v_mean = 4
        # self.mean = 4
        # self.var = 0.0001
        self.gpf = gp.GaussianProcessRegressor(kernel = 0.5 * gp.kernels.Matern(length_scale=1, nu=2.5, length_scale_bounds="fixed"), alpha=0.15)
        self.gpv = gp.GaussianProcessRegressor(kernel = 4 + np.sqrt(2) * gp.kernels.Matern(length_scale=1,nu=2.5, length_scale_bounds="fixed"), alpha=0.001)
        self.x = []
        self.f = []
        self.v = []
        self.recs = []

    #maybe the model works best for regret around 0.03?
    def next_recommendation(self):
        """
        Recommend the next input to sample.

        Returns
        -------
        recommendation: np.ndarray
            1 x domain.shape[0] array containing the next point to evaluate
        """

        # TODO: enter your code here
        # In implementing this function, you may use optimize_acquisition_function() defined below.

        x_next = self.optimize_acquisition_function()
        # while self.gpv.predict(x_next) <= SAFETY_THRESHOLD:
        #     x_next = self.optimize_acquisition_function()

        self.recs.append(x_next[0])
        return x_next

    def optimize_acquisition_function(self):
        """
        Optimizes the acquisition function.

        Returns
        -------
        x_opt: np.ndarray
            1 x DOMAIN.shape[0] array containing the point that maximize the acquisition function.
        """

        def objective(x):
            return -self.acquisition_function(x)

        def upperb(x):
            mean_v,std_v = self.gpv.predict(np.atleast_2d(x), return_std=True)
            fc = (mean_v + self.beta_v * std_v)
            return np.mean(fc)

        def lowerb(x):
            mean_v,std_v = self.gpv.predict(np.atleast_2d(x), return_std=True)
            fc = (mean_v - self.beta_v * std_v)
            return np.mean(fc)

        f_values = []
        x_values = []

        # Restarts the optimization 20 times and pick best solution
        for _ in range(20):
            x0 = DOMAIN[:, 0] + (DOMAIN[:, 1] - DOMAIN[:, 0]) * \
                 np.random.rand(DOMAIN.shape[0])
            # bounds = NonlinearConstraint(lb=lowerb(x0), ub=upperb(x0))
            const = NonlinearConstraint(fun=upperb, lb=-np.inf, ub=SAFETY_THRESHOLD)
            const_lo = NonlinearConstraint(fun=lowerb, lb=-np.inf, ub=SAFETY_THRESHOLD)
            # result = fmin_l_bfgs_b(objective, x0=x0, bounds=DOMAIN, approx_grad=True)
            # result = fmin_cobyla(objective, x0=x0, cons=upperb)
            # x_values.append(np.clip(result[0], *DOMAIN[0]))
            # f_values.append(-result[1])
            #print(result)
            result = minimize(objective, x0, bounds=DOMAIN, constraints=const)
            x_values.append(np.clip(result["x"], *DOMAIN[0]))
            f_values.append(-result["fun"])
        ind = np.argmax(f_values)
        x_opt = x_values[ind].item()
        #print(x_values[ind])
        return np.atleast_2d(x_opt)

    def acquisition_function(self, x):
        """
        Compute the acquisition function.

        Parameters
        ----------
        x: np.ndarray
            x in DOMAIN of f

        Returns
        ------
        af_value: float
            Value of the acquisition function at x
        """
        #print(x.shape)
        mean, std = self.gpf.predict(np.atleast_2d(x), return_std=True)
        mean_v, std_v = self.gpv.predict(np.atleast_2d(x), return_std=True)
        nd = norm
        fmax = 1.0
        xi = 0

        # Z = (mean - fmax - xi) / std
        # af_value = (mean - fmax - xi) * nd.cdf(Z) + std * norm.pdf(Z)
        # print(af_value.shape)
        # print((mean_v + std_v)[0])
        af_value = mean +self.beta * std
        if mean_v + std_v * self.beta_v >= SAFETY_THRESHOLD:
            af_value -= self.beta * np.max([mean_v + std_v, 4])

        return np.mean(af_value)

    def add_data_point(self, x, f, v):
        """
        Add data points to the model.

        Parameters
        ----------
        x: np.ndarray
            Hyperparameters
        f: np.ndarray
            Model accuracy
        v: np.ndarray
            Model training speed
        """

        self.x.append(x)
        self.f.append(f)
        self.v.append(v)

        x_n = np.reshape(self.x, [-1,1])
        f_n = np.reshape(self.f, [-1,1])
        v_n = np.reshape(self.v, [-1,1])

        #print(x_n, f_n, v_n)

        self.gpf.fit(x_n, f_n)
        self.gpv.fit(x_n, v_n)

    def get_solution(self):
        """
        Return x_opt that is believed to be the maximizer of f.

        Returns
        -------
        solution: np.ndarray
            1 x DOMAIN.shape[0] array containing the optimal solution of the problem
        """
        mask = np.array(self.v) < SAFETY_THRESHOLD
        f_msk = np.array(self.f)[mask]
        x_msk = np.array(self.x)[mask]
        ind = np.argmax(f_msk)
        return np.atleast_2d(x_msk[ind])

    def plot(self, plot_recommendation: bool = True):
        """Plot objective and constraint posterior for debugging (OPTIONAL).

        Parameters
        ----------
        plot_recommendation: bool
            Plots the recommended point if True.
        """
        plt.ylabel("values for x")
        plt.plot(self.x)
        plt.plot(self.f)
        plt.show()

""" Toy problem to check code works as expected """

def check_in_domain(x: float):
    """Validate input"""
    x = np.atleast_2d(x)
    return np.all(x >= DOMAIN[None, :, 0]) and np.all(x <= DOMAIN[None, :, 1])

def f(x: float):
    """Dummy logP objective"""
    mid_point = DOMAIN[:, 0] + 0.5 * (DOMAIN[:, 1] - DOMAIN[:, 0])
    return - np.linalg.norm(x - mid_point, 2)

def v(x: float):
    """Dummy SA"""
    return 2.0

def get_initial_safe_point():
    """Return initial safe point"""
    x_domain = np.linspace(*DOMAIN[0], 4000)[:, None]
    c_val = np.vectorize(v)(x_domain)
    x_valid = x_domain[c_val < SAFETY_THRESHOLD]
    np.random.seed(0)
    np.random.shuffle(x_valid)
    x_init = x_valid[0]

    return x_init

def main():
    """FOR ILLUSTRATION / TESTING ONLY (NOT CALLED BY CHECKER)."""
    # Init problem
    agent = BO_algo()

    # Add initial safe point
    x_init = get_initial_safe_point()
    obj_val = f(x_init)
    cost_val = v(x_init)
    agent.add_data_point(x_init, obj_val, cost_val)

    # Loop until budget is exhausted
    for j in range(20):
        # Get next recommendation
        x = agent.next_recommendation()

        # Check for valid shape
        assert x.shape == (1, DOMAIN.shape[0]), \
            f"The function next recommendation must return a numpy array of " \
            f"shape (1, {DOMAIN.shape[0]})"

        # Obtain objective and constraint observation
        obj_val = f(x) + np.random.randn()
        cost_val = v(x) + np.random.randn()
        agent.add_data_point(x, obj_val, cost_val)
        agent.plot()

    # Validate solution
    solution = agent.get_solution()
    assert check_in_domain(solution), \
        f'The function get solution must return a point within the' \
        f'DOMAIN, {solution} returned instead'

    # Compute regret
    regret = (0 - f(solution))

    print(f'Optimal value: 0\nProposed solution {solution}\nSolution value '
          f'{f(solution)}\nRegret {regret}\nUnsafe-evals TODO\n')

if __name__ == "__main__":
    main()


import json
from collections import Counter
from typing import Dict, Iterator, List, Tuple

import itchat
from jieba.analyse import extract_tags
from pyecharts import options
from pyecharts.charts import WordCloud
from pyecharts.globals import SymbolType, ThemeType, RenderType

if __name__ == '__main__':

    # 登陆微信
    print('登陆微信 ...')
    itchat.auto_login(hotReload=True)
    itchat.dump_login_status()

    # 读取朋友列表
    print('读取朋友列表 ...')
    friends = itchat.get_friends(update=True)

    # 微信定义的朋友属性，其中很多并没有官方的解释
    attribute_list: List[str] = [
        'MemberList', 'Uin', 'UserName', 'NickName',
        'HeadImgUrl', 'ContactFlag', 'MemberCount',
        'RemarkName', 'HideInputBarFlag', 'Sex',
        'Signature', 'VerifyFlag', 'OwnerUin',
        'PYInitial', 'PYQuanPin', 'RemarkPYInitial',
        'RemarkPYQuanPin', 'StarFriend',
        'AppAccountFlag', 'Statues', 'AttrStatus',
        'Province', 'City', 'Alias', 'SnsFlag',
        'UniFriend', 'DisplayName', 'ChatRoomId',
        'KeyWord', 'EncryChatRoomId', 'IsOwner'
    ]

    # 保存用户属性用的空列表
    friend_list: List[Dict] = list()

    # 读取用户属性
    print('读取用户属性...')
    for one_friend in friends:
        one: Dict[str, str] = dict()
        for one_attr in attribute_list:
            one[one_attr] = one_friend[one_attr]
        friend_list.append(one)

    # 可选：把读到的属性存盘
    with open('friends_data.json', 'w') as file:
        json.dump(friend_list, file, ensure_ascii=False)

    # 保存关键词的空列表
    all_tag_list: List[str] = list()

    # 从用户属性列表里，读取所有的用户签名
    print('读取所有的用户签名...')
    signature_list: Iterator = (one['Signature'] for one in friend_list)
    signature_list = filter(lambda x: len(str(x).strip()) > 0,
                            signature_list)  # 过滤掉空的签名

    # 定义忽略的词
    ignore_word_list: Tuple = (
        '<', 'span', 'class', '=', '\"', '\'', 'emoji', '>', '<', '/', 'gt',
        'lt'
    )

    # 从签名当中抽取关键词
    print('从签名当中抽取关键词...')
    for sig in signature_list:
        tag_list: Iterator = extract_tags(sig)  # 抽取关键词

        # 过滤不需要的词
        tag_list = filter(lambda x: len(str(x).strip()) > 0, tag_list)  # 过滤空词
        tag_list = filter(  # 过滤汉字、英文字母、数字之外的字符
            lambda x:
            all(uchar >= '\u4E00' and uchar <= '\u9FA5' for uchar in x)
            or
            all(uchar >= '\u0030' and uchar <= '\u0039' for uchar in x)
            or
            all(
                (uchar >= '\u0041' and uchar <= '\u005A') or (
                        uchar >= '\u0061' and uchar <= '\u007A')
                for uchar in x)
            ,
            tag_list
        )
        tag_list = filter(lambda x: x not in ignore_word_list,tag_list)  # 过滤忽略的单词

        # 把当前这条签名中过滤出来的关键词，添加到关键词列表当中
        all_tag_list += tag_list

    # 对关键词计数
    print('对关键词计数...')
    tag_counter: Counter = Counter(all_tag_list)

    # 生成词云数据
    words = [(key, tag_counter[key]) for key in tag_counter]

    # 创建词云
    print('创建词云...')
    title = f'{friend_list[0]["NickName"]}的朋友们的微信签名词云'

    tag_word_cloud: WordCloud = WordCloud(
        init_opts=options.InitOpts(
            theme=ThemeType.ESSOS,
            width='800px',
            height='600px',
            page_title=title,

        ),
    )
    tag_word_cloud.set_global_opts(
        title_opts=options.TitleOpts(title=title),
        toolbox_opts=options.ToolboxOpts(
            is_show=True,
            orient='horizontal',
        ),
    )

    tag_word_cloud.add(
        '',
        words,
        word_size_range=[10, 40],
        shape=SymbolType.RECT
    )

    tag_word_cloud.render(path=f'{title}.html')

    print('done')


from collections import namedtuple
import altair as alt
import pandas as pd
import streamlit as st
import numpy as np
from collections import Counter

# Set Page Config - Main title, icon and setting the default layout to be wide
st.set_page_config(
    page_title="Randomised Trialer",
    page_icon="ðŸŽ²",
    layout="wide",
    initial_sidebar_state="expanded"
)
# Initial headings
st.title("Mr Matheson's Randomised Trialer")
st.subheader("Randomly generate probability simulations", divider="rainbow")

# Sidebar with Heading, includes slider for opts_n - how many options in each trial.
with st.sidebar:
  st.header("Set up the Simulation")
  opts_n = st.slider("Number of Options", min_value=2, max_value=20, value=4)
  variable_prob = st.toggle('Use Variable Probabilities')

  opts_name = []
  opts_val = []

  total = 0

  # Loops to allow for variable number of options. Adds the different text inputs to the sidebar dynamically
  for i in range(1, opts_n + 1):
    name = st.text_input(f"Option{i} Name:", value=f"Option{i}")
    opts_name.append(name)
    if variable_prob:
      n = st.slider(f"How many for {name}?", key=f"option{i}", min_value=1, max_value=20, value=1)
      opts_val.append(n)
      total += n
    else:
      opts_val.append(1)
      total += 1

# Sets the probability depending on the overall total of items, divided by the value of each option
prob = [x / total for x in opts_val]

# Sets up the pie graph.
pie_source = pd.DataFrame({"category": opts_name, "value": prob})

# Pie graph spinner using Altair.
pie = alt.Chart(pie_source).mark_arc().encode(
    theta="value",
    color="category"
)

# 2 column layout. Pie graph in the left, Control for the number of simulations in the right
col1, col2 = st.columns(2)
with col1:
  st.subheader("Theoretical Probability")
  st.altair_chart(pie, use_container_width=True, theme=None)

with col2:
  # n = st.slider("Number of Simulations (n):", min_value=1, max_value=10000, value=50)
  n = st.number_input("Number of Simulations (1 - 10,000)", min_value=1, max_value=10000, value= 50)

# This is using numpy to run the simulations n times, using the probabilities
sampleNumbers = np.random.choice(opts_name, n, p=prob)

sl = list(sampleNumbers)
counts = []
# To keep the original order, counts are calculated one at a time
for name in opts_name:
  counts.append(sl.count(name))

sampleVals = pd.DataFrame( {
  "Selection": opts_name,
  "Frequency": counts,
  "Theoretical Probability": prob
})
# Expected value is kind of useful, so this calculates it.
sampleVals['Expected Value'] = sampleVals['Theoretical Probability'] * n

st.subheader("Simulation Results")
col3, col4 = st.columns(2)
with col3:
  # Trying out a bar chart with tick marks from altair
  bar = alt.Chart(sampleVals).mark_bar().encode(
    x='Selection',
    y='Frequency'
  )

  #Altair's bar chart with ticks is basically two charts put on the same axis
  tick = alt.Chart(sampleVals).mark_tick(
      color='red',
      thickness=2,
      size=40 * 0.9,  # controls width of tick.
  ).encode(
      x='Selection',
      y='Expected Value'
  )
  c = bar + tick
  st.altair_chart(c, use_container_width=True, theme=None)

with col4:
  # Table with all the good stuff in it. The work is already done - just make it show
  st.subheader("Results Table")
  st.dataframe(sampleVals)
  st.subheader("Full set of results (in order)")
  st.write(sampleNumbers)


import datetime
import os
import pathlib
import stat
import time
import typing as tp

from pyvcs.index import GitIndexEntry, read_index  # type: ignore
from pyvcs.objects import hash_object  # type: ignore
from pyvcs.refs import get_ref, is_detached, resolve_head, update_ref  # type: ignore

def write_tree(gitdir: pathlib.Path, index: tp.List[GitIndexEntry], dirname: str = "") -> str:
    tree_inputs = []
    for entry in index:
        _, title = os.path.split(entry.name)
        if dirname:
            titles = dirname.split("/")
        else:
            titles = entry.name.split("/")
        if len(titles) != 1:
            prefix = titles[0]
            title = f"/".join(titles[1:])
            mode = "40000"
            tree_input = f"{mode} {prefix}\0".encode()
            tree_input += bytes.fromhex(write_tree(gitdir, index, title))
            tree_inputs.append(tree_input)
        else:
            if dirname and entry.name.find(dirname) == -1:
                continue
            with open(entry.name, "rb") as file:
                info = file.read()
            mode = str(oct(entry.mode))[2:]
            tree_input = f"{mode} {title}\0".encode()
            tree_input += bytes.fromhex(hash_object(info, "blob", write=True))
            tree_inputs.append(tree_input)

    tree_binary = b"".join(tree_inputs)
    return hash_object(tree_binary, "tree", write=True)

def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    if not author:
        author = (
            os.getenv("GIT_AUTHOR_NAME") + " " + f"<{os.getenv('GIT_AUTHOR_EMAIL')}>"  # type: ignore
        )
    if time.timezone > 0:
        timezone = "-"
    else:
        timezone = "+"
    timezone += f"{abs(time.timezone) // 60 // 60:02}{abs(time.timezone) // 60 % 60:02}"
    info = [f"tree {tree}"]
    if parent is not None:
        info.append(f"parent{parent}")
    info.append(f"author {author} {int(time.mktime(time.localtime()))} {timezone}")
    info.append(f"committer {author} {int(time.mktime(time.localtime()))} {timezone}")
    info.append(f"\n{message}\n")
    return hash_object("\n".join(info).encode(), "commit", write=True)