import random
import time

bling = "http://img.mogodeer.cn/images/yuan/4.png"
star = "http://img.mogodeer.cn/image/health/star.png"
liuxing = "http://img.mogodeer.cn/images/yuan/liuxing.png"
pageColor = '#FEB621'
guestColor = '#FEB621'

AUDITING = False  #是否是审核状态
ENABLE_PAY = True #是否开启支付

def starblink():
    efbkink1 = blink("0.8, 0.4, 0.8, 1.2")
    efbkink1 = blink("0.8, 0.4, 0.8, 1.2")
    efbkink2 = blink("0.8, 0.2, 0.3, 1.2")
    efbkink3 = blink("1.2, 0.5, 0.5, 1.2")
    efbkink4 = blink("0.5, 0.8, 0.7, 1.2")
    efmove1 = move(path=[(350,-20),(-80,350)],c=0,t=3.0)
    efmove2 = move(path=[(550,-150),(-160,550)],c=0,t=3.5,d=1)
    efmove3 = move(path=[(770,200),(-150,850)],c=0,t=4.0,d=0.5)
    effade1 = fadeout(t=2.5,c=0)
    effade2 = fadeout(t=3.0,d=1,c=0)
    effade3 = fadeout(t=3.5,d=0.5,c=0)
    Image(src=star,pos=[30,20,25,25],effect=efbkink1)
    Image(src=star,pos=[370,130,22,22],effect=efbkink1)
    Image(src=star,pos=[200,40,15,15],effect=efbkink2)
    Image(src=star,pos=[240,250,16,16],effect=efbkink3)
    Image(src=star,pos=[160,290,20,20],effect=efbkink2)
    Image(src=star,pos=[300,20,16,16],effect=efbkink4)
    Image(src=star,pos=[600,60,25,25],effect=efbkink1)
    Image(src=star,pos=[320,180,29,20],effect=efbkink3)
    Image(src=star,pos=[560,220,15,15],effect=efbkink1)
    Image(src=star,pos=[440,320,17,17],effect=efbkink1)
    Image(src=star,pos=[220,170,17,17],effect=efbkink4)
    Image(size=[75,75], pos=[350,-20], src=liuxing, effect=relativeMove(t=3.0,p=0,c=0,rd=(-430,370)))
    Image(size=[80,80], pos=[550,-150], src=liuxing, effect=relativeMove(t=3.5,p=0,c=0,d=1,rd=(-710,700)))
    Image(src=liuxing,pos=[770, 200],size=[85,85],effect=relativeMove(t=4,p=0,c=0,d=0.5,rd=(-920,650)))

def main():
    with MoApp(appid='wx468ad783f165eea0', name='好友回忆墙',withLogin=True):
        with Page(name='begin',enableShare=True, onReady=beginReady):
            with Box(name='entrance',pos=[0,0], hidden=True,width=750):
                Image(position='fixed', top=0,size=[750,1500],src="img/bg1.jpg")
                starblink()
                ImageAvatar(pos=['center',430],size=[160,160],borderRadius='50%')
                Image(pos=[340,130],size=[300,70],src="http://material.motimaster.com/yuyuan/Duudle/create/4ad72652b048c5f9b890c624f88a7986.png",effect=fadein(d=0.5,t=2,c=0,p=1,s=0))
                Image(pos=[60,210],size=[300,70],src="http://material.motimaster.com/yuyuan/Duudle/create/bce9ecef06295fad6af331cd2e3a85f6.png",effect=fadein(d=1,t=2,c=0,p=1,s=0))
                Image(pos=[400,270],size=[300,70],src="http://material.motimaster.com/yuyuan/Duudle/create/4db38b7fd28b7ff588aa8b9d558bb9b8.png",effect=fadein(d=1.5,t=2,c=0,p=1,s=0))
                Image(pos=[100,340],size=[300,70],src="http://material.motimaster.com/yuyuan/Duudle/create/5be1b2f94b910ef607b3cbbd140702a9.png",effect=fadein(d=2,t=2,c=0,p=1,s=0))

                Image(pos=['center',620],size=[550,300],src="http://material.motimaster.com/yuyuan/Duudle/create/0b8149cc3aa0f85e11da99a04f26ccaf.png",effect=fadein(d=0.5,t=2,c=1,p=1,s=0))

                Button(text='创建我的好友回忆墙', name='begin',fontWeight=600,openType='getUserInfo',color='#663300',size=[430,90],pos=['center',1000],backgroundColor="#FEB621",borderRadius='10px',boxShadow='-1px 15px 30px -12px black',border="1rpx solid #FFD886",onTap = toBegin)
            # with Box(name='auditing_box', pos=[0,0], hidden=True, width=750):
            #     Image(name='image1',pos=[0,-40],size=[750,1325],src="img/bg2.jpg")
            #     ImageAvatar(pos=['center', 30], size=[160,160], borderRadius='50%')
            #     Text(name='text1',text='每个名字都有自己的点数', color='#FFFFFF', fontSize=24, pos=['center', 400])
            #     Input(name='input_host_name', pos= ['center',600], size=[480,80],
            #           placeholder = '请输入你的名字', border='2px solid #F24040',background='255 255 255 0.3',color='#F46060',textAlign='center')
            #     Button(name='button1', text = '提交', pos=['center',938],size=[360,78],background = 'rgba(242,64,64,0.82)',
            #                            lineHeight = 78,fontSize=36,fontWeight = 'bolder',borderRadius = '500px',
            #                            color = '#FFFFFF',boxShadow ='4px 8px 1px 3px rgba(0,0,0,0.2)',openType='getUserInfo',
            #                            onTap = [moui.showLoading('加载中...'), computeNameScore, moui.hideLoading()])

            with Box(name='loading_box', pos=[0,0], width=750):
               Image(src='img/loading.gif', size=[200, 40], pos=['center', 600])
               Text(text='加载中,请稍后...', width=750, textAlign='center', color='#ffffff', pos=['center', 700])

        with Page(name='page1', barColor='#2a2c3b', barStyle='white',enableShare=True, onReady = page1Ready):
            Image(position='fixed', top=0,size=[750,1500],src="img/bg1.jpg")
            starblink()
            Image(name='hostAvatar',pos=['center', 20],  size=[150, 150], borderRadius='50%')
            with Box(size=[650, 120],marginBottom=20, pos=['center', 200]):
                Text(name='hostName', pos=['center', 0],size=['inherit', 'inherit'],color='#FFFFFF',textAlign='center')
            #Image(name='bkimg', pos=[0,0],size=[750,1500],src="img/bg0.jpg")  #背景设置
            ContactButton(name='helpBtn',hidden=True,plain=True, border="None", pos=[650,70], size=[70, 70],borderRadius='50%',boxShadow='0px 0px 0px 2rpx gray', background='http://material.motimaster.com/harvey/5455/myrose/13266bbea43f54ee7f32d9e979f0c7d5.png')
            with ScrollBox(pos=[30, 330], size=[690,650], scrollY=True):
                with Grid(name='things', column=3):
                    with Box(width=230,height=105):
                        with Box(size=[171, 80],pos=['center',0],marginBottom=25, border='1px solid #FFD886',borderRadius='8px', background='{item.background}', color='{item.color}',
                            onTap=moui.request(makeChioce, index='{item.index}'),  display='flex',flexDirection='row',alignItems='center',justifyContent='center'):
                            Text(text='{item.text}', fontSize=26, textAlign='center',position='relative')

            Button(name='btn', text='确定',pos=['center',1030], type='plainDefault', openType='getUserInfo',border="1rpx solid #FFD886",boxShadow='-1px 15px 30px -12px black',fontSize='18px',backgroundColor="#FEB621",borderRadius='8px', onTap=submit)

            #Button(name='btn2', text='我也要玩',pos=['center',1020], type='plainDefault', background=pageColor,
            #   onTap=moui.goto('index'), hidden=True)
            # with Box(name='shareBtn', top=350, hidden=True):
                # Button(text='保存', left=150, type='miniDefault', background=pageColor,
                    # onTap=[moui.showLoading('制作中...'), onSaveImage, moui.hideLoading()])
                # ShareButton(text='分享',right=150, type='miniDefault', background=pageColor)

        with Page(name='mainpage', background="#2A2C3B",onReady=mainPageReady, onPullDownRefresh=mainPageReady, barColor='#2a2c3b', barStyle='white', enableShare=True):
            Image(position='fixed', top=0,size=[750,1500],src="img/bg1.jpg")

            with Box(pos=[0,0],position='relative'):

                Image(pos=[120,68],size=[70,2],src="img/line.png")
                Image(pos=[553,68],size=[70,2],src="img/line.png")
                Text(text='好友得分榜', color='#FFD886', fontSize=36, pos=['center', 40])
                Image(name='backLeida', pos=[49,135],size=[650,679],src="http://material.motimaster.com/yuyuan/Duudle/create/7029a94695b5c003052970aa0c4841bd.png")
                ef1 = rotate(deg=(0,360), c=0, p=0, t=5, s=0, o=(25.6,0))
                Image(name='leida',pos=[261,485],size=[439,330],src="img/leida2.png",effect=ef1)
                Image(pos=[323,437],size=[104,104],src="img/guangquan.png",effect=fadein(d=1,t=1,c=0,p=1,s=0))
                Image(name='authorAvatar', pos=[340, 453],  size=[70, 70], borderRadius='50%')
                Image(pos=[340, 453], size=[70, 70], borderRadius='50%')

                with List(name='guest_stars', background='blue'):
                    Image(position='absolute', top='{item.guangtop}', left='{item.guangleft}', src='img/guangquan.png', size=[104, 104], effect=fadeto(size=(1,0.5),d=1,t=1,c=0,p=1,s=0))
                    Image(position='absolute', top='{item.top}', left='{item.left}', src='{item.avatar}', size=[70, 70], borderRadius='50%',effect=fadeto(size=(1,0.5),d=1,t=1,c=0,p=1,s=0))

                #星星闪烁
                efbkink1 = blink("0.8, 0.4, 0.8, 1.2")
                efbkink2 = blink("0.8, 0.2, 0.3, 1.2")
                efbkink3 = blink("1.2, 0.5, 0.5, 1.2")
                efbkink4 = blink("0.5, 0.8, 0.7, 1.2")
                star = "http://img.mogodeer.cn/image/health/star.png"
                Image(src=star,pos=[10,710,15,15],effect=efbkink1)
                Image(src=star,pos=[300,130,15,15],effect=efbkink1)
                Image(src=star,pos=[200,40,25,25],effect=efbkink2)
                Image(src=star,pos=[60,250,20,20],effect=efbkink3)
                Image(src=star,pos=[60,490,20,20],effect=efbkink2)
                Image(src=star,pos=[300,520,15,15],effect=efbkink4)
                Image(src=star,pos=[400,660,25,25],effect=efbkink1)
                Image(src=star,pos=[340,290,15,15],effect=efbkink3)
                Image(src=star,pos=[360,280,15,15],effect=efbkink1)
                Image(src=star,pos=[440,320,18,18],effect=efbkink1)

                ContactButton(name='helpBtn',hidden=True,plain=True, border="None", pos=[650,70], size=[70, 70],borderRadius='50%',boxShadow='0px 0px 0px 2rpx gray', background='http://material.motimaster.com/harvey/5455/myrose/13266bbea43f54ee7f32d9e979f0c7d5.png')

                #好友得分详情
                ef55 = slideindown(t=2,c=0)
                Image(pos=[120,883],size=[70,2],src="img/line.png")
                Image(pos=[553,883],size=[70,2],src="img/line.png")
                Text(text='好友得分详情', pos=['center', 855], color='#FFD886', fontSize=36)
                Text(name='tip1',effect=ef55,hidden=True, text='点击底部按钮分享给好友来测吧！', pos=['center', 580], color='#FFFFFF', fontSize=36)
                Text(name='tip2', effect=ef55,hidden=True, text='↓↓↓', pos=['center', 650], color='#F0739B', fontSize=36)

                #详解框+内容
                with List(name='guest_records', pos=[37, 961], marginBottom=100):
                    with Box(width=684, height='{item.height}rpx',border='1px solid #5F4270',borderRadius='2%',background='#121639',marginBottom=20):
                        Box(pos=[128, 54], size=[90, 90],border='0px solid #fff',borderRadius='50%',background='#fff')
                        Image(src='{item.host_avatar}', pos=[133, 59], size=[80, 80], borderRadius='50%',)
                        Box(pos=[460, 54], size=[90, 90],border='0px solid #fff',borderRadius='50%',background='#fff')
                        Image(src='{item.guest_avatar}', pos=[465, 59], size=[80, 80], borderRadius='50%')
                        Box(pos=[269, 122], size=[140, 2],border='2px solid #F17093',borderRadius='0%',background='#F17093')
                        Text(text='{item.score}分', pos=['center', 34],color='#FFF', fontSize=42)
                        Text(text='{item.host_nick}', pos=[70, 160],size=[200,90],textAlign='center',color='#fff', fontSize=24)
                        Text(text='{item.guest_nick}', pos=[410, 160],size=[200,90],textAlign='center',color='#fff', fontSize=24)

                        Button(hidden='{item.hide_show_momery}',text='查看与ta的回忆', pos=['center', 160], size=[175,40], color='#663300',fontSize=23, lineHeight=40,border="1rpx solid #FFD886",background='#FEB621',
                        onTap=moui.request(checkDetail, host_id='{item.host_openid}', guest_id='{item.guest_openid}'))
                        Button(hidden='{item.hide_pay}',text='查看与ta的回忆', pos=['center', 160], size=[175,40], color='#663300',fontSize=23, lineHeight=40,border="1rpx solid #FFD886",background='#FEB621',
                        onTap=moui.confirm('温馨提示:','查看全部好友的选择(包括未来进入的好友),只需支付金额3.99',moui.request(checkDetailPay, host_id='{item.host_openid}', guest_id='{item.guest_openid}')))

                        Text(text='友情结语：', pos=[60, 240],color='#ED6E91', fontSize=30)
                        Text(text='{item.fit_words}', pos=[210, 240],color='#FFF', fontSize=30,size=[430, 240])

                        with Box(right=10,top=10,size=[40,40],hidden='{item.hide_delete}'):
                            with Image(name='delete',src='http://material.motimaster.com/harvey///4fe3d04c831c479268f0d039e0c5f88b.png',size=[40,40],pos=[0,0]):
                                this.onTap = moui.confirm('温馨提醒','删除的记录将不能恢复，您确认删除嘛?',moui.request(deleteRecord, rid='{item.id}'))

            with Mask(name='ansMask', hidden=True):
                with ScrollBox(scrollY=True, background='rgba(17,17,17,0.8)',borderRadius='10px',border='1px solid #FFD886',size=[550, 700], pos=['center',200]):
                    with List(name='guest_detail',position='relative'):
                        with Box(height=50):
                            Text(text='{item.answer}',fontSize=28,pos=['center',0],color="#FFFFFF")

            Box(name='bottomBox',size=[750, 100],background="#4E7ED8",border='0px solid #fff',position='fixed', bottom=0, borderRadius='0%')

            Button(name='shareBtn', hidden=True,formType='submit', onTap = goShare, text='邀请好友来测 >', size=[750, 110], position='fixed', bottom=0,borderRadius='0%',
                lineHeight=110, background="#FEB621", color="#663300", fontSize=38, fontWeight=600,openType='getUserInfo')
            ShareButton(name='shareBtnAuditing', hidden=False, formType='submit', text='邀请好友来测 >', size=[750, 100], position='fixed', bottom=0,borderRadius='0%',
                lineHeight=100, background="#FEB621", color="#663300", fontSize=36, fontWeight=600,openType='getUserInfo')

            # Box(name='midline',size=[2, 50],background="#FFF",hidden=True, border='0px solid #fff',position='fixed', right=380, bottom=28, borderRadius='0%')

            Button(name='beginPlay', hidden=True, position='fixed', bottom=0, text='创建我的好友回忆墙 >', size=[750, 100],
                lineHeight=100, background="#FEB621", color="#663300", fontSize=36,openType='getUserInfo', fontWeight=900,onTap=toBegin)

        with Page(name='share',enableShare=True):
            this.onReady = shareReady

            Image(name='shareImage',hidden=True,src='http://material.motimaster.com/yuyuan/Duudle/create/93c539e06f357977dc224f88e952ba3f.jpg',pos=[23,23,704,704])
            ImageAvatar(name='avatar',pos=[297,393,149,149],borderRadius='50%')

            Button(name='saveShareImage', hidden=True,onTap=[moui.showLoading(),saveShareImage,moui.hideLoading()],text='保存',fontWeight=900,lineHeight=80,pos=[175,780,400,80], boxShadow='-1px 10px 5px -5px #BBBBBB',fontSize='16px', color='#663300',border='1px solid #FFD886',backgroundColor="#FEB621")
            ShareButton(text='分享到好友群',pos=[175,923,400,80], color='#FFD886',border="1rpx solid #FFD886",fontSize='16px',lineHeight=80,boxShadow='-1px 15px 30px -12px black',background='#000000',type='primary')
async def beginReady(user, app, page, mo):
    if AUDITING == True:
        page.loading_box.hidden=True
        mo.redirectTo('page1',mode='auditing')
        #page.auditing_box.hidden=False
    else:
        page.loading_box.hidden=True
        rets = mo.db.hosts.find({'openid':user.openid})
        page.entrance.hidden = False
        if len(rets) !=0:
            mo.redirectTo('mainpage',is_host=1, hostopenid=user.openid)

async def computeNameScore(user, app, page, mo):
    mo.showAlert('名字点数','您的名字点数为%s'% str(int(random.random()*100)))

async def checkDetailPay(user, app, page, mo, params):
    page.data.host_id = params.host_id
    page.data.guest_id = params.guest_id
    mo.console(page.data.host_id)
    mo.console(page.data.guest_id)
    mo.wxpay.pay('查看与ta的回忆', 0.1, onPaySuccess,  onPayFail)

async def onPaySuccess(user, app, page, mo):
    tmpRecord = mo.db.guests.find({'openid':page.data.host_id,'hostopenid':page.data.guest_id})
    click_list = tmpRecord[0]['clickState']
    page.guest_detail.data = []
    page.ansMask.hidden = False
    l = [e for idx, e in enumerate(events) if click_list[idx]==1]
    for i in range(len(l)):
        page.guest_detail.data.append({'answer': l[i]})

    user.unlockAll = True
    mainPageReady(user, app, page, mo)

async def onPayFail(user, app, page, mo):
    pass
async def toBegin(user, app, page, mo):
    mo.goto('mainpage', is_host = 1)

async def goShare(user, app, page, mo):
    mo.goto('share', hostopenid = user.openid)

async def saveShareImage(user, app, page, mo):
   mo.saveImage(page.data.url)

def shareReady(user, app, page, mo):
    if AUDITING == False:
        page.saveShareImage.text = '保存朋友圈海报'
        page.saveShareImage.hidden = False

    params = {
        "page":'page1',
        "width":140,
        'options':{
            "openid": user.openid,
            'avatar':user.avatarUrl,
            'nick':user.nickName
        }
    }
    retParams = mo.acode.getWxAcodeUrl(params)
    erweima = None
    if retParams['ret'] == 0:
        erweima = retParams['url']

        canvas = mo.mopic.createCanvas(750, 750)
    canvas.addImage('http://material.motimaster.com/yuyuan/Duudle/create/93c539e06f357977dc224f88e952ba3f.jpg', pos=[0,0,750,750])

    canvas.addImage(erweima, pos=[225,350,300,300], mask='circle')
    canvas.addImage(user.avatarUrl, pos=[305, 430,140,140], mask='circle')
    res = canvas.makeImage()
    mo.console(res)
    if res['ret'] == 0:
        page.shareImage.src=res['url']
        page.data.url = res['url']

    page.shareImage.hidden = False
    page.avatar.hidden = True
    page.share.title = '你和%s的友情能打几分？来试试！' % user.nickName
    page.share.imageUrl = 'http://material.motimaster.com/yuyuan/Duudle/create/1fb03a716bec6ee8742dcbd80a1a0c77.jpg'
    page.share.page = 'page1'

    page.share.options = {
        'openid': user.openid,
        'avatar':user.avatarUrl,
        'nick':user.nickName
    }

async def page1Ready(user, app, page, mo):
    if page.options.mode == 'auditing' and page.options.openid == None:
        page.hostName.text = '在你心中，要一起做哪些事，才算是你的满分好友呢？'
        all_event = [{'index':x, 'text':events[x]} for x in range(30)]
        things_list = all_event.copy()
        for item in things_list:
            item['background'], item['color'] = 'rgba(17,17,17,0.39)', '#FFD886'
            mo.console('-%s-\n' %item['text'])
        page.things.data = things_list
        clickState = [0]*32
        page.data.set('clickState', clickState)
        page.data.set('things_list', things_list)
        page.btn.hide()

        return
    record = mo.db.guests.find({'hostopenid':page.options.openid, 'openid':user.openid})
    if page.options.openid == user.openid: # host进入跳转到mainpage
        mo.redirectTo('mainpage',is_host = 1)
        return
    if record: # guest答过跳转到mainpage
        mo.redirectTo('mainpage',is_host = 0, hostopenid=page.options.openid)
        return
    page.hostAvatar.src = page.options.avatar
    page.hostName.text = '来选出你和%s的共同回忆吧~看看你和TA的友情能拿多少分？' %page.options.nick
    all_event = [{'index':x, 'text':events[x]} for x in range(30)]
    things_list = all_event.copy()
    for item in things_list:
        item['background'], item['color'] = 'rgba(17,17,17,0.39)', '#FFD886'
        mo.console('-%s-\n' %item['text'])
    page.things.data = things_list
    clickState = [0]*32
    page.data.set('clickState', clickState)
    page.data.set('things_list', things_list)
    page.btn.hide()

async def checkDetail(user, app, page, mo, params):
    if params.host_id != user.openid and params.guest_id != user.openid:
        mo.showAlert('温馨提示:','亲，不好意思，该功能只对主人开放')
        return
    tmpRecord = mo.db.guests.find({'openid': params.guest_id,'hostopenid':params.host_id})
    click_list = tmpRecord[0]['clickState']
    page.guest_detail.data = []
    page.ansMask.hidden = False
    l = [e for idx, e in enumerate(events) if click_list[idx]==1]
    for i in range(len(l)):
        page.guest_detail.data.append({'answer': l[i]})

async def makeChioce(user, app, page, mo, params):
    all_event = [{'index':x, 'text':events[x]} for x in range(30)]
    clickState = page.data.get('clickState')
    things_list = page.data.get('things_list')
    for item in things_list:
        if item['index'] == params.index:
            if clickState[item['index']] == 0:
                item['background'], item['color'] = guestColor, 'black'
                clickState[item['index']] = 1
                if clickState.count(1) > 0:
                    page.btn.show()
            else:
                item['background'], item['color'] = 'rgba(17,17,17,0.39)', '#FFD886'
                clickState[item['index']] = 0
                if clickState.count(1) == 0:
                    page.btn.hide()
            break
    page.data.set('clickState', clickState)
    page.data.set('things_list', things_list)
    page.things.data = things_list

async def submit(user, app, page, mo):
    if page.options.mode == 'auditing' and page.options.openid == None:
        mo.redirectTo('mainpage', is_host = 1, hostopenid=page.options.openid)
        return
    clickState = page.data.get('clickState')
    count = sum(clickState)

    if count==1:
        score = random.randint(40,43)
    elif count==2:
        score = random.randint(44,47)
    elif count==3:
        score = random.randint(48,51)
    elif count==4:
        score = random.randint(51,54)
    elif count==5:
        score = random.randint(55,58)
    elif count==6:
        score = random.randint(59,62)
    elif count==7:
        score = random.randint(63,66)
    elif count==8:
        score = random.randint(67,70)
    elif count==9:
        score = random.randint(71,74)
    elif count==10:
        score = random.randint(75,78)
    elif count==11:
        score = random.randint(79,82)
    elif count==12:
        score = random.randint(83,86)
    elif count==13:
        score = random.randint(87,90)
    elif count==14:
        score = random.randint(91,93)
    elif count==15:
        score = random.randint(94,96)
    elif count==16:
        score = random.randint(97,98)
    elif count==17:
        score = 99
    else:
        score = 100

    if count in list(range(1,6)):
        words = random.choice([
                '虽然共同的回忆有点少，但这样的友情不多不少刚刚好。',
                '我们之间还差点小默契，但合适的距离能产生最合适的友情。',
                '互斥又互相吸引，我们的故事不会轰轰烈烈，但细水长流。',
                '我们不一定是最合拍，但一定是对方心中的无可替代。',
                '虽然错过了很多风景，但是未来的旅途一定会携手同行。',
                '即使有各自不同的轨道，但也能给彼此带来不一样的光和热。',
                '见面会嫌弃，离开会想念，其实内心很想粘着你~',
                '冰与火也能摩擦出光亮，我们在磨合中彼此靠近，共同进步。'
                ])
    elif count in list(range(6,9)):
        words = random.choice([
                '是彼此的一道光，给对方带来无限温暖和正能量。',
                '或许我们之间还需要磨合，但未来一定可以成全最好的自己。',
                '相爱又相互伤害，但只要你需要我，我就会在。',
                '你和我都是自由的风，却总是会在相同的时空意外相逢。',
                '双商都高，沟通不累，心照不宣是我们独有的默契。',
                '相见恨晚，志趣相投，你我都是彼此最美丽的遇见。'
                ])
    elif count in [9,10]:
        words = random.choice([
                '是彼此的小幸运，未来一定要去看更美的风景。',
                '无论快乐还是悲伤，都是彼此最不设心防的倾诉对象。',
                '这个世界很善变，但我们之间的默契随时都经得起考验。',
                '你和我是贴合的两块拼图，是理性与感性的互补。',
                '势均力敌，惺惺相惜，你和我拥有相同的颜色。'
                ])
    elif count in [11,12,13]:
        words = random.choice([
                '因为遇见，所以欣赏；因为欣赏，所以陪伴。',
                '会互相拆台也会互相崇拜，若要仗剑天涯，你是最佳拍档。',
                '相处从不会累，因为在一起时快乐总是加倍。',
                '水乳交融，恰到好处，你的一个眼神，我就能懂。',
                '天生默契，彼此之间就像是磁铁般相互吸引靠近。',
                '吃喝玩乐，样样有你，你让我拥有了更有趣的人生。'
                ])
    elif count in [14,15,16]:
        words = random.choice([
                '和优秀的人在一起会更优秀，一起打造完美世界吧！',
                '可以一秒读懂对方，连沉默都是心照不宣的默契。',
                '心灵相通，一拍即合，是你让我看到了更大的世界。',
                '会把脆弱留给对方，因为在彼此面前无需筑起心防。',
                '吵着闹着，乐在其中，有你在的时候总是最舒心。',
                '同甘共苦，福祸相依，一起哭，一起笑，一起闹。'
                ])
    else:
        words = random.choice([
                '就算世界毁灭，我们都不离不弃，绝对不松手。',
                '相遇花光了所有的运气，所以未来一定要彼此珍惜。',
                '就像是连体婴，相互陪伴是最长情的生命告白。',
                '小秘密只愿和你分享，我最信任你，也最依赖你。',
                '天作之合，完美搭配，永远是彼此最坚实的后盾。'
                ])

    mo.db.guests.insert({
        'openid'     : user.openid,
        'nick'       : user.nickName,
        'avatar'     : user.avatarUrl,
        'hostopenid' : page.options.openid,
        'score'      : score,
        'statement'  : words,
        'clickState' : clickState,
        'timestamp'  : int(time.time())
    })
    mo.goto('mainpage', is_host = 0, hostopenid=page.options.openid)

async def mainPageReady(user, app, page, mo):

    hide_pay = True

    if int(page.options.is_host) == 1:
        if user.unlockAll != True:
            hide_pay = False
        host = mo.db.hosts.find({'openid':user.openid})

        if host == []:
            tmp_id = mo.db.hosts.insert({
                'openid'    : user.openid,
                'nick'      : user.nickName,
                'avatar'    : user.avatarUrl,
                'timestamp' : int(time.time())
            })
            host = mo.db.hosts.find({'id': tmp_id})
        page.shareBtn.show()
        page.beginPlay.hide()
    else:

        hide_pay = True
        host = mo.db.hosts.find({'openid':page.options.hostopenid})
        page.shareBtn.hide()
        page.beginPlay.show()
    page.helpBtn.show()
    page.authorAvatar.src = host[0]['avatar']

    page.guest_records.data = []
    page.guest_stars.data = []
    guests = mo.db.guests.find({'hostopenid':host[0]['openid']})
    guests = sorted(guests, key=lambda x:-x['timestamp'])
    if len(guests) == 0 and AUDITING == False:
        page.tip1.show()
        page.tip2.show()

    if AUDITING or ENABLE_PAY == False:
        hide_pay = True

    for guest in guests:
        if guest['nick'] is None:
            continue

        hide_delete = True
        if user.openid == guest['openid'] or user.openid == guest['hostopenid']:
            hide_delete = False

        page.guest_records.data.append({
            'id'              : guest['id'],
            'host_avatar'     : host[0]['avatar'],
            'guest_avatar'    : guest['avatar'],
            'host_nick'       : host[0]['nick'],
            'guest_nick'      : guest['nick'],
            'score'           : guest['score'],
            'fit_words'       : guest['statement'],
            'height': 360,
            'guest_openid': guest['openid'],
            'host_openid': host[0]['openid'],
            'hide_delete': hide_delete,
            'hide_pay': hide_pay,
            'hide_show_momery': not hide_pay,
        })

        score = guest['score']
        angle = random.randint(1, 89)

        dis   = 90 + 100 * (100 - score) / 24
        dtop  = dis * math.sin(math.radians(angle))
        dleft = dis * math.cos(math.radians(angle))

        top  = 488 + random.choice([-1, 1]) * dtop - 35
        left = 375 + random.choice([-1, 1]) * dleft - 35

        guangtop  = top - 17
        guangleft = left - 17

        page.guest_stars.data.append({
            'avatar' : guest['avatar'],
            'top' : '%drpx' % top,
            'left' : '%drpx' % left,
            'guangtop' : '%drpx' % guangtop,
            'guangleft' : '%drpx' % guangleft
        })
    count = len(page.guest_records.data)
    if count > 0:
        page.guest_records.data[count-1]['height'] = page.guest_records.data[count-1]['height'] + 130
        page.shareBtn.size = [750,100]
        page.shareBtn.left = 0
        page.shareBtn.text = '邀请好友来测'
        # page.midline.show()
    else:
        page.leida.hidden = True

    page.share.title = '你和%s的友情能打几分？来试试！' % host[0]['nick']
    page.share.imageUrl = 'http://material.motimaster.com/yuyuan/Duudle/create/1fb03a716bec6ee8742dcbd80a1a0c77.jpg'
    page.share.page = 'page1'
    page.share.options = {
        'openid':host[0]['openid'],
        'avatar':host[0]['avatar'],
        'nick':host[0]['nick']
    }

    if AUDITING:
        page.shareBtn.hidden = True
        page.shareBtnAuditing.hidden = False

    else:
        page.shareBtn.hidden = False
        page.shareBtnAuditing.hidden = True

    mo.console('mainready %s' % page.share.options)

async def deleteRecord(user, app, page, mo, params):
    mo.console('确定删除')
    rid = params.rid
    mo.console(rid)
    mo.db.guests.delete(rid)
    mainPageReady(user, app, page, mo)

events=[
'一起吃过饭',
'一起合过影',
'一起唱过K',
'一起看过电影',
'一起组过队打游戏',
'一起逛过街',
'一起打过球',
'一起喝过酒',
'一起熬过夜',
'一起煲过电话粥',
'一起庆过生',
'一起逃过课',
'一起罚过站',
'一起抄过作业',
'一起追过喜欢的人',
'一起打过架',
'一起通宵看过球',
'一起玩过桌游',
'一起做过饭',
'一起骑行过',
'一起爬过山',
'一起去过游乐园',
'一起旅过游',
'一起追过星',
'一起听过演唱会',
'一起穿过基友/闺蜜装',
'一起洗过澡',
'一起搓过背',
'一起同床睡过觉',
'一起哭过'
]


from Bio import SeqIO
from Bio.Seq import Seq

def map_bowtie(f, index_name):
    handle = open(f, 'rU')
    dna = list(SeqIO.parse(handle, 'fasta'))
    handle.close()
    map_dict = {}
    counter = 1 #To comply with the GFF format file specifications needs to start at 1
    cat_genes = open(f + '.seq', 'a')
    cat_genes.write('>' + index_name + '\n') #FASTA header

    seqid_counter = 1 #To order the output of the sequence

    for sequence in dna:
        gene_len = len(str(sequence.seq))

        description = list()
        description.append(sequence.id) #id
        description.append(index_name) #bowtie index name
        description.append(counter) #start
        description.append(counter + gene_len) #end
        description.append('CDS') #Feature type: This can be exon, promotor, etc for us CDS it's ok i guess
        description.append('.') #score ???
        description.append('+') #strand
        description.append('ID=CDS'+str(seqid_counter).zfill(4)) #CDS0001, CDS0002, etc
        description.append('\n')

        map_dict[seqid_counter] = description
        seqid_counter += 1
        counter += (gene_len)
        cat_genes.write(str(sequence.seq))

    with open(f + '.map', 'w') as m:
        m.write('##gff-version 3\n')
        m.writelines('\t'.join(map(str,map_dict[k])) for k in map_dict.keys())
    return


import os

import torch

class CheckPoint(object):

    def __init__(self, root, save_fn, load_fn, record_filename="checkpoint.txt", num_record=-1, clean=False):
        self.root = root
        self.save_fn = save_fn
        self.load_fn = load_fn
        self.filename = record_filename
        self.num_record = num_record

        if not os.path.exists(root):
            os.makedirs(root)

        # clean the record file
        record_filename = os.path.join(self.root, self.filename)
        if clean and os.path.exists(record_filename):
            with open(record_filename, "w") as f:
                f.write('')

    def read_record_file(self):
        record_filename = os.path.join(self.root, self.filename)
        if not os.path.exists(record_filename):
            return []
        with open(record_filename, "r") as f:
            records = f.read().split()
            records = [i for i in records if i.strip()]
            return records

    def write_record_file(self, records):
        record_filename = os.path.join(self.root, self.filename)
        with open(record_filename, "w") as f:
            for record in records:
                f.write("{}\n".format(record))

    def save(self, filename, *args):
        if not os.path.isabs(filename):
            filename = os.path.join(self.root, filename)
        self.save_fn(filename, *args)
        records = self.read_record_file()
        records.append(filename)

        if 0 < self.num_record < len(records):
            while self.num_record < len(records):
                record = records.pop(0)
                try:
                    os.remove(record)
                except Exception:
                    pass

        self.write_record_file(records)

    def load(self, filename):
        self.load_fn(filename)

    def try_load_last(self):
        record_filename = os.path.join(self.root, self.filename)
        if not os.path.exists(record_filename):
            return
        with open(record_filename, "r") as f:
            records = f.read().split()
            records = [i for i in records if i.strip()]

        if len(records) > 0:
            self.load_fn(records[-1])

def search_checkpoint_records(save_dir):
    checkpoint_files = []
    if os.path.exists(save_dir):
        checkpoint_record = os.path.join(save_dir, "checkpoint.txt")
        if os.path.exists(checkpoint_record):
            for line in open(checkpoint_record):
                if line.strip() != "":
                    # print(line.strip())
                    checkpoint_files.append(line.strip())
    while len(checkpoint_files) > 5:
        try:
            print("remove {}".format(checkpoint_files[0]))
            os.remove(os.path.join(save_dir, checkpoint_files.pop(0)))
        except Exception:
            pass

    return checkpoint_files

def save_checkpoint_records(checkpoint_files, save_dir):
    with open(os.path.join(save_dir, "checkpoint.txt"), "w") as f:
        for checkpoint_file in checkpoint_files:
            f.write("{}\n".format(checkpoint_file))

def save_checkpoint(model, optimizer, scheduler, epoch, path):
    save_dir = os.path.dirname(path)
    checkpoint_files = search_checkpoint_records(save_dir)
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    if len(checkpoint_files) == 5:
        try:
            os.remove(os.path.join(save_dir, checkpoint_files.pop(0)))
        except Exception:
            pass
    checkpoint_files.append(os.path.basename(path))
    torch.save({
        "epoch": epoch,
        "model_state_dict": model.state_dict(),
        "optimizer_state_dict": optimizer.state_dict(),
        "scheduler_state_dict": scheduler.state_dict(),
    }, path)

    save_checkpoint_records(checkpoint_files, save_dir)

def load_checkpoint(save_path):
    checkpoint_path = save_path
    if os.path.isdir(save_path) and os.path.exists(save_path):
        checkpoint_records = search_checkpoint_records(save_path)
        if len(checkpoint_records) == 0:
            raise FileNotFoundError(os.path.join(save_path, "checkpoint.txt"))
        checkpoint_path = os.path.join(save_path, checkpoint_records[-1])
    print("restore checkpoint from {}".format(checkpoint_path))
    if os.path.exists(checkpoint_path):
        return torch.load(checkpoint_path, map_location="cpu")
    else:
        raise FileNotFoundError(checkpoint_path)

def log_loss(losses, save_dir, epoch, mode="train"):
    assert isinstance(losses, list)
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    with open(os.path.join(save_dir, "{}.txt".format(mode)), "a") as f:
        f.write("{} ".format(epoch))
        for loss in losses:
            f.write("{} ".format(loss))
        f.write("\n")


# Python Code
# Opening a google map in a browser and taking from clipboard or command
import sys,webbrowser,pyperclip
# here sys is for command line argv is what we will type if its greater than 1
# We added / joined that data and gave it to add.
if len(sys.argv)>1:
	add = ''.join(sys.argv[1:])
else:
	add = pyperclip.paste()
#pyperclip is used for clipboard
webbrowser.open('www.google.com/maps/search/?api=1&query='+add)
# now above link is for opening and searching maps
# Searching example :
# New York
# Aurangabad
# Rajasthan


# uncompyle6 version 3.6.7
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: /Users/martijndevos/Documents/anydex-core/pyipv8/ipv8/dht/storage.py
# Compiled at: 2019-05-16 09:27:10
from __future__ import absolute_import
import time, hashlib
from collections import defaultdict

class Value(object):
    """
    Class for storing DHT values.
    """

    def __init__(self, id_, data, max_age, version):
        self.id = id_
        self.data = data
        self.last_update = time.time()
        self.max_age = max_age
        self.version = version

    @property
    def age(self):
        return time.time() - self.last_update

    @property
    def expired(self):
        return self.age > self.max_age

    def __eq__(self, other):
        return self.id == other.id

    def __hash__(self):
        return 0

class Storage(object):
    """
    Class for storing key-value pairs in memory.
    """

    def __init__(self):
        self.items = defaultdict(list)

    def put(self, key, data, id_=None, max_age=86400, version=0):
        id_ = id_ or hashlib.sha1(data).digest()
        new_value = Value(id_, data, max_age, version)
        try:
            index = self.items[key].index(new_value)
            old_value = self.items[key][index]
            if new_value.version >= old_value.version:
                del self.items[key][index]
                self.items[key].insert(0, new_value)
                self.items[key].sort(key=lambda v: 1 if v.id == key else 0)
        except ValueError:
            self.items[key].insert(0, new_value)
            self.items[key].sort(key=lambda v: 1 if v.id == key else 0)

    def get(self, key, limit=None):
        if key in self.items:
            return [ value.data for value in self.items[key][:limit] ]
        return []

    def items_older_than(self, min_age):
        items = []
        for key in self.items:
            items += [ (key, value.data) for value in self.items[key] if value.age > min_age ]

        return items

    def clean(self):
        for key in self.items:
            for index, value in reversed(list(enumerate(self.items[key]))):
                if value.expired:
                    del self.items[key][index]
                else:
                    break


from math import sqrt
import numpy as np
from scipy import linalg
from sklearn import datasets

def cholesky(A, b):
    n = len(A)
    L = np.zeros((n,n))

    # Decomposição de Cholesky
    for i in range(n):
        for k in range(i+1):
            left_elements_sum = sum(L[i][j] * L[k][j] for j in range(k)) # Nem roda para a primeira iteracao

            if (i == k): # Elementos da diagonal
                if A[i][i] - left_elements_sum < 0:
                    print("A[i][i] eh {:.19f}".format(A[i][i]))
                    print("left_elements_sum eh {:.19f}".format(left_elements_sum))
                L[i][k] = sqrt(A[i][i] - left_elements_sum)
            else:
                L[i][k] = (A[i][k] - left_elements_sum) / L[k][k]

    y_vector = np.array(np.zeros(n))

    # STEP 8
    y_vector[0] = b[0] / L[0][0]

    # STEP 9
    for i in range (1, n): # CHECK
        sum_y = sum(L[i][j] * y_vector[j] for j in range(i))
        y_vector[i] = (b[i] - sum_y) / L[i][i]

    # STEP 10
    x_vector = np.array(np.zeros(n))

    x_vector[-1] = y_vector[-1] / L[-1][-1]

    # STEP 11
    for i in range(n-2, -1, -1):
        sum_x = sum(L[j][i] * x_vector[j] for j in range(i+1, n))
        x_vector[i] = (y_vector[i] - sum_x) / L[i][i]

    # STEP 12
    return x_vector

# A = np.array([[6, 3, 4, 8], [3, 6, 5, 1], [4, 5, 10, 7], [8, 1, 7, 25]])
A = np.array([[4, 2, 2], [2, 6, 2], [2, 2, 5]])
# B = np.array([[25, 15, -5],
# [15, 18, 0],
# [-5, 0, 11]])

dimension = 18
# reference_matrix = A
reference_matrix = linalg.hilbert(dimension)
# reference_matrix = datasets.make_spd_matrix(dimension)

vector_b = np.array([reference_matrix[i].sum() for i in range (0, len(reference_matrix))]) # Generating vector b, the sum of Hilbert matrices rows
# vector_b = [0, 1, 0]
vector_x = cholesky(reference_matrix, vector_b)

# print("Matriz referência:")
# print(augmented_hilbert_matrix)

# print("L:")
# print(L)

# print(linalg.cholesky(reference_matrix))

# print("L transposta:")
# print(np.transpose(L))

print("vector_x:")
print(vector_x)


#!/usr/bin/env python3

import numpy as np

class Map:
    elf_identifier = "E"
    goblin_identifier = "G"

    def __init__(self, init_list):
        self._map = np.array(init_list)
        self._rounds_count = 0
        self._elves = []
        self._goblins = []
        for coord in np.transpose(np.where(np.multiply(self._map != "#", self._map != "."))):
            pos = (coord[1], coord[0])
            player = self._map[tuple(coord)]
            if player == self.goblin_identifier:
                self._goblins.append(Fighter(pos, str(player)))
            elif player == self.elf_identifier:
                self._elves.append(Fighter(pos, str(player)))
            else:
                raise ValueError("Unrecognized fighter: {}".format(player))
            self._map[tuple(coord)] = "."

    def __getitem__(self, key):
        if type(key) != tuple:
            raise IndexError("invalid index value: {}".format(key))
        elif len(key) != 2:
            raise IndexError("key tuple should be of size 2 ({} found)".format(len(key)))
        t_key = (key[1], key[0])
        for elf in self._elves:
            if elf._coord == key:
                return self.elf_identifier
        for goblin in self._goblins:
            if goblin._coord == key:
                return self.goblin_identifier
        return self._map[t_key]

    def __repr__(self):
        res = ""
        fighters = ""
        for y in range(self._map.shape[0]):
            for x in range(self._map.shape[1]):
                elem = self[x,y]
                res+= elem
                if elem in (self.elf_identifier, self.goblin_identifier):
                    fighters+= str(self.fighter_at((x,y))) + "\n"

            res+="\n"

        return res
        return res+fighters[:len(fighters)-1]

    def fighter_at(self, key):
        if type(key) != tuple:
            raise IndexError("invalid index value: {}".format(key))
        elif len(key) != 2:
            raise IndexError("key tuple should be of size 2 ({} found)".format(len(key)))

        for elf in self._elves:
            if elf._coord == key:
                return elf
        for goblin in self._goblins:
            if goblin._coord == key:
                return goblin
        raise IndexError("no fighter found at given coordinates: {}".format(key))

    def take_turn(self):
        fighters = sorted(self._elves + self._goblins, key=lambda x: (x._coord[1], x._coord[0])) # Ordered list of fighters
        for fighter in fighters: # We iterate through each fighter
            ## WINNER CHECKING PHASE ##

            if self.winner(): # If we already have a winner
                self._rounds_count-= 1 # We remove this round because it was not completed
                break

            if not fighter.is_alive(): # The fighter may have been killed by another fighter
                continue

            ## MOVING PHASE ##

            opponents = self._goblins if fighter._side == self.elf_identifier else self._elves # Get the list of opponents of the current fighter
            target_coords = sorted([item for sublist in [neighbour_coords(t._coord) for t in opponents] for item in sublist], key=lambda x: (x[1], x[0])) # Get the neighboring tiles for each opponent, and order them
            if not fighter._coord in target_coords: # If the fighter is already on a target, don't move it
                fighter_dijkstra, distances = self.dijkstra(fighter, target_coords) # Compute dijkstra for the current fighter

                min_dist = None
                min_targets = []
                for target_coord in target_coords: # We find the first reachable target coordinate
                    if distances[target_coord] == -1: # Target is unreachable
                        continue
                    if (min_dist == None) or (distances[target_coord] < min_dist):
                        min_dist = distances[target_coord]
                        min_targets = [target_coord]
                    elif (min_dist != None) and (distances[target_coord] == min_dist):
                        min_targets.append(target_coord)
                if len(min_targets) != 0: # If we have a reachable target
                    candidate_moves = [] # Each value is [move, destination tile], so that we can resolve a tie
                    for min_target in min_targets:
                        candidate_moves.append([fighter_dijkstra[min_target][0], min_target])

                    candidate_moves = sorted(candidate_moves, key=lambda x: (x[1][1], x[1][0], x[0][1], x[0][0]))

                    fighter._coord = candidate_moves[0][0] # And we move the player

            ## ATTACKING PHASE ##

            neighbours = neighbour_coords(fighter._coord)
            targets = []
            for neighbour in neighbours: # We get each available target among fighter's neighbours
                try:
                    candidate = self.fighter_at(neighbour)
                    if candidate._side != fighter._side:
                        targets.append(candidate)
                except IndexError: # We skip this neighbour is there is no target
                    pass
            if len(targets) == 0: # If we have no target, the fighter doesn't attack
                continue

            targets = sorted(targets, key=lambda x: (x._health, x._coord[1], x._coord[0])) # We sort potential target by health, then by reading order
            target = targets[0]

            killed = fighter.hit(target)

            if killed:
                if target._side == self.goblin_identifier:
                    self._goblins.remove(target)
                else:
                    self._elves.remove(target)

        # At last we increase the rounds counter
        self._rounds_count+= 1

    def dijkstra(self, origin, t_coords):
        target_coords = t_coords.copy()
        distances = np.transpose(np.ones_like(self._map, dtype=int)) # We use a transposed distance array, to work using our coordinate system (X,Y) instead of matrixes's one (Y,X)
        distances[:] = -1
        distances[origin._coord] = 0

        result = np.ones_like(distances, dtype=list) # An item looks like [<coord of the move to perform to eventually reach this point>, <next step>] (a coord is a 2-tuple)
        result[:] = None

        w, h = distances.shape
        nodes = [(a,b) for a,b in zip(list(np.repeat(np.arange(w), h)), list(np.arange(h))*w) if (self[a,b] == ".") or ((a,b) == origin._coord)]
        first_moves = neighbour_coords(origin._coord)

        while (len(nodes) != 0) and (len(target_coords) != 0):
            # We find the nearest non explored node from origin
            min_dist = -1
            nearest = None
            for node in nodes:
                dist = distances[node]
                if (dist != -1) and ((min_dist == -1) or (dist < min_dist)):
                    min_dist = dist
                    nearest = node

            if nearest is None: # No more reachable nodes
                break

            # We remove the nearest non explored node from the list of non explored nodes, and if it was a target node we remove it from the list of non explored target nodes as well
            nodes.remove(nearest)
            if nearest in target_coords:
                target_coords.remove(nearest)

            # We update distances for each neighbor of nearest
            neighbours = neighbour_coords(nearest)

            for neighbour in neighbours:
                if (self[neighbour] == ".") and ((distances[neighbour] == -1) or (distances[neighbour] >= distances[nearest] + 1)):
                    if neighbour in first_moves: # If we are computing the first moves around the origin
                        result[neighbour] = [neighbour, nearest] # Nearest is the origin here
                        distances[neighbour] = 1
                    else:
                        #if (distances[neighbour] != distances[nearest] + 1) or ((nearest[1], nearest[0]) < (result[neighbour][1], result[neighbour][0])):
                        if (distances[neighbour] != distances[nearest] + 1) or ((result[nearest][0][1], result[nearest][0][0]) < (result[neighbour][0][1], result[neighbour][0][0])):
                            result[neighbour] = [result[nearest][0], nearest]
                            distances[neighbour] = distances[nearest] + 1

        return result, distances

    def winner(self):
        return self.elf_identifier if len(self._goblins) == 0 else self.goblin_identifier if len(self._elves) == 0 else None

class Fighter:
    def __init__(self, pos, side, health=200, power=3):
        if (type(pos) != tuple) or (len(pos) != 2):
            raise ValueError("pos should be a tuple of size 2 ({} given)".format(type(pos)))
        if (type(health) != int) or (health <= 0):
            raise ValueError("health should be a positive integer ({} given)".format(health))
        if (type(power) != int) or (power <= 0):
            raise ValueError("power should be a positive integer ({} given)".format(power))
        if (type(side) != str):
            raise ValueError("side should be a string ({} given)".format(type(side)))
        self._coord = pos
        self._side = side
        self._health = health
        self._power = power

    def __repr__(self):
        return "{}({}, {})={}".format(self._side, self._coord[0], self._coord[1], self._health, self._power)

    def is_alive(self):
        return self._health > 0

    def hit(self, target):
        if type(target) != type(self):
            raise ValueError("target should be a Fighter ({} given)".format(type(target)))
        target._health-= self._power
        return target._health <= 0

def neighbour_coords(nearest):
    return [(nearest[0], nearest[1]-1), (nearest[0]-1, nearest[1]), (nearest[0]+1, nearest[1]), (nearest[0], nearest[1]+1)]

def play_file(path, verbose=False):
    raw_map = []
    with open(path) as input_file:
        for _, raw_line in enumerate(input_file):
            raw_map.append(list(raw_line.replace("\n", "")))

    battle_map = Map(raw_map)

    if verbose:
        pass
        print("Initial map")
        print(battle_map)
        print("")
    while battle_map.winner() is None:
        battle_map.take_turn()
        if verbose:
            if battle_map.winner() is None:
                print("Round #{}".format(battle_map._rounds_count))
            else:
                print("We've got a winner!")
            print(battle_map)
            print("")

    score = sum([f._health for f in battle_map._elves+battle_map._goblins])
    result = battle_map._rounds_count * score
    return result

print("Answer for puzzle #29: {}".format(play_file("input", verbose=True)))


""" Face Color Machine Learning code """
from collections import Counter
import pprint
import base64
from io import BytesIO
from facenet_pytorch import MTCNN, InceptionResnetV1, extract_face
from PIL import Image, ImageDraw
import numpy as np
import cv2
from sklearn.cluster import KMeans
import imutils
from matplotlib import pyplot as plt
#from matplotlib.figure import Figure
#path = 'backend/ml/image/anne-marie'
plt.switch_backend('Agg')

resnet = InceptionResnetV1(pretrained='vggface2').eval()

def img_to_face(image_path):
    if not isinstance(image_path, str):
        final_path = image_path
    else:
        final_path = 'media/' + str(image_path)
    img = Image.open(final_path).convert('RGB')
    mtcnn = MTCNN(image_size=100)
    # Get cropped and prewhitened image tensor
    img_cropped = mtcnn(img, save_path='media/output/face.png')
    # Calculate embedding (unsqueeze to add batch dimension)
    img_embedding = resnet(img_cropped.unsqueeze(0))
    # Or, if using for VGGFace2 classification
    resnet.classify = True
    img_probs = resnet(img_cropped.unsqueeze(0))

#img_to_face(path)

def extractSkin(image):
    # Taking a copy of the image
    img = image.copy()
    # Converting from BGR Colours Space to HSV
    img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # Defining HSV Threadholds
#     lower_threshold = np.array([0, 0, 0], dtype=np.uint8) # 0 48 80
#     upper_threshold = np.array([255, 255, 255], dtype=np.uint8) # 26 255 255

    lower_threshold = np.array([0, 48, 80], dtype=np.uint8) # 0 48 80 0 133 77
    upper_threshold = np.array([20, 255, 255], dtype=np.uint8) # 26 255 255 255 173 127

    # Single Channel mask,denoting presence of colours in the about threshold
    skinMask = cv2.inRange(img, lower_threshold, upper_threshold)

    # Cleaning up mask using Gaussian Filter
    skinMask = cv2.GaussianBlur(skinMask, (3, 3), 0)

    # Extracting skin from the threshold mask
    skin = cv2.bitwise_and(img, img, mask=skinMask)

    # Return the Skin image
    return cv2.cvtColor(skin, cv2.COLOR_HSV2BGR)

def removeBlack(estimator_labels, estimator_cluster):

    # Check for black
    hasBlack = False

    # Get the total number of occurance for each color
    occurance_counter = Counter(estimator_labels)

    # Quick lambda function to compare to lists
    def compare(x, y): return Counter(x) == Counter(y)

    # Loop through the most common occuring color
    for x in occurance_counter.most_common(len(estimator_cluster)):

        # Quick List comprehension to convert each of RBG Numbers to int
        color = [int(i) for i in estimator_cluster[x[0]].tolist()]

        # Check if the color is [0,0,0] that if it is black
        if compare(color, [0, 0, 0]) == True:
            # delete the occurance
            del occurance_counter[x[0]]
            # remove the cluster
            hasBlack = True
            estimator_cluster = np.delete(estimator_cluster, x[0], 0)
            break

    return (occurance_counter, estimator_cluster, hasBlack)

def getColorInformation(estimator_labels, estimator_cluster, hasThresholding=False):

    # Variable to keep count of the occurance of each color predicted
    occurance_counter = None

    # Output list variable to return
    colorInformation = []

    # Check for Black
    hasBlack = False

    # If a mask has be applied, remove th black
    if hasThresholding == True:

        (occurance, cluster, black) = removeBlack(
            estimator_labels, estimator_cluster)
        occurance_counter = occurance
        estimator_cluster = cluster
        hasBlack = black

    else:
        occurance_counter = Counter(estimator_labels)

    # Get the total sum of all the predicted occurances
    list_occurance_counter = list(occurance_counter.values())
    totalOccurance = int(sum(list_occurance_counter))

    # Loop through all the predicted colors
    for x in occurance_counter.most_common(len(estimator_cluster)):

        index = (int(x[0]))

        # Quick fix for index out of bound when there is no threshold
        index = (index-1) if ((hasThresholding & hasBlack)
                              & (int(index) != 0)) else index

        # Get the color number into a list
        color = estimator_cluster[index].tolist()

        # Get the percentage of each color
        color_percentage = (int(x[1])/totalOccurance)

        # make the dictionay of the information
        colorInfo = {"cluster_index": index, "color": color,
                     "color_percentage": color_percentage}

        # Add the dictionary to the list
        colorInformation.append(colorInfo)

    return colorInformation

def extractDominantColor(image, number_of_colors= 20, hasThresholding=False):

    # Quick Fix Increase cluster counter to neglect the black(Read Article)
    if hasThresholding == True:
        number_of_colors += 1

    # Taking Copy of the image
    img = image.copy()

    # Convert Image into RGB Colours Space
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    # Reshape Image
    img = img.reshape((img.shape[0]*img.shape[1]), 3)

    # Initiate KMeans Object
    estimator = KMeans(n_clusters=number_of_colors, random_state=0)

    # Fit the image
    estimator.fit(img)

    # Get Colour Information
    colorInformation = getColorInformation(
        estimator.labels_, estimator.cluster_centers_, hasThresholding)
    return colorInformation

def savepic(user_id):
    """save pictures """
    image = cv2.imread("media/output/face.png")
    plt.subplot(3, 1, 1)
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    skin = extractSkin(image)
    plt.subplot(3, 1, 2)
    plt.imshow(cv2.cvtColor(skin, cv2.COLOR_BGR2RGB))
    dominantcolors = extractDominantColor(skin, hasThresholding=True)
    colour_bar = plotColorBar(dominantcolors)
    plt.subplot(3, 1, 3)
    plt.axis("off")
    plt.imshow(colour_bar)
    plt.savefig('media/output/colorbar' + user_id + '.png')
    plt.close()
    #fig = Figure()
    #ax = fig.subplots()
    #ax.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), cv2.cvtColor(skin, cv2.COLOR_BGR2RGB),
    # colour_bar)
    #buf = BytesIO()
    #fig.savefig('color_bar', format="png")
    return

def plotColorBar(colorInformation):
    """ create a 500*100 color bar """
    color_bar = np.zeros((100, 500, 3), dtype="uint8")

    top_x = 0
    for x in colorInformation:
        bottom_x = top_x + (x["color_percentage"] * color_bar.shape[1])

        color = tuple(map(int, (x['color'])))

        cv2.rectangle(color_bar, (int(top_x), 0),
                      (int(bottom_x), color_bar.shape[0]), color, -1)
        top_x = bottom_x
    return color_bar

def tone_analysis(img_path, user_id):
    """ tone_analysis method """
    # pylint: disable=line-too-long,no-member,too-many-locals,no-self-use
    img_to_face(img_path)
    image = cv2.imread("media/output/face.png")
    savepic(user_id)
    image = imutils.resize(image, width=250)
    skin = extractSkin(image)
    dominantColors = extractDominantColor(skin, hasThresholding=True)
    max_color = [0,0,0]
    sel_color = [0,0,0]
    site1 = 0
    site2 = 1
    for i in range(20):
        lum = dominantColors[i].get('color')[0]*0.2126 + dominantColors[i].get('color')[1]*0.7152 + dominantColors[i].get('color')[2]*0.0722
        max_lum = max_color[0]*0.2126 + max_color[1]*0.7152 + max_color[2]*0.0722
        sel_lum = sel_color[0]*0.2126 + sel_color[1]*0.7152 + sel_color[2]*0.0722
        if max_lum < lum:
            sel_color[0] = max_color[0]
            sel_color[1] = max_color[1]
            sel_color[2] = max_color[2]
            max_color[0] = dominantColors[i].get('color')[0]
            max_color[1] = dominantColors[i].get('color')[1]
            max_color[2] = dominantColors[i].get('color')[2]
            site2 = site1
            site1 = i
        elif sel_lum < lum:
            sel_color[0] = dominantColors[i].get('color')[0]
            sel_color[1] = dominantColors[i].get('color')[1]
            sel_color[2] = dominantColors[i].get('color')[2]
            site2 = i
    return sel_color


from abc import ABCMeta, abstractmethod

import numpy

from moravka_dp.input.document_source import LabeledDoc
from moravka_dp.utils.docs_utils import doc_to_tokens_list

class InputDataProviderBase(object):
    __metaclass__ = ABCMeta
    _dimension = -1

    @abstractmethod
    def make_data(self, docs, all_labels):
        """
        Child classes must implemented this.
        This function should convert documents (collection of LabeledDoc instances) into two numpy matrices, where each
         row of the first matrix is a vector representation of one document and corresponding row of the second matrix
         contains vector representation of this document's labels.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: matrix of documents' representations and matrix of their labels' representations
        """
        pass

    def get_input_dimension(self):
        """
        Returns length of vectors that represent the documents.
        Implementing subclasses must set this field (_dimension).

        :return: Length of vectors that represent the documents.
        """
        if self._dimension < 1:
            raise ValueError('Implementing input provider did not set dimension!')
        return self._dimension

    @abstractmethod
    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        pass

class InputProviderWordVectors(InputDataProviderBase):
    """
    Provides documents represented as matrices (of size vector_length X num_words) of word vectors if mode is 'matrix',
     or as vectors (of size vector_length) made of averaged word vectors if mode is 'avg'.

    The word vectors are trained by Gensim' word2vec.
    """

    def __init__(self, word_vectors, num_words=100, mode='matrix'):
        """
        :param word_vectors: instance of moravka_dp.input.distributed_representation.MyWord2vec class
        :param num_words: maximum of words that are to be taken from each document; if the document is shorter,
        the resulting matrix will be padded with zeros
        :param mode: how to form document's representation. If mode is 'matrix' then document will be a matrix formed
         from word vectors. If mode is 'avg' these word vectors will be averaged forming a single vector.
        """
        self._num_words = num_words
        if word_vectors is None:
            raise ValueError('Word Vectors can\'t be None')
        self._word_vectors = word_vectors
        self._dimension = word_vectors.get_dimension()
        if mode not in ['matrix', 'avg']:
            raise ValueError('Mode must be one of: matrix, avg')
        self._mode = mode

    def _get_vector(self, word):
        """
        Returns word vector for a given word.
        Returns None, If word2vec's vocabulary doesn't contain this word.

        :param word: a word
        :return: word vector or None for unknown words
        """
        return self._word_vectors.get_word_vector(word)

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where first matrix represents
         documents. Second one represents documents' labels.

        The SECOND matrix is always 2-dimensional, where each row represents one document's labels.

        The FIRST matrix is 3-dimension if the MODE parameter is 'matrix', where each layer represents one document.
        If the MODE parameter is 'avg', this matrix is 2-dimensional (one row = one document)

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: float matrix of documents' vector representations and integer matrix representation of their labels
        """
        ret_dataset = numpy.zeros(shape=[len(docs), self._num_words, self._dimension], dtype=float)
        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)], dtype=int)
        for index, doc in enumerate(docs):
            word_idx = 0
            for word in doc_to_tokens_list(doc):
                if word_idx == self._num_words:
                    break
                vec = self._get_vector(word)
                if vec is not None:
                    ret_dataset[index, word_idx] = vec
                    word_idx += 1
            labels = doc.labels
            for lab in labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1

        if self._mode == 'avg':
            ret_dataset = ret_dataset.mean(axis=1)
        return ret_dataset, ret_labels

    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        return {'Type': 'Word vectors', 'Num_words': self._num_words,
                'Word2Vec:': self._word_vectors.get_config_dict()}

class InputProviderWordVectorsEmb(InputProviderWordVectors):
    """
     Provides documents represented as a vector of vocabulary indices(of size num_words) for NN's embedding layer.
      You can use method get_embeddings() to retrieve matrix of all words in vocabulary (matrix will have size
      vocabulary_size X num_words). This matrix can be inserted into the embedding layer.

     The word vectors are trained by Gensim' word2vec.
    """

    def __init__(self, word_vectors, dic, vocabulary_size=10000, num_words=100):
        """

        :param word_vectors: instance of moravka_dp.input.distributed_representation.MyWord2vec class
        :param dic: instance of gensim.corpora.Dictionary
        :param vocabulary_size: vocabulary size
        :param num_words: number of valid words in each document (if the document has more, the words will be cut off.
        If the document has less, it will be padded with zeros)
        """
        super().__init__(word_vectors, num_words=num_words)
        self._vocabulary_size = vocabulary_size
        self._dictionary = dic

    def get_embeddings(self):
        """
        :return: list (of length vocabulary_size) of embeddings for all words in the vocabulary
        """
        emb = numpy.zeros(shape=(self._vocabulary_size, self._dimension))
        for key, value in self._dictionary.token2id.items():
            emb[value] = self._word_vectors.get_word_vector(key)
        return emb

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where first matrix represents
         documents. Second one represents documents' labels.

        The SECOND matrix is always 2-dimensional, where each row represents one document's labels.

        The FIRST matrix is always 2-dimensional, where each row represents one document. Document is represented by a
        vector (of length 'num_words' (constructor parameter)) of vocabulary indices of words in this document.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: float matrix of documents' vector representations and integer matrix representation of their labels
        """
        ret_dataset = numpy.zeros(shape=[len(docs), self._num_words])
        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)], dtype=int)
        for index, doc in enumerate(docs):
            vec = numpy.zeros(shape=self._num_words)
            idx = 0
            for word in doc_to_tokens_list(doc):
                if word in self._dictionary.token2id:
                    vec[idx] = self._dictionary.token2id[word]
                    idx += 1
                if idx == self._num_words:
                    break
            ret_dataset[index] = vec
            labels = doc.labels
            for lab in labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1
        return ret_dataset, ret_labels

    def get_input_dimension(self):
        return self._num_words

    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        return {'Type': 'Vector (embedding)', 'Vocabulary size': self._vocabulary_size,
                'Num_words': str(self._num_words), 'Word2Vec': self._word_vectors.get_config_dict()}

class InputProviderWordVectorsHier(InputDataProviderBase):
    """
    Provides documents represented as matrices (of size vector_length X num_words) of sentence vectors. Each sentence
     vector is formed by averaging word vectors.

    The word vectors are trained by Gensim's word2vec.
    """

    def __init__(self, word_vectors, num_sentences=15):
        """
        :param word_vectors: instance of moravka_dp.input.distributed_representation.MyWord2vec class
        :param num_sentences: maximum of sentences that are to be taken from each document; if the document is shorter,
        the resulting matrix will be padded with zeros. This parameter must be greater than 0
        """
        self._num_sentences = num_sentences
        if word_vectors is None:
            raise ValueError('Word Vectors can\'t be None')
        self._dimension = word_vectors.get_dimension()
        self._word_vectors = word_vectors

    def _get_vector(self, word):
        """
        Returns word vector for a given word.
        Returns None, If word2vec's vocabulary doesn't contain this word.

        :param word: a word
        :return: word vector or None for unknown words
        """
        return self._word_vectors.get_word_vector(word)

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where first matrix represents
         documents. Second one represents documents' labels.

        The SECOND matrix is 2-dimensional, where each row represents one document's labels.

        The FIRST matrix is 3-dimension, where each layer represents one document.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: float matrix of documents' vector representations and integer matrix representation of their labels
        """
        ret_dataset = numpy.zeros(shape=[len(docs), self._num_sentences, self._dimension], dtype=float)
        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)], dtype=int)
        for index, doc in enumerate(docs):
            sent_idx = 0
            sent_repr = numpy.zeros(shape=[0, self._dimension], dtype=float)
            for sentence in doc.content:
                if sent_idx == self._num_sentences:
                    break
                for word in sentence.split():
                    vec = self._get_vector(word)
                    if vec is not None:
                        sent_repr = numpy.vstack([sent_repr, vec])
                if sent_repr.shape[0] == 0:
                    sent_repr = numpy.zeros(shape=[1, self._dimension], dtype=float)
                ret_dataset[index, sent_idx] = sent_repr.mean(axis=0)
                sent_idx += 1
            for lab in doc.labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1

        return ret_dataset, ret_labels

    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        return {'Type': 'Word vectors (hierarchical)', 'Num_sentences': self._num_sentences,
                'Word2Vec:': self._word_vectors.get_config_dict()}

class InputProviderParagraphVectors(InputDataProviderBase):

    def __init__(self, paragraph_vectors=None, input_dimension=150):
        """
        :param paragraph_vectors: instance of moravka_dp.distributed_representation.MyDoc2vec class
        :param input_dimension: dimension of document vectors
        """
        self._dimension = input_dimension
        if paragraph_vectors is None:
            raise Exception('Paragraph Vectors can\'t be None')
        self._paragraphVectors = paragraph_vectors

    def _get_vector(self, doc, doc_id=None):
        """
        Returns paragraph vector for a given document (LabeledDoc instance).

        :param doc: LabeledDoc instance
        :param doc_id: document id (to retrieve a vector of a document that was used for training)
        :return: paragraph vector
        """
        return self._paragraphVectors.get_doc_vector(doc, doc_id)

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where each
         row of the first matrix is a vector representation of one document and corresponding row of the second matrix
         contains vector representation of this document's labels.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: float matrix of documents' vector representations and integer matrix representation of their labels
        """
        ret_dataset = numpy.zeros(shape=[len(docs), self._dimension], dtype=float)
        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)], dtype=int)
        for index, doc in enumerate(docs):
            vec = self._get_vector(doc, doc_id=doc.id)
            if vec is not None:
                ret_dataset[index] = vec
            labels = doc.labels
            for lab in labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1
        return ret_dataset, ret_labels

    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        return {'Type': 'Paragraph vectors', 'Doc2Vec:': self._paragraphVectors.get_config_dict()}

class InputProviderParagraphVectorsHier(InputProviderParagraphVectors):

    def __init__(self, paragraph_vectors=None, input_dimension=150, num_sentences=20):
        """
        :param paragraph_vectors: instance of moravka_dp.distributed_representation.MyDoc2vec class
        :param input_dimension: dimension of document vectors
        :num_sentences: maximal number of sentences (=rows of a matrix that represents a document)
        """
        super().__init__(paragraph_vectors, input_dimension)
        self._num_sentences = num_sentences

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where each
         row of the first matrix is a vector representation of one document and corresponding row of the second matrix
         contains vector representation of this document's labels.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: float matrix of documents' vector representations and integer matrix representation of their labels
        """
        ret_dataset = numpy.zeros(shape=[len(docs), self._num_sentences, self._dimension], dtype=float)
        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)], dtype=int)
        for index, doc in enumerate(docs):
            sent_idx = 0
            for idx, sentence in enumerate(doc.content):
                if sent_idx == self._num_sentences:
                    break
                d_id = str(doc.id) + '_' + str(idx)
                vec = self._get_vector(LabeledDoc(content=[sentence], labels=doc.labels, doc_id=d_id), doc_id=d_id)
                if vec is not None:
                    ret_dataset[index, sent_idx] = vec
                    sent_idx += 1
            labels = doc.labels
            for lab in labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1
        return ret_dataset, ret_labels

    def get_config_dict(self):
        return {'Type': 'Paragraph vectors (hierarchical)', 'Doc2Vec:': self._paragraphVectors.get_config_dict()}

class InputProviderBagOfWords(InputDataProviderBase):

    def __init__(self, tokenizer, mode='binary', vocabulary_size=20000, num_words=100):
        """
        Converts collection of documents into a matrix (each row (a sparse vector) represents one document) in a
         BoW fashion.
        If mode parameter is 'index', each row will be of length num_words. Otherwise its length will be vocabulary_size

        :param tokenizer: a tokenizer - instance of keras.preprocessing.text.Tokenizer
        :param mode: one of: binary, count, tfidf, freq or index
        :param vocabulary_size: dimension of document vectors (rows of the matrix), equal to the length of the
         tokenizer's vocabulary, required for 'binary', 'count', 'tfidf' and 'freq' modes.
        :param num_words: required when mode is 'index'. Length of document's vector representation = how many words
         from each document should be taken into account (padded with zeros if document has less than num_words words)
        """
        self._dimension = vocabulary_size
        self._vocabulary_size = vocabulary_size
        if mode == 'index':
            self._dimension = num_words
        if mode not in ("binary", "count", "tfidf", "freq", "index"):
            raise Exception('Invalid mode: ' + str(mode) + '\nExpected one of: binary, count, freq, tfidf, index')
        self._mode = mode
        self._tokenizer = tokenizer
        self._num_words = num_words

    def make_data(self, docs, all_labels):
        """
        Converts documents (collection of LabeledDoc instances) into two numpy matrices, where each
         row of the first matrix is a vector representation of one document and corresponding row of the second matrix
         contains vector representation of this document's labels.

        :param docs: collection of LabeledDoc instances
        :param all_labels: dictionary of all valid labels: {'label name', 'label id'}
        :return: matrix of documents' representations and matrix of their labels' representations
        """
        docTexts = []
        docLabels = []
        for doc in docs:
            docTexts.append(' '.join(doc.content))
            docLabels.append(doc.labels)

        if self._mode == 'index':
            ret_data = numpy.zeros(shape=(len(docs), self._num_words))
            for index, text in enumerate(docTexts):
                idx = 0
                for word in text.split()[:self._num_words]:
                    if word in self._tokenizer.word_index:
                        ret_data[index, idx] = self._tokenizer.word_index[word]
                        idx += 1
        else:
            ret_data = self._tokenizer.texts_to_matrix(docTexts, mode=self._mode)

        ret_labels = numpy.zeros(shape=[len(docs), len(all_labels)])
        for index, labels in enumerate(docLabels):
            for lab in labels:
                idx = int(all_labels[lab])
                ret_labels[index, idx] = 1.0
        return ret_data, ret_labels

    def get_config_dict(self):
        """
        Return instance's configuration as a dictionary
        :return: dictionary containing this instance's configuration
        """
        return {'Type': 'Bag-of-words', 'Mode': self._mode, 'Vocabulary size': self._vocabulary_size,
                'Num words': self._num_words}


from typing import Generator

import httpx

api_url = "https://wellcomecollection.cdn.prismic.io/api/v2"

def get_master_ref() -> str:
    response = httpx.get(api_url).json()
    return [ref["ref"] for ref in response["refs"] if ref["isMasterRef"]][0]

master_ref = get_master_ref()

def count_documents() -> int:
    response = httpx.get(
        api_url + "/documents/search",
        params={"ref": master_ref},
    ).json()
    return response["total_results_size"]

def get_document_types() -> list:
    response = httpx.get(
        api_url,
        params={"ref": master_ref},
    ).json()
    return response["types"].keys()

def yield_documents(batch_size: int) -> Generator[dict, None, None]:
    for type in get_document_types():
        response = httpx.get(
            api_url + "/documents/search",
            params={
                "ref": master_ref,
                "q": f'[[at(document.type, "{type}")]]',
                "pageSize": batch_size,
            },
        ).json()

        while True:
            for result in response["results"]:
                yield result
            if response["next_page"] is None:
                break
            else:
                response = httpx.get(response["next_page"]).json()


import unittest
from sense_hat import SenseHat
import time

tint = [["tint1", [216, 220, 200]], ["tint2", [176, 180, 200]], ["tint3", [196, 100, 200]], ["tint4", [8, 8, 200]]]

class TestTint(unittest.TestCase):
    pass

def test_generator(tint):
    def test(self):
        sense = SenseHat()
        sense.clear()
        time.sleep(1)
        sense.clear(tint)
        time.sleep(2)
        led_tint = sense.get_pixel(1, 1)
        self.assertListEqual(tint, led_tint, "Expected tint is {0} but Led tinted to {1}".format(tint, led_tint))

    return test

if __name__ == '__main__':
    for t in tint:
        test_name = 'test_{}'.format(t[0])
        test = test_generator(t[1])
        setattr(TestTint, test_name, test)
    unittest.main()


# coding: utf-8
import argparse
import asyncio

import urwid

from rolling.client.http.client import HttpClient
from rolling.gui.controller import Controller
from rolling.gui.image.widget import ImageWidget
from rolling.kernel import Kernel

def run(args: argparse.Namespace) -> None:
    def exit_(*args, **kwargs):
        raise urwid.ExitMainLoop()

    image_widget = ImageWidget(args.image, callback=exit_)
    client = HttpClient(server_address="http://127.0.0.1")

    loop = asyncio.get_event_loop()
    kernel = Kernel(loop=loop)
    controller = Controller(client=client, kernel=kernel, root_menu_mode="exit_only")
    controller.view.main_content_container.original_widget = image_widget

    controller.main()

def main() -> None:
    parser = argparse.ArgumentParser(description="View image in 256 term colors")
    parser.add_argument("image", type=str, help="image path")
    args = parser.parse_args()
    run(args)

if __name__ == "__main__":
    main()


#!/usr/bin/python3

import os
import glob
import time
from typing import List

import cv2
import numpy as np

from keras.optimizers import Adam

from .unet import unet
from .utils.metric_utils import dice_coef, dice_coef_loss
from .utils.img_processing_utils import binarize_img, mkdir_s

weights_path = os.path.realpath(__file__)
weights_path = weights_path.replace(
    "robin/binarize.py",
    "weights/bin_weights.hdf5")

def main(
    input: str = os.path.join(".", "input"),
    output: str = os.path.join(".", "output"),
    weights_path: str = weights_path,
    batchsize: int = 2,
) -> List[np.ndarray]:
    """Binarize images from input directory and
    write them to output directory.

    Parameters
    ----------
    input: str, optional
        input path for images
    output: str, optional
        output path to save images
    weights_path: str, optional
        path to weights file
    batchsize: int, optional
        batchsize to use in model prediction

    Retuns
    ------
    List[numpy.ndarray]
        list of binary images in np.ndarray format

    Notes
    -----
    All input image names should be in png format "sample_1.png".
    All output image names will end with "_bin" like "sample_1_bin.png".

    Example
    -------
    robin.binarize.main('input_path', 'output_path', 2)

    """
    try:
        assert (batchsize > 0) and isinstance(batchsize, int)
    except Exception:
        print("batchsize should be > 0 and int but given {}".format(batchsize))
    try:
        assert (os.path.isdir(input))
    except Exception:
        print("Input path is not valid")

    start_time = time.time()

    fnames_in = list(glob.iglob(os.path.join(
        input,
        "**",
        "*.png*"), recursive=True))
    model = None
    if len(fnames_in) != 0:
        mkdir_s(output)
        model = unet()
        model.compile(
            optimizer=Adam(lr=1e-4),
            loss=dice_coef_loss,
            metrics=[dice_coef])
        model.load_weights(weights_path)

    bin_img_list = []

    for fname in fnames_in:
        print("binarizing -> {0}".format(fname))
        img = cv2.imread(fname, cv2.IMREAD_GRAYSCALE).astype(np.float32)
        img = binarize_img(img, model, batchsize)
        cv2.imwrite(
            os.path.join(
                output,
                os.path.split(fname)[-1].replace(".png", "_bin.png")),
            img
        )
        bin_img_list.append(img)
    print("finished in {0:.2f} seconds".format(time.time() - start_time))
    return bin_img_list

if __name__ == "__main__":
    main()


class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        DPmin = nums[:]
        DPmax = nums[:]
        for i in range(1,n):
            candidates = [nums[i]*DPmin[i-1],nums[i]*DPmax[i-1],nums[i]]
            DPmax[i] = max(candidates)
            DPmin[i] = min(candidates)
        return max(DPmax)


import shodan

SHODAN_API_KEY = "YOUR_API_KEY"
api = shodan.Shodan(SHODAN_API_KEY)
words = open("bug_bounty-wordList.txt", "r")
django_debug_list = open("laravel-debug-list.txt", "w")
for word in words.readlines():
    query = "html:'Whoops! There was an error' ssl:" + word.strip('\n')
    try:
        result = api.search(query)
        print(f'Result found : {result["total"]}')
        for result in result['matches']:
            print(word)
            print(f'IP: {result["ip_str"]}')
            port = result['port']
            if port in [80, 443]:
                if port == 443:
                    ip = "https://" + result['ip_str']
                else:
                    ip = "http://" + result['ip_str']
            else:
                ip = "http://" + result['ip_str'] + "" + str(port)
            django_debug_list.write(ip + "\n")
            print("")
    except Exception as e:
        print(e)


#coding:utf-8

class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        nums.sort()
        res_list = []
        for i in range(len(nums)-3):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            for j in range(i+1,len(nums)):
                if j != i+1  and nums[j] == nums[j-1]:
                    continue
                r = j+1
                k = len(nums) - 1
                while r < k :
                    sum = nums[i]+nums[j]+nums[r]+nums[k]
                    if (sum == target):
                        res_list.append([nums[i],nums[j],nums[r],nums[k]])
                        while r < k and nums[r] == nums[r+1]:
                            r+=1
                        while r < k and nums[k] == nums[k-1]:
                            k-=1
                        #当满足条件后，去除重复的数字
                        r = r+1
                        k = k-1
                    elif sum < target:
                        r+=1
                    else:
                        k-=1

        return res_list

if __name__ == '__main__':
    S = Solution()
    # nums = [-3,-2,-1,0,0,1,2,3]
    # target = 0
    # nums = [-1,0,1,2,-1,-4]
    # target = -1
    # nums = [-1,2,2,-5,0,-1,4]
    # target = 3
    nums = [-3,-1,0,2,4,5]
    target = 1
    output = S.fourSum(nums,target)
    print('output:',output)


import os
import glob
import argparse
import re, string, unicodedata
import numpy as np
import pandas as pd
import nltk
import contractions
import inflect
from nltk import word_tokenize
from nltk.corpus import stopwords, wordnet
from nltk.stem import LancasterStemmer, WordNetLemmatizer

def splitter(text):
    return " ".join(text.split("|"))

# Detaching concatenated words
def detach_words(text):
    """Detach Concatenated Words"""
    idx = 0
    new_text = []
    for i in text:
        idx+=1
        if i.isupper():
            if not text[idx-1] == '-':# or not text[idx-3] == ' - ':
                new_text.append(' ' + i)
            else:
                new_text.append(i)
    new_text = re.sub("w/","", re.sub("^ ","", re.sub("  "," ", "".join(new_text))))
    new_text = re.sub(" -","-", re.sub("- ","-", re.sub(" - ","-", new_text)))
    new_text = re.sub("^/","", re.sub("^-","", new_text))
    return new_text

# Replace contractions
def replace_contractions(text):
    """Replace contractions in string of text"""
    try:
        x = contractions.fix(text)
    except UnicodeEncodeError as e:
        return ""
    return x

# Tokenize
def tokenize_text(text):
    try:
        x = nltk.word_tokenize(text)
    except UnicodeEncodeError as e:
        return ""
    return x

# Remove non ascii characters
def remove_non_ascii(words):
    """Remove non-ASCII characters from list of tokenized words"""
    new_words = []
    for word in words:
        word = re.sub("[ ]"," ", re.sub("^/","", re.sub("^-","",word)))
        new_word = unicodedata.normalize('NFKD', word).encode('ascii', 'ignore').decode('utf-8', 'ignore')
        new_words.append(new_word)
    return new_words

# Convert every word to lowercase
def to_lowercase(words):
    """Convert all characters to lowercase from list of tokenized words"""
    new_words = []
    for word in words:
        new_word = re.split('([a-zA-Z]+)/', word.lower())
        new_words.extend(new_word)
    return new_words

# Remove punctuations
def remove_punctuation(words):
    """Remove punctuation from list of tokenized words"""
    new_words = []
    for word in words:
        new_word = re.sub(r'\.',' ', re.sub(r'[^\./\w\s-]', '', word))
        if new_word != '':
            new_words.append(new_word)
    return new_words

# Replace numbers
def replace_numbers(words):
    """Replace all interger occurrences in list of tokenized words with textual representation"""
    p = inflect.engine()
    new_words = []
    for word in words:
        if word.isdigit():
            new_word = p.number_to_words(word)
            new_words.append(new_word)
        else:
            new_words.append(word)
    return new_words

# Remove stopwords
def remove_stopwords(words):
    """Remove stop words from list of tokenized words"""
    new_words = []
    for word in words:
        if word not in stopwords.words('english'):
            new_words.append(word)
    return new_words

def remove_single_letters(words):
    """Removes single letter words"""
    new_words = []
    for i in words:
        if len(i) > 2:
            new_words.append(i)
    return new_words

def remove_only_numbers(words):
    """Removes only numbers without any letters"""
    new_words = []
    for i in words:
        if re.search("\d", i):
            if re.search("[a-zA-Z]", i):
                new_words.append(i)
        else:
            new_words.append(i)
    return new_words

def pos_tagger(words):
    """Returns only nouns and adjectives"""
    new_words = []
    for word,tag in nltk.pos_tag(words):
        if tag.startswith('J') or tag.startswith('N'):
            new_words.append(word)
    return sorted(set(new_words))

def stem_words(words):
    """Stem words in list of tokenized words"""
    stemmer = LancasterStemmer()
    stems = []
    for word in words:
        stem = stemmer.stem(word)
        stems.append(stem)
    return stems

def convert_numbers_to_words(text):
    """Breaks alphanumeric words to counterparts"""
    text = re.sub(r"\W+", " ", text)
    def number_inflection(text):
        idx = 0
        new_text = []
        try:
            for i in text:
                if i.isdigit():
                    if not text[idx+1].isdigit() and not text[idx+1].isspace():
                        new_text.extend([i,' '])
                    else:
                        new_text.append(i)
                else:
                    new_text.append(i)
                idx+=1
        except IndexError as e:
            new_text.append(i)
            pass
        return new_text
    return ''.join(number_inflection(text))

def get_wordnet_pos(words):
    for word in words:
        if word.startswith('J'):
            return wordnet.ADJ
        elif word.startswith('V'):
            return wordnet.VERB
        elif word.startswith('N'):
            return wordnet.NOUN
        elif word.startswith('R'):
            return wordnet.ADV
        else:
            return wordnet.NOUN

def lemmatize(words):
    """Lemmatize words in the list of tokenized words"""
    lemma = []
    lemmatizer = WordNetLemmatizer()
    for word, tag in nltk.pos_tag(words):
        tag = get_wordnet_pos(tag)
        lemma.append(lemmatizer.lemmatize(word, tag))
    return lemma

def get_word_frequency_from_pd(text, remove_stopwords_bool=False):
#     try:
#         text = " ".join(str(text).split('|')[2:])
#     except UnicodeEncodeError as e:
#         pass
    text = re.sub(r"#(\w+)", "", str(text).lower())
    text = re.sub(r'\|',' ', str(text))
    text = replace_contractions(text)
    text = convert_numbers_to_words(text)
    words = tokenize_text(text)
    words = replace_numbers(words)
    words = remove_non_ascii(words)
    words = to_lowercase(words)
    words = remove_punctuation(words)
    words = remove_only_numbers(words)
    words = lemmatize(words)
    if remove_stopwords_bool:
        words = remove_stopwords(words)
    text = re.sub(r" +"," ", re.sub("[^\w\s]"," ", re.sub("[0-9]+","", " ".join(words))))
    #words = pos_tagger(words)
    #words = remove_single_letters(words)
    # if remove_similar:
    #     words, master_list = remove_similar_words(words, master_list)
    return text

def get_word_frequency_from_pn(text, remove_stopwords_bool=False):
    text = re.sub(r"#(\w+)", "", str(text).lower())
    text = re.sub(r'\|',' ', str(text))
    text = replace_contractions(text)
    text = convert_numbers_to_words(text)
    words = tokenize_text(text)
    words = replace_numbers(words)
    words = remove_non_ascii(words)
    words = to_lowercase(words)
    words = remove_punctuation(words)
    words = remove_only_numbers(words)
    words = lemmatize(words)
    if remove_stopwords_bool:
        words = remove_stopwords(words)
    text = re.sub(r" +"," ", re.sub("[^\w\s]"," ", re.sub("[0-9]+","", " ".join(words))))
    return text


'''Token storage and retrieval.'''
from .keyword import Keyword, names
from .token import Token, TokenType
from .token_reader import read_keyword

class UnexpectedInputError(Exception):
    '''Exception raised when the input was not as expected.'''

    def __init__(self, message: str, token=None):
        super().__init__(message)
        self.__token = token

    @property
    def token(self):
        '''The token found when parsing input.'''
        return self.__token

class TokenManager:
    '''Handles parsing tokens from a string.'''

    def __init__(self, text: str):
        self.__processed = []
        self.__remaining = text.strip()

    @property
    def finished(self) -> bool:
        '''Whether all text has been processed.'''
        return len(self.__remaining) == 0

    def __advance(self, count: int):
        self.__remaining = self.__remaining[count:]

    def __previous(self) -> str:
        if not self.__processed:
            return ''
        return ' after \'{0}\''.format(self.__processed[-1].text)

    def expect_end(self):
        '''Requires that all input has been processed.'''
        if not self.finished:
            raise UnexpectedInputError(
                'Expected end of input{0}, found \'{1}\'.'
                .format(self.__previous(), self.__remaining))

    def expect_keyword(self, word: Keyword) -> Token:
        '''Attempts to read the given Keyword.'''
        assert word != Keyword.INVALID
        return self.expect(TokenType.KEYWORD, word)

    def expect_one_of(self, words: list) -> Token:
        '''Attempts to parse one of the given keywords.'''
        for word in words:
            assert word != Keyword.INVALID

        result = self.expect(TokenType.KEYWORD)
        if result.keyword not in words:
            raise UnexpectedInputError(
                'Invalid keyword: Found {0}, expected one of {1}'
                .format(result.text, names(words)),
                result)
        return result

    def expect(self, type_expected: TokenType,
               word=Keyword.INVALID) -> Token:
        '''Attempts to parse a requested type of token/keyword.'''
        if self.finished:
            raise UnexpectedInputError(
                'No more input. Expected token of type {0}'
                .format(type_expected.name))

        result = None
        to_advance = 0
        if type_expected == TokenType.KEYWORD:
            result, to_advance = read_keyword(self.__remaining)
        else:
            raise Exception('Unhandled token type.')
        self.__advance(to_advance)
        self.__processed.append(result)

        if result.category != type_expected:
            raise UnexpectedInputError(
                'Invalid type of token: Found {0}, expected {1}'
                .format(result.category.name, type_expected.name), result)
        if (word != Keyword.INVALID and
                type_expected == TokenType.KEYWORD and result.keyword != word):
            raise UnexpectedInputError(
                'Invalid keyword: Found {0}, expected {1}'
                .format(result.text, word.name.lower()), result)
        return result