from casatools import logsink
setisimlog=logsink('setisim.log')
setisimlog.setlogfile='setisim.log'
setisimlog.setglobal(True)

from collections import defaultdict
from casatasks import tclean, split, listobs, plotants, imstat, clearcal, visstat, flagdata, flagmanager
from casatasks import uvcontsub, flagdata, gencal, plotweather, setjy, gaincal, bandpass, applycal, fluxscale, importgmrt
from casaviewer import imview
from casaplotms import plotms
from pathlib import Path
from astropy.wcs import WCS
from astropy.time import Time, TimeDelta
import matplotlib.pyplot as plt
import numpy as np
import io
import base64
from os import curdir, path, makedirs, remove, getcwd
import glob
from shutil import rmtree
from matplotlib import rcParams, rc
import os
from casatools import ms, msmetadata, table
from pyvirtualdisplay import Display

# casalog.filter('DEBUG1')
msmd = msmetadata()

from casatools import image as IA
from astropy.wcs import WCS
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar

def __clear_tmp(wd,cimagename):
    filelist = glob.glob(path.join(wd, cimagename+'*'))
    for f in filelist:
        try:
            rmtree(f)
        except OSError:
            remove(f)
def save_fig(plt, fig, kind='base64', output='output.jpg'):
    if kind == 'base64':
        buf = io.BytesIO()
        fig.savefig(buf, format='png', bbox_inches='tight',
                    transparent=True, pad_inches=0)
        buf.seek(0)
        string = base64.b64encode(buf.read())
        plt.close()
        return string
    elif kind == 'plot':
        plt.show()
        return 'plotted'
    else :
        if not path.exists('output'):
            makedirs('output')
        newPath = 'output/'+output
        opt = newPath
        if path.exists(newPath):
            numb = 1
            while path.exists(newPath):
                newPath = "{0}_{2}{1}".format(
                    *path.splitext(opt) + (numb,))
                try :
                    if path.exists(newPath):
                        numb += 1
                except:
                    pass
        fig.savefig(newPath, format=kind, bbox_inches='tight',
                    pad_inches=0)
        print("saved {}".format(newPath))
        plt.close()
        return newPath

def fetch_sources(vis):
    """
    fetch calibrator and target sources from the measurement set and return dictionary
    """
    pmcalf = '0'
    pmcals = '1'

    bpcalf = '0'
    bpcals = '3'

    fdcalf = '0'
    fdcals = '1'

    targets = '2'
    targetf = '1'

    return {'pmcalf':pmcalf, 'pmcals':pmcals,
            'bpcalf':bpcalf, 'bpcals':bpcals,
           'fdcalf':fdcalf, 'fdcals':fdcals,
           'targetf':targetf, 'targets':targets
           }

def genpng(cimg, chno=0, out='output.jpg', norm_max=None, **kwargs):
    ia = IA()
    ia.open(cimg)
    pix = ia.getchunk()[:,:,0,chno]
    csys = ia.coordsys()
    ia.close()

    rad_to_deg =  180/np.pi
    w = WCS(naxis=2)
    w.wcs.crpix = csys.referencepixel()['numeric'][0:2]
    w.wcs.cdelt = csys.increment()['numeric'][0:2]*rad_to_deg
    w.wcs.crval = csys.referencevalue()['numeric'][0:2]*rad_to_deg
    w.wcs.ctype = ['RA---SIN', 'DEC--SIN']
    fig = plt.figure(figsize=(20, 10))
    ax = plt.subplot(1, 1, 1, projection=w)
#     p1 = int(pix.shape[0]*0.25)
#     p2 = int(pix.shape[0]*0.75)

#     im = ax.imshow(pix[p1:p2,p1:p2].transpose(), origin='lower',  cmap=plt.cm.viridis)
    if norm_max:
        try:
            norm_max=float(norm_max)
            im = ax.imshow(pix.transpose(), origin='lower',
                           cmap=plt.cm.gist_heat, interpolation="lanczos",
                           norm=colors.CenteredNorm(norm_max/2.0)
            )
        except:
            im = ax.imshow(pix.transpose(), origin='lower',
                           cmap=plt.cm.gist_heat, interpolation="none",
                           norm=colors.CenteredNorm(0.0))

    else:
        im = ax.imshow(pix.transpose(), origin='lower',
                       cmap=plt.cm.gist_heat, interpolation="none",
                    #    norm=colors.CenteredNorm(0.0)
                       )

    plt.colorbar(im, ax=ax)
    ax.set_xlabel('Right Ascension')
    ax.set_ylabel('Declination')
    ax.set_title(str(out))
#     ax.add_size_bar(1/3600./f_hst[0].header["cdelt2"],
#                      r"$1^{\prime\prime}$", loc=3,
#                      borderpad=0.2)
    scalebar = AnchoredSizeBar(ax.transData,
                           5, r"$5^{\prime\prime}$", 'lower right',
                           pad=0.1,
                           color='white',
                           frameon=False,
                           size_vertical=1, borderpad=0.5, sep=5,
#                            fontproperties=fontprops
                   )
    ax.add_artist(scalebar)
    kind = kwargs['kind'] or 'jpg'
    save_fig(plt, fig, kind, output=out+f'{chno}.jpg')

def bandpass_fc(csource, suffix='_init',ref_ant='C00', plotfolder='bp_plots/',fspw = '0:101~1900',
                outvis='', **kwargs):
    cwd = getcwd()

    params={'reset':False,
            'quackinterval':10.0,
            'quackmode':'beg', 'bad_antenna':'','onvis':None,
                   }
#     params = defaultdict(lambda: -1, def_params)
    params.update(kwargs)
    if params['reset']:
        flagdata(vis=csource,mode='unflag', field='', spw='', antenna='', timerange='')
        clearcal(vis=csource)

    #### initialize ###########################
    s=fetch_sources(csource)
    csource_stem = Path(csource).stem

    ########## bandpass flagging ##############
    flagdata(vis=csource, mode='clip', clipzeros=True, flagbackup=False, action='apply') # clip zero amplitude
    flagdata(vis=csource, mode='shadow', tolerance=0.0, flagbackup=False, action='apply') # shadowing

    print(f' tfcrop on scan : {s["bpcals"]}')
    flagdata(vis=csource, mode='tfcrop', spw='0', scan=s["bpcals"], datacolumn='data', action='apply',
             flagbackup=True)
    print(f' tfcrop on scan : {s["pmcals"]}')
    flagdata(vis=csource, mode='tfcrop', spw='0', scan=s["pmcals"], datacolumn='data', action='apply',
             flagbackup=True)
    if params['bad_antenna']:
        flagdata(vis=csource, antenna=params['bad_antenna'],action='apply')

    ###### initial bandpass ##########
    csource_flagged = outvis or csource_stem+f'_scan{s["bpcals"]}_flagged.MS'
    bptab={}
    bptab['Ph_init'], bptab['BP_init']='bp_ph.initPh', 'bp_BP.initBP'

    os.system(f'rm -rf {bptab["Ph_init"]} {bptab["BP_init"]}')
    gaincal(vis=csource, caltable=bptab['Ph_init'],
            selectdata=True, scan=s['bpcals'],
            solint=' int ', spw=fspw, refant=ref_ant, minblperant=3,
            minsnr=3.0, calmode='p')
    bandpass(vis=csource, caltable=bptab['BP_init'],
            field=s['bpcalf'],
            solint=' inf ', combine='scan', refant=ref_ant,
            minblperant=3, minsnr=10.0, gaintable=bptab['Ph_init'],
    #          selectdata=True, scan=bpcals,
            interp='nearest', solnorm=False)

    if params['onvis']:
        applycal(vis=params['onvis'], field='', calwt=False, gaintable=bptab['BP_init'])
        print(f'splitting ms....{csource_flagged}')
        split(params['onvis'],csource_flagged)
    else:
        applycal(vis=csource, gaintable=bptab['BP_init'], calwt=False, scan=s['bpcals'])
        applycal(vis=csource, gaintable=bptab['BP_init'], calwt=False, scan=s['pmcals'])
        applycal(vis=csource, gaintable=bptab['BP_init'], calwt=False, scan=s['targets'])

        print(f'splitting ms....{csource_flagged}')
        split(csource,csource_flagged)

def rflag_pp(csource, scan, datacolumn='corrected'):
    csource_stem = Path(csource).stem
    outvis = csource_stem + 'rf.MS'
    flagdata(vis=csource, mode='rflag', spw='0', datacolumn=datacolumn, scan=scan,
            freqdevscale=2.5, timedevscale=3.5, extendflags=True, action='apply',
    #          display='both',
            timeavg=True , flagbackup=True
            )
    flagdata(csource, mode='extend', growfreq=80.0, growtime=60.0, action='apply', extendpols=True)
    try :
        print('...splitting corrected column')
        split(vis=csource, outputvis=outvis, datacolumn='corrected', keepflags=False)
    except:
        print('...splitting data column')
        split(vis=csource, outputvis=outvis, datacolumn='data', keepflags=False)

def dical0(csource, suffix='_init', ref_ant='C00', gspw='0:201~1800', field='0',):
    #### initialize ###########################
    s=fetch_sources(csource)
    csource_stem = Path(csource).stem

    gtab={}
    gtab['delay']=csource_stem+'.K'+suffix
    gtab['bph']=csource_stem+'.P.G'+suffix
    gtab['bp']=csource_stem+'.B'+suffix
    gtab['intph']=csource_stem+'.IP.G'+suffix
    gtab['scnph']=csource_stem+'.SP.G'+suffix
    gtab['amp']=csource_stem+'.A.G'+suffix

    os.system(f'rm -rf {gtab["delay"]}')
    gaincal(vis=csource, caltable=gtab['delay'],
            field=field,
            selectdata=True, scan=s['pmcals'],
            solint='inf', refant=ref_ant, gaintype='K')

    os.system(f'rm -rf {gtab["bph"]}')
    gaincal(vis=csource, caltable=gtab['bph'],
            field=field,
            spw=gspw, refant=ref_ant,
            calmode='p', solint='int',
            minsnr=3.0, gaintype='G',
            gaintable=[gtab['delay']])

    os.system(f'rm -rf {gtab["bp"]}')
    bandpass(vis=csource,
             caltable=gtab["bp"],
             spw ='0',
             field=field,
             solint='inf',
             refant=ref_ant,
             solnorm = True,bandtype='B', gaintable=[gtab['bph'], gtab['delay']],
        minsnr=3.0, fillgaps=8, parang = True,
             interp=['nearest,nearestflag','nearest,nearestflag'])

    # to fix Amp vs time
    os.system(f'rm -rf {gtab["intph"]}')
    gaincal(vis=csource,
            caltable=gtab["intph"],
            field=field,
            spw='0',
            refant=ref_ant,
            calmode='p',
            solint='int',
            minsnr=3.0,
            gaintable=[gtab['bph'], gtab['delay']]
           )

    # no enough for interpolating the phase solutions in time
    os.system(f'rm -rf {gtab["scnph"]}')
    gaincal(vis=csource,
            caltable=gtab['scnph'],
            field=field,
            spw='0',
            refant=ref_ant,
            calmode='p',
            solint='inf',
            combine='',
            minsnr=3.0,
            gaintable=[gtab['bph'], gtab['delay']]
           )

    # scaling amplitude gains skipping fluxscale as our flux-calibrator is also our
    # bandpass and gain calibrator, the absolute flux scale will already be ok
    os.system(f'rm -rf {gtab["amp"]}')
    gaincal(vis=csource,
            caltable=gtab['amp'],
            field=field,
            spw='0', selectdata=True, scan=s['pmcals'],
            solint='inf', combine='', refant=ref_ant,
            calmode='ap', minsnr=3.0,
            gaintable=[gtab['bph'], gtab['delay'], gtab['intph']])
    applycal(
        vis=csource,
        field=s['bpcalf'],
        gaintable=[gtab['delay'],gtab['bp'],gtab['scnph'],gtab['amp']],
        gainfield=[s['bpcalf'],s['bpcalf'],s['bpcalf'],s['bpcalf']],
        parang=True, calwt=False, applymode='calflagstrict', flagbackup=True)

    applycal(
        vis=csource,
        field=s['targetf'],
        gaintable=[gtab['delay'],gtab['bp'],gtab['scnph'],gtab['amp']],
        gainfield=[s['bpcalf'],s['bpcalf'],s['bpcalf'],s['bpcalf']],
        calwt=False, applymode='calflagstrict', flagbackup=True)
    return {'tables':gtab}

def dical(csource, suffix='_di', ref_ant='C00', gspw='0:201~1800', **kwargs):
    #### initialize ###########################
    params={'ph':False, 'bp' : False, 'ampvtime':False,
    'solint':'inf','field':'0', }
    params.update(kwargs)
    csource_stem=Path(csource).stem
    s=fetch_sources(csource)
    gtab={}
    gtab['delay']=csource_stem+'.K'+suffix
    gtab['bph']=csource_stem+'.P.G'+suffix
    gtab['bp']=csource_stem+'.B'+suffix
    gtab['intph']=csource_stem+'.IP.G'+suffix
    gtab['scnph']=csource_stem+'.SP.G'+suffix
    gtab['amp']=csource_stem+'.A.G'+suffix

    if params['ph']:
        os.system(f'rm -rf {gtab["intph"]}')
        gaincal(vis=csource,
            caltable=gtab['intph'],
            field=params['field'], spw='0', refant=ref_ant, calmode='p', solint=params['solint'],
            combine='',
            minsnr=3.0)
        applycal(vis=csource, field=params['field'], gaintable=[gtab['intph']], interp='linear')
        outvis=Path(csource).stem+suffix+'.MS'
        print(f'phase calibration of field:{params["field"]} on {csource_stem}')
        print(f'splitting: {outvis}, calibrated field="0"')
        os.system(f'rm -rf {outvis}')
        split(vis=csource, outputvis=outvis, datacolumn='corrected',
          field=params['field'], keepflags=False)

    if params['bp']:
        os.system(f'rm -rf {gtab["delay"]}')
        gaincal(vis=csource, caltable=gtab['delay'],
                field=params['field'],
                selectdata=True, scan=s['pmcals'],
                solint='inf', refant=ref_ant, gaintype='K')

        os.system(f'rm -rf {gtab["bph"]}')
        gaincal(vis=csource, caltable=gtab['bph'],
                field=params['field'],
                spw=gspw, refant=ref_ant,
                calmode='p', solint='int',
                minsnr=3.0, gaintype='G',
                gaintable=[gtab['delay']])

        os.system(f'rm -rf {gtab["bp"]}')
        bandpass(vis=csource,
                caltable=gtab["bp"],
                spw ='0',
                field=params['field'],
                solint='inf',
                refant=ref_ant,
                solnorm = True,bandtype='B', gaintable=[gtab['bph'], gtab['delay']],
            minsnr=3.0, fillgaps=8, parang = True,
                interp=['nearest,nearestflag','nearest,nearestflag'])
    if params['ampvtime']:
        # to fix Amp vs time
        os.system(f'rm -rf {gtab["intph"]}')
        gaincal(vis=csource,
                caltable=gtab["intph"],
                field=field,
                spw='0',
                refant=ref_ant,
                calmode='p',
                solint='int',
                minsnr=3.0,
                gaintable=[gtab['bph'], gtab['delay']]
            )

        # no enough for interpolating the phase solutions in time
        os.system(f'rm -rf {gtab["scnph"]}')
        gaincal(vis=csource,
                caltable=gtab['scnph'],
                field=field,
                spw='0',
                refant=ref_ant,
                calmode='p',
                solint='inf',
                combine='',
                minsnr=3.0,
                gaintable=[gtab['bph'], gtab['delay']]
            )

        # scaling amplitude gains skipping fluxscale as our flux-calibrator is also our
        # bandpass and gain calibrator, the absolute flux scale will already be ok
        os.system(f'rm -rf {gtab["amp"]}')
        gaincal(vis=csource,
                caltable=gtab['amp'],
                field=field,
                spw='0', selectdata=True, scan=s['pmcals'],
                solint='inf', combine='', refant=ref_ant,
                calmode='ap', minsnr=3.0,
                gaintable=[gtab['bph'], gtab['delay'], gtab['intph']])
        applycal(
            vis=csource,
            field=s['bpcalf'],
            gaintable=[gtab['delay'],gtab['bp'],gtab['scnph'],gtab['amp']],
            gainfield=[s['bpcalf'],s['bpcalf'],s['bpcalf'],s['bpcalf']],
            parang=True, calwt=False, applymode='calflagstrict', flagbackup=True)

        applycal(
            vis=csource,
            field=s['targetf'],
            gaintable=[gtab['delay'],gtab['bp'],gtab['scnph'],gtab['amp']],
            gainfield=[s['bpcalf'],s['bpcalf'],s['bpcalf'],s['bpcalf']],
            calwt=False, applymode='calflagstrict', flagbackup=True)
    return {'tables':gtab}

def init_flag(csource, **kwargs):

    params={'reset':False,
            'quackinterval':10.0,
            'quackmode':'beg', 'badant':'', 'badchan':'','clip':[0,50],'refant':'C00',
            'scan':'', 'extend':False
                   }
    params.update(kwargs)
    if params['reset']:
        flagdata(vis=csource,mode='unflag', field='', spw='', antenna='', timerange='')
        clearcal(vis=csource)

    s=fetch_sources(csource)
    csource_stem = Path(csource).stem

    flagdata(vis=csource, mode='clip', clipzeros=True, scan=params['scan'],clipminmax=params['clip'], flagbackup=False, action='apply') # clip zero amplitude
    flagdata(vis=csource, mode='shadow', tolerance=0.0, scan=params['scan'],flagbackup=False, action='apply') # shadowing
    if params['quackmode']:flagdata(vis=csource, mode='quack', scan=params['scan'],quackinterval=params['quackinterval'], quackmode=params['quackmode'],
             flagbackup=False, action='apply')
    if params['badant']: flagdata(vis=csource, antenna=str(params['badant']),action='apply')
#     flagdata(vis=csource, mode='tfcrop', flagbackup=True, action='apply', extendpols=True, extendflags=True)
    if params['extend']:flagdata(vis=csource, mode='extend', growfreq=80.0, growtime=60.0, action='apply', extendpols=True, extendflags=True)

def flagsummary(vis):
    fsummary = flagdata(vis, mode='summary')
    sof=fsummary.keys()
    fgen=['name','type', 'total', 'flagged']
    totflag=np.round((fsummary['flagged']/fsummary['total'])*100,2)
    print(f"{fsummary['name']}\n-----\nTotal flagged:{totflag}%")
    flaggable={}
    for s in sof:

        if s in fgen:
            pass
        else:
            print(f'\n{s}:\n')
            for k in fsummary[s]:
                v=fsummary[s][k]
                perc = np.round((fsummary[s][k]['flagged']/fsummary[s][k]['total'])*100,2)

                if perc>totflag and s=='antenna':
                    flaggable[k]=perc

                print(f"{k}:{perc}%")
    antmax = max(flaggable, key=flaggable.get)
    ant3sigma=np.round(float(totflag)+((float(flaggable[str(antmax)])-float(totflag))/3),2)
    print(f'antenna 3 sigma : {ant3sigma}')
    for ant,perc in flaggable.items():
        if perc>ant3sigma:
            print(f'flaggable antenna:{ant}')
    # print(f'flaggable antenna:{antmax}\n {flaggable}')
    return {'flaggable':flaggable}

def selfcal_model(calibrated_target, goodchans='0:500~600', ref_ant='C00'):
    ctarget_stem = str(Path(calibrated_target).stem)

    sctarget={}
    sctarget['sc1']=ctarget_stem+'.model1.MS'
    sctarget['sc2']=ctarget_stem+'.model2.MS'
    sctarget['sc3']=ctarget_stem+'.model3.MS'

    sgtab={}
    sgtab['sc1']='sc1.gcal'
    sgtab['sc2']='sc2.gcal'
    sgtab['sc3']='sc3.gcal'
    os.system(f"rm -rf {sctarget['sc1']}* {sctarget['sc2']}* {sctarget['sc3']}* {sgtab['sc1']}* {sgtab['sc2']}* {sgtab['sc3']}* {ctarget_stem}.model.cimage")

    tclean(vis=calibrated_target,
           datacolumn='data',
           imagename=ctarget_stem+'.model.cimage',
           spw=goodchans,
           specmode='mfs',
           niter=100,
           threshold='1.5Jy',
           imsize=[256,256], cell='1arcsec',
           weighting='briggs', robust=0.2,
           savemodel='modelcolumn')
    gaincal(vis=calibrated_target,
            caltable=sgtab['sc1'],
            field='0', spw='0', refant=ref_ant, calmode='p', solint='30s', combine='',
            minsnr=3.0)
    applycal(vis=calibrated_target, field='0', gaintable=[sgtab['sc1']], interp='linear')
    split(vis=calibrated_target, outputvis=sctarget['sc1'], datacolumn='corrected',
          field='0', keepflags=False)

    tclean(vis=sctarget['sc1'], datacolumn='data',
           imagename=sctarget['sc1']+'.cimage',
           spw=goodchans,
           specmode='mfs',
           niter=500,
           threshold='500mJy',
           imsize=[256,256],cell='1arcsec',
           weighting='briggs', robust=0.2,
           savemodel='modelcolumn')
    gaincal(vis=sctarget['sc1'], caltable=sgtab['sc2'],
            field='0', spw='0', refant=ref_ant, calmode='p', solint='10s', combine='',
            minsnr=3.0)
    applycal(vis=sctarget['sc1'], field='0', gaintable=[sgtab['sc2']], interp='linear')
    split(vis=sctarget['sc1'], outputvis=sctarget['sc2'], datacolumn='corrected',
          field='0', keepflags=False)

    tclean(vis=sctarget['sc2'], datacolumn='data',
           imagename=sctarget['sc2']+'.cimage', spw=goodchans,
           specmode='mfs',
           niter=1000, threshold='100mJy',
           imsize=[256,256], cell='1arcsec', weighting='briggs', robust=0.2,
           savemodel='modelcolumn')
    gaincal(vis=sctarget['sc2'], caltable=sgtab['sc3'],
            field='0', spw='0', refant=ref_ant, calmode='ap', solint='int', combine='',
            minsnr=3.0)
    applycal(vis=sctarget['sc2'], field='0', gaintable=[sgtab['sc3']], interp='linear')

    os.system(f'rm -rf {sctarget["sc3"]}.*')
    split(vis=sctarget['sc2'], outputvis=sctarget['sc3'], datacolumn='corrected',
          field='0', keepflags=False)

    tclean(vis=sctarget['sc3'], datacolumn='data',
           imagename=sctarget['sc3']+'.cimage', spw=goodchans,
           specmode='mfs',
           niter=1000, threshold='100mJy',
           imsize=[256,256], cell='1arcsec', weighting='briggs', robust=0.2,
           savemodel='modelcolumn')
    return {'model_imagename':sctarget['sc3']+'.cimage', 'model_vis':sctarget['sc3']}

def tclean_spectral_image(vis, imagename, f=None, suffix='', norm_max=None):
    os.system(f'rm -rf {imagename}.*')
    if f:
        rest_freq = str(f)+'MHz'
        f=float(f)
    tclean(vis=vis, datacolumn='data',
           imagename=imagename, spw=f'0:596~597.5MHz',#{rest_freq}',
           specmode='cube', outframe='bary', veltype='radio', restfreq=rest_freq,
           niter=10000000, threshold='0.05Jy',
           imsize=[256,256], cell='1arcsec',
        #    pbcor=True,
           weighting='briggs', robust=0.0,
           perchanweightdensity=True, savemodel='none',
           interpolation='nearest')
    msmd.open(vis)
    nchan = msmd.nchan(0)
    chanwidths = float(msmd.chanwidths(0, 'MHz')[0])
    freqstart = float(msmd.chanfreqs(0, 'MHz')[0])
    msmd.done()
    n = (f - freqstart)/chanwidths
    if not n == float(int(n)):
        plotchans = [int(n), int(n+1)]
    else:
        plotchans = [int(n)]
    for i in range(len(plotchans)):
        genpng(imagename+'.image',i,out=f"{imagename}_{plotchans[i]}.bary.cube", norm_max=norm_max, kind='jpg')
    #   imview(raster={'file':f"{imagename}"+'.image', 'colormap': 'Hot Metal 1'},
#        zoom={'channel': 0, },
#        axes={'z':'Frequency',},
#         out=f"{imagename}"+suffix+'.bary.cube.1'+'.png',
#       )
#     imview(raster={'file':f"{imagename}"+'.image', 'colormap': 'Hot Metal 1'},
#            zoom={'channel': 1, },
#            axes={'z':'Frequency',},
#             out=f"{imagename}"+suffix+'.bary.cube.2'+'.png',
#           )

def tclean_continuum_image(science_vis_cont, imagename, suffix='', norm_max=None):
    os.system(f'rm -rf {imagename} {imagename}.*')
    tclean(vis=science_vis_cont, datacolumn='data',
       imagename=imagename, spw='0',
       specmode='mfs',
       niter=1000, threshold='50mJy',
       imsize=[256,256], cell='1arcsec', weighting='briggs', robust=0.2,
#        savemodel='modelcolumn'
      )
    if norm_max is None:
        norm_max=imstat(imagename+'.image')['max'][0]
    genpng(imagename+'.image',0,out=f"{imagename}"+suffix, norm_max=norm_max, kind='jpg')
    return norm_max
#     imview(raster={'file':f"{imagename}"+'.image', 'colormap': 'Hot Metal 1'},
#             out=f"{imagename}"+suffix+'.cont'+'.png',

#           )

def fast_spectral_image(calvis, cvis, timerange='',f=None, suffix=''):
    os.system(f'rm -rf {cvis}*')
    rest_freq=None
    if f:
        rest_freq = str(f)+'MHz'
    # msmd.open(calvis)
    # msmd.chanwidths()
    fitspw=f'0:{rest_freq}'
    print(f"split({calvis}, {cvis}, timerange={timerange}, datacolumn='data')")
    split(calvis, cvis, timerange=timerange, datacolumn='data', )#spw='0:590~610MHz')
    if rest_freq is not None:
        uvcontsub(cvis, field='0',
            # fitspw=fitspw, #'0:0.566~0.575GHz',
            fitspw='0:596~597.5MHz',
            excludechans=True,
            fitorder=1,
            want_cont=False,
            )
        science_vis=cvis+'.contsub'
        # science_vis_cont=cvis+'.cont'
        # norm_max=tclean_continuum_image(science_vis_cont, science_vis_cont+'.cimage', suffix=suffix+'.cont')
        tclean_spectral_image(science_vis, science_vis+'.cimage',f=f, suffix=suffix+'.cube')
    else:
        tclean_continuum_image(cvis, cvis+'.cimage', suffix=suffix)

def plotd(visfile, **kwargs):
    display = Display(visible=0,size=(1024,768))
    display.start()

    plotfolder=f'plots/{Path(visfile).stem}/'
    if not path.exists(plotfolder):
        try:
            oumask = os.umask(0)
            makedirs(plotfolder)
        except:
            os.umask(oumask)
            makedirs(plotfolder, 775)
    print(f'plotting in folder: {plotfolder}')
    vis = visfile
    metadata=listobs(vis, verbose=True)
    msmd.open(vis)
    nchan = msmd.nchan(0)
    msmd.done()

    fieldl = {k.replace('field_', ''):{'name':v['name']} for k,v in metadata.items() if 'field_' in k}
    scanl = {k.replace('scan_', ''):v['0']['FieldName'] for k,v in metadata.items() if 'scan_' in k}
    for fk,fv in fieldl.items():
        fieldl[str(fk)]['scans']=[k.replace('scan_', '') for k,v in metadata.items() if ('scan_' in k) and (v['0']['FieldId']==int(fk))]
    metadata.update({'fieldl':fieldl, 'scanl':scanl})
    params={'spw':'',#f'0:{int(nchan*0.4)}~{int(nchan*0.6)}',
    'avgchannel' :str(nchan),
    'uvrange':'',
    'antenna':'C00', 'scan':'', 'corr':'',
    'xaxis':[''], 'yaxis':['']}
    params.update(kwargs)
    spw, avgchannel, uvrange, antenna = params['spw'], params['avgchannel'], params['uvrange'], params['antenna']
    print(f"{spw}, {avgchannel}, {uvrange}, {antenna}")
    # selectedfield=metadata['fieldl']['4']
    scanlist = params['scan'] or scanl.keys()
    comb={'amp':{'freq':{'averagedata':True,'avgtime':'1e9', 'avgbaseline':False, 'avgchannel':''},
             'time':{'averagedata':False,'avgtime':'', 'avgbaseline':False, 'avgchannel':''},
             'uvwave':{'averagedata':False,'avgtime':'', 'avgbaseline':False, 'avgchannel':''}
            },
      'phase':{'freq':{'averagedata':True,'avgtime':'1e9', 'avgbaseline':False, 'avgchannel':''},
               'time':{'averagedata':True,'avgtime':'', 'avgbaseline':True, 'avgchannel':nchan},
               'uvwave':{'averagedata':False,'avgtime':'', 'avgbaseline':False, 'avgchannel':nchan},
               'amp':{'averagedata':True,'avgtime':'1e9', 'avgbaseline':False, 'avgchannel':''}
              },
     }
    _pd={}
    for k,v in comb.items():
        for yi in params['yaxis']:
            if yi:
                if yi==k:
                    for xi in params['xaxis']:
                        for vi in v:
                            if xi and (xi==vi):
                                try:
                                    _pd[k][vi]=comb[k][vi]
                                except:
                                    _pd[k]={vi:comb[k][vi]}
                                break
                            else:
                                try:
                                    _pd[k][vi]=comb[k][vi]
                                except:
                                    _pd[k]={vi:comb[k][vi]}

            else:
                for xi in params['xaxis']:
                    for vi in v:
                        if xi:
                            if xi==vi:
                                try:
                                    _pd[k][vi]=comb[k][vi]
                                except:
                                    _pd[k]={vi:comb[k][vi]}
                                break
                        else:
                            try:
                                _pd[k][vi]=comb[k][vi]
                            except:
                                _pd[k]={vi:comb[k][vi]}
    try:
        for scan in scanlist:
            scan=str(scan)
            print(scan)
            # print(_pd)
            for yaxis,xaxes in _pd.items():
                for xaxis,avgdata in xaxes.items():
                    print(f'{yaxis} vs {xaxis}')
                    plotms(vis=vis, scan=scan, antenna=antenna, spw=spw, correlation=params['corr'],
                        xaxis=xaxis, yaxis=yaxis, coloraxis='corr', title=f'{scanl[str(scan)]}:{yaxis} vs {xaxis} - {scan}',
                        showgui=False,
                        averagedata=avgdata['averagedata'], avgtime=avgdata['avgtime'], avgbaseline=avgdata['avgbaseline'],
                        avgchannel=str(avgdata['avgchannel']),
                        uvrange=uvrange,
                        plotfile=plotfolder+f"{yaxis}_v_{xaxis}.{scanl[str(scan)]}.{scan}.png", overwrite=True)

    finally:
        display.stop()


def findeven(a):
    # for i in range(0,21):
    mod = a % 2
    if mod==0:
        return a

filtered = filter(findeven, range(0,21))
print(filtered)

print('The filtered even numbers are:')
for s in filtered:
    print(s)


import random  # For generating random numbers
import sys
from turtle import isvisible  # We will use sys.exit to exit the program
import pygame
from pygame.locals import *
from scipy.fftpack import diff  # Basic pygame imports
from environment import environment
from agent import DQN, DQNagent
from agent_cn import DQN_cn, DQNagent_cn
import copy as cp
import torch
import numpy as np
import torchvision.transforms as T
from PIL import Image
import matplotlib.pyplot as plt
import collections
#CN trained bird worked good on manual input test environment!?!?!?
from agentPG_cp import PolicyNet

# Global Variables for the game
FPS = 32
scr_width = 289
scr_height = 511
display_screen_window = pygame.display.set_mode((scr_width, scr_height))
play_ground = scr_height * 0.8
game_image = {}
game_audio_sound = {}
player = 'images/bird.png'
bcg_image = 'images/background.png'
pipe_image = 'images/pipe.png'
resize = T.Compose([T.ToPILImage(),
            T.Resize(40, interpolation=Image.CUBIC),
            T.ToTensor()])

def welcome_main_screen():
    """
    Shows welcome images on the screen
    """

    p_x = int(scr_width / 5)
    p_y = int((scr_height - game_image['player'].get_height()) / 2)
    msgx = int((scr_width - game_image['message'].get_width()) / 2)
    msgy = int(scr_height * 0.13)
    b_x = 0
    while True:
        for event in pygame.event.get():
            # if user clicks on cross button, close the game
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()

            # If the user presses space or up key, start the game for them
            elif event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
                return
            else:
                display_screen_window.blit(game_image['background'], (0, 0))
                display_screen_window.blit(game_image['player'], (p_x, p_y))
                display_screen_window.blit(game_image['message'], (msgx, msgy))
                display_screen_window.blit(game_image['base'], (b_x, play_ground))
                pygame.display.update()
                time_clock.tick(FPS)

def main_gameplay(game):
    while True:
        flapper = False
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
                if game.p_y > 0:
                    flapper = True
                    game_audio_sound['wing'].play()

        p_middle_positions = game.p_x + game_image['player'].get_width() / 2
        for pipe in game.up_pips:
            pip_middle_positions = pipe['x'] + game_image['pipe'][0].get_width() / 2
            if pip_middle_positions <= p_middle_positions < pip_middle_positions + 4:
                game_audio_sound['point'].play()

        if game.isGameOver:
            game_audio_sound['hit'].play()
            game.restart()
            return

        if flapper:
            flapper = False
            game.update(True)
        else:
            game.update(False)

        display_screen_window.blit(game_image['background'], (0, 0))
        for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
            display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
            display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

        display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
        display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
        d = [int(x) for x in list(str(game.score))]
        w = 0
        for digit in d:
            w += game_image['numbers'][digit].get_width()
        Xoffset = (scr_width - w) / 2

        for digit in d:
            display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
            Xoffset += game_image['numbers'][digit].get_width()
        #imgdata = pygame.surfarray.array3d(display_screen_window) ######
        pygame.display.update()
        time_clock.tick(FPS)

def get_screen(imdata):
        screen = imdata.transpose((2, 0, 1))
        screen = np.ascontiguousarray(screen, dtype=np.float32) / 255
        screen = torch.from_numpy(screen)
        return resize(screen).unsqueeze(0)

def read_action(action):
        if action == 0:
            return False
        else:
            return True

def SelectAction(policyNet, currentState):
    actionProbabilityDis = policyNet(currentState) #takes a state and returns policy dis

    #selects random action based on policy
    selection = random.random()
    if selection < actionProbabilityDis.item():
        return True
    else:
        return False

def manual(game):
    if game.cur_state[1] > game.cur_state[2] - 75.0:
        return True
    else:
        return False

if __name__ == "__main__":

    isHumanPlayer = False
    testAgent = True
    manual_is = False
    testAgent_PG = False
    test_cn_agent = False

    pygame.init()
    time_clock = pygame.time.Clock()
    pygame.display.set_caption('Flappy Bird Game')
    game_image['numbers'] = (
        pygame.image.load('images/0.png').convert_alpha(),
        pygame.image.load('images/1.png').convert_alpha(),
        pygame.image.load('images/2.png').convert_alpha(),
        pygame.image.load('images/3.png').convert_alpha(),
        pygame.image.load('images/4.png').convert_alpha(),
        pygame.image.load('images/5.png').convert_alpha(),
        pygame.image.load('images/6.png').convert_alpha(),
        pygame.image.load('images/7.png').convert_alpha(),
        pygame.image.load('images/8.png').convert_alpha(),
        pygame.image.load('images/9.png').convert_alpha(),
    )

    game_image['message'] = pygame.image.load('images/message.png').convert_alpha()
    game_image['base'] = pygame.image.load('images/base.png').convert_alpha()
    game_image['pipe'] = (pygame.transform.rotate(pygame.image.load(pipe_image).convert_alpha(), 180),
                          pygame.image.load(pipe_image).convert_alpha()
                          )

    # Game sounds
    game_audio_sound['die'] = pygame.mixer.Sound('sounds/die.wav')
    game_audio_sound['hit'] = pygame.mixer.Sound('sounds/hit.wav')
    game_audio_sound['point'] = pygame.mixer.Sound('sounds/point.wav')
    game_audio_sound['swoosh'] = pygame.mixer.Sound('sounds/swoosh.wav')
    game_audio_sound['wing'] = pygame.mixer.Sound('sounds/wing.wav')

    game_image['background'] = pygame.image.load(bcg_image).convert()
    game_image['player'] = pygame.image.load(player).convert_alpha()

    pipe_width = game_image['pipe'][0].get_width()
    pipe_height = game_image['pipe'][0].get_height()
    player_width = game_image['player'].get_width()
    player_height = game_image['player'].get_height()
    base_height = game_image['base'].get_height()
    #print(scr_width)
    #print(scr_height)
    #print(pipe_width)
    #print(pipe_height)
    #print(player_width)
    #print(player_height)
    #print(base_height)
    game = environment(scr_width, scr_height,pipe_width,pipe_height,player_width,player_height,base_height,difficulty=4)
    #Diff 0,2,4

    n_test = 2000000
    score_ls = np.zeros(n_test)

    if isHumanPlayer:
        while True:
            welcome_main_screen()  # Shows welcome screen to the user until he presses a button
            main_gameplay(game)  # This is the main game function

    ########  DENSE #########

    elif testAgent:
        #FPS = 256
        FPS = 64
        for ep in range(n_test):
            old_score = 0
            agent = DQNagent(0,0)
            model = DQN(agent.n_input, agent.n_actions, agent.n_hidden)
            #model.load_state_dict(torch.load('C:/Users/jespe/Documents/GitHub/Flappy_git/Flappy_jesper/net1.pt'))
            model.load_state_dict(torch.load('C:/Users/Jesper/OneDrive/Dokument/GitHub/Flappy_git/Flappy_jesper/net_dense.pt'))
            model.eval()
            game.update(False)
            while True:
                for event in pygame.event.get():
                    if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                        pygame.quit()
                        sys.exit()
                state = torch.tensor(game.cur_state)
                if game.isGameOver:
                    score_ls[ep] = old_score
                    break
                action  = model(state).argmax().item()

                if read_action(action):
                    game_audio_sound['wing'].play()
                if game.score != old_score:
                    old_score = game.score
                    print(f"Your score is {old_score}")
                    game_audio_sound['point'].play()

                game.update(read_action(action))

                display_screen_window.blit(game_image['background'], (0, 0))
                for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
                    display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
                    display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

                display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
                display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
                d = [int(x) for x in list(str(game.score))]
                w = 0
                for digit in d:
                    w += game_image['numbers'][digit].get_width()
                Xoffset = (scr_width - w) / 2

                for digit in d:
                    display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
                    Xoffset += game_image['numbers'][digit].get_width()

                pygame.display.update()
                time_clock.tick(FPS)

    ########  MANUAL #########

    elif manual_is:
        FPS = 256
        for ep in range(n_test):
            old_score = 0

            game.update(False)
            while True:
                for event in pygame.event.get():
                    if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                        pygame.quit()
                        sys.exit()
                state = torch.tensor(game.cur_state)
                if game.isGameOver:
                    score_ls[ep] = old_score
                    break

                if manual(game):
                    game_audio_sound['wing'].play()
                if game.score != old_score:
                    old_score = game.score
                    print(f"Your score is {old_score}")
                    game_audio_sound['point'].play()

                game.update(manual(game))

                display_screen_window.blit(game_image['background'], (0, 0))
                for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
                    display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
                    display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

                display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
                display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
                d = [int(x) for x in list(str(game.score))]
                w = 0
                for digit in d:
                    w += game_image['numbers'][digit].get_width()
                Xoffset = (scr_width - w) / 2

                for digit in d:
                    display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
                    Xoffset += game_image['numbers'][digit].get_width()

                pygame.display.update()
                time_clock.tick(FPS)

    ########## POLICY ##############

    elif testAgent_PG:
        FPS = 256
        for ep in range(n_test):
            old_score = 0
            model = PolicyNet()
            #model.load_state_dict(torch.load('C:/Users/jespe/Documents/GitHub/Flappy_git/Flappy_jesper/net1.pt'))
            model.load_state_dict(torch.load('C:/Users/Jesper/OneDrive/Dokument/GitHub/Flappy_git/Flappy_jesper/pissnisse.pt'))
            model.eval()
            game.update(False)
            while True:
                for event in pygame.event.get():
                    if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                        pygame.quit()
                        sys.exit()
                state = torch.tensor(game.cur_state)
                if game.isGameOver:
                    score_ls[ep] = old_score
                    break
                #action  = model(state).argmax().item()

                if SelectAction(model, state):
                    game_audio_sound['wing'].play()
                if game.score != old_score:
                    old_score = game.score
                    print(f"Your score is {old_score}")
                    game_audio_sound['point'].play()

                game.update(SelectAction(model, state))

                display_screen_window.blit(game_image['background'], (0, 0))
                for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
                    display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
                    display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

                display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
                display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
                d = [int(x) for x in list(str(game.score))]
                w = 0
                for digit in d:
                    w += game_image['numbers'][digit].get_width()
                Xoffset = (scr_width - w) / 2

                for digit in d:
                    display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
                    Xoffset += game_image['numbers'][digit].get_width()

                pygame.display.update()
                time_clock.tick(FPS)

    ############ CONVOLUTION #############

    elif test_cn_agent:
        FPS = 128
        for ep in range(n_test):
            old_score = 0
            agent = DQNagent_cn(0,0)
            model = DQN_cn(agent.scr_height, agent.scr_width, agent.n_actions)
            #model.load_state_dict(torch.load('C:/Users/jespe/Documents/GitHub/Flappy_git/Flappy_jesper/net1.pt'))
            model.load_state_dict(torch.load('C:/Users/Jesper/OneDrive/Dokument/GitHub/Flappy_git/Flappy_jesper/net_cnn10.pt'))
            model.eval()
            game.update(False)

            display_screen_window.blit(game_image['background'], (0, 0))
            for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
                display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
                display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

            display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
            display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
            d = [int(x) for x in list(str(game.score))]
            w = 0
            for digit in d:
                w += game_image['numbers'][digit].get_width()
            Xoffset = (scr_width - w) / 2

            for digit in d:
                display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
                Xoffset += game_image['numbers'][digit].get_width()
            imgdata = pygame.surfarray.array3d(display_screen_window)

            last_screen = get_screen(imgdata)
            current_screen = get_screen(imgdata)

            state = current_screen - last_screen
            while True:
                for event in pygame.event.get():
                    if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                        pygame.quit()
                        sys.exit()
                #state = torch.tensor(game.cur_state)
                if game.isGameOver:
                    score_ls[ep] = old_score
                    game_audio_sound['hit'].play()
                    break
                action  = model(state).argmax().item()

                if read_action(action):
                    game_audio_sound['wing'].play()
                if game.score != old_score:
                    old_score = game.score
                    print(f"Your score is {old_score}")
                    game_audio_sound['point'].play()

                game.update(read_action(action))

                display_screen_window.blit(game_image['background'], (0, 0))
                for pip_upper, pip_lower in zip(game.up_pips, game.low_pips):
                    display_screen_window.blit(game_image['pipe'][0], (pip_upper['x'], pip_upper['y']))
                    display_screen_window.blit(game_image['pipe'][1], (pip_lower['x'], pip_lower['y']))

                display_screen_window.blit(game_image['base'], (game.b_x, play_ground))
                display_screen_window.blit(game_image['player'], (game.p_x, game.p_y))
                d = [int(x) for x in list(str(game.score))]
                w = 0
                for digit in d:
                    w += game_image['numbers'][digit].get_width()
                Xoffset = (scr_width - w) / 2

                for digit in d:
                    display_screen_window.blit(game_image['numbers'][digit], (Xoffset, scr_height * 0.12))
                    Xoffset += game_image['numbers'][digit].get_width()
                imgdata = pygame.surfarray.array3d(display_screen_window)
                last_screen = cp.deepcopy(current_screen)
                current_screen = get_screen(imgdata)
                pygame.display.update()
                time_clock.tick(FPS)

    score_ls = score_ls.astype(int)
    meany = np.mean(score_ls)
    print(f'Best score obtained durring testing: {max(score_ls)}')
    print(f'Mean of scores: {meany}')
    print(f'Standard deviation of scores: {np.std(score_ls)}')
    plt.figure()
    plt.plot(score_ls,label='Score')
    plt.plot([0, len(score_ls)-1],[meany,meany],label='Mean Score')
    plt.xlabel('Episode Number')
    plt.ylabel('Score')
    plt.legend()

    plt.figure()
    #plt.hist(score_ls, bins=max(score_ls))
    d = collections.Counter(score_ls)
    plt.bar(d.keys(), d.values())

    plt.xlabel('Score')
    plt.ylabel('Frequency')

    plt.show()


import random

def choose_options():
    opciones= ("piedra","papel","tijera")
    user_option= input("Escribe piedra, papel o tijera ==>  " ).lower()

    if not user_option in opciones:
        print(" Ingrese una opción valida")
        return None, None
    computer_option = random.choice (opciones)
    print("-"*30)
    print ("Has elegido ", user_option)
    print ("La computadora ha elegido " + computer_option)
    return user_option, computer_option

def check_rules(user_option, computer_option, user_wins , computer_wins):
    if user_option==computer_option:
        print ("Has empatado con la computadora")

    elif user_option== "piedra":
        if computer_option=="tijera":
            print ("Felicidades, has ganado")
            user_wins += 1
        elif computer_option == "papel":
            print ("Lo siento. Has perdido esta ronda")
            computer_wins += 1
    elif user_option == "papel":
        if computer_option == "piedra":
            print ("Felicidades, has ganado")
            user_wins += 1
        elif computer_option == "tijera":
            print ("Lo siento. Has perdido esta ronda")
            computer_wins += 1
    elif user_option == "tijera":
        if computer_option == "papel":
            print ("Felicidades, has ganado")
            user_wins += 1

        elif computer_option == "piedra":
            print ("Lo siento. Has perdido esta ronda")
            computer_wins += 1
    return user_wins, computer_wins

def run_game():
    rounds=1
    computer_wins = 0
    user_wins = 0

    while True:
        print()
        print ("*" *30)
        print ("RONDA # => ", rounds)
        print ("Ganes de la computadora => ", computer_wins)
        print("Ganes del Usuario => ", user_wins)
        print ("*" * 30)
        print()
        rounds += 1

        user_option, computer_option= choose_options()
        user_wins, computer_wins= check_rules(user_option, computer_option, user_wins, computer_wins)

        if computer_wins == 2:
            print ("LA COMPUTADORA HA GANADO LA PARTIDA")
            exit()
        if user_wins == 2:
            print ("EN HORA BUENA, LE HAS GANADO LA PARTIDA A LA COMPUTADORA")
            exit()
run_game()


import cv2
from time import time
import numpy as np

from lib.capture import RotMGCapture
from lib.vision import Vision
from lib.conductor import Conductor

capture = RotMGCapture()
vision = Vision("static/stats.png", debug=True)
conductor = Conductor("r", "f", "v")

loop_time = time()
while(True):
    screenshot = capture.get_screenshot()
    #cv2.imshow('result', vision.process_screenshot(screenshot))
    data = vision.process_screenshot(screenshot)
    if data:
        conductor.conductor(data)

    print('FPS {}'.format(1 / (time() - loop_time)))
    loop_time = time()

    if cv2.waitKey(1) == ord('q'):
        cv2.destroyAllWindows()
        break


'''

Difficulty: Medium
https://www.youtube.com/watch?v=Vn2v6ajA7U0

Given an integer array nums that may contain duplicates, return all possible subsets (the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

'''
from typing import List

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()

        def backtrack(i, subset):
            if i == len(nums):
                res.append(subset[::])
                return

            subset.append(nums[i])
            backtrack(i + 1, subset)
            subset.pop()

            while i + 1 < len(nums) and nums[i] == nums[i + 1]:
                i += 1

            backtrack(i + 1, subset)

        backtrack(0, [])
        return res


import logging
import csv
import numpy as np
from matplotlib import pyplot as plt

ALLOC_POLICY_DICT = {
    0: 'SJF',  # 'short job first', SJF
    1: 'SJU',  # SJF with estimator using USER feature
    2: 'SJG',  # SJF with estimator using GROUP, USER feature
    4: 'SJGG',  # SJF with estimator using GROUP, USER, GPU feature
    8: 'FIFO',  # FIFO, the default
}

PREEMPT_POLICY_DICT = {
    0: 'SDF',  # 'smallest_duration_first'
    1: 'SSF',  # 'smallest_size_first
    2: 'LGF',  # 'large_gpu_first', # LGF, size:num_gpu
}

GPU_TYPE_INT_DICT = {
    "CPU":  0,
    "MISC": 1,
    "T4":   2,
    "P100": 3,
    "V100": 4
}

def print_fn(log, level=1):
    LOG_LEVEL_DEBUG = 0
    LOG_LEVEL_INFO = 1
    LOG_LEVEL_WARNING = 2
    LOG_LEVEL_ERROR = 3
    if level == LOG_LEVEL_DEBUG:
        logging.debug(log)
    elif level == LOG_LEVEL_INFO:
        logging.info(log)
    elif level == LOG_LEVEL_WARNING:
        logging.warning(log)
    elif level == LOG_LEVEL_ERROR:
        logging.error(log)
        exit()

def _repr_job_concise(job_dict):
    return "J %s([G %s,C %s]-D %s)" % (job_dict['job_id'], job_dict['num_gpu'], job_dict['num_cpu'], job_dict['duration'])

def _repr_job_preempt(job_dict):
    return "J %s-[G %s,C %s]-O:%3s/D:%3s" % (job_dict['job_id'], job_dict['num_gpu'], job_dict['num_cpu'], job_dict['on_time'], job_dict['duration'])

def _repr_job_done(job_dict):
    job_repr_concise = "J %s([G %s,C %s]-D %s-N %s)" % (job_dict['job_id'], job_dict['num_gpu'], job_dict['num_cpu'], job_dict['duration'], job_dict['node'])
    return "%25s: %4s ---> %4s" % (job_repr_concise, job_dict['jct'] - job_dict['duration'], job_dict['jct'])

def _add_describe(describe_file):
    if describe_file is None:
        return None
    describe_dict = {}
    with open(describe_file, 'r') as fd:
        reader = csv.DictReader(fd, delimiter=',')
        for row in reader:
            for k, v in row.items():
                if k=='count':
                    row[k] = int(v)
                elif k in ['mean', 'std', 'min', '25%', '50%', '75%', 'max']:
                    if v == '':
                        v = 0
                    row[k] = float(v)
            describe_dict[row['user']] = row
    return describe_dict  # dd['ae8ed1']['50%']==38.4

def _add_job(job_list, job_dict, describe_dict=None):
    # Add job (job_dict) into job_list
    for key, value in job_dict.items():
        if value is not None and value.isdigit() and key != 'user':
            if type(value) == str:
                job_dict[key] = round(float(value))
            else:  # duration becomes an int
                job_dict[key] = round(value)
        elif key in ['wait_time','user_dur','user_gpu_dur','group_dur','group_gpu_dur']:
            try:
                job_dict[key] = float(value)
            except:
                pass

    keys = ['num_cpu', 'num_gpu', 'submit_time', 'num_inst']
    for key in keys:
        if key not in job_dict or job_dict[key] == '':
            if key in ['num_cpu', 'num_gpu']:
                job_dict[key] = 0
            else:  # key in ['submit_time', 'num_inst']
                job_dict[key] = 1
        else:
            if key in ['num_cpu', 'num_gpu']:  # in %
                job_dict[key] = round(100 * float(job_dict[key]))
            else:
                job_dict[key] = round(float(job_dict[key]))

    # Add entries to be used in scheduling
    job_dict['duration'] = int(float(job_dict['duration']))
    if job_dict['duration'] <= 0:
        job_dict['duration'] = 1  # fix duration == 0 problem.
    job_dict['size'] = int((job_dict['num_gpu'] + job_dict['num_cpu']) * job_dict['duration']) # (gpu + cpu) x duration
    job_dict['on_time'] = 0
    job_dict['wasted'] = 0
    job_dict['jct'] = -1
    job_dict['resource'] = [job_dict['num_gpu'], job_dict['num_cpu']] # list of resources
    job_dict['node'] = None

    # Add duration estimation
    if describe_dict is not None:
        jd_user = describe_dict.get(job_dict['user'])
        if jd_user is not None:
            job_dict['dur_avg'] = float(jd_user['mean'])  # expectation
            job_dict['dur_std'] = float(jd_user['std'])  # standard deviation
            job_dict['dur_med'] = float(jd_user['50%'])  # median
            job_dict['dur_trim_mean'] = float(jd_user['trim_mean'])  # discard 10% top and 10% tail when calc. mean

    # Remove original unused entries
    for drop_col in ['fuxi_job_name','fuxi_task_name','inst_id','running_cluster','model_name','iterations','interval','vc','jobid','status']:
        if drop_col in job_dict: job_dict.pop(drop_col)

    job_list.append(job_dict)

def add_user_round_robin_id(job_list):
    # Add a new sorting metrics, user_rrid, to enforce scheduler picking jobs from multiple users
    # when all users' primary metrics are the same (e.g., 0).
    user_rrid_dict = {}  # a new dict each time
    for job in job_list:
        user = job['user']
        rrid = user_rrid_dict.get(user, None)
        if rrid is None:
            rrid = 0
            user_rrid_dict[user] = 1
        else:
            user_rrid_dict[user] += 1
        job['user_rrid'] = rrid

def large_job_pruning(job_list, gpu_limit, cpu_limit):
    if job_list is None:
        return []
    for job in job_list:
        if 'num_gpu' in job and job['num_gpu'] > gpu_limit:
            gpu_was = job['num_gpu']
            job['num_gpu'] = gpu_limit
            print_fn("{:s}: GPU {:d} ==> {:d}".format(_repr_job_concise(job), gpu_was, gpu_limit))
        if 'num_cpu' in job and job['num_cpu'] > cpu_limit:
            cpu_was = job['num_cpu']
            job['num_cpu'] = cpu_limit
            print_fn("{:s}: CPU {:d} ==> {:d}".format(_repr_job_concise(job), cpu_was, cpu_limit))
    return job_list

def plot_cluster_util(npyfile, to_date=False):
    cluster_util = np.load(npyfile)
    cluster_time, cluster_cpu, cluster_gpu = cluster_util[0], cluster_util[1], cluster_util[2]

    plt.clf()
    plt.plot(cluster_time, cluster_cpu / 10, label='10CPU')
    plt.plot(cluster_time, cluster_gpu, label='GPU')
    plt.legend()
    try:
        plt.savefig(str(npyfile).split('.npy')[0]+".png")
    except:
        plt.savefig("cluster_util")

def plot_job_stats(npyfile, to_date=False):
    plt.figure(figsize=(16, 6), dpi=120)
    job_stats = np.load(npyfile)
    job_submit_time, job_duration, job_jct, job_gpu_type, job_num_inst, job_id = job_stats[0], job_stats[1], job_stats[2], job_stats[3], job_stats[4], job_stats[5]
    job_queue_delay = job_jct - job_duration

    plt.clf()
    plt.plot(job_submit_time, job_queue_delay, color='orange', label='queue_delay')
    plt.plot(job_submit_time, job_duration, color='black', alpha=0.3, label='duration')
    plt.legend()
    try:
        plt.savefig(str(npyfile).split('.npy')[0]+".png")
    except:
        plt.savefig("job_stats")

def plot_multi_job_stats(npyfiles, to_date=False):
    plt.clf()
    plt.figure(figsize=(12, 6), dpi=120)

    for npyfile in npyfiles:
        job_stats = np.load(npyfile)
        job_submit_time, job_duration, job_jct, job_gpu_type, job_num_inst, job_id = job_stats[0], job_stats[1], job_stats[2], job_stats[3], job_stats[4], job_stats[5]
        job_queue_delay = job_jct - job_duration

        try:
            label=ALLOC_POLICY_DICT[int(str(npyfile).split('.log.a')[1].split('-p')[0])]
        except KeyError:
            label = str(npyfile).split('.log.')[1].split('-job_stats.npy')[0]
        plt.plot(job_submit_time, job_queue_delay, alpha=0.5, label=label+'-queue_delay')
        plt.plot(job_submit_time, job_duration, color='grey', alpha=0.3, label='job duration')
    plt.legend(loc='upper left')
    plt.title("Arrival jobs' duration and queueing delay")
    plt.xlabel("Submitted Time")
    plt.ylabel("Run/Wait Time")
    try:
        plt.savefig(str(npyfile).split('.log.')[0]+"-job_stats.png")
    except:
        plt.savefig("job_stats")

def plot_multi_cluster_util(npyfiles, to_date=False):
    plt.clf()
    plt.figure(figsize=(12, 6), dpi=120)

    for npyfile in npyfiles:
        cluster_util = np.load(npyfile)
        cluster_time, cluster_cpu, cluster_gpu = cluster_util[0], cluster_util[1], cluster_util[2]

        try:
            label=ALLOC_POLICY_DICT[int(str(npyfile).split('.log.a')[1].split('-p')[0])]
        except KeyError:
            label = str(npyfile).split('.log.')[1].split('-cluster_util.npy')[0]
        plt.plot(cluster_time, cluster_gpu, alpha=0.5, label=label+'-GPU')
    plt.legend(loc='upper left')
    plt.title("Cluster Utilization")
    plt.xlabel("Time")
    plt.ylabel("Resource")
    try:
        plt.savefig(str(npyfile).split('.log.')[0]+"-cluster_util.png")
    except:
        plt.savefig("cluster_util")


# -*- coding: utf-8 -*-
import nltk
from ABSAli1 import preProcessing
from ABSAli1 import entity
import logging
from gensim.models.word2vec import Word2Vec
from sklearn.cluster import KMeans
import pickle
import pandas

logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s',level=logging.INFO)

#词嵌入，并将两种词向量作为位置特征字典
#训练词向量
def trainingForWords(texts,fnum,filepath,sg,hs):
    #设定词向量参数

    sentences=[str(text).split(' ') for text in texts]  #.lower()
    # print(sentences)
    print('分词完成，开始训练')

    num_features=fnum #词向量的维度
    min_word_count=3 #词频数最低阈值
    num_workers=8 #线程数,想要随机种子生效的话，设为1
    context=10 #上下文窗口大小
    downsampling=1e-3 #与自适应学习率有关
    num_iter=15 #没有加额外数据时，设置为100最佳(添加额外数据后30最佳)
    hs=hs
    sg=sg#是否使用skip-gram模型

    model_path=filepath
    model=Word2Vec(sentences,workers=num_workers,hs=hs,
                   size=num_features,min_count=min_word_count,seed=77,iter=num_iter,
                   window=context,sample=downsampling,sg=sg)
    model.init_sims(replace=True)#锁定训练好的word2vec,之后不能对其进行更新
    model.save(model_path)#讲训练好的模型保存到文件中
    print('训练完成')
    return model

#加载word2vec模型
def loadForWord(filepath):
    model=Word2Vec.load(filepath)
    print('word2vec模型读取完毕')
    return model

def trainingEmbedding(vector_len=150,d_type='re',add_extra=False):
    if d_type=='re':
        d_name='Restaurants'
        extraFile='data/extra/yelp/Restaurants_Raw.csv'
    else:
        d_name='LapTops'
        extraFile='data/extra/amzon/LapTops_Raw.csv'

    print('------训练%s数据的Word2Vec------'%d_name)
    train_corpus=preProcessing.loadXML('data/origin/%s_Train_v2.xml'%d_name)                #判断训练集合法
    test_corpus=preProcessing.loadXML('data/origin/%s_Test_Data_PhaseA.xml'%d_name)         #判断测试集合法
    print('数据集合并完成')

    corpus=train_corpus.corpus
    corpus=train_corpus.corpus+test_corpus.corpus

    del train_corpus
    del test_corpus

    bio_entity=entity.BIO_Entity(corpus,d_type)
    texts=bio_entity.texts

    #向SemEval-2014文件中的'Restaurants'和'LapTops'添加额外的数据
    if add_extra==True:
        print('添加额外语料:%s'%extraFile)
        extra_csv=pandas.read_csv(extraFile)  #,encoding='gbk'
        extra_texts=list(extra_csv['text'])
        texts=texts+extra_texts
        del extra_csv
        del extra_texts
        print('额外语料加载完成')

    print('创建WordEmbedding')
    trainingForWords(texts,vector_len,'model/%s.w2v'%d_name,1,0)        #Word2Vec中采用Skipgram
    print('创建WordEmbedding_CBOW')
    trainingForWords(texts,vector_len,'model/%s.w2v_cbow'%d_name,0,0)  #Word2Vec中采用CBOW
#采用skipgram模型和cbow模型，之所以训练两组是为了丰富后面的特征。

#为什么采用Keman处理
#在后面要进行特征抽取任务中，我们当然不能直接把单词的词向量丢到CRF里去学习（这可不是LSTM这种NN模型，要CRF学习词向量的每一维的转换关系，消耗上是不能接受的，且没有意义），
#这里合理做法是我之前提到的TOP选手的做法，将全体单词词向量做Kmeans聚类，每一个单词都会得到一个聚类类别，反映了其大体语义，我们将单词的类别作为CRF的位置特征。

def kmeansClusterForW2V(filepath,outpath,cluster_num):
    W2Vmodel=loadForWord(filepath)
    vocab=list(W2Vmodel.wv.vocab.keys())
    vectors=[W2Vmodel[vocab[i]] for i in (range(len(vocab)))]
    print('开始聚类')
    clf=KMeans(n_clusters=cluster_num,random_state=77)
    clf.fit(vectors)
    print('聚类完成，开始讲词典转化为类别字典')
    dict_re={vocab[i]:clf.labels_[i] for i in range(len(vocab))}
    print('保存字典。。。。')
    with open(outpath,'wb') as f:
        pickle.dump(dict_re,f)
    return dict_re

def loadDict(dictpath):
    print('载入字典：%s'%dictpath)
    with open(dictpath,'rb') as f:
        dict_re=pickle.load(f)
    return dict_re

#对词向量进行聚类处理，    位置特征字典序列  簇的类别为10
def createCluster(cluster_num=10,d_type='re'):
    if d_type=='re':
        d_name='Restaurants'
    else:
        d_name='LapTops'

    print('创建W2V聚类')
    kmeansClusterForW2V('model/%s.w2v'%d_name,'cluster/%s_w2v.pkl'%d_type,cluster_num)
    print('W2V聚类群创建完毕！')
    print('创建W2V_CBOW聚类')
    kmeansClusterForW2V('model/%s.w2v_cbow'%d_name,'cluster/%s_w2v_c.pkl'%d_type,cluster_num)
    print('W2V聚类群创建完毕！')

if __name__=='__main__':
     print('word2vecProcessing')
     # trainingEmbedding(300,'re')
     # createCluster(100,'re',  True,True,True)

     # trainingEmbedding(300,'lp',True,   True,True,True)
     # createCluster(200,'lp',  True,True,True)

     # W2V=loadForWord('embeddingModels/Laptops.w2v')


### Code from https://github.com/patrickloeber/python-fun/tree/master/snake-pygame

import pygame
import random
from enum import Enum
from collections import namedtuple
from config import *
from Snake import Snake
import numpy as np

pygame.init()

font = pygame.font.SysFont('arial', 25)

class Direction(Enum):
    RIGHT = 1
    LEFT = 2
    UP = 3
    DOWN = 4

Point = namedtuple('Point', 'x, y')

# rgb colors
WHITE = (255, 255, 255)
BLUE = (0, 0, 200)
BLUE1 = (0, 0, 255)
BLUE2 = (0, 100, 255)
GREEN = (0, 200, 0)
GREEN1 = (0, 255, 0)
GREEN2 = (100, 255, 0)
BLACK = (0,0,0)

class SnakeGameAI:
    """
    game should be in the following shape:
    type game = {
        height: number,
        width: number,
        gameMoves: {
                snakeBody: Point[]
                food: Point
            }[]
    }
    These are the basics variables needed
    """
    def __init__(self, game, s=SPEED):
        if len(game['gameMoves']) == 0:
            raise Exception("No game moves given")
        try:
            self.w = game['width']
            self.h = game['height']
            self.currMove = 0
            firstMove = game['gameMoves'][0]
            self.snake = firstMove['snakeBody']
            self.food = firstMove['food']

            self.display = pygame.display.set_mode((self.w, self.h), pygame.NOFRAME)
            pygame.display.set_caption('Snake')
            self.clock = pygame.time.Clock()
        except:
            raise Exception("Missing game data")

    def updateUi(self):
        self.display.fill(BLACK)

        for pt in self.snake:
            pygame.draw.rect(self.display, BLUE1, pygame.Rect(pt.x, pt.y, BLOCK_SIZE, BLOCK_SIZE))
            pygame.draw.rect(self.display, BLUE2, pygame.Rect(pt.x+4, pt.y+4, 12, 12))

            food = self.food
            pygame.draw.rect(self.display, BLUE, pygame.Rect(food.x, food.y, BLOCK_SIZE, BLOCK_SIZE))

        pygame.display.flip()
        self.clock.tick(self.s)


from distutils.version import LooseVersion
import numpy as np
import os
from six.moves import xrange
import tensorflow as tf
import time
import warnings
import math
import sys
sys.path.append('../')

from .utils import batch_indices, _ArgsWrapper

def model_loss(y, model, mean=True):
    """
    Define loss of TF graph
    :param y: correct labels
    :param model: output of the model
    :param mean: boolean indicating whether should return mean of loss
                 or vector of losses for each input of the batch
    :return: return mean of loss if True, otherwise return vector with per
             sample loss
    """

    op = model.op
    if op.type == "Softmax":
        logits, = op.inputs
    else:
        logits = model

    out = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y)

    if mean:
        out = tf.reduce_mean(out)
    return out

def initialize_uninitialized_global_variables(sess):
    """
    Only initializes the variables of a TensorFlow session that were not
    already initialized.
    :param sess: the TensorFlow session
    :return:
    """
    # List all global variables
    global_vars = tf.global_variables()

    # Find initialized status for all variables
    is_var_init = [tf.is_variable_initialized(var) for var in global_vars]
    is_initialized = sess.run(is_var_init)

    # List all variables that were not initialized previously
    not_initialized_vars = [var for (var, init) in
                            zip(global_vars, is_initialized) if not init]

    # Initialize all uninitialized variables found, if any
    if len(not_initialized_vars):
        sess.run(tf.variables_initializer(not_initialized_vars))

def model_train(sess, x, y, predictions, X_train, Y_train, save=False,
                predictions_adv=None, init_all=True, evaluate=None,
                feed=None, args=None, rng=None):
    """
    Train a TF graph
    :param sess: TF session to use when training the graph
    :param x: input placeholder
    :param y: output placeholder (for labels)
    :param predictions: model output predictions
    :param X_train: numpy array with training inputs
    :param Y_train: numpy array with training outputs
    :param save: boolean controlling the save operation
    :param predictions_adv: if set with the adversarial example tensor,
                            will run adversarial training
    :param init_all: (boolean) If set to true, all TF variables in the session
                     are (re)initialized, otherwise only previously
                     uninitialized variables are initialized before training.
    :param evaluate: function that is run after each training iteration
                     (typically to display the test/validation accuracy).
    :param feed: An optional dictionary that is appended to the feeding
                 dictionary before the session runs. Can be used to feed
                 the learning phase of a Keras model for instance.
    :param args: dict or argparse `Namespace` object.
                 Should contain `nb_epochs`, `learning_rate`,
                 `batch_size`
                 If save is True, should also contain 'train_dir'
                 and 'filename'
    :param rng: Instance of numpy.random.RandomState
    :return: True if model trained
    """
    args = _ArgsWrapper(args or {})

    # Check that necessary arguments were given (see doc above)
    assert args.nb_epochs, "Number of epochs was not given in args dict"
    assert args.learning_rate, "Learning rate was not given in args dict"
    assert args.batch_size, "Batch size was not given in args dict"

    if save:
        assert args.train_dir, "Directory for save was not given in args dict"
        assert args.filename, "Filename for save was not given in args dict"

    if rng is None:
        rng = np.random.RandomState()

    # Define loss
    loss = model_loss(y, predictions)
    if predictions_adv is not None:
        loss = (loss + model_loss(y, predictions_adv)) / 2

    train_step = tf.train.AdamOptimizer(learning_rate=args.learning_rate)
    update_op = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_op):
        train_step = train_step.minimize(loss)

    with sess.as_default():
        if hasattr(tf, "global_variables_initializer"):
            if init_all:
                tf.global_variables_initializer().run()
            else:
                initialize_uninitialized_global_variables(sess)
        else:
            warnings.warn("Update your copy of tensorflow; future versions of "
                          "guardai_util may drop support for this version.")
            sess.run(tf.initialize_all_variables())

        for epoch in xrange(args.nb_epochs):
            # Compute number of batches
            nb_batches = int(math.ceil(float(len(X_train)) / args.batch_size))
            assert nb_batches * args.batch_size >= len(X_train)

            # Indices to shuffle training set
            index_shuf = list(range(len(X_train)))
            rng.shuffle(index_shuf)

            prev = time.time()
            for batch in range(nb_batches):

                # Compute batch start and end indices
                start, end = batch_indices(
                    batch, len(X_train), args.batch_size)

                # Perform one training step
                feed_dict = {x: X_train[index_shuf[start:end]],
                             y: Y_train[index_shuf[start:end]]}
                if feed is not None:
                    feed_dict.update(feed)
                train_step.run(feed_dict=feed_dict)
            assert end >= len(X_train)  # Check that all examples were used
            cur = time.time()
            print("Epoch " + str(epoch) + " took " +
                         str(cur - prev) + " seconds")

            if evaluate is not None:
                evaluate()

        if save:
            train_dir = os.path.join(args.train_dir, str(args.nb_epochs - 1))
            if not os._exists(train_dir):
                os.makedirs(train_dir)
            save_path = os.path.join(train_dir, args.filename)
            saver = tf.train.Saver()
            saver.save(sess, save_path)
            print("Completed model training and saved at: " +
                         str(save_path))
        else:
            print("Completed model training.")

    return True

def model_eval(sess, x, y, predictions, X_test=None, Y_test=None,
               feed=None, args=None):
    """
    Compute the accuracy of a TF model on some data
    :param sess: TF session to use when training the graph
    :param x: input placeholder
    :param y: output placeholder (for labels)
    :param predictions: model output predictions
    :param X_test: numpy array with training inputs
    :param Y_test: numpy array with training outputs
    :param feed: An optional dictionary that is appended to the feeding
             dictionary before the session runs. Can be used to feed
             the learning phase of a Keras model for instance.
    :param args: dict or argparse `Namespace` object.
                 Should contain `batch_size`
    :return: a float with the accuracy value
    """
    args = _ArgsWrapper(args or {})

    assert args.batch_size, "Batch size was not given in args dict"
    if X_test is None or Y_test is None:
        raise ValueError("X_test argument and Y_test argument "
                         "must be supplied.")

    # Define accuracy symbolically
    if LooseVersion(tf.__version__) >= LooseVersion('1.0.0'):
        correct_preds = tf.equal(tf.argmax(y, axis=-1),
                                 tf.argmax(predictions, axis=-1))
    else:
        correct_preds = tf.equal(tf.argmax(y, axis=tf.rank(y) - 1),
                                 tf.argmax(predictions,
                                           axis=tf.rank(predictions) - 1))

    # Init result var
    accuracy = 0.0

    with sess.as_default():
        # Compute number of batches
        nb_batches = int(math.ceil(float(len(X_test)) / args.batch_size))
        assert nb_batches * args.batch_size >= len(X_test)

        X_cur = np.zeros((args.batch_size,) + X_test.shape[1:],
                         dtype=X_test.dtype)
        Y_cur = np.zeros((args.batch_size,) + Y_test.shape[1:],
                         dtype=Y_test.dtype)
        for batch in range(nb_batches):
            if batch % 100 == 0 and batch > 0:
                print("Batch " + str(batch))

            # Must not use the `batch_indices` function here, because it
            # repeats some examples.
            # It's acceptable to repeat during training, but not eval.
            start = batch * args.batch_size
            end = min(len(X_test), start + args.batch_size)

            # The last batch may be smaller than all others. This should not
            # affect the accuarcy disproportionately.
            cur_batch_size = end - start
            X_cur[:cur_batch_size] = X_test[start:end]
            Y_cur[:cur_batch_size] = Y_test[start:end]
            feed_dict = {x: X_cur, y: Y_cur}
            if feed is not None:
                feed_dict.update(feed)
            cur_corr_preds = correct_preds.eval(feed_dict=feed_dict)

            accuracy += cur_corr_preds[:cur_batch_size].sum()

        assert end >= len(X_test)

        # Divide by number of examples to get final value
        accuracy /= len(X_test)

    return accuracy

def model_argmax(sess, x, predictions, samples, feed=None):
    """
    Helper function that computes the current class prediction
    :param sess: TF session
    :param x: the input placeholder
    :param predictions: the model's symbolic output
    :param samples: numpy array with input samples (dims must match x)
    :param feed: An optional dictionary that is appended to the feeding
             dictionary before the session runs. Can be used to feed
             the learning phase of a Keras model for instance
    :return: the argmax output of predictions, i.e. the current predicted class
    """
    feed_dict = {x: samples}
    if feed is not None:
        feed_dict.update(feed)
    probabilities = sess.run(predictions, feed_dict)

    if samples.shape[0] == 1:
        return np.argmax(probabilities)
    else:
        return np.argmax(probabilities, axis=1)

def model_prediction(sess, x, predictions, samples, feed=None, batch_size=128):
    """
    Compute the probability of all classes for inputs
    :param sess: TF session
    :param x: the input placeholder
    :param predictions: the model's symbolic output
    :param samples: numpy array with input samples (dims must match x)
    :param feed: An optional dictionary that is appended to the feeding
             dictionary before the session runs. Can be used to feed
             the learning phase of a Keras model for instance
    :param batch_size: the size of inputs per batch
    :return: the output probability
    """
    nb_classes = 2
    nb_batches = int(math.ceil(float(samples.shape[0]) / batch_size))

    pros_all=np.zeros(shape=(samples.shape[0],nb_classes), dtype='float32')

    for batch in range(nb_batches):
        start=batch*batch_size
        end=(batch+1)*batch_size
        if end>samples.shape[0]:
            end=samples.shape[0]

        feed_dict = {x: samples[start:end]}
        if feed is not None:
            feed_dict.update(feed)
        pros=sess.run(predictions, feed_dict)

        for i in range(start,end):
            pros_all[i]=pros[i-start]
    return pros_all


import unittest, logging, sys
sys.path.insert(0, '../')
from models.poems.limerick import limerick
from models.poems.parseLines import parse, parse_all
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from models.poems.poem import Tweet, Poem, engine
from sqlalchemy.sql import text

class TestLimerick(unittest.TestCase):
    def setUp(self):
      try:
        app = Flask(__name__)
        app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://localhost/test'
        db = SQLAlchemy(app)
        db.drop_all()
        db.create_all()
        db.session.add(Tweet('The limerick packs laughs anatomical', 'url1', 'limerick_test1', 10, 'AO1F', 'anatomical'))
        db.session.add(Tweet('Into space that is quite economical', 'url2', 'limerick_test1', 10, 'AO1F', 'economical'))
        db.session.add(Tweet("But the good ones I've seen", 'url3', 'limerick_test1', 6, 'IY1N', 'seen'))
        db.session.add(Tweet("So seldom are clean", 'url4', 'limerick_test1', 6, 'IY1N', 'clean'))
        db.session.add(Tweet("And the clean ones so seldom are comical", 'url5', 'limerick_test1', 10, 'AO1F', 'comical'))

        db.session.commit()
      except Exception as e:
        db.session.rollback()

    def test_valid(self):
        ''' Test a valid amount of tweets '''
        poem = limerick('limerick_test1')
        poem = [t.text for t in poem.tweets]
        self.assertTrue(poem[0] == "The limerick packs laughs anatomical")
        self.assertTrue(poem[1] == "Into space that is quite economical")
        self.assertTrue(poem[2] == "But the good ones I've seen")
        self.assertTrue(poem[3] == "So seldom are clean")
        self.assertTrue(poem[4] == "And the clean ones so seldom are comical")

    def test_invalid(self):
        ''' Tests insufficient amount of appropriate tweets '''
        self.assertRaises(Exception, limerick, 'limerick_test2')

    def test_invalid_duplicates(self):
        ''' Test no duplicates '''
        self.assertRaises(Exception, limerick, 'limerick_test3')

    def test_invalid_nonenglish(self):
        ''' Test no non-english lines '''
        self.assertRaises(Exception, limerick, 'limerick_test4')

    def test_valid_variance(self):
        ''' Limerick should choose lines that have similar syllable counts '''
        poem = limerick('limerick_test1')
        poem = [t.text for t in poem.tweets]
        self.assertTrue(poem[0] == "The limerick packs laughs anatomical")
        self.assertTrue(poem[1] == "Into space that is quite economical")
        self.assertTrue(poem[2] == "But the good ones I've seen")
        self.assertTrue(poem[3] == "So seldom are clean")
        self.assertTrue(poem[4] == "And the clean ones so seldom are comical")

    def test_urls(self):
        ''' Ensure the poems have the correct urls attached '''
        poem = limerick('limerick_test1')
        poem = [t.url for t in poem.tweets]
        self.assertTrue(poem[0] == 'url1')
        self.assertTrue(poem[1] == 'url2')
        self.assertTrue(poem[2] == 'url3')
        self.assertTrue(poem[3] == 'url4')
        self.assertTrue(poem[4] == 'url5')

if __name__ == '__main__':
    logging.basicConfig(stream=sys.stderr, level=logging.INFO)
    unittest.main()


"""
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/

You are given an integer array prices where prices[i] is the price of a given stock on the ith day, and an integer k.

Find the maximum profit you can achieve. You may complete at most k transactions.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

Example 1:

Input: k = 2, prices = [2,4,1]
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:

Input: k = 2, prices = [3,2,6,5,0,3]
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. Then buy on day 5 (price = 0)
and sell on day 6 (price = 3), profit = 3-0 = 3.

Constraints:

0 <= k <= 100
0 <= prices.length <= 1000
0 <= prices[i] <= 1000
"""

from functools import lru_cache

class Solution:

    def maxProfit(self, k, prices):
        """
        State:
            i: ith day
            s: state: 0 - buy, 1 - sell
            k: remaining transactions
        """

        # @lru_cache
        # def helper(i, s, k):
        #     if i == len(prices):
        #         return 0
        #     if k == 0:
        #         return 0
        #     # buy / sell
        #     if s == 0:
        #         do_something = -prices[i] + helper(i+1, 1, k)
        #         do_nothing = helper(i+1, 0, k)
        #         return max(do_nothing, do_something)
        #     else:
        #         do_something = prices[i] + helper(i+1, 0, k-1)
        #         do_nothing = helper(i+1, 1, k)
        #         return max(do_nothing, do_something)
        #
        # return helper(0, 0, k)

        n = len(prices)
        cache = [[[0] * (k+1) for _ in range(2)] for _ in range(n+1)]

        for o in range(1, k+1):
            for i in range(n-1, -1, -1):
                cache[i][0][o] = max(cache[i+1][1][o]-prices[i], cache[i+1][0][o])
                cache[i][1][o] = max(cache[i+1][0][o-1]+prices[i], cache[i+1][1][o])

        return cache[0][0][-1]


import collections

Node = collections.namedtuple('Node', ['left', 'right', 'value'])

def contains(root, value):
    if root is None:
        return False
    if root.value == value:
        return True

    if root.left is None and root.right is None:
        return False

    if root.value > value:
        return contains(root.left, value)
    else:
        return contains(root.right, value)
import collections

n1 = Node(value=1, left=None, right=None)
n3 = Node(value=3, left=None, right=None)
n2 = Node(value=2, left=n1, right=n3)

print(contains(n2, 3))


from django.http import HttpResponse
from django.template import Template, Context
from django.template.loader import get_template
from django.shortcuts import render
from django.http import JsonResponse
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder
from joblib import load
from django.core.files import File
import os
import numpy as np
import json
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.safestring import mark_safe
from django.template import Library
import sys
import boto3
from django.conf import settings

# 'fuelType', 'km', 'make', 'model', 'price', 'transmissionType', 'year',
#        'cubicCapacity', 'doors', 'hp'

def inicio(request):
    # ----------------------lectura de json para los select ---------------------------
    marcas_id = open(
        os.path.dirname(os.path.realpath(__file__)) + "/json/marcas_id.json",
        "rb",
    )

    marca_model_id = open(
        os.path.dirname(os.path.realpath(__file__)) +
        "/json/marca_model_id.json",
        "rb",
    )

    with marcas_id as file:
        data = json.load(file)
        data_json = json.dumps(data)

    with marca_model_id as file2:
        data2 = json.load(file2)
        data_json2 = json.dumps(data2)

    # ----------------------lectura de json para los select ---------------------------

    aws_access_key_ID = settings.AWS_ACCESS_KEY_ID
    aws_secret_access_KEY = settings.AWS_SECRET_ACCESS_KEY
    aws_session_TOKEN = settings.AWS_SESSION_TOKEN
    endpPoint = settings.ENDPOINT
    bucket = settings.BUCKET
    region_NAME = settings.REGION_NAME

    if request.POST:
        # 'fuelType', 'km', 'make', 'model','transmissionType', 'year','cubicCapacity', 'doors', 'hp'
        fuelType = request.POST['fuelType']
        km = request.POST['km']
        make = request.POST['make']
        model = request.POST['model']
        transmissionType = request.POST['transmissionType']
        year = request.POST['year']
        cubicCapacity = request.POST['cubicCapacity']
        doors = request.POST['doors']
        hp = request.POST['hp']

        data_usuario = f"{fuelType},{km},{make},{model},{transmissionType},{year},{cubicCapacity},{doors},{hp}"
        # print(data_usuario)

        client = boto3.Session(
            aws_access_key_id=aws_access_key_ID,
            aws_secret_access_key=aws_secret_access_KEY,
            aws_session_token=aws_session_TOKEN,
            region_name=region_NAME).client('sagemaker-runtime')

        response = client.invoke_endpoint(
            EndpointName=endpPoint, ContentType='text/csv', Accept='text/csv', Body=data_usuario)
        response = response['Body'].read().decode('utf-8')

        return render(request, "resultado.html", {"predict": response})

    return render(request, "inicio.html", {"marcas_id": data_json, "marca_model_id": data_json2})


import sys
import pathlib
import logging
from exceptions import ArgvException, NotTextFile, CrypterBaseException
from crypter import Caesar, Shift

def get_file_text(path):
    """Get the file from a text file"""
    with open(path) as fin:
        content = fin.read()
    return content

ROOT = pathlib.Path(__file__).parent
LOGS_DIR = ROOT / "logs"

try:
    LOGS_DIR.mkdir(exist_ok=True)
except OSError:
    logs_file_name = None
else:
    logs_file_name = LOGS_DIR / "log.log"

logging.basicConfig(level=logging.DEBUG,
                    format="%(asctime)s %(levelname)s line:  %(lineno)d %(message)s",
                    filename=logs_file_name)

def get_path_from_argv(idx):
    """Get path from CLI using sys module and is taking 1 argument which is the index"""
    if len(sys.argv) == 1:
        raise ArgvException("Error: Argumentul Path nu a fost gasit")

    path = pathlib.Path(sys.argv[idx])
    if not path.is_file():
        raise NotTextFile(f"Error: Nu am gasit fisierul {sys.argv[idx]}")
    return path

def crypt(msg, cypher):
    """Returns a string with the encrypted message and takes 2 arguments"""
    return str(cypher.crypt(msg))

def write_crypt_msg(path, msg, cipher):
    """Writes the encrypted message in a file text and takes 3 arguments"""
    with open(path, "w") as f:
        crypt_mes = f.write(crypt(msg, cipher))
    return crypt_mes

"""----------------------------------------------------------------------------------------------------------------"""

def decrypt(msg, cypher):
    """Returns a string with the decrypted message and takes 2 arguments"""
    return str(cypher.decrypt(msg))

def write_decrypt_msg(path, msg, cipher):
    """Writes the decrypted message in a file text and takes 3 arguments"""
    with open(path, "w") as f:
        decrypt_mes = f.write(decrypt(msg, cipher))
    return decrypt_mes

main_msg = get_file_text("my_text.txt")
my_cypher = Caesar(3)
my_cypher2 = Shift(5)
crypt_msg = get_file_text("encrypted.txt")

if sys.argv[1] == "c":
    try:
        logging.info(f"The file {get_path_from_argv(2)} will be encrypted")
        encrypted_msg = "encrypted.txt"
    except OSError:
        encrypted_msg = None
    except CrypterBaseException as err:
        logging.error(err)
    else:
        write_crypt_msg(encrypted_msg, main_msg, my_cypher2)
        logging.info(f"In {encrypted_msg} file you will find the encrypted message")

elif sys.argv[1] == "d":
    try:
        logging.info(f"The file {get_path_from_argv(2)} will be decrypted")
        decrypted_msg = "decrypted.txt"
    except OSError:
        decrypted_msg = None
    except CrypterBaseException as err:
        logging.error(err)
    else:
        if crypt_msg.split()[0] == 'Shift':
            write_decrypt_msg(decrypted_msg, crypt_msg, my_cypher2)
            logging.info(f"In {decrypted_msg} file you will find the decrypted message")
        elif crypt_msg.split()[0] == 'Caesar':
            write_decrypt_msg(decrypted_msg, crypt_msg, my_cypher)
            logging.info(f"In {decrypted_msg} file you will find the decrypted message")
        else:
            logging.info("Message cannot be decrypted")
else:
    raise NotTextFile("Command dose not exist")


import copy
from .template import BASE_TEMPLATE_PROPERTIES
from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA

VMWARE_TEMPLATE_PROPERTIES = {
    "vmx_path": {
        "description": "Path to the vmx file",
        "type": "string",
        "minLength": 1,
    },
    "usage": {
        "description": "How to use the VMware VM",
        "type": "string",
        "default": ""
    },
    "linked_clone": {
        "description": "Whether the VM is a linked clone or not",
        "type": "boolean",
        "default": False
    },
    "first_port_name": {
        "description": "Optional name of the first networking port example: eth0",
        "type": "string",
        "default": ""
    },
    "port_name_format": {
        "description": "Optional formatting of the networking port example: eth{0}",
        "type": "string",
        "default": "Ethernet{0}"
    },
    "port_segment_size": {
        "description": "Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2",
        "type": "integer",
        "default": 0
    },
    "adapters": {
        "description": "Number of adapters",
        "type": "integer",
        "minimum": 0,
        "maximum": 10,  # maximum adapters support by VMware VMs,
        "default": 1
    },
    "adapter_type": {
        "description": "VMware adapter type",
        "enum": ["default", "e1000", "e1000e", "flexible", "vlance", "vmxnet", "vmxnet2", "vmxnet3"],
        "default": "e1000"
    },
    "use_any_adapter": {
        "description": "Allow GNS3 to use any VMware adapter",
        "type": "boolean",
        "default": False
    },
    "headless": {
        "description": "Headless mode",
        "type": "boolean",
        "default": False
    },
    "on_close": {
        "description": "Action to execute on the VM is closed",
        "enum": ["power_off", "shutdown_signal", "save_vm_state"],
        "default": "power_off"
    },
    "console_type": {
        "description": "Console type",
        "enum": ["telnet", "none"],
        "default": "none"
    },
    "console_auto_start": {
        "description": "Automatically start the console when the node has started",
        "type": "boolean",
        "default": False
    },
    "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
}

VMWARE_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
VMWARE_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
VMWARE_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}"
VMWARE_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vmware_guest.svg"

VMWARE_TEMPLATE_OBJECT_SCHEMA = {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "A VMware template object",
    "type": "object",
    "properties": VMWARE_TEMPLATE_PROPERTIES,
    "required": ["vmx_path"],
    "additionalProperties": False
}


import time
import pickle
import datetime

import matplotlib.pyplot as plt
import numpy as np

from sacred import Experiment
from sacred.observers import FileStorageObserver, RunObserver

from constrained_bai.driver import get_driver
from constrained_bai.driver_bandit import DriverBandit

# changes the run _id and thereby the path that the FileStorageObserver
# writes the results
# cf. https://github.com/IDSIA/sacred/issues/174
class SetID(RunObserver):
    priority = 50  # very high priority to set id

    def started_event(
        self, ex_info, command, host_info, start_time, config, meta_info, _id
    ):
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")
        custom_id = "{}".format(timestamp)
        return custom_id  # started_event returns the _run._id

ex = Experiment("driver_solve_with_restarts")
ex.observers = [SetID(), FileStorageObserver("results")]

@ex.config
def cfg():
    problem = {"cars_trajectory": "blocked", "goal": "target_velocity"}
    penalty_lambda = 1
    n_restarts = 10
    constraint = None
    experiment_label = None

@ex.automain
def run(_run, seed, problem, penalty_lambda, n_restarts, constraint, experiment_label):
    env = get_driver(
        problem["cars_trajectory"],
        problem["goal"],
        penalty_lambda=penalty_lambda,
        constraint=constraint,
    )
    env_eval = get_driver(
        problem["cars_trajectory"],
        problem["goal"],
        penalty_lambda=penalty_lambda,
        constraint="default",
    )

    max_rew = -float("inf")
    max_features = None

    for _ in range(n_restarts):
        policy, policy_features, _ = env.get_optimal_policy()
        reward = np.dot(policy_features, env.reward_w)
        if env.constraint_w is not None:
            constraint = np.dot(policy_features, env.constraint_w)
        else:
            constraint = None
        print("reward", reward, "constraint", constraint)
        if (constraint is None or constraint < env.threshold) and reward > max_rew:
            print("updating solution")
            max_rew = reward
            max_features = policy_features

    reward = np.dot(max_features, env_eval.reward_w)
    constraint = np.dot(max_features, env_eval.constraint_w)

    print("Found solution with")
    print("reward", reward)
    print("constraint", constraint)

    return {"reward": reward, "constraint": constraint}


# notes
'''
This file is for housing the main dash application.
This is where we define the various css items to fetch as well as the layout of our application.
'''

# package imports
import dash
from dash import html
import dash_bootstrap_components as dbc
from flask import Flask
import os

# local imports
from utils.settings import APP_HOST, APP_PORT, APP_DEBUG, DEV_TOOLS_PROPS_CHECK

from components import navbar, footer

server = Flask(__name__)
app = dash.Dash(
    __name__,
    server=server,
    use_pages=True,    # turn on Dash pages
    external_stylesheets=[
        dbc.themes.BOOTSTRAP,
        dbc.icons.FONT_AWESOME
    ],  # fetch the proper css items we want
    meta_tags=[
        {   # check if device is a mobile device. This is a must if you do any mobile styling
            'name': 'viewport',
            'content': 'width=device-width, initial-scale=1'
        }
    ],
    suppress_callback_exceptions=True,
    title='Dash app structure'
)

server.config.update(SECRET_KEY=os.getenv('SECRET_KEY'))

def serve_layout():
    '''Define the layout of the application'''
    return html.Div(
        [
            navbar,
            dbc.Container(
                dash.page_container,
                class_name='my-2'
            ),
            footer
        ]
    )

app.layout = serve_layout   # set the layout to the serve_layout function
server = app.server         # the server is needed to deploy the application

if __name__ == "__main__":
    app.run_server(
        host=APP_HOST,
        port=APP_PORT,
        debug=APP_DEBUG,
        dev_tools_props_check=DEV_TOOLS_PROPS_CHECK
    )


# Задача 2
#    Словом в данной задаче считается последовательность букв,
#    ограниченная пробелами или началом или концом строки.
#    Выведите все слова из строки в столбик. НЕЛЬЗЯ ПОЛЬЗОВАТЬСЯ МЕТОДАМИ СТРОК (split)

# Формат ввода
# Вводится строка.

# Формат вывода
# Выведите слова из строки по одному.

# Пример 1
# Ввод

# Hello, world!
# Вывод
# Hello,
# world!
# Пример 2
# Ввод

# My heart in the Highland
# Вывод
# My
# heart
# in
# the
# Highland

str_a = "Python is an easy to learn, powerful programming language."

for i in range(len(str_a)):
    if str_a[i] != ' ':
        print(str_a[i], end='')
    else:
        print('\n', end='')