import asyncio
from threading import Thread
from datetime import datetime, timedelta
import os.path
import json

import discord
from discord.errors import LoginFailure
from discord.utils import get as discord_fetch

from utils import Console, cfg, app_scheduler, SuccessEmbed, ErrorEmbed, InfoEmbed

loop = asyncio.new_event_loop()
app_scheduler.main_loop = loop
client = discord.Client(loop=loop)
SHL = Console(prefix="BundestagsBot")

CONTENT_PATH = "content" if os.path.isdir("content") else "content-default"
SHL.info(f"Using content path: {CONTENT_PATH}")

about_embed = InfoEmbed(title="Help")
with open(os.path.join("static", "info.txt"), "r", encoding="utf-8") as fh:
    about_embed.description = fh.read()

class UserStat:
    def __init__(self, user_obj: discord.Member):
        self.user_obj = user_obj
        self.count = 1

    def __str__(self):
        return f"{self.user_obj.display_name}: {self.count}"

async def assign_active_member(*args):
    SHL.info("Fetching last messages.")
    guild = await client.fetch_guild(cfg.get("guild_id"))
    SHL.debug(f"Guild: {guild}")

    # Remove all "active" members
    SHL.info("Remove active role from all users.")
    for role in cfg.get("apply_roles"):
        role = guild.get_role(role)
        async for member in guild.fetch_members():
            if role not in member.roles:
                continue
            SHL.debug(f"Remove {role} from {member}")
            try:
                await member.remove_roles(role)
            except:
                SHL.debug(f"Failed for {member}")

    # Find new active members
    channels = await guild.fetch_channels()

    announcement_channel = await client.fetch_channel(cfg.get("announce_channel"))
    log_channel = await client.fetch_channel(cfg.get("log_channel"))

    users = {}
    before = datetime.now()
    after = datetime.now() - timedelta(days=31)

    with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
        unsubs = json.load(fh)["unsub_ids"]

    SHL.debug(f"{len(unsubs)} users unsubbed.")

    for channel in channels:
        if not isinstance(channel, discord.TextChannel):
            continue
        if channel.id in cfg.get("exclude_channels"):
            continue

        SHL.debug(f"Fetching {channel.name}")
        async for message in channel.history(limit=None, before=before, after=after):
            uid = message.author.id
            if uid in unsubs:  # filter opt-out user
                continue
            if uid in users:
                users[uid].count += 1
            else:
                users[uid] = UserStat(message.author)

    sorted_list = sorted([x for x in users.values() if x.count >= cfg.get("needed_messages")],
                         key=lambda item: item.count, reverse=True)
    SHL.debug(f"{len(sorted_list)} users sent enough messages.")

    log_embed = InfoEmbed(title="Aktivste User - Log")
    for stat in sorted_list:  # active user
        try:
            member = await guild.fetch_member(stat.user_obj.id)
        except:  # if user left or got banned
            continue
        SHL.debug(f"Apply roles for {member}")
        log_embed.description += f"{member.mention} : {stat.count} Nachrichten.\n"
        for role in cfg.get("apply_roles"):
            assign_role = discord_fetch(guild.roles, id=role)
            try:
                await member.add_roles(assign_role)
            except:
                SHL.debug(f"Failed for {stat.user_obj}")
                break
    await log_channel.send(embed=log_embed)

    announcement = InfoEmbed(title="Aktivste User", description="Für die Auswahl der Stammmitglieder.\n"
                                                                "Nachrichtenanzahl im letzten Monat.")
    for stat in sorted_list[:3]:  # most active user
        member = await guild.fetch_member(stat.user_obj.id)
        announcement.description += f"{member.mention} : {stat.count} Nachrichten.\n"

    await announcement_channel.send(embed=announcement)
    await log_channel.send(embed=announcement)
    SHL.info("Done.")

@client.event
async def on_message(message: discord.Message):
    if message.content.startswith("_analyze"):
        SHL.info(f"{message.author} used {message.content}")
        if any([x in message.content.lower() for x in ["help", "info", "details", "about"]]):
            await message.channel.send(embed=about_embed)
            return

        if "true" in message.content.lower():
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
                data = json.load(fh)
            try:
                data["unsub_ids"].remove(message.author.id)
            except ValueError:
                pass
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "w") as fh:
                json.dump(data, fh)
            await message.channel.send(embed=SuccessEmbed(title="Analyzer",
                                                          description="Deine Nachrichten werden nun wieder erfasst."))
            return

        if "false" in message.content.lower():
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
                data = json.load(fh)
            if message.author.id not in data["unsub_ids"]:
                data["unsub_ids"].append(message.author.id)
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "w") as fh:
                json.dump(data, fh)
            await message.channel.send(embed=SuccessEmbed(title="Analyzer",
                                                          description="Deine Nachrichten werden nun nicht erfasst.\n"
                                                                      "Um diesen Vorgang rückgängig zu machen verwende `_analyze true`."))
            return

def start_bot():
    try:
        token = cfg.options["BOT_TOKEN"]
    except KeyError:
        SHL.error(f"========================")
        SHL.error(f"'BOT_TOKEN' not found in config files!")
        return
    try:
        SHL.info(f"Logging in.")
        client.run(token, reconnect=cfg.options.get("use_reconnect", False))
    except LoginFailure:
        SHL.error(f"========================")
        SHL.error(f"Login failure!")
        SHL.error(f"Please check your token.")
        return

thread_sched = Thread(target=app_scheduler.schedule_check, name="sched")
thread_sched.start()
app_scheduler.schedule_daily(func=assign_active_member, tag="test")
start_bot()


import pytest
from selenium import webdriver

def pytest_addoption(parser):
    parser.addoption("--browser", default="chrome")
    parser.addoption("--app_host", default="http://192.168.1.73")
    parser.addoption("--executor", default="192.168.1.73")

@pytest.fixture
def browser(request):

    bro = request.config.getoption("--browser")
    app_host = request.config.getoption("--app_host")
    executor = request.config.getoption("--executor")

    caps = {"browserName": bro}

    wd = webdriver.Remote(command_executor=f"http://{executor}:4444/wd/hub", desired_capabilities=caps)
    request.addfinalizer(wd.quit)
    wd.get(app_host)
    return wd


"""module that asks for user input and calculates price of item plus MB tax"""
def taxcalc(num):
    """Calculates tax according to rates of MB"""
    taxed_price = num + (num*(12/100))
    return taxed_price
#actual run
while True:
    try:
        NUM = float(input("How much is your item?: "))
    except ValueError:
        print("Please make sure to input a number")
        continue
    else:
        PRINT_TERM = float(taxcalc(NUM))
        print("Your item's price before tax is, ${ORI:.2f}.".format(ORI=NUM))
        print("Your item's price after tax is, ${PRT:.2f}.".format(PRT=PRINT_TERM))
        break


import os
import time
#time.sleep(17000)

selectFolds = [1, 3, 5, 7, 9, 11, 13, 15]
#selectFolds = [1, 15, 3, 13]
#selectFolds = [5, 11, 7, 9]
#selectFolds = [3, 7, 15]
#selectFolds = [1, 5, 9, 11, 13]
trials = xrange(0, 10)

nodeType=os.environ.get('RCAC_SCRATCH')
queue=""
if "snyder" in nodeType:
    queue='ribeirob'
if "hammer" in nodeType:
    queue='csit'
queue = 'csit'

#names, 1 - amazon_DVD_20000, 2 - facebook, 3 - amazon_Music_10000
"""
dataSets=["amazon_Music_10000"]
memory =[5]
summaries = [3]
prTypes = ["neutral"]
netTypes=["LSTMPAR"]
singlePRs=[0]
biasselves = ["posneg"]
degrees=[1, 0]
limits=[0]

"""
#dataSets=["amazon_DVD_7500"]
#dataSets=["amazon_DVD_7500"]
#dataSets=["IMDB_5"]
#dataSets = ["amazon_DVD_20000", "facebook"]
#dataSets=["amazon_Music_64500"]
#dataSets=["amazon_Music_7500"]
#dataSets=["amazon_DVD_20000", "amazon_Music_64500"]
#dataSets=["amazon_Music_7500"]
#dataSets=["amazon_DVD_7500", "amazon_DVD_20000"]
dataSets = ["amazon_Music_64500", "amazon_Music_7500"]
#dataSets=["amazon_DVD_7500", "amazon_DVD_20000", "amazon_Music_64500", "amazon_Music_7500"]
#dataSets = ["patents_computers_50attr"]
memory =[10]
summaries = [3]
prTypes = ["neutral"]
netTypes=["LSTM"]
singlePRs=[0]
biasselves = ["none"]
degrees=[1]
limits=[0]
usePrevWeights=[1]
noDeg0s = [1]
dataAug=["none"]
#dataAug=["none", "swapdown"]
#dataAug=["swapdown", "swap"]
#dataAug=["swapdown"]
#dataAug=["none", "swap", "swapdown"]
#dataAug=["swap", "swapdown"]
#dataAug=["attr", "attrdown"]
#dataAug=["none", "swap", "swapdown", "attr", "attrdown"]
#dataAug = ["attr", "swap", "attrup", "attrdown", "swapup", "swapdown"]
#dataAug = ["swapTriple", "swapQuad"]
#dataAug = ["swapup", "swapdown"]
randInit = [1]
#usePRs = ["for", "back"]
usePRs = [0]
gpus = ["cpu"]
#PostFix="PPR"
#PostFix="N2V"
PostFix=""
buildStr='./parallel_commands '
for nettype in netTypes:
    for mem in memory:
        for prtype in prTypes:
            for singlepr in singlePRs:
                for bias in biasselves:
                    for deg in degrees:
                        for limit in limits:
                            for summ in summaries:
                                for weight in usePrevWeights:
                                    for deg0 in noDeg0s:
                                        for aug in dataAug:
                                            for test in dataSets:
                                                for rinit in randInit:
                                                    for usepr in usePRs:
                                                        for gpu in gpus:
                                                            for trial in trials:
                                                                for fold in selectFolds:
                                                                    submitStr="qsub -q "+queue+" -v nettype='" + str(nettype)+"',mem='" +str(mem)+"',prtype='" + prtype + "',singlepr='"+str(singlepr) + "',test='"+str(test) + "',bias='" + bias + "',deg='" + str(deg) + "',limit='" +str(limit)+ "',summ='"+str(summ)+"',weight='"+str(weight)+ "',nodeg='" +str(deg0) + "',aug='" + str(aug) + "',rinit='" +str(rinit) + "',usepr='" + str(usepr)  + "',gpu='" + str(gpu) +  "',trial='"+str(trial)+"',fold='"+str(fold)+  "' rnn_exp32"+PostFix+".sub"
                                                                    print(submitStr)
                                                                    os.system(submitStr)


"""first

Revision ID: 0f888546217f
Revises:
Create Date: 2019-10-14 15:33:59.160912+00:00

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '0f888546217f'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('user',
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(length=64), nullable=False),
    sa.Column('visited', sa.DateTime(), nullable=False),
    sa.PrimaryKeyConstraint('user_id'),
    sa.UniqueConstraint('username')
    )
    op.create_table('post',
    sa.Column('message_id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('message', sa.String(length=1024), nullable=False),
    sa.Column('created', sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['user.user_id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('message_id')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('post')
    op.drop_table('user')
    # ### end Alembic commands ###


from constants import LYRICS_FOLDER_NAME
import os
import re

def main():
    lyricsFiles = os.listdir(LYRICS_FOLDER_NAME)
    lyricsFilesWithFullPath = map(
        lambda lyricsFile: os.path.join(LYRICS_FOLDER_NAME, lyricsFile), lyricsFiles
    )
    for lyricsFile in lyricsFilesWithFullPath:
        fin = open(lyricsFile, "r")
        lyrics = fin.read().strip()
        fin.close()

        lyrics = re.sub(r"\[[^\[\]]*\]", "", lyrics)
        lyrics = re.sub(r"[\n]+", "\n", lyrics)
        lyrics = lyrics.strip()

        fout = open(lyricsFile, "w")
        fout.write(lyrics)
        fout.close()

if __name__ == "__main__":
    main()


import math
import vtk
from PythonMetricsCalculator import PerkEvaluatorMetric

class RotationTotal( PerkEvaluatorMetric ):

  # Static methods
  @staticmethod
  def GetMetricName():
    return "Rotation Total"

  @staticmethod
  def GetMetricUnit():
    return "deg"

  # Instance methods
  def __init__( self ):
    PerkEvaluatorMetric.__init__( self )

    self.rotationTotal = 0
    self.matrixPrev = None

  def AddTimestamp( self, time, matrix, point, role ):
    if ( self.matrixPrev == None or self.matrixPrev == None ):
      self.matrixPrev = vtk.vtkMatrix4x4()
      self.matrixPrev.DeepCopy( matrix )
      return

    invertPrev = vtk.vtkMatrix4x4()
    invertPrev.DeepCopy( self.matrixPrev )
    invertPrev.Invert()

    currChangeMatrix = vtk.vtkMatrix4x4()
    vtk.vtkMatrix4x4().Multiply4x4( matrix, invertPrev, currChangeMatrix )

    currChangeTransform = vtk.vtkTransform()
    currChangeTransform.SetMatrix( currChangeMatrix )

    angleChange = [ 0, 0, 0, 0 ]
    currChangeTransform.GetOrientationWXYZ( angleChange )

    currAngleChange = min( angleChange[ 0 ], 360 - angleChange[ 0 ] )
    self.rotationTotal += currAngleChange

    self.matrixPrev = vtk.vtkMatrix4x4()
    self.matrixPrev.DeepCopy( matrix )

  def GetMetric( self ):
    return self.rotationTotal


#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Collect and modify hosts from '360kb' Automatically
'''
__author__="NoBystander"
import requests
import bs4

root_url="http://www.360kb.com"
index_url=root_url+"/kb/2_122.html"

def get_urls():
    response = requests.get(index_url)
    soup = bs4.BeautifulSoup(response.text)
    return [a for a in soup.select('pre')]

s=str(get_urls()[0])

with open('C:\Windows\System32\Drivers\etc\hosts','w') as f:
    f.write('#Collect By '+__author__+' Using Python\n')
    f.write(s[s.find('#google'):s.find('</pre>')])


import datetime
import json
import re
import urllib

from dateutil.parser import parse as dateparse
from flask import g
from influenceexplorer import InfluenceExplorer
import requests
import sunlight

from calloncongress import settings
from calloncongress.helpers import (bill_type_for, bill_number_for, state_for,
                                    rep_title_for, party_for)

sunlight.config.API_KEY = settings.SUNLIGHT_KEY
ie = InfluenceExplorer(settings.SUNLIGHT_KEY)

def legislators_for_zip(zipcode):
    """ Find legislators that represent the specified zipcode.
        Results are cached in the datastore for faster lookup.
        If more than one member of the House represents a zipcode,
        both legislators will be returned.

        zipcode: the 5-digit zipcode to search
    """

    # attempt to find cached legislators
    doc = g.db.legislatorsByZipcode.find_one({'zipcode': zipcode})

    if doc is None:

        # load from Sunlight Congress API if not cached locally
        results = sunlight.congress.locate_legislators_by_zip(zipcode)

        # create a copy of the Legislator object dict
        legislators = [_format_legislator(r) for r in results]

        # sort the legislators by reverse title so Senators are listed
        # before members of the House
        legislators.sort(lambda x, y: -cmp(x['short_title'], y['short_title']))

        # save new zipcode results document
        g.db.legislatorsByZipcode.insert({
            'timestamp': g.now,
            'zipcode': zipcode,
            'legislators': legislators,
        })

    else:

        # get legislators from cache
        legislators = doc['legislators']

    return legislators

def legislator_by_bioguide(bioguide):
    """ Finds and caches a legislator with the given bioguide id. """
    doc = g.db.legislatorByBioguideId.find_one({'bioguide_id': bioguide})

    if doc is None:
        try:
            legislator = _format_legislator(sunlight.congress.legislator(bioguide))
            g.db.legislatorByBioguideId.insert({
                'timestamp': g.now,
                'bioguide_id': bioguide,
                'legislator': legislator,
            })
        except sunlight.errors.SunlightException:
            legislator = None
    else:
        legislator = doc['legislator']

    return legislator

def _format_legislator(l):
    try:
        if hasattr(l, '__dict__'):
            l = l.__dict__.copy()
        else:
            l = l.copy()
    except AttributeError:
        pass
    l['short_title'] = l['title']
    l['title'] = rep_title_for(l['title'])
    l['fullname'] = "%s %s %s" % (l['title'],
                                  l.get('firstname') or l.get('first_name'),
                                  l.get('lastname') or l.get('last_name'))

    return l

def resolve_entity_id(crp_id):
    """ Convert a CRP candidate ID into an IE entity ID.
        Cached locally for better performance.
    """

    doc = g.db.crpMapping.find_one({'crp_id': crp_id})

    if doc is None:
        entity_id = ie.entities.id_lookup("urn:crp:recipient", crp_id)[0]['id']
        g.db.crpMapping.insert({
            'crp_id': crp_id,
            'entity_id': entity_id,
        })
    else:
        entity_id = doc['entity_id']

    return entity_id

def top_contributors(legislator):
    entity_id = resolve_entity_id(legislator['crp_id'])
    contribs = ie.pol.contributors(entity_id, cycle='2012', limit=10)
    return contribs

def legislator_bio(legislator):
    entity_id = resolve_entity_id(legislator['crp_id'])
    metadata = ie.entities.metadata(entity_id)
    return metadata['metadata']['bio'].encode('ascii', 'xmlcharrefreplace')

def committee_iter(committees):
    for comm in committees:
        yield comm.name
        if comm.subcommittees:
            for subcomm in comm.subcommittees:
                yield subcomm.name

def committees(legislator):
    comms = sunlight.congress.committees(member_ids=g.legislator['bioguide_id'])
    names = " ".join("%s." % c for c in committee_iter(comms))
    return names

def recent_votes(legislator):

    VOTES = {
        'Yea': 'yes',
        'Nay': 'no',
    }

    url = "http://api.realtimecongress.org/api/v1/votes.json"

    voter_key = "voter_ids.%s" % legislator['bioguide_id']

    params = {
        'per_page': 5,
        'vote_type': 'passage',
        '%s__exists' % voter_key: True,
        'sections': "question,result,%s" % voter_key,
    }

    resp = requests.get(url, params=params, headers={'X-APIKEY': settings.SUNLIGHT_KEY})

    result_keys = (('', 'passed'), ('was', 'rejected'), ('', 'failed'))
    data = json.loads(resp.content)['votes']
    for vote in data:
        voted = vote['voter_ids'][legislator['bioguide_id']]
        vote['voted'] = VOTES.get(voted, voted)
        vote['question'] = vote['question'].split(':')[-1].strip()
        if vote['question'].lower().startswith('on '):
            vote['question'] = vote['question'][3:]
        for key in result_keys:
            try:
                vote_result_index = vote['result'].lower().index(key[1])
                vote['result'] = "%s %s" % (key[0], vote['result'][vote_result_index:])
            except ValueError:
                continue
        del vote['voter_ids']

    return data

def upcoming_bills(window=settings.UPCOMING_BILL_DAYS):
    timeframe = [datetime.datetime.today(), datetime.datetime.today() + datetime.timedelta(days=window)]
    formatstr = '%Y-%m-%d'
    bills = sunlight.congress.upcoming_bills(
                                legislative_day__gte=timeframe[0].strftime(formatstr),
                                legislative_day__lte=timeframe[1].strftime(formatstr),
                                order='legislative_day__asc')

    return [_format_bill(bill) for bill in bills]

def bill_search(number=None):
    bills = sunlight.congress.bills(number=number, order='last_action_at__desc')[:8]
    return [_format_bill(bill) for bill in bills]

def get_bill_by_id(bill_id=None):
    try:
        return _format_bill(sunlight.congress.bills(bill_id=bill_id)[0])
    except IndexError:
        return None

def _format_bill(bill):
    bill = bill.copy()
    btype = bill_type_for(bill['bill_id'])
    bnumber = bill.get('number') or bill_number_for(bill['bill_id'])
    bdate = bill.get('legislative_day') or bill.get('last_action_at')
    try:
        bdate = dateparse(bdate).strftime('%B %e')
    except:
        bdate = 'unknown date'
    title = (bill.get('popular_title') or
             bill.get('short_title') or
             bill.get('official_title') or '')
    ctx = bill.get('context', [])
    bill['summary'] = bill.get('summary') or ''
    bill_context = {
        'date': bdate,
        'chamber': bill['chamber'],
        'bill_type': btype,
        'bill_number': bnumber,
        'bill_title': title.encode('ascii', 'ignore'),
        'bill_description': '\n'.join(ctx).encode('ascii', 'ignore'),
    }
    if len(bill.get('actions', [])):
        bill_context.update(bill_status="%s on %s" % (bill['last_action'].get('text'),
                                                      dateparse(bill['last_action'].get('acted_at')).strftime('%B %e, %Y')))
    else:
        bill_context.update(bill_status='No known actions taken yet.')

    sponsor = bill.get('sponsor')
    if sponsor:
        sponsor_party = sponsor.get('party')
        sponsor_state = sponsor.get('state')
        if sponsor_party and sponsor_state:
            bill_context.update(sponsor="Sponsored by: %s, %s, %s" % (_format_legislator(sponsor)['fullname'],
                                                                  party_for(sponsor['party']),
                                                                  state_for(sponsor['state'])))
        else:
            bill_context.update(sponsor="Sponsored by: %s" % _format_legislator(sponsor)['fullname'])

    cosponsors = bill.get('cosponsors', [])
    if len(cosponsors):
        bill_context.update(cosponsors="Cosponsored by: %s" %
            ', '.join(["%s, %s, %s" % (_format_legislator(cs)['fullname'],
                                       party_for(cs['party']),
                                       state_for(cs['state'])) for cs in cosponsors]))

    bill.update(bill_context=bill_context)
    return bill

def election_offices_for_zip(zipcode):
    doc = g.db.electionOfficesByZipcode.find_one({'zipcode': zipcode})

    if doc is None:
        try:
            turbovote_url = "https://turbovote.org/api/clerk/%s?token=%s"
            offices = [_format_election_office(office) for office in json.loads(requests.get(turbovote_url % (zipcode, settings.TURBOVOTE_KEY)).content)['result']]
            doc = {
                'timestamp': g.now,
                'zipcode': zipcode,
                'offices': offices
            }
            if isinstance(doc['offices'], dict):
                doc['offices'] = [doc['offices']]
            g.db.electionOfficesByZipcode.insert(doc)
        except:
            return []

    return doc['offices']

def _format_election_office(office):
    if office.get('phone'):
        phone = re.sub(r'[^\d]+', '', office['phone'])
        office['phone'] = None
        try:
            if len(phone) == 11:
                office['phone'] = "%s-%s-%s" % (phone[1:4], phone[4:7], phone[7:11])
            elif len(phone) == 10:
                office['phone'] = "%s-%s-%s" % (phone[0:3], phone[3:6], phone[6:10])
        except:
            pass

    return office

def subscribe_to_bill_updates(**kwargs):
    from flask import request
    headers = {
        'X-Twilio-Signature': request.headers.get('X-Twilio-Signature', ''),
        'X-Twilio-Request-URI': request.url,
        'X-Twilio-Post-Body': urllib.urlencode(request.form),
    }
    params = kwargs
    r = requests.post('https://scout.sunlightfoundation.com/remote/subscribe/sms', data=params, headers=headers)
    if r.status_code == 200:
        return True
    else:
        return False


# /data2/wyf/code/jojogan-3d/training/projectors/w_projector.py
import copy
import wandb
import numpy as np
import torch
import torch.nn.functional as F
from tqdm import tqdm
import dnnlib
from PIL import Image
import numpy as np
import math
import PIL
import cv2
import os
import sys
import json
import torchvision.models as models
import torchvision.transforms as transforms
from torchvision.utils import save_image
# 当前目录指定
# sys.path.append('/data2/dxw/code/github/iccv2023/jojogan_encoder/')
sys.path.append('/data2/wyf/code/jojogan-3d')
from face_parsing.logger import setup_logger
from face_parsing.model import BiSeNet
from utils import log_utils
from configs import global_config, paths_config, hyperparameters
from ..volumetric_rendering.ray_sampler import RaySampler
from utils.camera_utils import compute_rotation_matrix_from_quaternion, euler2rot, rot6d_to_rotmat
from ..warping_loss import calc_warping_loss
import snoop
from criteria.id_loss import IDLoss
from lpips import LPIPS
# from criteria.moco_loss import MocoLoss
from skimage.metrics import structural_similarity as ssim
from skimage.metrics import peak_signal_noise_ratio as psnr

def mtx_similar2(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    如果矩阵大小不一样会在左上角对齐，截取二者最小的相交范围。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:相似度（0~1之间）
    '''
    if arr1.shape != arr2.shape:
        minx = min(arr1.shape[0],arr2.shape[0])
        miny = min(arr1.shape[1],arr2.shape[1])
        differ = arr1[:minx,:miny] - arr2[:minx,:miny]
    else:
        differ = arr1 - arr2
    numera = np.sum(differ**2)
    denom = np.sum(arr1**2)
    similar = 1 - (numera / denom)
    return similar

def mtx_similar1(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    计算矩阵相似度的一种方法。将矩阵展平成向量，计算向量的乘积除以模长。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:实际是夹角的余弦值，ret = (cos+1)/2
    '''
    farr1 = arr1.ravel()
    farr2 = arr2.ravel()
    len1 = len(farr1)
    len2 = len(farr2)
    if len1 > len2:
        farr1 = farr1[:len2]
    else:
        farr2 = farr2[:len1]
    numer = np.sum(farr1 * farr2)
    denom = np.sqrt(np.sum(farr1**2) * np.sum(farr2**2))
    similar = numer / denom
    return  (similar+1) / 2 # 姑且把余弦函数当线性

def calc_l2loss(real_images, generated_images):
    l2_criterion = torch.nn.MSELoss(reduction='mean')
    loss = l2_criterion(real_images, generated_images)
    return loss

def calc_ssim(img1_path, img2_path):
    '''
    Parameters
    ----------
    img1_path : str
        图像1的路径.
    img2_path : str
        图像2的路径.

    Returns
    -------
    ssim_score : numpy.float64
        结构相似性指数（structural similarity index，SSIM）.

    References
    -------
    https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html

    '''
    img1 = Image.open(img1_path).convert('L')
    img2 = Image.open(img2_path).convert('L')
    img2 = img2.resize(img1.size)
    img1, img2 = np.array(img1), np.array(img2)
    # 此处因为转换为灰度值之后的图像范围是0-255，所以data_range为255，如果转化为浮点数，且是0-1的范围，则data_range应为1
    ssim_score = ssim(img1, img2, data_range=255)
    return ssim_score

def calc_psnr(img1_path, img2_path):
    '''
    Parameters
    ----------
    img1_path : str
        图像1的路径.
    img2_path : str
        图像2的路径.

    Returns
    -------
    psnr_score : numpy.float64
        峰值信噪比(Peak Signal to Noise Ratio, PSNR).

    References
    -------
    https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio

    '''
    img1 = Image.open(img1_path)
    img2 = Image.open(img2_path)
    img2 = img2.resize(img1.size)
    img1, img2 = np.array(img1), np.array(img2)
    # 此处的第一张图像为真实图像，第二张图像为测试图像
    # 此处因为图像范围是0-255，所以data_range为255，如果转化为浮点数，且是0-1的范围，则data_range应为1
    psnr_score = psnr(img1, img2, data_range=255)
    return psnr_score

def vis_parsing_maps(im, parsing_anno, stride, save_im=False, save_path='vis_results/parsing_map_on_im.jpg'):
    # Colors for all 20 parts
    part_colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0],
                   [255, 0, 85], [255, 0, 170],
                   [0, 255, 0], [85, 255, 0], [170, 255, 0],
                   [0, 255, 85], [0, 255, 170],
                   [0, 0, 255], [85, 0, 255], [170, 0, 255],
                   [0, 85, 255], [0, 170, 255],
                   [255, 255, 0], [255, 255, 85], [255, 255, 170],
                   [255, 0, 255], [255, 85, 255], [255, 170, 255],
                   [0, 255, 255], [85, 255, 255], [170, 255, 255]]
    im = np.array(im)
    vis_im = im.copy().astype(np.uint8)
    vis_parsing_anno = parsing_anno.copy().astype(np.uint8)
    vis_parsing_anno = cv2.resize(vis_parsing_anno, None, fx=stride, fy=stride, interpolation=cv2.INTER_NEAREST)
    vis_parsing_anno_color = np.zeros((vis_parsing_anno.shape[0], vis_parsing_anno.shape[1], 3)) + 255
    num_of_class = np.max(vis_parsing_anno)
    for pi in range(1, num_of_class + 1):
        index = np.where(vis_parsing_anno == pi)
        vis_parsing_anno_color[index[0], index[1], :] = part_colors[pi]
    vis_parsing_anno_color = vis_parsing_anno_color.astype(np.uint8)
    # print(vis_parsing_anno_color.shape, vis_im.shape)
    vis_im = cv2.addWeighted(cv2.cvtColor(vis_im, cv2.COLOR_RGB2BGR), 0.4, vis_parsing_anno_color, 0.6, 0)
    # Save result or not
    if save_im:
        cv2.imwrite(save_path[:-4] +'.png', vis_parsing_anno)
        cv2.imwrite(save_path, vis_im, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
    return vis_im

def calc_mask(pred_images_path, target_e4e_path, respth=paths_config.root_path + '/face_parsing/res/test_res', dspth=paths_config.root_path + '/face_parsing/res/data', cp=paths_config.root_path + '/face_parsing/pretrained/79999_iter.pth'):
    if not os.path.exists(respth):
        os.makedirs(respth)
    n_classes = 19
    net = BiSeNet(n_classes=n_classes)
    net.cuda()
    save_pth = os.path.join('res/cp', cp)
    net.load_state_dict(torch.load(save_pth))
    net.eval()
    to_tensor = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
    ])
    with torch.no_grad():
        for image_path in os.listdir(dspth):
            img = Image.open(os.path.join(dspth, image_path))
            image = img.resize((512, 512), Image.BILINEAR)
            img = to_tensor(image)
            img = torch.unsqueeze(img, 0)
            img = img.cuda()
            out = net(img)[0]
            parsing = out.squeeze(0).cpu().numpy().argmax(0)
            vis_parsing_maps(image, parsing, stride=1, save_im=True, save_path=os.path.join(respth, image_path))
    # pred_out_images_path = '/data2/dxw/code/github/iccv2023/jojogan_encoder/face_parsing/res/test_res/pred_images.jpg'
    # target_out_e4e_path = '/data2/dxw/code/github/iccv2023/jojogan_encoder/face_parsing/res/test_res/target_e4e.jpg'
    # pred_out_images_path = '/data2/wyf/code/jojogan-3d/face_parsing/res/test_res/pred_images.jpg'
    # target_out_e4e_path = '/data2/wyf/code/jojogan-3d/face_parsing/res/test_res/target_e4e.jpg'
    pred_out_images_path = paths_config.root_path + '/face_parsing/res/test_res/pred_images.jpg'
    target_out_e4e_path = paths_config.root_path + '/face_parsing/res/test_res/target_e4e.jpg'
    pred_images = Image.open(pred_out_images_path)
    pred_images = pred_images.resize((512, 512), Image.BILINEAR)
    pred_images = to_tensor(pred_images)
    pred_images = torch.unsqueeze(pred_images, 0)
    pred_images = pred_images.cuda()
    target_e4e = Image.open(target_out_e4e_path)
    target_e4e = target_e4e.resize((512, 512), Image.BILINEAR)
    target_e4e = to_tensor(target_e4e)
    target_e4e = torch.unsqueeze(target_e4e, 0)
    target_e4e = target_e4e.cuda()
    return pred_images,target_e4e

def jojogan_img_loss_eg3d(generator,w_pivot,cam_pose,target_img):
    # 生成扰动的w
    z = torch.randn(1, generator.z_dim).to('cuda')
    ws = generator.mapping(z, cam_pose)  # [N, L, C]
    # alpha越大，保持原本风格越大，alpha越小，随机性越大。
    in_latent = w_pivot.clone()
    # 低分辨率的style 控制姿态、脸型、配件 比如眼镜、发型等style,高分辨率的style控制肤色、头发颜色、背景色等style。
    id_swap=[7,8,9,10,11,12,13]
    # id_swap=[1,3,5,7,9,10,11,12,13]
    # id_swap=[1,3,5,7]
    alpha=0.2
    in_latent[:, id_swap,:] = alpha*w_pivot[:, id_swap,:] + (1-alpha)*ws[:, id_swap,:]
    # c.shape = (1, 25)
    # w_styles.shape = (4, 18, 512)
    # trainable_img = self.generator_nada(w_styles, c=c.repeat(w_styles.shape[0], 1), truncation=truncation, randomize_noise=randomize_noise)[0]
    # trainable_img.shape = (4, 3, 512, 512)
    # in_latent用那个呢
    truncation=1,
    truncation_latent=None
    randomize_noise=True
    trainable_img_jojogan = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    # 原始
    # img = generator.synthesis(in_latent, cam_pose, noise_mode='const')['image']
    lpips_fn = lpips.LPIPS(net='vgg').to('cuda') # 用于度量两个图片的相似度
    loss = lpips_fn(F.interpolate(trainable_img_jojogan, size=(256,256), mode='area'), F.interpolate(target_img, size=(256,256), mode='area')).mean()
    return loss,trainable_img_jojogan

def jojogan_img_loss_ide3d_all(generator,w_pivot,cam_pose,target_img):
    truncation=1,
    truncation_latent=None
    randomize_noise=True
    # 使用方法例子：trainable_img_jojogan = self.generator_jojogan(w_styles, c=c.repeat(w_styles.shape[0], 1), truncation=truncation, randomize_noise=randomize_noise)[0]
    # 生成扰动的w
    z = torch.randn(1, 512).to('cuda')
    ws = generator.style([z], cam_pose)  # [N, L, C]
    # alpha越大，保持原本风格越大，alpha越小，随机性越大。
    in_latent = w_pivot.clone()
    # 低分辨率的style 控制姿态、脸型、配件 比如眼镜、发型等style,高分辨率的style控制肤色、头发颜色、背景色等style。
    id_swap=[7,9,11,13,14,15,16,17]
    # id_swap=[1,3,5,7,9,10,11,12,13]
    # id_swap=[1,3,5,7]
    alpha=0.1
    in_latent[:, id_swap,:] = alpha*w_pivot[:, id_swap,:] + (1-alpha)*ws[:, id_swap,:]
    # c.shape = (1, 25)
    # w_styles.shape = (4, 18, 512)
    trainable_img_jojogan = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    # trainable_img.shape = (4, 3, 512, 512)
    # 网络出来的结果不需要再tranform正则化，因为本来就是01分布的了
    with torch.no_grad():
        trainable_img_jojogan_nograd = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    lpips_fn = lpips.LPIPS(net='vgg').to('cuda') # 用于度量两个图片的相似度
    loss = lpips_fn(F.interpolate(trainable_img_jojogan, size=(256,256), mode='area'),F.interpolate(target_img, size=(256,256), mode='area')).mean()
    # 查看输出的图片，扰动是否正确
    # 这里是训练的图片
    # from torchvision.utils import save_image
    # path_jojo1='/data1w_data/code/github/iccv2023/jojoloss_an.png'
    # path_jojo2='/data1w_data/code/github/iccv2023/jojoloss.png'
    # save_image(trainable_img_jojogan,path_jojo1)
    # save_image(trainable_img_jojogan,path_jojo2,normalize=True)
    # 查看输出的图片，扰动是否正确
    # 这里是起点的图片
    # from torchvision.utils import save_image
    # path_jojo1_nograd='/data1w_data/code/github/iccv2023/jojoloss_an__nograd.png'
    # path_jojo2_nograd='/data1w_data/code/github/iccv2023/jojoloss_nograd.png'
    # save_image(trainable_img_jojogan_nograd,path_jojo1_nograd)
    # save_image(trainable_img_jojogan_nograd,path_jojo2_nograd,normalize=True)
    return loss,trainable_img_jojogan,trainable_img_jojogan_nograd

# @snoop(f'{paths_config.output_data_path}/debug.log') # 保存debug信息
def project(
        G,
        target: torch.Tensor, # [C,H,W] and dynamic range [0,255], W & H must match G output resolution
        *,
        num_steps=1000,
        w_avg_samples=10000,
        initial_learning_rate=0.01,
        lr_rampdown_length=0.25,
        initial_noise_factor=0.05,
        noise_ramp_length=0.75,
        lr_rampup_length=0.05,
        regularize_noise_weight=1e5,
        device: torch.device,
        use_wandb=False,
        initial_w=None,
        cam_encoder = None,
        e4e_encoder = None,
        outdir=None,
        w_name: str
):
    # 读取超参数字典
    args_file = open(paths_config.args_path, 'r')
    args_dic = eval(args_file.read())
    # Load VGG16 feature detector.
    # url = 'https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/metrics/vgg16.pt'
    # with dnnlib.util.open_url(url) as f:
    #     vgg16 = torch.jit.load(f).eval().to(device)
    vgg16_path = '/data2/wyf/input/jojogan-3d/vgg16.pt'
    vgg16 = torch.jit.load(vgg16_path).eval().to(device)
    # Call other vgg for warping loss
    torch_vgg = models.vgg16(pretrained=True).features.eval().cuda()
    for param in torch_vgg.parameters():
        param.requires_grad_(False)
    layers = '14' #7, 14, 21 -> 128,128,128 / 256, 64, 64 / 512, 32, 32
    # Load networks
    G = copy.deepcopy(G).eval().requires_grad_(False).to(device).float() # type: ignore
    cam_predictor = copy.deepcopy(cam_encoder).eval().cuda()
    if global_config.use_quaternions:
        cam_lr = hyperparameters.cam_lr_quat
    elif global_config.use_6d:
        cam_lr = hyperparameters.cam_lr_6d
    else:
        cam_lr = hyperparameters.cam_lr_2d
    e4e_enc = copy.deepcopy(e4e_encoder).eval().cuda()
    ray_generator = RaySampler()
    target_e4e = (((target+ 1) / 2) * 255).unsqueeze(0).to(device).to(torch.float32)
    if target_e4e.shape[2] > 256:
        target_e4e = F.interpolate(target_e4e, size=(256, 256), mode='area')
    _ = vgg16(target_e4e, resize_images=False, return_lpips=True) # for normalizing the target image
    radius = 2.7 # 设置半径为2.7
    init_ext = torch.Tensor([1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 2.7, 0, 0, 0, 1]).reshape(-1,4,4).cuda() # 相机外参矩阵,表示初始canonical角度
    intrinsic = torch.tensor([4.2647, 0, 0.5, 0, 4.2647, 0.5, 0, 0, 1]).unsqueeze(0).cuda() # 相机内参矩阵,表示焦距
    canonical_cam = torch.cat([init_ext.reshape(-1, 16), intrinsic], dim=-1) # 相机内外参矩阵
    # Calculate mean w
    with torch.no_grad():
        pred_ext_init = euler2rot(torch.tensor([math.pi/2]), torch.tensor([math.pi/2]), torch.zeros(1, 1), batch_size=1)
        cam_init = torch.cat([pred_ext_init, intrinsic], dim=-1) # init camera -> canonical pose
    cam_avg_samples = cam_init.repeat(w_avg_samples, 1)
    z_samples = np.random.RandomState(123).randn(w_avg_samples, G.z_dim)
    w_samples = G.mapping(torch.from_numpy(z_samples).to(device), cam_avg_samples, truncation_cutoff=14, truncation_psi=0.7)
    w_samples = w_samples[:, :1, :].cpu().numpy().astype(np.float32)
    w_avg = np.mean(w_samples, axis=0, keepdims=True)
    w_avg_tensor = torch.from_numpy(w_avg).to(global_config.device)
    w_std = (np.sum((w_samples - w_avg) ** 2) / w_avg_samples) ** 0.5
    mean_w = initial_w if initial_w is not None else torch.from_numpy(w_avg).cuda()
    start_w = e4e_enc(target_e4e).unsqueeze(1)
    # Setup noise inputs.
    noise_bufs = {name: buf for (name, buf) in G.backbone.synthesis.named_buffers() if 'noise_const' in name}
    noise_bufs2 = {name: buf for (name, buf) in G.superresolution.named_buffers() if 'noise_const' in name}
    # Features for target image.
    target_images_contiguous = target.unsqueeze(0).contiguous()
    target_images = (((target+ 1) / 2) * 255).unsqueeze(0).to(device).to(torch.float32)
    if target_images.shape[2] > 256:
        target_images = F.interpolate(target_images, size=(256, 256), mode='area')
    target_features = vgg16(target_images, resize_images=False, return_lpips=True)
    # Setup optimizer
    w_opt = torch.tensor(mean_w + start_w, dtype=torch.float32, device=device, requires_grad=True)
    start_translation = torch.zeros(1, 3).cuda() # 旋转扰动translation的初始值
    translation_opt = torch.tensor(start_translation, dtype=torch.float32, device=device, requires_grad=True) # 建立旋转扰动translation
    w_optimizer = torch.optim.Adam([w_opt] + list(noise_bufs.values()) + list(noise_bufs2.values()), betas=(0.9, 0.999), lr=hyperparameters.first_inv_lr) # 建立隐变量w的优化器
    cam_optimizer = torch.optim.Adam(cam_predictor.parameters(), lr=cam_lr, betas=(0.9, 0.999)) # 建立相机pose的优化器
    translation_optimizer = torch.optim.Adam([translation_opt], lr=hyperparameters.translation_lr) # 建立旋转扰动translation的优化器

    pose_flag = 4 # 1是旋转扰动translation,2是平移扰动movepose,3是固定pose添加偏置再优化,4是固定pose添加固定偏置
    if pose_flag == 2 or pose_flag == 3:
        start_movepose = 0.00 # 平移扰动movepose的初始值
        movepose_opt = torch.tensor(start_movepose, dtype=torch.float32, device=device, requires_grad=True) # 建立平移扰动movepose
        movepose_optimizer = torch.optim.Adam([movepose_opt], lr=hyperparameters.movepose_lr) # 建立平移扰动movepose的优化器
        movepose_lambda = lambda step:1/(step+1) # 计算平移扰动movepose的学习率衰减函数(学习率lr = 原始lr x 衰减函数lambda)
        torch.optim.lr_scheduler.LambdaLR(optimizer=movepose_optimizer, lr_lambda=movepose_lambda, last_epoch=-1, verbose=False) # 设置平移扰动movepose的学习率衰减策略
    # Init noise.
    for buf in noise_bufs.values():
        buf[:] = torch.randn_like(buf)
        buf.requires_grad = True
    for buf in noise_bufs2.values():
        buf[:] = torch.randn_like(buf)
        buf.requires_grad = True
    ###############################################################################################################
    for step in tqdm(range(num_steps)): # 训练核心代码
        if pose_flag == 1: # 对pose添加旋转扰动translation优化
            if global_config.use_quaternions:
                pred_quat = cam_predictor(target_images)
                pred_rotmat = compute_rotation_matrix_from_quaternion(pred_quat) # 计算3x3的旋转矩阵pred_rotmat
            elif global_config.use_6d: # 只有afhq数据集才用这个
                pred_6d = cam_predictor(target_images)
                pred_rotmat = rot6d_to_rotmat(pred_6d)
            else:
                pred_angles = cam_predictor(target_images)
                theta = math.pi/2 + pred_angles[:, 0]
                phi = math.pi/2 + pred_angles[:, 1]
                roll = torch.zeros(1, 1)
                pred_rotmat = euler2rot(theta, phi, roll, batch_size=1).reshape(-1, 4, 4)[:, :3, :3]
            # 添加可优化的扰动
            pred_ext_tmp = torch.eye(4).unsqueeze(0).repeat(pred_rotmat.shape[0], 1, 1).cuda() # 4x4的单位矩阵pred_ext_tmp
            pred_translation = -radius * pred_rotmat[:, :3, 2] # 取3x3的旋转矩阵第三列再 x 半径
            pred_ext_tmp[:, :3, :3] = pred_rotmat # 将4x4单位矩阵的前三行前三列赋值为旋转矩阵pred_rotmat
            translation_opt_world = -torch.bmm(pred_ext_tmp[:, :3, :3], translation_opt.unsqueeze(-1)) * 2.7 # 计算4x4单位矩阵的前3x3 x 扰动translation(初始为[0,0,0])
            tmp_translation = translation_opt_world.squeeze(-1) + pred_translation # 相乘结果 + 原本的旋转矩阵 x 半径
            tmp_translation = tmp_translation / torch.norm(tmp_translation, dim=-1) * 2.7 # 相加结果归一化再 x 半径得到tmp
            # Formulate extrinsic matrix and input cam
            pred_ext = torch.eye(4).unsqueeze(0).cuda() # 4x4的单位矩阵pred_ext
            pred_ext[:, :3, 3] = tmp_translation # 将4x4单位矩阵的前三行的第四列赋值为上面计算结果tmp-->外参矩阵的平移部分
            pred_ext[:, :3, :3] = pred_ext_tmp[:, :3, :3] # 将4x4单位矩阵的前三行前三列赋值为旋转矩阵pred_rotmat-->外参矩阵的旋转部分
            pred_cam = torch.cat([pred_ext.reshape(-1, 16), intrinsic], dim=-1) # 预测出的相机内外参矩阵,这个就是25位的相机位姿
        elif pose_flag == 2: # 对pose添加平移扰动movepose优化
            pred_ext = torch.eye(4).unsqueeze(0).cuda() # 4x4的单位矩阵pred_ext
            pred_ext[:, 1, 3] = pred_ext[:, 1, 3] + movepose_opt # 将4x4单位矩阵的第二行第四列添加平移扰动movepose偏置-->外参矩阵的平移部分
            pred_cam = torch.cat([pred_ext.reshape(-1, 16), intrinsic], dim=-1) # 预测出的相机内外参矩阵,这个就是25位的相机位姿
            print('平移扰动movepose的学习率lr=', movepose_optimizer.param_groups[0]['lr']) # 打印平移扰动movepose的学习率lr
            print('平移扰动movepose=', movepose_opt) # 打印平移扰动movepose
        elif pose_flag == 3: # 固定pose添加偏置再优化
            with open(args_dic['json_dir'], 'rb') as f: # 读取json文件
                label_list = json.load(f)['labels']
            label_list = dict(label_list)
            pred_cam = torch.Tensor([label_list[f'{w_name}.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            pred_cam[0][7] = pred_cam[0][7] + movepose_opt # 添加相机外参矩阵的pose偏置再优化movepose_opt
            print('平移扰动movepose的学习率lr=', movepose_optimizer.param_groups[0]['lr']) # 打印平移扰动movepose的学习率lr
            print('平移扰动movepose=', movepose_opt) # 打印平移扰动movepose
        elif pose_flag == 4: # 固定pose添加固定偏置
            with open(args_dic['json_dir'], 'rb') as f: # 读取json文件
                label_list = json.load(f)['labels']
            label_list = dict(label_list)
            #··················································
            # 真人图可以估计pose，直接从dataset.json中读取pose
            # pred_cam = torch.Tensor([label_list[f'{w_name}.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            # 类真人图无法估计pose，只能用00035.jpg再加偏置
            pred_cam = torch.Tensor([label_list[f'10005.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            pred_cam[0][7] = pred_cam[0][7] + 0.00 # 手动添加相机外参矩阵的pose固定偏置
            #··················································
        else:
            print('error in pose_flag')
            assert 0
        t = (step - hyperparameters.cam_preheat_steps) / (num_steps - hyperparameters.cam_preheat_steps)
        w_noise_scale = w_std * initial_noise_factor * max(0.0, 1.0 - t / noise_ramp_length) ** 2
        lr_ramp = min(1.0, (1.0 - t) / lr_rampdown_length)
        lr_ramp = 0.5 - 0.5 * np.cos(lr_ramp * np.pi)
        lr_ramp = lr_ramp * min(1.0, t / lr_rampup_length)
        lr = initial_learning_rate * lr_ramp
        for param_group in w_optimizer.param_groups:
            param_group['lr'] = lr
        # Synth images from opt_w.
        if step < hyperparameters.cam_preheat_steps:
            ws_expand = w_opt.repeat(1,14,1) # 重复了14层
        else:
            w_noise = torch.randn_like(w_opt) * w_noise_scale
            ws_expand = (w_opt + w_noise).repeat(1,14,1) # 重复了14层
        ###############################################################################################################
        # 这里利用扰动后的pose生成图像，后续的loss计算也全部来自于此
        pred_dict = G.synthesis(ws_expand, pred_cam, noise_mode='const', force_fp32=True) # 添加噪声生成图像
        pred_depths = pred_dict['image_depth']
        pred_images = pred_dict['image']* 127.5 + 128
        # if global_config.visualize_opt_process: # 保存训练过程中每个step的图像
        #     if os.path.isdir(outdir + f'_pivot/{w_name}') == 0:
        #         os.makedirs(outdir + f'_pivot/{w_name}')
        #     if step % 50 == 0:
        #         with torch.no_grad():
        #             intimg = (pred_images.squeeze(0).permute(1,2,0)).clamp(0, 255).to(torch.uint8)
        #         PIL.Image.fromarray(intimg.cpu().numpy(), 'RGB').save(outdir + f'_pivot/{w_name}/{step}.png') # 保存图像
        if step % 50 == 0: # 这里保存的是w_pivot，哪里才能保存w呢？
            ws_clone_1, pred_cam_clone = ws_expand.clone().detach(), pred_cam.clone().detach() # 克隆一份w_pivot和pose_pivot
            # print('ws_clone_1',ws_clone_1)
            # print('pred_cam_clone',pred_cam_clone)
            np.save(args_dic['output_dir'] + f'_pivot/w_{step}.npy',ws_clone_1.cpu().numpy()) # 保存w_pivot
            np.save(args_dic['output_dir'] + f'_pivot/cam_{step}.npy',pred_cam_clone.cpu().numpy()) # 保存pose_pivot
# warp_loss
        if args_dic['warp_lambda'] > 0:
            warp_loss = None
            ws_clone, canonical_cam_clone = ws_expand.clone().detach(), canonical_cam.clone().detach() # 克隆一份w和pose
            # 这个calc_warping_loss函数里面生成图像只用了canonical视角。那些其他的视角参数是转回去warp使用的
            warp_loss, test_img = calc_warping_loss(ws_clone, canonical_cam_clone, pred_ext, init_ext, intrinsic, pred_depths, target_images_contiguous,G, torch_vgg, ray_generator, layers = layers)
            # if global_config.visualize_warp_process:
            #     if step % 10 == 0:
            #         intwarp = (test_img.squeeze(0).permute(1,2,0) * 127.5 + 128).clamp(0, 255).to(torch.uint8)
            #         if os.path.isdir(f'./warp_image_test/warp_{w_name}') == 0:
            #             os.makedirs(f'./warp_image_test/warp_{w_name}')
            #         PIL.Image.fromarray(intwarp.cpu().numpy(), 'RGB').save(f'./warp_image_test/warp_{w_name}/{step}.png')
# dist_loss
        if args_dic['dist_lambda'] > 0:
            if pred_images.shape[2] > 256:
                pred_images = F.interpolate(pred_images, size=(256, 256), mode='area')
            synth_features = vgg16(pred_images, resize_images=False, return_lpips=True)
            dist_loss = (target_features - synth_features).square().sum()
# reg_loss
        if args_dic['reg_lambda'] > 0:
            reg_loss = 0.0
            for v in noise_bufs.values():
                noise = v[None, None, :, :] # must be [1,1,H,W] for F.avg_pool2d()
                while True:
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=3)).mean() ** 2
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=2)).mean() ** 2
                    if noise.shape[2] <= 8:
                        break
                    noise = F.avg_pool2d(noise, kernel_size=2)
            for v in noise_bufs2.values():
                noise = v[None, None, :, :]
                while True:
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=3)).mean() ** 2
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=2)).mean() ** 2
                    if noise.shape[2] <= 8:
                        break
                    noise = F.avg_pool2d(noise, kernel_size=2)
        #####################新加入的loss
# id_loss
        if args_dic['id_lambda'] > 0:
            calc_id_loss = IDLoss().to(device).eval()
            id_loss = calc_id_loss(pred_images, target_e4e)
# l2_loss
        if args_dic['l2_lambda'] > 0:
            l2_loss = calc_l2loss(pred_images, target_e4e)
# lpips_loss
        if args_dic['lpips_lambda'] > 0:
            # 可学习感知图像块相似度(Learned Perceptual Image Patch Similarity, LPIPS)也称为“感知损失”(perceptual loss)，用于度量两张图像之间的差别。LPIPS 比传统方法（比如L2/PSNR, SSIM, FSIM）更符合人类的感知情况。LPIPS的值越低表示两张图像越相似，反之，则差异越大。
            # https://blog.csdn.net/weixin_43135178/article/details/127664187
            calc_lpips_loss = LPIPS(net=hyperparameters.lpips_type).to(device).eval()
            lpips_loss = calc_lpips_loss(pred_images, target_e4e)
# mse_loss
        if args_dic['mse_lambda'] > 0:
            calc_mse_loss = torch.nn.MSELoss().to(device).eval()
            mse_loss = calc_mse_loss(pred_images, target_e4e)
# mask_loss
        if args_dic['mask_12_lambda'] > 0 or args_dic['mask_lpips_lambda'] > 0:
            pred_images_path = paths_config.root_path + '/face_parsing/res/data/pred_images.jpg'
            target_e4e_path = paths_config.root_path + '/face_parsing/res/data/target_e4e.jpg'
            save_image(pred_images, pred_images_path, normalize=True) # 加上normalize=True后图像颜色就正常了，相当于是逆向的normalization。更具体的说就是因为，原始的图像需要先normalize变成0-1才能输入网络，之后输出网络后，值也不对，需要逆向的标准化才行。注意这里的逆向标准化是mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)，不是什么*255之类的
            save_image(target_e4e, target_e4e_path, normalize=True)
            mask_pred,mask_target = calc_mask(pred_images_path, target_e4e_path)
            mask_12_loss = calc_l2loss(mask_pred, mask_target)
            mask_lpips_loss = calc_lpips_loss(mask_pred, mask_target)
# ssim_loss
        if args_dic['ssim_lambda'] > 0:
            ssim_loss = calc_ssim(pred_images_path,target_e4e_path)
# psnr_loss
        if args_dic['psnr_lambda'] > 0:
            psnr_loss = calc_psnr(pred_images_path,target_e4e_path)
        # print('------------------')
        # print('warp_loss        =', warp_loss) # 0.4720
        # print('dist_loss        =', dist_loss) # 0.5487
        # print('reg_loss         =', reg_loss) # 0.0572
        # print('id_loss          =', id_loss) # 0.3113
        # print('l2_loss          =', l2_loss) # 1.1953
        # print('lpips_loss       =', lpips_loss) # 0.4128
        # print('------------------')
        # print('mse_loss         =', mse_loss) # 1.1953
        # print('mask_12_loss     =', mask_12_loss) # 0.7218
        # print('mask_lpips_loss  =', mask_lpips_loss) # 0.5260
        # print('ssim_loss        =', ssim_loss) # 0.3716385775396315
        # print('psnr_loss        =', psnr_loss) # 11.674259838898443
        # print('------------------')
        loss = 0.0
        if args_dic['warp_lambda'] > 0:
            loss = loss + args_dic['warp_lambda'] * warp_loss
        if args_dic['dist_lambda'] > 0:
            loss = loss + args_dic['dist_lambda'] * dist_loss
        if args_dic['reg_lambda'] > 0:
            loss = loss + args_dic['reg_lambda'] * reg_loss
        if args_dic['id_lambda'] > 0:
            loss = loss + args_dic['id_lambda'] * id_loss
        if args_dic['l2_lambda'] > 0:
            loss = loss + args_dic['l2_lambda'] * l2_loss
        if args_dic['lpips_lambda'] > 0:
            loss = loss + args_dic['lpips_lambda'] * lpips_loss
        if args_dic['mse_lambda'] > 0:
            loss = loss + args_dic['mse_lambda'] * mse_loss
        if args_dic['mask_12_lambda'] > 0:
            loss = loss + args_dic['mask_12_lambda'] * mask_12_loss
        if args_dic['mask_lpips_lambda'] > 0:
            loss = loss + args_dic['mask_lpips_lambda'] * mask_lpips_loss
        if args_dic['ssim_lambda'] > 0:
            loss = loss + args_dic['ssim_lambda'] * ssim_loss
        if args_dic['psnr_lambda'] > 0:
            loss = loss + args_dic['psnr_lambda'] * psnr_loss
        # 金克斯最优loss = 1 * dist_loss + 1 * id_loss + 1 * lpips_loss
        # HyperStyle使用loss = 0.1 * id_loss + 1 * l2_loss + 0.8 * lpips_loss
        # loss = dist_loss + id_loss + lpips_loss + mask_loss_12
        # 新一轮：
        # loss = dist_loss + id_loss + lpips_loss + l2_loss
        if step < hyperparameters.cam_preheat_steps: # 50
            cam_optimizer.zero_grad()
            translation_optimizer.zero_grad()
            # movepose_optimizer.zero_grad()
            loss.backward()
            cam_optimizer.step()
            translation_optimizer.step() # 优化旋转扰动translation
            # movepose_optimizer.step() # 优化平移扰动movepose
        # elif step < 151:
        else:
            w_optimizer.zero_grad()
            cam_optimizer.zero_grad()
            translation_optimizer.zero_grad()
            # movepose_optimizer.zero_grad()
            loss.backward()
            cam_optimizer.step()
            w_optimizer.step() # 优化w
            translation_optimizer.step() # 优化旋转扰动translation
            # movepose_optimizer.step() # 优化平移扰动movepose
        # else:
        #     w_optimizer.zero_grad()
        #     cam_optimizer.zero_grad()
        #     #translation_optimizer.zero_grad()
        #     # movepose_optimizer.zero_grad()
        #     loss.backward()
        #     cam_optimizer.step()
        #     w_optimizer.step()
        #     #translation_optimizer.step()
        #     # movepose_optimizer.step()
        # Normalize noise.
        with torch.no_grad():
            for buf in noise_bufs.values():
                buf -= buf.mean()
                buf *= buf.square().mean().rsqrt()
            for buf in noise_bufs2.values():
                buf -= buf.mean()
                buf *= buf.square().mean().rsqrt()
    # freeze encoder for tuning step.
    with torch.no_grad():
        cam = pred_cam.clone().detach()
        ws_expand =ws_expand.clone().detach()
    del G
    del cam_predictor
    del e4e_enc
    torch.cuda.empty_cache()
    return ws_expand, cam


# -*- coding: utf-8 -*-
# Plot
import matplotlib.pyplot as plt

import os

# Libs
import numpy as np
import pandas as pd
import pickle

from mbcrossval import mbcfg

def crossval_boxplot(file):
    # load pickle file
    xvaldict = pickle.load(open(file, 'rb'))
    xval = xvaldict['statistic']

    # for convenience
    xval.tgrad *= 1000
    xval.tgrad = np.round(xval.tgrad, decimals=1)

    # some plotting stuff:
    labels = {'prcpsf': 'Precipitation Factor',
              'tliq': 'T liquid precipitation [deg C]',
              'tmelt': 'Melt temperature [deg C]',
              'tgrad': 'Temperature laps rate [K/km]'}
    # some plotting stuff:
    title = {'prcpsf': 'Precipitation Factor',
             'tliq': 'Liquid precipitation temperature',
             'tmelt': 'Melt temperature',
             'tgrad': 'Temperature laps rate'}

    allvar = {'prcpsf': 2.5, 'tliq': 2.0, 'tmelt': -1.0, 'tgrad': -6.5}

    for var in allvar.keys():
        f, ((ax0, ax1), (ax2, ax3)) = plt.subplots(2, 2, figsize=(13, 7))

        # find the entries with the standard values
        var0 = allvar.copy()
        del var0[var]
        idx = list(var0.keys())

        base = xval.loc[np.isclose(xval[idx[0]], var0[idx[0]]) &
                        np.isclose(xval[idx[1]], var0[idx[1]]) &
                        np.isclose(xval[idx[2]], var0[idx[2]])]

        # RMSE
        xval.boxplot(column='rmse', by=var, ax=ax0, grid=False,
                     positions=base[var], widths=0.2)
        base.plot(x=var, y='rmse', kind='scatter', ax=ax0, color='r',
                  linewidth=3, )
        ax0.set_ylabel('mean rmse')
        ax0.set_xlabel('')
        ax0.set_title('')
        ax0.set_ylim((200, 800))

        # BIAS
        xval.boxplot(column='bias', by=var, ax=ax1, grid=False,
                     positions=base[var], widths=0.2)
        base.plot(x=var, y='bias', kind='scatter', ax=ax1, color='r',
                  linewidth=3)
        ax1.plot(ax1.get_xlim(), (0.0, 0.0), 'k-', linewidth=1)
        ax1.set_ylabel('mean bias')
        ax1.set_xlabel('')
        ax1.set_title('')
        ax1.set_ylim((-400, 100))

        # STD quotient
        xval.boxplot(column='std_quot', by=var, ax=ax2, grid=False,
                     positions=base[var], widths=0.2)
        base.plot(x=var, y='std_quot', kind='scatter', ax=ax2, color='r',
                  linewidth=3)
        ax2.plot(ax2.get_xlim(), (1.0, 1.0), 'k-', linewidth=1)
        ax2.set_xlabel(labels[var])
        ax2.set_ylabel('mean std quotient')
        ax2.set_title('')
        ax2.set_ylim((0, 3))

        # CORE
        xval.boxplot(column='core', by=var, ax=ax3, grid=False,
                     positions=base[var], widths=0.2)
        base.plot(x=var, y='core', kind='scatter', ax=ax3, color='r',
                  linewidth=3)
        ax3.set_xlabel(labels[var])
        ax3.set_ylabel('mean corelation')
        ax3.set_title('')
        ax3.set_ylim((0.55, 0.65))

        # figure stuff

        f.suptitle('Crossvalidation results with respect to %s' % title[var])

        # f.tight_layout()
        plotname = os.path.join(mbcfg.PATHS['plotdir'],
                                '%s_crossval_box.png' % var)
        f.savefig(plotname, format='png')

    plt.show()

def crossval_timeseries(file):
    # load pickle file
    xvaldict = pickle.load(open(file, 'rb'))
    data = xvaldict['massbalance']
    # time series plots of mass balance

    # reindex for plotting
    reind = pd.Index(np.arange(data.index[0], data.index[-1]+1))

    for gd in data.columns.levels[0]:
        f, ax1 = plt.subplots(1, 1, figsize=(12, 5), sharey=True)

        ax1.plot(data[gd].measured.reindex(reind), 'ko-', linewidth=3,
                 label='Measured annual mass balance',
                 color='xkcd:charcoal')
        ax1.plot(data[gd].calibrated.reindex(reind), 'go-', linewidth=3,
                 label='OGGM: Calibrated t_star',
                 color='xkcd:bluish')
        ax1.plot(data[gd].crossvalidated.reindex(reind), 'ro-', linewidth=3,
                 label='OGGM: Crossvalidated t_star',
                 color='xkcd:reddish')
        ax1.set_xlabel('Years')
        ax1.set_ylabel('Specific mass-balance (mm w.e.)')
        ax1.legend(loc='best')

        name = xvaldict['per_glacier'].loc[gd].Name

        if name == '':
            ax1.set_title(gd)
        else:
            ax1.set_title('%s (%s)' % (gd, name))

        ax1.grid(True)
        f.tight_layout()
        plotname = os.path.join(mbcfg.PATHS['plotdir'], '%s.png' % gd)
        f.savefig(plotname, format='png')
        plt.close(f)

def crossval_histogram(file):
    # histogramplot of the crossvalidation. compare Marzeion 2012, Figure 3
    # load pickle file
    xvaldict = pickle.load(open(file, 'rb'))
    data = xvaldict['per_glacier']

    # Marzeion et al Figure 3
    f, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5), sharey=True)
    bins = np.arange(20) * 400 - 3800
    data['xval_bias'].plot(ax=ax1, kind='hist', bins=bins,
                           color='C3', label='')
    ax1.vlines(data['xval_bias'].mean(), 0, 120,
               linestyles='--', label='Mean')
    ax1.vlines(data['xval_bias'].quantile(), 0, 120, label='Median')
    ax1.vlines(data['xval_bias'].quantile([0.05, 0.95]), 0, 120,
               color='grey',
               label='5% and 95%\npercentiles')
    ax1.text(0.01, 0.99, 'N = {}'.format(len(data)),
             horizontalalignment='left',
             verticalalignment='top',
             transform=ax1.transAxes)

    ax1.set_ylim(0, 120)
    ax1.set_ylabel('N Glaciers')
    ax1.set_xlabel('Mass-balance error (mm w.e. yr$^{-1}$)')
    ax1.legend(loc='best')
    ax1.set_title('Cross validated t_star')
    data['interp_bias'].plot(ax=ax2, kind='hist', bins=bins, color='C0')
    ax2.vlines(data['interp_bias'].mean(), 0, 120, linestyles='--')
    ax2.vlines(data['interp_bias'].quantile(), 0, 120)
    ax2.vlines(data['interp_bias'].quantile([0.05, 0.95]), 0, 120,
               color='grey')
    ax2.set_xlabel('Mass-balance error (mm w.e. yr$^{-1}$)')
    ax2.set_title('Interpolated mu_star')
    plotname = os.path.join(mbcfg.PATHS['plotdir'], 'mb_histogram.png')
    plt.tight_layout()
    plt.savefig(plotname, format='png')


from datetime import datetime
now = datetime.now()
date = now.month + now.day
from PIL import Image
from playsound import playsound
import thread

thread.start_new_thread(playsound, ('music.mp3',))

tea_boba = [
    'Earl Grey Milk Tea',
    'Black Milk Tea',
    'Oolong Milk Tea',
    'Jasmine Milk Tea',
    'Classic Milk Tea',
]
recommended_tea_boba = tea_boba[date % len(tea_boba)]

fruit_boba = [
    'Mango Green Tea',
    'Peach Black Tea',
    'Lemon Darjeeling Tea',
]
recommended_fruit_boba = fruit_boba[date % len(fruit_boba)]

creama_boba = [
    'Earl Grey Creama',
    'Oreo Creama',
    'Chocolate Creama',
    'Classic Milk Tea Creama',
]
recommended_creama_boba = creama_boba[date % len(creama_boba)]

def select_boba(kind, boba_list):
    print("Okay! Here is a list of %s boba: ") % kind
    for i in range(len(boba_list)):
        print('%i. %s') % (i, boba_list[i])
    selection = int(raw_input("Which one would you like? To select one, enter a number: "))
    if 0 <= selection < len(boba_list):
        boba = boba_list[selection]
    else:
        print("I'm sorry, but I didn't quite get that. Can you repeat that again? ")
        return
    print("Okay, great! We will make you your %s in no time!") % boba
    return boba

def boba_shop():
    print("Hello, and welcome to our boba shop.")
    if raw_input("Enter 'y' or 'yes' to proceed: ") not in ('y', 'yes'):
        print("Thank you for checking us out. Please come again.")
        return

    print("""1. I want to choose a boba!
2. I want a boba recommendation!
3. I want to make my own boba!""")

    help_input = raw_input("Please enter a number: ")
    if help_input == '1':
        print("""Okay, good! Sounds like you want to choose from our wide selection of bobas!
1. Milk Tea
2. Fruit Tea
3. Sea Salt Creama""")
        type_of_boba = raw_input("What type of boba are you looking for? Please enter a number: ")

        if type_of_boba == '1':
            boba = select_boba("Milk Tea Boba", tea_boba)

        if type_of_boba == '2':
            boba = select_boba("Fruit Tea Boba", fruit_boba)

        if type_of_boba == '3':
            boba = select_boba("Creama Boba", creama_boba)

    elif help_input == '2':
        print("""Okay, sounds like you want a recommendation!
Let me ask you some questions.""")

        creamy_or_sappari = raw_input("Do you like cream? Enter 'y' or 'n': ")
        if creamy_or_sappari == 'y':
            salty_or_not = raw_input("Do you like something salty? Enter 'y' or 'n': ")

            if salty_or_not == 'y':
                boba = recommended_creama_boba
                print("Great choice! I recommend %s!") % boba

            elif salty_or_not == 'n':
                boba = recommended_tea_boba
                print("Great taste! I recommend %s!") % boba

            else:
                print("Sorry, I didn't quite get that! Please try again. ")
                return

        elif creamy_or_sappari == 'n':
            likecitrus = raw_input("Do you like citrus fruits? Enter 'y' or 'n'.")

            if likecitrus == 'y':
                boba = 'Lemon Darjeeling Tea'
                print("Great! I recommend %s!") % boba

            elif likecitrus == 'n':
                boba = recommended_fruit_boba
                print("Great! I recommend %s!") % boba

            else:
                print("Sorry, I didn't quite get that! Please try again. ")
                return
        else:
            print("Sorry, I didn't quite get that! Please try again. ")
            return

    elif help_input == '3':
        print("Okay, so you want to make your own boba! Let's get started!")
        proceed = raw_input("Enter 'y' or 'yes' to proceed: ")

        if proceed == 'y' or proceed == 'yes':
            print("Here is a list of tea that we offer: 1. Black Tea, 2. Green Tea, 3. Earl Grey Tea")
            type_of_tea = raw_input("What type of tea would you like to get? Enter a number: ")

            if type_of_tea == '1':
                boba = 'black tea'
            elif type_of_tea == '2':
                boba = 'green tea'
            elif type_of_tea == '3':
                boba = 'earl grey tea'
            else:
                print("Sorry, I didn't quite get that! Please try again. ")
                return
        # else:   TODO: fic this part
        #     print("I'm sorry, ")
        #
        #     creaminess_of_tea = raw_input("Do you want to add milk? Type 'y' or 'n'.")
        #
        #     if creaminess_of_tea == 'y':
        #         creaminess_of_tea = 'milk'
        #     else:
        #         creaminess_of_tea = 'no milk'
        #
        #     boba = "%s with %s" % (type_of_tea, creaminess_of_tea)
        #
        #     print("Okay, we've got your order!")

    proceed = raw_input("Enter 'y' or 'yes' to proceed: ")

    if proceed.lower() == 'y' or proceed.lower() == "'y'" or proceed.lower() == 'yes':

            print("Here is a list of toppings that we offer.")
            print("1. Pearls, 2. Lychee, 3.Grassjelly, 4.Creama")
            toppings = raw_input("Would you like to get any toppings? Type a number or answer 'n' for no: ")

            if toppings == '1':
                toppings = "pearls"
            elif toppings == '2':
                toppings = "lychee"
            elif toppings == '3':
                toppings = "grassjelly"
            elif toppings == '4':
                toppings = "creama"
            elif toppings == 'n':
                toppings = "no toppings"
            else:
                print("Sorry, I didn't quite get that! Please try again.")
                return

            print("Okay, great!")

    else:
        print("It seems like you didn't enter a valid number. Please come back again!")
        return

    proceed = raw_input("Enter 'y' or 'yes' to proceed: ")

    if proceed.lower() == 'y' or proceed.lower() == "'y'" or proceed.lower() == 'yes':

        print("Now, please specify preferred percentage of ice.")
        percentage_of_ice = raw_input("Enter a number between 0-100: ")

        print("Now, please specify preferred sugar level.")
        percentage_of_sugar = raw_input("Enter a number between 0-100: ")

    else:
        print("Sorry, I didn't quite get that! Please try again.")
        return

    proceed = raw_input("Enter 'y' or 'yes' to proceed: ")

    if proceed.lower() == 'y' or proceed.lower() == "'y'" or proceed.lower() == 'yes':
        print("Great! Your boba is almost ready.")
        print("We just need one more thing.")
        name = raw_input("What is your name? ")

    else:
        print("Sorry, I didn't quite get that! Please try again.")
        return

#confirmation of order
    proceed = raw_input("Enter 'y' or 'yes' to proceed: ")

    if proceed.lower() == 'y' or proceed.lower() == "'y'" or proceed.lower() == 'yes':
        print("Thanks, %s! So let's confirm your order.") % name
        print("You ordered: %s with toppings of %s, ice level is %s and sweetness level is %s.") % (boba, toppings, percentage_of_ice, percentage_of_sugar)

    else:
        print("Sorry, I didn't quite get that! Please try again.")
        return

    proceed = raw_input("Is this correct? Enter 'y' or 'yes' to proceed: ")

    if proceed.lower() == 'y' or proceed.lower() == "'y'" or proceed.lower() == 'yes':
        print("Okay, %s! Your boba is now ready.") %name

        boba = boba.replace(' ', '')
        boba = boba.lower()
        order = boba + "_" + toppings
        address = order + ".png"
        im = Image.open(address)
        im.show()

    else:
        print("Sorry, I didn't quite get that! Please try again.")
        return

    proceed = raw_input("Enter 'q' or 'quit' to leave shop: ")

    if proceed.lower() == 'q' or proceed.lower() == "'q'" or proceed.lower() == 'quit':
        print('Thanks for getting boba from us! We hope you come again!')

    else:
        print("Sorry, I didn't quite get that! Please try again.")
        return

boba_shop()


import os
from keras import layers
from keras import models
from keras import optimizers
from data_preprocessing import train_generator, validation_generator
import matplotlib.pyplot as plt

os.environ['KMP_DUPLICATE_LIB_OK']='True'

# Conv2D 와 MaxPolling2D를 활용해서 층을 연결한다.
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D(2, 2))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.summary()

model.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])

history = model.fit_generator(train_generator, steps_per_epoch=100, epochs=100, validation_data = validation_generator, validation_steps=50)

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

model.save('cats_and_dogs_small_1.h5')


class Solution:
    # @param S, a list of integer
    # @return a list of lists of integer
    def subsets(self, S):
        n = len(S)

        result = []

        S.sort()

        for i in range(2**n):
            self.addSol(i, S, result)

        return result

    def addSol(self, i, S, result):
        temp = []
        for j in range(len(S)):
            if self.getBit(i, j):
                temp.append(S[j])

        result.append(temp)

    def getBit(self, i, j):
        mask = 1 << j

        return i & mask


#!/usr/bin/env python
import json
import os
import yaml

PATCH_LABELS = ["patch", "fix", "bug", "docs"]
MINOR_LABELS = ["minor", "feature"]
MAJOR_LABELS = ["major", "release"]

chartName = os.getenv('CHART_NAME')

with open(chartName + "/Chart.yaml", 'r') as chart:
    d = yaml.safe_load(chart)

bump = None
labels = [l.get("name")
          for l in json.loads(os.environ['GITHUB_CONTEXT'])['event']
          ['pull_request'].get('labels', [])]

if len([value for value in PATCH_LABELS if value in labels]) > 0:
    bump = "patch"
elif len([value for value in MINOR_LABELS if value in labels]) > 0:
    bump = "minor"
elif len([value for value in MAJOR_LABELS if value in labels]) > 0:
    bump = "major"

if bump:
    print(" ".join([d['version'], bump]))
else:
    print("nobump")


# -*- coding: utf-8 -*-
"""
multi-class perceptron
hypothesis: h = argmax(np.matmul(x, theta))
loss function: customed
Created on Sun Aug 29 11:10:11 2021
@author: lee
"""
import numpy as np
import matplotlib.pyplot as plt

#%% 数据生成
data_size = 360
m = 4
cov = [[1, 0],[0, 1]]
x = np.random.multivariate_normal([0, 0], cov, data_size//9)
x = np.row_stack((x, np.random.multivariate_normal([-m, m], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([m, -m], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([m, 0], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([m, m], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([0, m], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([-m, 0], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([-m, -m], cov, data_size//9)))
x = np.row_stack((x, np.random.multivariate_normal([0, -m], cov, data_size//9)))
x = np.column_stack((np.ones(data_size), x))
y = np.zeros((data_size, 3))
y[:data_size//3, 0] = 1
y[data_size//3:2*data_size//3, 1] = 1
y[2*data_size//3:data_size, 2] = 1

#%% 参数设定
theta = np.random.randn(3, 3)

#%% 超参数设定
train_count = 1000
batch_size = 64
lr = 1e-3

#%% 假说函数
def calHypo(x, theta):
    _h = np.matmul(x, theta)
    h = np.zeros_like(_h)
    h[np.arange(x.shape[0]), np.argmax(_h, axis=1)] = 1
    return h

#%% 损失函数
def calLoss(x, y, theta):
    h = calHypo(x, theta)
    loss = (h - y) * np.matmul(x, theta)
    return np.sum(loss) / x.shape[0]

#%% 准确率
def accuracy(x, y, theta):
    h = calHypo(x, theta)
    compare = (np.argmax(h, 1) == np.argmax(y, 1))
    return np.sum(compare)/x.shape[0]

#%% 显示
x1 = [[i / 10] * (160) for i in range(-80, 80)]
x1 = np.array(x1)
x1 = x1.flatten()
x2 = [i / 10 for i in range(-80, 80)] * (160)
x2 = np.array(x2)
x0 = np.ones(len(x1))
xt = np.column_stack((x0, x1, x2))
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
loss_list = []

#%% 训练
for i in range(1, train_count + 1):
    mask = np.random.choice(data_size, batch_size)
    train_x, train_y = x[mask], y[mask]
    h = calHypo(train_x, theta)
    grad = np.matmul(train_x.T, (h - train_y))
    theta = theta - lr*grad

    if i % (train_count // 20) == 0:
        loss = calLoss(x, y, theta)
        loss_list.append(loss)

        t_data = np.argmax(calHypo(xt, theta), 1)
        ax1.cla()
        mask0 = [i for i in range(len(t_data)) if t_data[i] == 0]
        mask1 = [i for i in range(len(t_data)) if t_data[i] == 1]
        mask2 = [i for i in range(len(t_data)) if t_data[i] == 2]
        ax1.scatter(xt[mask0, 1], xt[mask0, 2], color='blue', marker='s', s=10)
        ax1.scatter(xt[mask1, 1], xt[mask1, 2], color='red', marker='s', s=10)
        ax1.scatter(xt[mask2, 1], xt[mask2, 2], color='green', marker='s', s=10)
        data_size = x.shape[0]
        ax1.scatter(x[:data_size//3, 1], x[:data_size//3, 2], color='darkblue')
        ax1.scatter(x[data_size//3:2*data_size//3, 1], x[data_size//3:2*data_size//3, 2], color='darkred')
        ax1.scatter(x[2*data_size//3:data_size, 1], x[2*data_size//3:data_size, 2], color='darkgreen')
        ax1.set_title(i)

        ax2.cla()
        ax2.plot(range(len(loss_list)), loss_list)
        ax2.set_title('loss:' + str(loss))

        print('accuracy: ', accuracy(x, y, theta))
        plt.pause(0.1)


import os
import numpy
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# from Cython.Build import cythonize

mkl_dir = os.environ.get("MKLROOT", None)
if not mkl_dir:
    raise RuntimeError("MKLROOT is not set, "
                       "please make sure MKL is properly installed!")

ext_modules = [Extension(
    name="mklpy",
    sources=[
        "mkl.pyx",
        "mkl_conv.cpp",
        ],
    include_dirs=[numpy.get_include(), "%s/include" % (mkl_dir)],
    language="C++",
    libraries=["mklml_intel", "iomp5"],
    library_dirs=["%s/lib" % (mkl_dir)]
    )]

setup(
    name="mklpy",
    cmdclass={"build_ext": build_ext},
    ext_modules=ext_modules,
    )


# https://www.jiuzhang.com/solutions/paint-house
# https://medium.com/@derekfan/九章算法-動態規劃-序列型-67a3d64bf2bb
# https://leetcode.com/articles/paint-house/

class Solution:
    def minCost(self, costs: List[List[int]]) -> int:
        # return self.dp_search(costs)
        return self.dp_search_v2(costs)

    def dp_search_v2(self, costs):
        if len(costs) == 0:
            return 0

        for i in range(len(costs) - 2, -1, -1):
            # Total cost of painting ith house red.
            costs[i][0] += min(costs[i + 1][1], costs[i + 1][2])
            # Total cost of painting ith house blue.
            costs[i][1] += min(costs[i + 1][0], costs[i + 1][2])
            # Total cost of painting ith house green.
            costs[i][2] += min(costs[i + 1][0], costs[i + 1][1])

        return min(costs[0])

    def dp_search(self, costs):
        # O(3*N)
        dp = [[0] * 3 for _ in range(len(costs) + 1)]
        colors = [0, 1, 2]
        for i in range(1, len(costs) + 1):
            for j in range(3):
                dp[i][j] = min([dp[i - 1][k] + costs[i - 1][k] for k in colors[:j] + colors[j + 1:]])

        return min(dp[-1])


from nltk import *
def postagger(sent):
	text = word_tokenize(sent)
	posTagged = pos_tag(text)
	simplifiedTags = [(word, map_tag('en-ptb', 'universal', tag)) for word, tag in posTagged]
	return simplifiedTags
class Rules:
    def rule_Acknowledgement(self,h):
        words = map(lambda x : x.lower(),h[0]["sentences"])
        if (("thanks" in words) or ("thank" in words) or ('yes' in words)) or ( 'i' in words and 'do' in words) and '?' not in words:
            return 1
        else:
            return 0

    def rule_Disagreement(self,h):
        words = h[0]["sentences"]
        if (("not" in words) or ("no" in words) or ('else' in words) or ('alternative' in words)):
            return 1
        else:
            return 0

    def rule_Greeting(self,h):
        words = h[0]["sentences"]
        if (("hi" in words) or ('hello' in words) or ('hey' in words)):
            return 1
        else:
            return 0

    def rule_Agreement(self,h):
        words = h[0]["sentences"]
        if (("true" in words) or ("yes" in words) or ('indeed' in words)):
            return 1
        else:
            return 0

    def eval(self,h):
        if(self.rule_Acknowledgement(h)==1):
            return "acknowledgement"
        elif self.rule_Greeting(h)==1:
            return "greeting"
        elif self.rule_Disagreement(h)==1:
            return "disagreement"
        elif self.rule_Agreement(h) == 1:
            return "agreement"
        else:
            return ""


import numpy as np
import cv2
import math

from lane_lib import masking

# Class for lane detection on video frames
class LaneDetect():

    def __init__(self, M, Minv):

        self.M = M
        self.Minv = Minv
        self.initialised = False

        # BGR format
        self.colour_orange = (0, 165, 255) #(255, 0, 0)
        self.colour_red = (0, 0, 255)
        self.colour_green = (0, 255, 0)
        self.colour_light_blue = (180, 180, 50)

    # Main method to preprocess raw image, find lane lines and annotate input frame
    def detect(self, img, frame_overlay=True):

        # Apply binary masking
        self.mask = masking.BinaryMasking(img).mask
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_size = self.mask.shape

        # Warp image to bird-eye view perspective
        self.img_binary_warped = cv2.warpPerspective(self.mask, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)
        self.img_colour_warped = cv2.warpPerspective(img, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)

        # Initialise for the first time to calculate base lane positions
        # Otherwise, search around margin from previous position
        if not self.initialised:
            if not self.init():
                return self.result_img
        else:
            self.update()

         # Thickness of fit lane lines to be drawn
        margin = 30

        # Define search window around the previous left and right fits
        left_search1 = np.array([(np.vstack([self.left_polyfit_x - margin, self.plot_y])).T])
        left_search2 = np.array([np.flipud((np.vstack([self.left_polyfit_x + margin, self.plot_y])).T)])
        left_pts = np.hstack((left_search1, left_search2))
        right_search1 = np.array([(np.vstack([self.right_polyfit_x - margin, self.plot_y])).T])
        right_search2 = np.array([np.flipud((np.vstack([self.right_polyfit_x + margin, self.plot_y])).T)])
        right_pts = np.hstack((right_search1, right_search2))

        # Draw the lane onto the warped blank image
        img_search_window = np.zeros_like(self.img_colour_warped)

        cv2.fillPoly(img_search_window, np.int_([left_pts]), self.colour_red)
        cv2.fillPoly(img_search_window, np.int_([right_pts]), self.colour_green)

        left_line = np.array([(np.vstack([self.left_polyfit_x[::-1], self.plot_y[::-1]])).T])
        right_line = np.array([(np.vstack([self.right_polyfit_x, self.plot_y])).T])
        line_pts = np.hstack((left_line, right_line))
        cv2.fillPoly(img_search_window, np.int_([line_pts]), self.colour_light_blue)

        img_lane = cv2.warpPerspective(img_search_window, self.Minv, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)

        if frame_overlay:
            self.result_img = cv2.addWeighted(img, 1.0, img_lane, 0.6, 0)
        else:
            self.result_img = img_lane

        # Calculate curvature and annotate video
        self.lane_curvature()

        # Convert back to RGB colour space
        self.result_img = cv2.cvtColor(self.result_img, cv2.COLOR_BGR2RGB)

        return self.result_img

    # Calculate lane line curvature and annotate final image
    def lane_curvature(self):

        # Lane curvature
        y_m_px = 30. / 720      # meters/pixel in y direction
        x_m_px = 3.7 / 700      # meters/pixel in x direction

        # Calculate radius of curvature using maximum value of y (bottom-most of the frame)
        plot_y_max = np.max(self.plot_y)
        self.left_curve_rad = ((1 + (2 * self.left_polyfit[0] * plot_y_max * y_m_px + self.left_polyfit[1] * x_m_px)**2)**1.5) / np.absolute(2 * self.left_polyfit[0])
        self.right_curve_rad = ((1 + (2 * self.right_polyfit[0] * plot_y_max * y_m_px + self.right_polyfit[1] * x_m_px)**2)**1.5) / np.absolute(2 * self.right_polyfit[0])
        self.curvature = (self.left_curve_rad + self.right_curve_rad) / 2.0

        # Calculate offset of car from the centre
        self.offset = ((self.left_polyfit_x[10] + self.right_polyfit_x[10] - self.mask.shape[1]) / 2) * x_m_px

        if self.offset > 0:
            self.direction = 'Right'
        else:
            self.direction = 'Left'

        # Annotate video
        cv2.putText(self.result_img,
                    'Offset from Center = %.2f m (%s)' % (np.abs(self.offset), self.direction),
                    (int(self.mask.shape[1] * 0.35), 100), cv2.FONT_HERSHEY_SIMPLEX, 0.75, self.colour_orange, 2)

        cv2.putText(self.result_img,
                    'Radius of Curvature = %.2f m' % self.curvature,
                    (int(self.mask.shape[1] * 0.36), 140), cv2.FONT_HERSHEY_SIMPLEX, 0.75, self.colour_orange, 2)

    # Visualising Search Windows and Fit Lane Lines (used in Jupyter notebook)
    def draw_debug(self, img):

        # Undistort image frame
        img = cv2.undistort(img, self.mtx, self.dist, None, self.mtx)

        # Apply binary masking
        binary_masking = masking.BinaryMasking(img)
        self.mask = binary_masking.mask
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_size = self.mask.shape

        # Warp image to bird-eye view perspective
        self.img_binary_warped = cv2.warpPerspective(self.mask, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)
        img_binary_warped2 = np.copy(self.img_binary_warped)

        # Draw the lane onto the warped blank image
        self.img_search_window = np.zeros_like(img)

        # Initialise for the first time to calculate base lane positions
        self.init(silent=False)

        # Thickness of fit lane lines to be drawn
        margin = 15

        # Define search window around the previous left and right fits
        left_search1 = np.array([(np.vstack([self.left_polyfit_x - margin, self.plot_y])).T])
        left_search2 = np.array([np.flipud((np.vstack([self.left_polyfit_x + margin, self.plot_y])).T)])
        left_pts = np.hstack((left_search1, left_search2))
        right_search1 = np.array([(np.vstack([self.right_polyfit_x - margin, self.plot_y])).T])
        right_search2 = np.array([np.flipud((np.vstack([self.right_polyfit_x + margin, self.plot_y])).T)])
        right_pts = np.hstack((right_search1, right_search2))

        # Draw Left and Right Lane Lines
        cv2.fillPoly(self.img_search_window, np.int_([left_pts]), self.colour_red)
        cv2.fillPoly(self.img_search_window, np.int_([right_pts]), self.colour_green)

        # Draw Lane surface area (Between Left and Right Lanes)
        img_lane_area = np.zeros_like(img)
        left_line = np.array([(np.vstack([self.left_polyfit_x[::-1], self.plot_y[::-1]])).T])
        right_line = np.array([(np.vstack([self.right_polyfit_x, self.plot_y])).T])
        line_pts = np.hstack((left_line, right_line))
        cv2.fillPoly(img_lane_area, np.int_([line_pts]), self.colour_light_blue)

        # Combination 1: Left and Right fit lane lines + Search Window
        img_binary_warped_rgb = cv2.cvtColor(binary_masking.cv2_uint8(self.img_binary_warped), cv2.COLOR_GRAY2BGR)
        result_img = cv2.addWeighted(img_binary_warped_rgb, 0.8, self.img_search_window, 1.0, 0)

        # Combination 2: Lane Area + Binary Mask
        img_binary_warped2 = cv2.cvtColor(binary_masking.cv2_uint8(img_binary_warped2), cv2.COLOR_GRAY2BGR)
        result_img = cv2.addWeighted(img_lane_area, 0.7, result_img, 1.0, 0)

        # Final combination: Combination 1 + Combination 2
        self.result_img = cv2.addWeighted(img_binary_warped2, 0.8, result_img, 1.0, 0)

    # Initialise lane lines base position using histogramming and windowing from
    def init(self, silent=True):

        # Take a histogram of the image
        histogram = np.sum(self.img_binary_warped[:,:], axis=0)

        # Find the peak of the left and right of the histogram as the initial x for the two lanes
        centre = np.int(histogram.shape[0] / 2)
        left_x_init = np.argmax(histogram[:centre])
        right_x_init = np.argmax(histogram[centre:]) + centre

        # Choose the number of vertically stacked windows to divide the frame into
        num_windows = 8

        # Set height of windows
        window_height = np.int(self.img_binary_warped.shape[0] / num_windows)

        # Identify the x and y positions of all nonzero pixels in the image
        valid_xy = self.img_binary_warped.nonzero()
        valid_y = np.array(valid_xy[0])
        valid_x = np.array(valid_xy[1])

        # Current positions to be updated for each window
        left_x_current = left_x_init
        right_x_current = right_x_init

        # Set the width of the windows +/- margin
        margin = 100

        # Set minimum number of pixels found to recenter window
        minpix = 30

        # Store left and right lane pixel indices
        left_lane_idx = []
        right_lane_idx = []

        # Iterate through the windows one by one
        for window in range(num_windows):
            # Find window boundaries in x and y covering both lane lines
            win_y_low = self.img_binary_warped.shape[0] - (window + 1) * window_height
            win_y_high = self.img_binary_warped.shape[0] - window * window_height

            win_x_left_low = left_x_current - margin
            win_x_left_high = left_x_current + margin
            win_x_right_low = right_x_current - margin
            win_x_right_high = right_x_current + margin

            if not silent:

                # Draw windows and fit lane lines for visualisation
                left_rect_pts = [[win_x_left_low, win_y_low],
                                 [win_x_left_low, win_y_high],
                                 [win_x_left_high, win_y_high],
                                 [win_x_left_high, win_y_low]]

                right_rect_pts = [[win_x_right_low, win_y_low],
                                 [win_x_right_low, win_y_high],
                                 [win_x_right_high, win_y_high],
                                 [win_x_right_high, win_y_low]]

                cv2.fillPoly(self.img_binary_warped, np.int_([left_rect_pts]), self.colour_light_blue[::-1])
                cv2.fillPoly(self.img_binary_warped, np.int_([right_rect_pts]), self.colour_light_blue[::-1])

                cv2.rectangle(self.img_binary_warped,
                              (win_x_left_low, win_y_low), (win_x_left_high, win_y_high),
                              thickness=3, color=self.colour_light_blue)
                cv2.rectangle(self.img_binary_warped,
                              (win_x_right_low, win_y_low), (win_x_right_high, win_y_high),
                              thickness=3, color=self.colour_light_blue)

            good_left_idx_tmp = ((valid_y >= win_y_low) &
                                 (valid_y < win_y_high) &
                                 (valid_x >= win_x_left_low) &
                                 (valid_x < win_x_left_high)).nonzero()

            # Get the last nonzero index of left lane
            good_left_idx = good_left_idx_tmp[len(good_left_idx_tmp) - 1]

            good_right_idx_tmp = ((valid_y >= win_y_low) &
                                  (valid_y < win_y_high) &
                                  (valid_x >= win_x_right_low) &
                                  (valid_x < win_x_right_high)).nonzero()
            # Get the first nonzero index of right lane
            good_right_idx = good_right_idx_tmp[0]

            # Append these indices to the lists
            left_lane_idx.append(good_left_idx)
            right_lane_idx.append(good_right_idx)

            # If you found > minpix pixels, recenter next window on their mean position
            if len(good_left_idx) > minpix:
                left_x_current = np.int(np.mean(valid_x[good_left_idx]))

            if len(good_right_idx) > minpix:
                right_x_current = np.int(np.mean(valid_x[good_right_idx]))

        # Concatenate the arrays of indices
        left_lane_idx = np.concatenate(left_lane_idx)
        right_lane_idx = np.concatenate(right_lane_idx)

        # Extract left and right line pixel positions
        left_x = valid_x[left_lane_idx]
        left_y = valid_y[left_lane_idx]
        right_x = valid_x[right_lane_idx]
        right_y = valid_y[right_lane_idx]

        # If empty pixels in any side, reject this frame
        if not (len(left_x) and len(left_y) and len(right_x) and len(right_y)):
            # import pdb;pdb.set_trace()
            self.initialised = False
            return False

        # Fit a 2nd order polynomial for left and right lane lines
        left_polyfit = np.polyfit(left_y, left_x, 2)
        right_polyfit = np.polyfit(right_y, right_x, 2)

        # Prepare x, y values for plotting
        plot_y = np.linspace(0, self.img_binary_warped.shape[0]-1, self.img_binary_warped.shape[0])
        left_polyfit_x = left_polyfit[0]*plot_y**2 + left_polyfit[1]*plot_y + left_polyfit[2]
        right_polyfit_x = right_polyfit[0]*plot_y**2 + right_polyfit[1]*plot_y + right_polyfit[2]

        self.left_lane_idx = left_lane_idx
        self.right_lane_idx = right_lane_idx
        self.plot_y = plot_y
        self.left_polyfit = left_polyfit
        self.right_polyfit = right_polyfit
        self.left_polyfit_x = left_polyfit_x
        self.right_polyfit_x = right_polyfit_x

        self.initialised = True

        return True

    # Update search around margin from previous position
    def update(self):

        img_binary_warped = self.img_binary_warped
        valid_xy = img_binary_warped.nonzero()
        valid_y = np.array(valid_xy[0])
        valid_x = np.array(valid_xy[1])
        margin = 30

        self.left_lane_idx = ((valid_x > (self.left_polyfit[0] * (valid_y**2) + self.left_polyfit[1] * valid_y + self.left_polyfit[2] - margin)) &
                              (valid_x < (self.left_polyfit[0] * (valid_y**2) + self.left_polyfit[1] * valid_y + self.left_polyfit[2] + margin)))
        self.right_lane_idx = ((valid_x > (self.right_polyfit[0] * (valid_y**2) + self.right_polyfit[1] * valid_y + self.right_polyfit[2] - margin)) &
                               (valid_x < (self.right_polyfit[0] * (valid_y**2) + self.right_polyfit[1] * valid_y + self.right_polyfit[2] + margin)))

        # Get pixel positions of both lane sides
        left_x = valid_x[self.left_lane_idx]
        left_y = valid_y[self.left_lane_idx]
        right_x = valid_x[self.right_lane_idx]
        right_y = valid_y[self.right_lane_idx]

        # import pdb;pdb.set_trace()
        if not (len(left_x) and len(left_y) and len(right_x) and len(right_y)):
            self.initialised = False
            return False

        # Fit 2nd order polynomial to left and right lines
        self.left_polyfit = np.polyfit(left_y, left_x, 2)
        self.right_polyfit = np.polyfit(right_y, right_x, 2)

        # Prepare x, y values for plotting
        self.plot_y = np.linspace(0, img_binary_warped.shape[0]-1, img_binary_warped.shape[0])
        self.left_polyfit_x = self.left_polyfit[0]*self.plot_y**2 + self.left_polyfit[1]*self.plot_y + self.left_polyfit[2]
        self.right_polyfit_x = self.right_polyfit[0]*self.plot_y**2 + self.right_polyfit[1]*self.plot_y + self.right_polyfit[2]

        return True


import pytest

from inventory_allocator import InventoryAllocator

ia = InventoryAllocator()

def test_1():
    print("\n\nRunning tests...\n--------------------------------")
    print("Test 1 ...")
    assert [
        {'w1': {'a': 2}}
    ] == ia.process_order({'a':2}, [
        {'name':'w1','inventory':{'a':3, 'aa':3, 'aaa': 3}}
    ])

def test_2():
    print("\nTest 2 ...")
    assert [
        {'w1': {'apple': 6, 'orange': 6}},
        {'w3': {'apple': 4}},
        {'w2': {'orange': 1, 'banana': 4}}
    ] == ia.process_order({'apple': 10, 'orange': 7, 'banana': 4}, [
        {'name': 'w1', 'inventory': {'apple': 6, 'orange': 6}},
        {'name': 'w2', 'inventory': {'banana': 4, 'orange': 1}},
        {'name': 'w3', 'inventory': {'banana': 3, 'orange': 3, 'apple': 5}}
    ])

# Test invalid order
def test_3():
    print("\nTest 3 ... Order cannot be filled")
    assert [] == ia.process_order({'apple':5}, [
        {'name':'w1', 'inventory':{'apple':2}},
        {'name':'w2', 'inventory':{'apple':2}}
    ])

# Test remove empty-items
def test_4():
    print("\nTest 4 ... Test removing empty items")
    co, cv = ia.remove_empty_items({'apple':-1}, [{'name':'a', 'inventory':{'apple':-10, 'banana':-15, 'choco':10}}, {'name':'b', 'inventory':{'b_apple':-10, 'b_banana':-15, 'b_choco':10}}])
    assert co == {} and cv == [{'name': 'a', 'inventory': {'choco': 10}}, {'name': 'b', 'inventory': {'b_choco': 10}}]

# Example 1 from github
def test_5():
    print("\nTest 5 ... Example 1 from problem statement")
    assert [{'owd': {'apple':1}}] == ia.process_order({'apple':1}, [
        {'name': 'owd', 'inventory' : {'apple':1}}
    ]
    )

# Example 2 from github
def test_6():
    print("\nTest 6 ... Example 2 from problem statement")
    assert [{'owd': {'apple':5}}, {'dm': {'apple':5}}] == ia.process_order({'apple':10}, [
        {'name': 'owd', 'inventory' : {'apple':5}},
        {'name': 'dm', 'inventory' : {'apple':5}}
    ]
    )

# Example 3 from github
def test_7():
    print("\nTest 7 ... Example 3 from problem statement - Order cannot be shipped because there is not enough inventory")
    assert [] == ia.process_order({'apple':1}, [
        {'name':'owd', 'inventory':{'apple':0}},
    ])

def test_8():
    print("\nTest 8 ... Example 4 from problem statement - Order cannot be shipped because there is not enough inventory")
    assert [] == ia.process_order({'apple':2}, [
        {'name':'owd', 'inventory':{'apple':1}},
    ])

# Empty order
def test_9():
    print("\nTest 9 ... Empty order")
    assert [] == ia.process_order({}, [
        {'name':'owd', 'inventory':{'apple':1}},
    ])

def test_10():
    print("\nTest 10 ... Empty warehouses")
    assert [] == ia.process_order({'apple':1}, [])

def test_11():
    print("\nTest 11 ... Empty warehouses")
    assert [{'w1': {'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1, 'f': 1, 'g': 1, 'h': 1, 'i': 1, 'j': 1, 'k': 1, 'l': 1, 'm': 1, 'n': 1, 'o': 1, 'p': 1, 'q': 1, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 1, 'w': 1, 'x': 1, 'y': 1, 'z': 1}}] == ia.process_order(
        {'a':1,'b':1,'c':1,'d':1,'e':1,'f':1,'g':1,'h':1,'i':1,'j':1,'k':1,'l':1,'m':1,'n':1,'o':1,'p':1,'q':1,'r':1,'s':1,'t':1,'u':1,'v':1,'w':1,'x':1,'y':1,'z':1},
        [{'name':'w1','inventory':{'a':1,'b':1,'c':1,'d':1,'e':1,'f':1,'g':1,'h':1,'i':1,'j':1,'k':1,'l':1,'m':1,'n':1,'o':1,'p':1,'q':1,'r':1,'s':1,'t':1,'u':1,'v':1,'w':1,'x':1,'y':1,'z':1}}]
    )