from logging import getLogger

from yadacoin.core.chain import CHAIN
from yadacoin.core.config import get_config
from yadacoin.core.block import Block
from yadacoin.core.transaction import (
    Transaction,
    Input,
    Output,
    NotEnoughMoneyException,
)
from yadacoin.core.transactionutils import TU

class NonMatchingDifficultyException(Exception):
    pass

class PartialPayoutException(Exception):
    pass

class PoolPayer(object):
    def __init__(self):
        self.config = get_config()
        self.app_log = getLogger("tornado.application")

    async def do_payout(self, already_paid_height=None):
        # first check which blocks we won.
        # then determine if we have already paid out
        # they must be 6 blocks deep
        if not already_paid_height:
            already_paid_height = (
                await self.config.mongo.async_db.share_payout.find_one(
                    {}, sort=[("index", -1)]
                )
            )
            if not already_paid_height:
                already_paid_height = {}

        won_blocks = self.config.mongo.async_db.blocks.aggregate(
            [
                {
                    "$match": {
                        "transactions": {
                            "$elemMatch": {
                                "inputs.0": {"$exists": False},
                            }
                        },
                        "transactions.outputs.to": self.config.address,
                        "index": {"$gt": already_paid_height.get("index", 0)},
                    }
                },
                {"$unwind": "$transactions"},
                {
                    "$match": {
                        "transactions.inputs.0": {"$exists": False},
                        "transactions.outputs.to": self.config.address,
                    }
                },
                {"$sort": {"index": 1}},
            ]
        )

        ready_blocks = []
        do_payout = False
        async for won_block in won_blocks:
            won_block = await self.config.mongo.async_db.blocks.find_one(
                {
                    "index": won_block["index"],
                    "id": won_block["id"],
                    "hash": won_block["hash"],
                }
            )
            won_block = await Block.from_dict(won_block)
            coinbase = won_block.get_coinbase()
            if coinbase.outputs[0].to != self.config.address:
                continue
            if self.config.debug:
                self.app_log.debug(won_block.index)
            if (
                won_block.index + self.config.payout_frequency
            ) <= self.config.LatestBlock.block.index:
                if len(ready_blocks) >= self.config.payout_frequency:
                    if self.config.debug:
                        self.app_log.debug(
                            "entering payout at block: {}".format(won_block.index)
                        )
                    do_payout = True
                    break
                else:
                    if self.config.debug:
                        self.app_log.debug(
                            "block added for payout {}".format(won_block.index)
                        )
                    ready_blocks.append(won_block)

        if not do_payout:
            return

        # check if we already paid out
        outputs = {}
        coinbases = []
        for block in ready_blocks:
            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks begin loop {}".format(block.index)
                )
            already_used = await self.already_used(block.get_coinbase())
            if already_used:
                await self.config.mongo.async_db.shares.delete_many(
                    {"index": block.index}
                )
                continue

            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks passed already_used {}".format(block.index)
                )
            existing = await self.config.mongo.async_db.share_payout.find_one(
                {"index": block.index}
            )
            if existing:
                pending = await self.config.mongo.async_db.miner_transactions.find_one(
                    {"inputs.id": block.get_coinbase().transaction_signature}
                )
                if pending:
                    return
                else:
                    # rebroadcast
                    transaction = Transaction.from_dict(existing["txn"])
                    await self.config.mongo.async_db.miner_transactions.insert_one(
                        transaction.to_dict()
                    )
                    await self.broadcast_transaction(transaction)
                    return
            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks passed existing {}".format(block.index)
                )
            try:
                shares = await self.get_share_list_for_height(block.index)
                if not shares:
                    continue
            except KeyError as e:
                self.app_log.warning(e)
                return
            except Exception as e:
                self.app_log.warning(e)
                return
            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks passed get_share_list_for_height {}".format(
                        block.index
                    )
                )
            coinbase = block.get_coinbase()
            if coinbase.outputs[0].to != self.config.address:
                return
            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks passed address compare {}".format(block.index)
                )
            pool_take = self.config.pool_take
            total_pool_take = coinbase.outputs[0].value * pool_take
            total_payout = coinbase.outputs[0].value - total_pool_take
            coinbases.append(coinbase)
            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks coinbases so far {}".format(coinbases)
                )

            if self.config.debug:
                self.app_log.debug(
                    "do_payout_for_blocks passed coinbase calcs {}".format(block.index)
                )
            for address, x in shares.items():
                if self.config.debug:
                    self.app_log.debug(
                        "do_payout_for_blocks shares loop {}".format(block.index)
                    )
                exists = await self.config.mongo.async_db.share_payout.find_one(
                    {"index": block.index, "txn.outputs.to": address}
                )
                if exists:
                    raise PartialPayoutException(
                        "this index has been partially paid out."
                    )

                if self.config.debug:
                    self.app_log.debug(
                        "do_payout_for_blocks passed shares exists {}".format(
                            block.index
                        )
                    )
                if address not in outputs:
                    outputs[address] = 0.0
                payout = total_payout * x["payout_share"]
                outputs[address] += payout
                if self.config.debug:
                    self.app_log.debug(
                        "do_payout_for_blocks passed adding payout to outputs {}".format(
                            block.index
                        )
                    )

        if not outputs and ready_blocks:
            await self.config.mongo.async_db.share_payout.insert_one(
                {"index": ready_blocks[-1].index}
            )

        if not coinbases:
            return

        outputs_formatted = []
        for address, output in outputs.items():
            outputs_formatted.append({"to": address, "value": output})

        if self.config.debug:
            self.app_log.debug(
                "do_payout_for_blocks done formatting outputs {}".format(
                    [{"id": coinbase.transaction_signature} for coinbase in coinbases]
                )
            )
        try:
            transaction = await Transaction.generate(
                fee=0.0001,
                public_key=self.config.public_key,
                private_key=self.config.private_key,
                inputs=[
                    {"id": coinbase.transaction_signature} for coinbase in coinbases
                ],
                outputs=outputs_formatted,
            )
            self.app_log.debug(
                "transaction generated: {}".format(transaction.transaction_signature)
            )
        except NotEnoughMoneyException as e:
            if self.config.debug:
                self.app_log.debug("not enough money yet")
                self.app_log.debug(e)
            return
        except Exception as e:
            if self.config.debug:
                self.app_log.debug(e)

        try:
            await transaction.verify()
        except Exception as e:
            if self.config.debug:
                self.app_log.debug(e)
            raise
        self.app_log.debug("transaction verified")
        await self.config.mongo.async_db.miner_transactions.insert_one(
            transaction.to_dict()
        )
        await self.config.mongo.async_db.share_payout.insert_one(
            {"index": block.index, "txn": transaction.to_dict()}
        )
        await self.broadcast_transaction(transaction)

    async def get_share_list_for_height(self, index):
        raw_shares = []
        async for x in self.config.mongo.async_db.shares.find(
            {"index": index, "address": {"$ne": None}}
        ).sort([("index", 1)]):
            raw_shares.append(x)
        if not raw_shares:
            return False
        total_difficulty = self.get_difficulty([x for x in raw_shares])
        shares = {}
        for share in raw_shares:
            address = share["address"].split(".")[0]
            if not self.config.address_is_valid(address):
                await self.config.mongo.async_db.shares.delete_many(
                    {"address": address}
                )
                raise Exception(
                    "get_share_list_for_height invalid address: {}, removing related shares".format(
                        address
                    )
                )

            if address not in shares:
                shares[address] = {
                    "blocks": [],
                }
            shares[address]["blocks"].append(share)

        add_up = 0
        for address, item in shares.items():
            test_difficulty = self.get_difficulty(item["blocks"])
            shares[address]["payout_share"] = float(test_difficulty) / float(
                total_difficulty
            )
            add_up += test_difficulty

        if add_up == total_difficulty:
            return shares
        else:
            raise NonMatchingDifficultyException()

    def get_difficulty(self, blocks):
        difficulty = 0
        for block in blocks:
            target = int(block["hash"], 16)
            difficulty += CHAIN.MAX_TARGET - target
        return difficulty

    async def already_used(self, txn):
        return await self.config.mongo.async_db.blocks.find_one(
            {"transactions.inputs.id": txn.transaction_signature}
        )

    async def broadcast_transaction(self, transaction):
        self.app_log.debug(f"broadcast_transaction {transaction.transaction_signature}")
        async for peer_stream in self.config.peer.get_sync_peers():
            await self.config.nodeShared.write_params(
                peer_stream, "newtxn", {"transaction": transaction.to_dict()}
            )
            if peer_stream.peer.protocol_version > 1:
                self.config.nodeClient.retry_messages[
                    (peer_stream.peer.rid, "newtxn", transaction.transaction_signature)
                ] = {"transaction": transaction.to_dict()}


"""v3.0.0-beta

This adds the needed schema and data updates for issue #75: Reordering of survey items.

Revision ID: 8d32f2e9269b
Revises:
Create Date: 2018-10-06 12:07:07.893786

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '8d32f2e9269b'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    op.add_column('dimension', sa.Column('position', sa.Integer()))
    op.add_column('question', sa.Column('position', sa.Integer()))
    upgrade_data()

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('question', 'position')
    op.drop_column('dimension', 'position')
    # ### end Alembic commands ###

def upgrade_data():
    from model import db
    t_question = db.metadata.tables['question']
    t_dimension = db.metadata.tables['dimension']
    t_questionnaire = db.metadata.tables['questionnaire']

    connection = op.get_bind()

    # fetch all dimensions
    join = sa.join(t_questionnaire, t_dimension,
                   t_questionnaire.c.id == t_dimension.c.questionnaire_id)
    results = connection.execute(
        sa.select([
            t_questionnaire.c.id,
            t_dimension.c.id
        ]).select_from(join)
    )

    # set positions starting from 0 for every unique questionnaire
    dimension_position_counters = dict()
    for row in sorted(results, key=lambda r: r[1]):
        questionnaire_id = row[0]
        dimension_id = row[1]

        if questionnaire_id not in dimension_position_counters:
            dimension_position_counters[questionnaire_id] = 0
        dimension_position = dimension_position_counters[questionnaire_id]

        connection.execute(
            t_dimension.update().where(
                t_dimension.c.id == dimension_id
            ).values(
                position=dimension_position
            )
        )
        dimension_position_counters[questionnaire_id] = dimension_position + 1

    # fetch all questions
    join = sa.join(t_dimension, t_question,
                   t_dimension.c.id == t_question.c.dimension_id)
    results = connection.execute(
        sa.select([
            t_dimension.c.id,
            t_question.c.id
        ]).select_from(join)
    )

    # set positions starting from 0 for every unique dimension
    question_position_counters = dict()
    for row in sorted(results, key=lambda r: r[1]):
        dimension_id = row[0]
        question_id = row[1]

        if dimension_id not in question_position_counters:
            question_position_counters[dimension_id] = 0
        question_position = question_position_counters[dimension_id]

        connection.execute(
            t_question.update().where(
                t_question.c.id == question_id
            ).values(
                position=question_position
            )
        )
        question_position_counters[dimension_id] = question_position + 1


from flask import Flask, request
import requests as req
import json
from json import dumps

app = Flask(__name__)

@app.route('/proxy/getbikes')
def get_bikes():
    res = req.get('http://api.citybik.es/v2/networks')
    return res.text

@app.route('/proxy/getnetwork')
def get_network():
    args = request.url.split('?')[1]
    res = req.get('http://api.citybik.es/v2/networks/{}'.format(args))

    return res.text

@app.route('/proxy/getlatlong')
def get_lat_long():
    args = request.url.split('?')[1]
    res = req.get('https://maps.googleapis.com/maps/api/geocode/json?{}'.format(args))

    return res.text

app.run(debug=True)


from flask import Flask, request
app = Flask(__name__)

import os
import json
import configparser
config = configparser.ConfigParser()
config.read('.config')
env = os.environ.get('ENV', 'dev')

from db_connector import DBConnector
db_connector = DBConnector(
    config[env]['url'],
    int(config[env]['port']),
    config[env]['database'],
    config[env]['collection']
)

from orm import ORM

from accounting import Accounting
from convertor import convert_for_accounting, from_accounting

def get_orm(func):
    def wrap_get_orm(*args, **kwargs):
        with db_connector as connector:
            orm = ORM(Accounting, connector)
            return func(orm, *args, **kwargs)
    return wrap_get_orm

def to_json(func):
    def wrap_to_json(*args, **kwargs):
        r = func(*args, **kwargs)
        if isinstance(r, list):
            r = [from_accounting(i) for i in r]
        else:
            r = from_accounting(r)
        return json.dumps(r)
    return wrap_to_json

@app.route('/')
def hello():
    return 'Hello World!'

@app.route('/accountings')
@get_orm
@to_json
def accountings(orm):
    return list(map(lambda cs: cs.to_dict(), orm.all()))

@app.route('/accounting', methods=['POST'])
@app.route('/accounting/<id>', methods=['GET', 'PUT'])
@to_json
@get_orm
def accounting(orm, id: str=None):
    if request.method == 'POST':
        new_cs = _get_accounting_from_request()
        return orm.create(new_cs.to_dict()).to_dict()
    if not id.isdigit():
        return {}
    _id = int(id)
    if request.method == 'GET':
        return orm.get(_id).to_dict()
    update_cs = _get_accounting_from_request()
    return orm.update(_id, update_cs.to_dict()).to_dict()

@app.route('/accountings/<year>/<month>', methods=['GET'], endpoint='get_accounting')
@get_orm
@to_json
def get_accounting(orm, year: str, month: str):
    from datetime import datetime
    from calendar import monthrange
    _year, _month = int(year), int(month)
    query = {'year': _year, 'month': _month}
    return list(map(lambda cs: cs.to_dict(), orm.all(query)))

def _get_accounting_from_request():
    data = convert_for_accounting(request.get_json())
    return Accounting(**data)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')


import asyncio
import os
from gear import Database
from gear.database import get_sql_config

MYSQL_CONFIG_FILE = os.environ.get('MYSQL_CONFIG_FILE')

async def delete_foreign_key_constraint(db, db_name, table_name, referenced_table_name, referenced_column_names):
    # https://dev.mysql.com/doc/refman/8.0/en/information-schema-key-column-usage-table.html

    assert referenced_column_names
    referenced_column_str = '(' + " OR ".join(['REFERENCED_COLUMN_NAME = %s' for _ in referenced_column_names]) + ')'

    query = f'''
SELECT CONSTRAINT_NAME as constraint_name
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = %s AND
  TABLE_NAME = %s AND
  REFERENCED_TABLE_NAME = %s AND
  {referenced_column_str};
'''

    query_args = [db_name, table_name, referenced_table_name] + referenced_column_names

    records = [record async for record in db.select_and_fetchall(query, query_args)]
    assert len(records) == len(referenced_column_names)

    constraint_names = {record['constraint_name'] for record in records}
    assert len(constraint_names) == 1
    constraint_name = list(constraint_names)[0]

    await db.just_execute(f'ALTER TABLE {table_name} DROP FOREIGN KEY `{constraint_name}`;')

async def main():
    db = Database()
    await db.async_init(config_file=MYSQL_CONFIG_FILE)

    try:
        sql_config = get_sql_config(maybe_config_file=MYSQL_CONFIG_FILE)
        db_name = sql_config.db
        assert db_name is not None

        await delete_foreign_key_constraint(db, db_name, 'attempt_resources', 'resources', ['resource'])
    finally:
        await db.async_close()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


import cv2
import numpy as np
import configparser
import ast
config = configparser.ConfigParser()
config.read('config.ini')
color = ast.literal_eval(config.get('style' , 'color'))
font = getattr(cv2, config.get('style' , 'font'))
def generateChArUcoBoard(squaresX, squaresY, filename=None):
    #definuje velikost A4 pri 300 dpi
    paperWidth, paperHeight = int(8.27 * 300), int(11.69 * 300)
    #velikost ctvercu a markeru
    squareLength = int((paperWidth-100) / squaresX)
    markerLength = int(squareLength * 0.7)
    #Vyber slovniku
    dict = cv2.aruco.DICT_6X6_250
    dictionary = cv2.aruco.getPredefinedDictionary(dict)
    #Vytvori desku
    board =cv2.aruco.CharucoBoard((squaresX, squaresY), squareLength, markerLength, dictionary)
    if filename is not None:
        #Vykresli desku
        img = board.generateImage((paperWidth, paperHeight))
        #Ulozi desku
        cv2.imwrite(filename, img)
        print("Board generated")

    return board
def charlibration(board,cap):
    #Vyber slovniku
    dict = cv2.aruco.DICT_6X6_250
    dictionary = cv2.aruco.getPredefinedDictionary(dict)
    charucoCorners = []
    charucoIds = []
    #Pokud je video otevreno
    while cap.isOpened():
        #Cte zaznam
        ret, frame = cap.read()
        # Detekce markeru
        corners, ids, _ = cv2.aruco.detectMarkers(frame, dictionary)
        # Pokud je nalezen aspon jeden marker --> len(corners) > 0 --> True
        if len(corners) > 0:
            ret, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(corners, ids, frame, board)
            # Pokud je deska nalezena(vic jak 15 rohů)
            if ret > 15:
                cv2.aruco.drawDetectedCornersCharuco(frame, charuco_corners,charuco_ids)
                #Vypise text ze deska byla nalezena
                cv2.putText(frame, 'Kalibracni vzor detekovan', (10, 50),font, 1, color, 2)
                #Pokud je stisknuta klavesa 0
                if cv2.waitKey(1) == ord('+'):

                    charucoCorners.append(charuco_corners)
                    charucoIds.append(charuco_ids)
                    #cv2.imwrite(f"frame{len(charucoCorners)}.jpg", frame)
                #Vykreslii detekovane rohy desky

            else:
                #Vypise text ze deska nebyla nalezena
                cv2.putText(frame, 'No charuco board detected', (10, 50),font, 1, color, 2)

        # Pokud neni nalezen zadny marker vypise text
        else:
            print("No obrazky detected")
            cv2.putText(frame, 'No obrazky detected', (10, 50),font, 1, color, 2)

        cv2.putText(frame, f'Pocet snimku{len(charucoCorners)}', (10, 100), font, 1, color, 2)
        #Zobrazeni vysledneho obrazku
        cv2.imshow('Calibration', frame)
        #Pokud je stisknuta klavesa + ukonci se program
        if cv2.waitKey(1) == ord('q'):
            print('pressed')
            break
    cap.release()
    cv2.destroyAllWindows()

    if len(charucoCorners) >2:
        print("Calibrating camera...")
        #Ziskani matice kamery
        h, w = frame.shape[:2]
        ret, mtx, dist,R,T = cv2.aruco.calibrateCameraCharuco(charucoCorners, charucoIds, board, (w,h),None,None)
        newmtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
        # Ulozeni matice kamery, distorze a novy matice kamery
        np.savez('calibration.npz', mtx=mtx, dist=dist, newmtx=newmtx)
        print("Calibration computation complete!")
    else:
        print("Not enough calibration data")
    return

squaresX = ast.literal_eval(config.get('calibration' , 'squaresX'))
squaresY = ast.literal_eval(config.get('calibration' , 'squaresY'))
filename = config.get('calibration' , 'filename')
if filename == 'None':
    filename = None
else:
    filename = filename
board = generateChArUcoBoard(squaresX,squaresY, filename)
cap = cv2.VideoCapture(0)
charlibration(board,cap)


from photo_searcher import app
#File_helperをfileとしてimport
from photo_searcher.helpers.file_helper import file_get_contents

import random  # デバッグ用
import os
import re
import glob
import execjs

#views.search()で必要なデータを返す
def set_show_data(keyword):
    # rows = file_get_contents('photo_searcher/static/img_list.txt')[:100]
    if len(keyword) > 0:
        rows = search_img_data(keyword)
    else:
        rows = []

    row_cnt = len(rows)

    return rows, row_cnt

#キーワードに見合う画像の検索
def search_img_data(keyword):
    #先頭または末尾のの不要なスペースを削除
    keyword = keyword.replace('\u3000', ' ')
    keyword = keyword.replace('  ', ' ')
    while True:
        if keyword[:1] == ' ':
            keyword = keyword[1:]
        elif keyword[-1:] == ' ':
            keyword = keyword[:-1]
        else:
            break
    sp_or = keyword.split(' OR ') #ORで区切る
    res_use = []
    for el in sp_or:
        #AND検索
        sp_and = el.split(' ')
        tmp_and_use = []
        tmp_and_unuse = []
        for el2 in sp_and:
            pathes = []
            if(re.sub("\\D", "", el2)):
                num = re.sub("\\D", "", el2)
                    #数字のみ後方一致
                pathes = glob.glob('photo_searcher/static/data_store/fc/' + num + '.keyword')
                tmp_array = [add_key_num(path) for path in pathes]
                if tmp_array:
                    s = set(tmp_array[0])
                    for t in tmp_array:
                        s |= set(t)
                    tmp_and_use.append(list(s))
            elif el2[0] == '-':
                pathes = glob.glob('photo_searcher/static/data_store/tf/' + el2[1:] + '.keyword')
                tmp_array = [add_key_words(path) for path in pathes]
                if tmp_array:
                    s = set(tmp_array[0])
                    for t in tmp_array:
                        s |= set(t)
                    tmp_and_unuse.extend(list(s))
            else:
                pathes = glob.glob('photo_searcher/static/data_store/tf/*' + el2 + '*.keyword')
                tmp_array = [add_key_words(path) for path in pathes]
                if tmp_array:
                    s = set(tmp_array[0])
                    for t in tmp_array:
                        s |= set(t)
                    tmp_and_use.append(list(s))
        #キーワードに関する配列毎に共通項を抽出
        if len(tmp_and_use) > 0:
            tmp = set(tmp_and_use[0])
            for el3 in tmp_and_use:
                tmp &= set(el3)
            # tmp = list(tmp)
            res_use.extend(list(tmp))
        if len(tmp_and_unuse) > 0:
            for el in tmp_and_unuse:
                if el in res_use:
                    res_use.remove(el)
    return list(set(res_use))

#使用するワードをリストに追加
#キーワードに関する画像データを返す
def add_key_words(path):
    response = []
    if len(response) > 0:
        response.clear()
    if os.path.exists(path) and os.path.isfile(path):
        with open(path, 'r') as r:
            for line in r:
                img_path = line.split('\t')[2].replace('\n','')
                response.append(img_path[2:])  #「..」を削除する
    return response

def add_key_num(path):
    response = []
    if len(response) > 0:
        response.clear()
    if os.path.exists(path) and os.path.isfile(path):
        with open(path, 'r') as r:
            for line in r:
                img_path = line.split('\t')[1].replace('\n','')
                response.append(img_path[2:])  #「..」を削除する
    return response

#jsのlocalStorageを参照して画面テーマを取得
def get_theme():
    ctx = execjs.compile("""
        function getTheme() {
            if(localStorage.getItem('theme')) {
                return localStorage.getItem('theme');
                // if(localStorage.getItem('theme') == 'dark') {
                //     return 'rgb(25, 25, 25)';
                // }else{
                //     return 'rgb(250, 250, 250)';
                // }
            }else{
                // return 'rgb(250, 250, 250)';
                return 'light';
            }
        }
    """)
    return ctx.call('getTheme')


import re, urlparse, urllib
from mako.template import Template

PAGE_TEMPLATE = '''

  % if cur_page > 1:

  % else:

  % endif

  % for p in plist:
  % if p == cur_page:

${ p }

  % elif p == notexist_page:

...

  % else:

${ p }

  % endif
  % endfor

  % if cur_page < page_sum:

  % else:

  % endif

  % if sepa_range:

    %for s in sepa_range:
    %if sepa == s:

${ s }

    % else:

${ s }

    % endif
    %endfor

  % endif

'''

def pagination( url, total, sepa, cur, list_size=5,
                sepa_range=[] ):

    if total <= sepa:
        return ''

    sepa_range = [x for x in sepa_range if x < total]

    page_sum = total / sepa
    if ( total % sepa ): page_sum += 1

    notexist_p = page_sum + 1

    last_p = page_sum
    start = ( cur / (list_size + 1) ) * list_size + 1
    end = start + list_size
    if end > last_p: end = last_p

    plist = range(start, end + 1)

    if end < last_p:
        plist.extend( [notexist_p, last_p] )

    if cur > list_size:
        plist.insert(0, notexist_p)
        plist.insert(0, 1)

    def _page_url(cur):
        return page_url(url, cur)

    d = { 'total': total, 'plist': plist,  'sepa': sepa,
          'cur_page': cur, 'page_sum': page_sum,
          'notexist_page': notexist_p,
          'page_url': _page_url }

    if sepa_range:
        def _psize_url(cur):
            return psize_url(url, cur)
        d['psize_url'] = _psize_url
        d['sepa_range'] = sepa_range

    t = Template( PAGE_TEMPLATE )
    return t.render(**d)

def page_url(uri, cur):

    if '?' not in uri:
        return uri + '?p=%s' % cur

    path, params = uri.split('?')
    new = []
    find_p = False
    for k, v in urlparse.parse_qsl( params ):
        if k == 'p':
            v = cur
            find_p = True
        new.append( (k, v) )

    if not find_p:
        new.append( ('p', cur) )

    return '?'.join([path, urllib.urlencode(new)])

def psize_url(uri, cur):

    if '?' not in uri:
        return uri + '?sepa=%s' % cur

    path, params = uri.split('?')
    new = []
    find_sepa = False
    for k, v in urlparse.parse_qsl( params ):
        if k == 'sepa':
            v = cur
            find_sepa = True
        if k == 'p':
            v = 1
        new.append( (k, v) )

    if not find_sepa:
        new.append( ('sepa', cur) )

    return '?'.join([path, urllib.urlencode(new)])


from app import app, db
from .models import User, Company, ModelIdea, Entry
from flask import render_template, flash, redirect, url_for, request, jsonify
from app.forms import LoginForm, RegistrationForm, EditProfileForm, CompanyRegistrationForm, \
                      ModelIdeaForm, HairTransForm, WeightLossForm, MuscleGainForm, PasswordResetForm
from flask_login import current_user, login_user, logout_user, login_required
from werkzeug.urls import url_parse
from .service import AIService
import base64

@app.route('/')
@app.route('/index')
def index():
    context = {'service': 'Hair Transplant',
               'call': 'Check it on the bar above'}
    return render_template('index.html', title='Home', context=context)

@app.route('/login', methods=["POST", "GET"])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid username or password')
            return redirect(url_for('login'))
        login_user(user, remember=form.remember_me.data)
        next_page = request.args.get('next')
        if not next_page or url_parse(next_page).netloc != '':
            next_page = url_for('index')
        return redirect(next_page)
    return render_template('login.html', title='Sign In', form=form)

@app.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User()
        form.populate_obj(user)
        user.set_password(form.password.data)
        user.save()

        flash('Congrats, you are now a registered user')
        return redirect(url_for('login'))
    return render_template('register.html', title='Register', form=form)

@app.route('/user/password_reset', methods=['GET', 'POST'])
def password_reset():
    while current_user.is_anonymous:
        form = PasswordResetForm()

        if form.validate_on_submit():
            user = User.initialize_password_reset(request.form.get('email'))

            flash('An email has been sent to {}'.format(user.email))
            return redirect(url_for('login'))

        return render_template('pwd_reset/pwd_reset.html', form=form)

@app.route('/comp_register', methods=['GET', 'POST'])
def comp_register():
    if current_user.is_authenticated and current_user.company_id is not None:
        company = Company.query.filter_by(id=current_user.company_id).first()
        flash('You already belong to company {}'.format(company.name))
        return redirect(url_for('index'))
    form = CompanyRegistrationForm()
    if form.validate_on_submit():
        company = Company(name=form.name.data, contact=form.contact.data)
        db.session.add(company)
        db.session.flush()
        current_user.company_id = company.id
        db.session.commit()
        flash('Company saved')
        return redirect(url_for('index'))  # This should redirect to company page
    return render_template('company.html', title='Company', form=form)

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('index'))

@app.route('/users/', methods=['GET'])
def get_users():
    users = User.query.all()
    return users

@app.route('/user/<username>')
@login_required
def user_details(username):
    user = User.query.filter_by(username=username).first_or_404()
    entries = Entry.query.filter_by(user_id=user.id).order_by(Entry.created.desc()).limit(5).all()
    company = Company.query.filter_by(id=user.company_id)

    for entry in entries:
        entry.image = base64.b64encode(bytes(entry.image)).decode(('utf-8'))
        # entry.image = entry
        # base64_image_string = base64.b64encode(binary_image_string).decode('utf-8')
        # entry = base64_image_string

    context = {
            'user': user,
            'company': company,
            'entries': entries}

    return render_template('user.html', user=user, context=context)

@app.route('/edit_profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm(current_user.username)
    if form.validate_on_submit():
        current_user.username = form.username.data
        db.session.commit()
        flash('You changes have been saved.')
        return redirect(url_for('edit_profile'))
    elif request.method == 'GET':
        form.username.data = current_user.username
    return render_template('edit_profile.html', title='Edit Profile', form=form)

@app.route('/model_idea', methods=['GET', 'POST'])
def model_idea():
    if current_user.is_anonymous:
        flash('You need to login to leave a model suggestion.')
        return redirect(url_for('index'))
    form = ModelIdeaForm()
    if form.validate_on_submit():
        idea = ModelIdea(user_id=current_user.id,
                      name=form.name.data,
                      category=form.category.data,
                      description=form.description.data)
        db.session.add(idea)
        db.session.commit()
        flash('Your idea has been submitted we will contact you as soon as possible.')
        return redirect(url_for('index'))
    return render_template('model_idea.html', title='Model Idea', form=form)

@app.route('/api_docs', methods=['GET', 'POST'])
def api_docs():
    return render_template('api_docs', title='API documentation')

@app.route('/products', methods=["GET"])
def products():
    entry_hair_transplant = Entry.query.filter_by(service='hair_transplant').first_or_404()
    entry_muscle_gain = Entry.query.filter_by(service='muscle_gain').first_or_404()
    entry_weight_loss = Entry.query.filter_by(service='weight_loss').first_or_404()

    ht_binary_image_string = bytes(entry_hair_transplant.image)
    ht_base64_image_string = base64.b64encode(ht_binary_image_string).decode('utf-8')

    mg_binary_image_string = bytes(entry_muscle_gain.image)
    mg_base64_image_string = base64.b64encode(mg_binary_image_string).decode('utf-8')

    wl_binary_image_string = bytes(entry_weight_loss.image)
    wl_base64_image_string = base64.b64encode(wl_binary_image_string).decode('utf-8')

    context = {'ht_image': ht_base64_image_string,
               'wl_image': wl_base64_image_string,
               'mg_image': mg_base64_image_string,
               'user': 'Ira'}

    return render_template('products.html', context=context)

@app.route('/docs', methods=["GET"])
def docs():
    return render_template('docs.html')

@app.route('/pricing', methods=["GET"])
def pricing():
    return render_template('pricing.html')

@app.route('/product/hair_trans', methods=['GET', 'POST'])
def hair_trans():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))
    form = HairTransForm()
    if form.validate_on_submit():
        user = current_user.id
        image = request.files['image']
        data = image.read()

        work_dict = {'user': user,
                     'image': data}

        AIService.hair_transplant_service(work_dict)

        return redirect(url_for('hair_transplant_result'))
    return render_template('hair_transplant.html', title='Hair Transplant Model', form=form)

@app.route('/product/hair_transplant_results', methods=['GET'])
def hair_transplant_result():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))

    entry = Entry.query.filter_by(user_id=current_user.id).order_by(Entry.created.desc()).first()

    binary_image_string = bytes(entry.image)
    base64_image_string = base64.b64encode(binary_image_string).decode('utf-8')

    context = {'image': base64_image_string,
               'user': 'Ira'}

    return render_template('hair_transplant_result.html', context=context)

@app.route('/product/weight_loss', methods=['GET', 'POST'])
def weight_loss():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))
    form = WeightLossForm()
    if form.validate_on_submit():
        user = current_user.id
        image = request.files['image']
        data = image.read()

        work_dict = {'user': user,
                     'image': data}

        AIService.weight_loss_service(work_dict)

        return redirect(url_for('weight_loss_result'))
    return render_template('weight_loss.html', title='Weight Loss Model', form=form)

@app.route('/product/weight_loss_results', methods=['GET'])
def weight_loss_result():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))

    entry = Entry.query.filter_by(user_id=current_user.id).order_by(Entry.created.desc()).first()

    binary_image_string = bytes(entry.image)
    base64_image_string = base64.b64encode(binary_image_string).decode('utf-8')

    context = {'image': base64_image_string,
               'user': 'Ira'}

    return render_template('weight_loss_result.html', context=context)

@app.route('/product/muscle_gain', methods=['GET', 'POST'])
def muscle_gain():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))
    form = MuscleGainForm()
    if form.validate_on_submit():
        user = current_user.id
        image = request.files['image']
        data = image.read()

        work_dict = {'user': user,
                     'image': data}

        AIService.muscle_gain_service(work_dict)

        return redirect(url_for('muscle_gain_result'))
    return render_template('muscle_gain.html', title='Muscle Gain Model', form=form)

@app.route('/product/muscle_gain_results', methods=['GET'])
def muscle_gain_result():
    if current_user.is_anonymous:
        flash('Please sign in to try out services.')
        return redirect(url_for('index'))

    entry = Entry.query.filter_by(user_id=current_user.id).order_by(Entry.created.desc()).first()

    binary_image_string = bytes(entry.image)
    base64_image_string = base64.b64encode(binary_image_string).decode('utf-8')

    context = {'image': base64_image_string,
               'user': current_user.username}

    return render_template('muscle_gain_result.html', context=context)


import argparse
import unicodedata
from lxml import etree as ET

def converter(ipa_text,phone_map,sorted_ipa):
    original = ipa_text[:]
    pron_text = []
    next_stress = "0"
    num_nuclei = 0
    while len(ipa_text) > 0:
        if ipa_text[0] == " ":
            ipa_text = ipa_text[1:]
        elif ipa_text[0] == "ˈ":
            next_stress = "1"
            ipa_text = ipa_text[1:]
        elif ipa_text[0] == "ˌ":
            next_stress = "2"
            ipa_text = ipa_text[1:]
        else:
            match = False
            for ipa in sorted_ipa:
                if ipa_text.startswith(ipa):
                    pron_text.append(phone_map[ipa][0])
                    if phone_map[ipa][1] == "true":
                        pron_text[-1] += next_stress
                        num_nuclei += 1
                        next_stress = "0"
                    ipa_text = ipa_text[len(ipa):]
                    match = True
                    break
            if match == False:
                print("WARNING: Could not match symbol",ipa_text[:1])
                ipa_text = ipa_text[1:]

    output = ' '.join(pron_text)
    if num_nuclei == 1 and "0" in output:
        output = output.replace("0","1")
    elif "0" in output and "1" not in output and "2" not in output:
        output = output.replace("0","")
        print("WARNING: polysyllabic word with no stress markers found -", \
                original)

    return output

def convert_lexicon(lex_xml,phone_map,sorted_ipa):
    tree = ET.parse(lex_xml)
    root = tree.getroot()
    for entry in root:
        entry.attrib["ipa"] = unicodedata.normalize("NFC", entry.get("ipa"))
        entry.attrib["pron"] = converter(entry.get("ipa"),phone_map,sorted_ipa)
        entry.attrib["provenance"] = "IPA conversion"
    return tree

def import_phone_map(mapping_xml):
    tree = ET.parse(mapping_xml)
    root = tree.getroot()
    phone_map = {}
    for entry in root:
        phone_map[unicodedata.normalize("NFC",entry.get("ipa"))] = \
                [entry.get("pron"),entry.get("nucleus")]
    return phone_map

def ipa_by_length(phone_map):
    sorted_ipa = []
    for ipa in sorted(phone_map, key=len, reverse=True):
        sorted_ipa.append(ipa)
    return sorted_ipa

def output_to_file(xml_tree,output_file):
    lexicon_output = open(output_file,"wb")
    tree.write(
            lexicon_output,pretty_print=True,
            xml_declaration=True,encoding="utf-8")

def parse_arguments():
    arg_parser = argparse.ArgumentParser(
            description="Select phoneset, lexicon, and output file")
    arg_parser.add_argument(
            "mapping",
            type=str,
            help="xml file that contains the mapping from IPA -> phones")
    arg_parser.add_argument(
            "lexicon",
            type=str,
            help="xml file containing lexicon with IPA to convert")
    arg_parser.add_argument(
            "output",
            default="lex.xml",
            type=str,
            help="Output file for storing the final lexicon")
    args = vars(arg_parser.parse_args())
    return args

if __name__ == "__main__":
    args = parse_arguments()
    mapping_xml = args["mapping"]
    lex_xml = args["lexicon"]
    output_file = args["output"]

    phone_map = import_phone_map(mapping_xml)
    sorted_ipa = ipa_by_length(phone_map)
    tree = convert_lexicon(lex_xml,phone_map,sorted_ipa)
    output_to_file(tree,output_file)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
r""" for testting the interfaces of the scripts.api. """
import scripts.api as api
import os
import unittest
from unit_test.test_cfg import ApiTestConfig as apiCfg

class AutoGenerateChecker(unittest.TestCase):
    def setUp(self):
        self._cfg = apiCfg

    def test_from_xls_write_py(self):
        r"""
        测试 api.from_xls_write_py()
        """
        self.__clean_up_py_file()
        api.from_xls_write_py(self._cfg.xls_path_1, self._cfg.in_path)
        try:
            import unit_test.testf.info_out1_test1 as o1_t1
            import unit_test.testf.info_out1_test2 as o1_t2
        except ImportError:
            raise Exception('Has not generate file.')
        self.assertEqual(o1_t1.btn_buy, self._cfg.out_test1_btn_buy, 'api.from_xls_write_py() test faild.')
        self.assertEqual(o1_t2.btn_sell, self._cfg.out_test2_btn_sell, 'api.from_xls_write_py() test faild.')

    def test_from_path_write_py(self):
        r"""
        测试 api.from_path_write_py()
        """
        self.__clean_up_py_file()
        api.from_path_write_py(self._cfg.dir_path, self._cfg.in_path)
        try:
            import unit_test.testf.info_out1_test1 as o1_t1
            import unit_test.testf.info_out1_test2 as o1_t2
            import unit_test.testf.info_out2_test1 as o2_t1
            import unit_test.testf.info_out2_test2 as o2_t2
        except ImportError:
            raise Exception('Has not generate file.')
        self.assertEqual(o1_t1.btn_buy, self._cfg.out_test1_btn_buy, 'api.from_path_write_py() test faild.')
        self.assertEqual(o1_t2.btn_sell, self._cfg.out_test2_btn_sell, 'api.from_path_write_py() test faild.')
        self.assertEqual(o2_t1.btn_cancel, self._cfg.out_test1_btn_cancel, 'api.from_path_write_py() test faild.')
        self.assertEqual(o2_t2.btn_close, self._cfg.out_test2_btn_close, 'api.from_path_write_py() test faild.')

    def __clean_up_py_file(self):
        r""" 文件清理 """
        try:
            os.remove(self._cfg.be_del_py1_1)
            os.remove(self._cfg.be_del_py1_2)
        except FileNotFoundError:
            pass
        try:
            os.remove(self._cfg.be_del_py2_1)
            os.remove(self._cfg.be_del_py2_2)
        except FileNotFoundError:
            pass

    def tearDown(self):
        self.__clean_up_py_file()

if __name__ == '__main__':
    unittest.main()


# -*- coding: utf-8 -*-
import airflow
from datetime import datetime, timedelta
from airflow.operators.hive_operator import HiveOperator
from airflow.operators.impala_plugin import ImpalaOperator
from utils.connection_helper import get_hive_cursor
from airflow.operators.python_operator import PythonOperator
from airflow.contrib.hooks.redis_hook import RedisHook
from airflow.hooks.hive_hooks import HiveCliHook
from airflow.operators.hive_to_mysql import HiveToMySqlTransfer
from airflow.operators.mysql_operator import MySqlOperator
from airflow.operators.dagrun_operator import TriggerDagRunOperator
from airflow.sensors.external_task_sensor import ExternalTaskSensor
from airflow.operators.bash_operator import BashOperator
from airflow.sensors.named_hive_partition_sensor import NamedHivePartitionSensor
from airflow.sensors.hive_partition_sensor import HivePartitionSensor
from airflow.sensors import UFileSensor
from plugins.TaskTimeoutMonitor import TaskTimeoutMonitor
from plugins.TaskTouchzSuccess import TaskTouchzSuccess
from airflow.sensors import OssSensor
import json
import logging
from airflow.models import Variable
import requests
import os

args = {
    'owner': 'yuanfeng',
    'start_date': datetime(2019, 11, 1),
    'depends_on_past': False,
    'retries': 3,
    'retry_delay': timedelta(minutes=2),
    'email': ['bigdata_dw@opay-inc.com'],
    'email_on_failure': True,
    'email_on_retry': False,
}

dag = airflow.DAG('dim_opos_bd_info_df',
                  schedule_interval="00 01 * * *",
                  default_args=args,
                  )

##----------------------------------------- 依赖 ---------------------------------------##

ods_sqoop_base_bd_admin_users_df_task = OssSensor(
    task_id='ods_sqoop_base_bd_admin_users_df_task',
    bucket_key='{hdfs_path_str}/dt={pt}/_SUCCESS'.format(
        hdfs_path_str="opos_dw_sqoop/opay_crm/bd_admin_users",
        pt='{{ds}}'
    ),
    bucket_name='opay-datalake',
    poke_interval=60,  # 依赖不满足时，一分钟检查一次依赖状态
    dag=dag
)

ods_sqoop_base_bd_city_df_task = OssSensor(
    task_id='ods_sqoop_base_bd_city_df_task',
    bucket_key='{hdfs_path_str}/dt={pt}/_SUCCESS'.format(
        hdfs_path_str="opos_dw_sqoop/opay_crm/bd_city",
        pt='{{ds}}'
    ),
    bucket_name='opay-datalake',
    poke_interval=60,  # 依赖不满足时，一分钟检查一次依赖状态
    dag=dag
)

##----------------------------------------- 变量 ---------------------------------------##

db_name = "opos_dw"
table_name = "dim_opos_bd_info_df"
hdfs_path = "oss://opay-datalake/opos/opos_dw/" + table_name

##----------------------------------------- 任务超时监控 ---------------------------------------##

def fun_task_timeout_monitor(ds, dag, **op_kwargs):
    dag_ids = dag.dag_id

    tb = [
        {"dag": dag, "db": "opos_dw", "table": "{dag_name}".format(dag_name=dag_ids), "partition": "country_code=nal/dt={pt}".format(pt=ds),
         "timeout": "1200"}
    ]

    TaskTimeoutMonitor().set_task_monitor(tb)

task_timeout_monitor = PythonOperator(
    task_id='task_timeout_monitor',
    python_callable=fun_task_timeout_monitor,
    provide_context=True,
    dag=dag
)

##----------------------------------------- 脚本 ---------------------------------------##

def dim_opos_bd_info_df_sql_task(ds):
    HQL = '''

set hive.exec.parallel=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.strict.checks.cartesian.product=false;

--01.首先清空组织机构层级临时表,然后插入最新的组织机构层级数据
--插入最新的数据
insert overwrite table opos_dw.dim_opos_bd_info_df partition(country_code,dt)
select
nvl(hcm.id,0) as hcm_id
,nvl(hcm.name,'-') as hcm_name
,nvl(level2.cm_id,0) as cm_id
,nvl(level2.cm_name,'-') as cm_name
,nvl(level2.rm_id,0) as rm_id
,nvl(level2.rm_name,'-') as rm_name
,nvl(level2.bdm_id,0) as bdm_id
,nvl(level2.bdm_name,'-') as bdm_name
,nvl(level2.bd_id,0) as bd_id
,nvl(level2.bd_name,'-') as bd_name

,'nal' as country_code
,'{pt}' as dt
from
  (select id,name,leader_id from  opos_dw_ods.ods_sqoop_base_bd_admin_users_df where dt = '{pt}' and job_id = 2) hcm
full join
  (select nvl(cm.leader_id,0) as leader_id,nvl(cm.id,0) as cm_id,nvl(cm.name,'-') as cm_name,nvl(level3.rm_id,0) as rm_id,nvl(level3.rm_name,'-') as rm_name,nvl(level3.bdm_id,0) as bdm_id,nvl(level3.bdm_name,'-') as bdm_name,nvl(level3.bd_id,0) as bd_id,nvl(level3.bd_name,'-') as bd_name from
    (select id,name,leader_id from  opos_dw_ods.ods_sqoop_base_bd_admin_users_df where dt = '{pt}' and job_id = 3) cm
  full join
    (select nvl(rm.leader_id,0) as leader_id,nvl(rm.id,0) as rm_id,nvl(rm.name,'-') as rm_name,nvl(level4.bdm_id,0) as bdm_id,nvl(level4.bdm_name,'-') as bdm_name,nvl(level4.bd_id,0) as bd_id,nvl(level4.bd_name,'-') as bd_name from
      (select id,name,leader_id from  opos_dw_ods.ods_sqoop_base_bd_admin_users_df where dt = '{pt}' and job_id = 4) rm
    full join
      (select nvl(bdm.leader_id,0) as leader_id,nvl(bdm.id,0) as bdm_id,nvl(bdm.name,'-') as bdm_name,nvl(bd.id,0) as bd_id,nvl(bd.name,'-') as bd_name from
        (select id,name,leader_id from  opos_dw_ods.ods_sqoop_base_bd_admin_users_df where dt = '{pt}' and job_id = 6) bd
      full join
        (select id,name,leader_id from  opos_dw_ods.ods_sqoop_base_bd_admin_users_df where dt = '{pt}' and job_id = 5) bdm
      on bdm.id=bd.leader_id) as level4
    on rm.id=level4.leader_id) as level3
  on cm.id=level3.leader_id) as level2
on hcm.id=level2.leader_id;

'''.format(
        pt=ds,
        before_1_day=airflow.macros.ds_add(ds, -1),
        table=table_name,
        now_day='{{macros.ds_add(ds, +1)}}',
        db=db_name
    )
    return HQL

# 主流程
def execution_data_task_id(ds, **kargs):
    hive_hook = HiveCliHook()

    # 读取sql
    _sql = dim_opos_bd_info_df_sql_task(ds)

    logging.info('Executing: %s', _sql)

    # 执行Hive
    hive_hook.run_cli(_sql)

    # 生成_SUCCESS
    """
    第一个参数true: 数据目录是有country_code分区。false 没有
    第二个参数true: 数据有才生成_SUCCESS false 数据没有也生成_SUCCESS

    """
    TaskTouchzSuccess().countries_touchz_success(ds, db_name, table_name, hdfs_path, "true", "true")

dim_opos_bd_info_df_task = PythonOperator(
    task_id='dim_opos_bd_info_df_task',
    python_callable=execution_data_task_id,
    provide_context=True,
    dag=dag
)

ods_sqoop_base_bd_admin_users_df_task >> dim_opos_bd_info_df_task
ods_sqoop_base_bd_city_df_task >> dim_opos_bd_info_df_task


import pygame, sys, random
from pygame.locals import *

from constants import *
from board import Board

class Game(object):

    HUMAN = True
    COMPUTER = False

    def __init__(self):
        #Initialization
        self.hit_shots = 0
        self.player = self.HUMAN

        self.is_human_ships_added = False
        self.number_of_human_ships = 0

        pygame.init()
        self.myfont = pygame.font.SysFont("monospace", 30)

        self.board = Board(BOARDHEIGHT, BOARDWIDTH)
        self.comp_board = Board(BOARDHEIGHT, BOARDWIDTH)
        self.screen = pygame.display.set_mode((window_width, window_height))
        self.board.add_random_ships(5) #Add computer ship on human board
        # self.comp_board.add_random_ships(5) #Add player ship on computer board

        while True:
            #Handle events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == MOUSEBUTTONUP: #otherwise
                    mousex, mousey = event.pos #set mouse positions to the new position
                    col, row = self._get_tile_at_pixel(self.is_human_ships_added, mousex, mousey)
                    if self.player and self.is_human_ships_added:
                        if isinstance(col, int):
                            if self.board.click_ship(row, col):
                                self.player = Game.COMPUTER
                                self.computer_turn()
                        if self.board.is_game_finished():
                            self.end_game()
                            break
                        elif self.comp_board.is_game_finished():
                            self.end_game()
                            break
                    elif self.is_human_ships_added == False:
                        if isinstance(col, int):
                            if self.comp_board.add_ships_manual(row, col) == True:
                                self.number_of_human_ships += 1
                                # print "Aktualnie number_of_human_ships {} / {} board.total_ships_length".format(self.number_of_human_ships, self.board.total_ships_length)
                            if self.number_of_human_ships == self.board.total_ships_length:
                                self.is_human_ships_added = True
            if self.is_human_ships_added and not self.board.is_game_finished() and not self.comp_board.is_game_finished():
                self._refresh_view()
            elif not self.is_human_ships_added:
                self.start_game()

    def _refresh_view(self):
        self.screen.fill(gray)
        self.draw()
        self.draw_shots()
        pygame.display.update()

    def start_game(self):
        self.screen.fill(gray)
        self.draw_empty_board()
        pygame.display.update()

    def computer_turn(self):
        if self.comp_board.last_shot:
            self.comp_board.near_shot()
        else:
            self.comp_board.random_shot()
        self.player = Game.HUMAN

    def draw_shots(self):
        self.shots = self.myfont.render("You hit "+(str(self.board.hit_shots)+" from "+str(self.board.total_ships_length))+" piece of ship", 1, (255,255,255))
        self.screen.blit(self.shots, (10,10))

    def _paint_tile(self, player, row, col, color):
        left, top = self._left_top_coords_tile(player, row, col)
        pygame.draw.rect(self.screen, color, (left, top, tile_size, tile_size))

    def draw(self):
        for row in xrange(self.board.height):
            for col in xrange(self.board.width):
                color = self.board.get_color(False, row, col)
                self._paint_tile("human", col, row, color)

        for row in xrange(self.comp_board.height):
            for col in xrange(self.comp_board.width):
                color = self.comp_board.get_color(True, row, col)
                self._paint_tile("computer", col, row, color)

        #Drawing lines
        board_width = BOARDWIDTH*tile_size
        board_height = BOARDHEIGHT*tile_size
        #Draw HUMAN horizontal lines
        for x in xrange(0, (BOARDWIDTH + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x, margin_y + x), (margin_x + board_width, margin_y + x))

        #Draw COMPUTER horizontal lines
        for x in xrange(0, (BOARDWIDTH + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x + board_width + 100, margin_y + x), (margin_x + 2 * board_width + 100, margin_y + x))

        #Draw HUMAN vertical lines
        for y in xrange(0, (BOARDHEIGHT + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x + y, margin_y), (margin_x + y, margin_y + board_height))

        #Draw COMPUTER vertical lines
        for y in xrange(0, (BOARDHEIGHT + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x + y + board_height + 100, margin_y), (margin_x + y + board_height + 100, margin_y + board_height))

    def draw_empty_board(self):
        for row in xrange(self.comp_board.height):
            for col in xrange(self.comp_board.width):
                color = self.comp_board.get_color(True, row, col)
                self._paint_tile("computer", col, row, color)
        #Drawing lines
        board_width = BOARDWIDTH*tile_size
        board_height = BOARDHEIGHT*tile_size
        #Draw COMPUTER horizontal lines
        for x in xrange(0, (BOARDWIDTH + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x + board_width + 100, margin_y + x), (margin_x + 2 * board_width + 100, margin_y + x))

        #Draw COMPUTER vertical lines
        for y in xrange(0, (BOARDHEIGHT + 1) * tile_size, tile_size):
            pygame.draw.line(self.screen, darkgrey, (margin_x + y + board_height + 100, margin_y), (margin_x + y + board_height + 100, margin_y + board_height))

    def end_game(self):
        self.screen.fill(gray)
        self.label = self.myfont.render("Game end!", 1, (255,255,255))
        if self.board.is_game_finished():
            self.label = self.myfont.render("You won!", 1, (255,255,255))
        elif self.comp_board.is_game_finished():
            self.label = self.myfont.render("Computer won!", 1, (255,255,255))
        self.screen.blit(self.label, ((window_width/2)-80, window_height/2))
        pygame.display.update()

    def _get_tile_at_pixel(self, is_human_ships_added, x, y):
        if is_human_ships_added == True:
            player = "human"
            for tilex in xrange(BOARDWIDTH):
                for tiley in xrange(BOARDHEIGHT):
                    left, top = self._left_top_coords_tile(player, tilex, tiley)
                    tile_rect = pygame.Rect(left, top, TILESIZE, TILESIZE)
                    if tile_rect.collidepoint(x, y):
                        return (tilex, tiley)
            return (None, None)
        else:
            player = "computer"
            for tilex in xrange(BOARDWIDTH):
                for tiley in xrange(BOARDHEIGHT):
                    left, top = self._left_top_coords_tile(player, tilex, tiley)
                    tile_rect = pygame.Rect(left, top, TILESIZE, TILESIZE)
                    if tile_rect.collidepoint(x, y):
                        return (tilex, tiley)
            return (None, None)

    def _left_top_coords_tile(self, player, row, col):
        if player == "human":
            left = row * tile_size + margin_x
            top = col * tile_size + margin_y
            return (left, top)
        elif player == "computer":
            left = row * tile_size + margin_x + BOARDWIDTH*tile_size + 100
            top = col * tile_size + margin_y
            return (left, top)


import io
import numpy as np

from torch import nn
import torch.utils.model_zoo as model_zoo
import torch.onnx

import onnx
import onnxruntime

# PyTorch Model
import torch.nn as nn
import torch.nn.init as init

class SuperResolutionNet(nn.Module):
    def __init__(self, upscale_factor, inplace=False):
        super(SuperResolutionNet, self).__init__()

        self.relu = nn.ReLU(inplace=inplace)
        self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2))
        self.conv2 = nn.Conv2d(64, 64, (3, 3), (1, 1), (1, 1))
        self.conv3 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1))
        self.conv4 = nn.Conv2d(32, upscale_factor ** 2, (3, 3), (1, 1), (1, 1))
        self.pixel_shuffle = nn.PixelShuffle(upscale_factor)

        self._initialize_weights()

    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = self.relu(self.conv2(x))
        x = self.relu(self.conv3(x))
        x = self.pixel_shuffle(self.conv4(x))
        return x

    def _initialize_weights(self):
        init.orthogonal_(self.conv1.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv2.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv3.weight, init.calculate_gain('relu'))
        init.orthogonal_(self.conv4.weight)

torch_model = SuperResolutionNet(upscale_factor=3)

# pretrained model
model_url = 'https://s3.amazonaws.com/pytorch/test_data/export/superres_epoch100-44c6958e.pth'
batch_size = 1

# initialize model with pretrained pth
map_location = lambda storage, loc: storage
if torch.cuda.is_available():
    map_location = None
torch_model.load_state_dict(model_zoo.load_url(model_url, map_location=map_location))

# evaluate
torch_model.eval()

# define input
x = torch.randn(batch_size, 1, 224, 224, requires_grad=True)
torch_out = torch_model(x)

# 모델 변환 to ONNX
torch.onnx.export(torch_model,               # 실행될 모델
                  x,                         # 모델 입력값 (튜플 또는 여러 입력값들도 가능)
                  "./ONNX/models/super_resolution.onnx",   # 모델 저장 경로 (파일 또는 파일과 유사한 객체 모두 가능)
                  export_params=True,        # 모델 파일 안에 학습된 모델 가중치를 저장할지의 여부
                  opset_version=10,          # 모델을 변환할 때 사용할 ONNX 버전
                  do_constant_folding=True,  # 최적화시 상수폴딩을 사용할지의 여부
                  input_names = ['input'],   # 모델의 입력값을 가리키는 이름
                  output_names = ['output'], # 모델의 출력값을 가리키는 이름
                  dynamic_axes={'input' : {0 : 'batch_size'},    # 가변적인 길이를 가진 차원
                                'output' : {0 : 'batch_size'}})

# ONNX
MODEL_PATH = './ONNX/models/super_resolution.onnx'
onnx_model = onnx.load(MODEL_PATH)

# check model have valid schema
onnx.checker.check_model(onnx_model)

ort_session = onnxruntime.InferenceSession(MODEL_PATH)

def to_numpy(tensor):
    return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()

# ONNX 런타임에서 계산된 결과값
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)}
ort_outs = ort_session.run(None, ort_inputs)

# ONNX 런타임과 PyTorch에서 연산된 결과값 비교
np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol=1e-03, atol=1e-05)

print("Exported model has been tested with ONNXRuntime, and the result looks good!")


from django.conf.urls import url

from views import *

urlpatterns = [
    url(r'^$', index),
    url(r'^register$', register),
    url(r'^login$', login),
    url(r'^quotes$', quotes),
    url(r'^addquote$', addquote),
    url(r'^addfave/(?P<id>\d+)$', addfave),
    url(r'^deletefave/(?P<id>\d+)$', deletefave),
    url(r'^showuser/(?P<id>\d+)$', showuser),
    url(r'^deletequote/(?P<id>\d+)$', deletequote),
    url(r'^logout$', logout),
]


import f90nml
import argparse
import json

parser = argparse.ArgumentParser(description='This program converts namelist.input file of SKRIPS-WRF to WRF only\'s namelist.input. The main work is to remove `auxinput5` related variables from `time_control` namegroup.')

parser.add_argument('--input', type=str, required=True, help='Input namelist file')
parser.add_argument('--output', type=str, required=True, help='Input namelist file')
parser.add_argument('--overwrite', action="store_true")

args = parser.parse_args()

print("Input file: %s" % (args.input,))
print("Output file: %s" % (args.output,))

namegroup = 'time_control'

in_nml = f90nml.read(args.input)

print("Original namegroup `%s`" % (namegroup,))
print(json.dumps(in_nml[namegroup], indent=4))

for varname in [
    "auxinput5_inname",
    "auxinput5_interval_s",
    "auxinput5_end_d",
    "io_form_auxinput5",
    "auxhist5_outname",
    "auxhist5_interval_s",
    "auxhist5_end_d",
    "io_form_auxhist5",
]:
    print("Removing variable: %s" % (varname,))
    del in_nml[namegroup][varname]

print("Writing file: %s" % (args.output,))
in_nml.end_comma = True
in_nml.write(args.output, force=args.overwrite)


import re
import math
import logging

import gobject
import gtk
import hippo
import cairo

from sugar.graphics.xocolor import XoColor
from sugar.util import LRU

_BADGE_SIZE = 0.45

class _SVGLoader(object):
    def __init__(self):
        self._cache = LRU(50)

    def load(self, file_name, entities, cache):
        if file_name in self._cache:
            icon = self._cache[file_name]
        else:
            icon_file = open(file_name, 'r')
            icon = icon_file.read()
            icon_file.close()

            if cache:
                self._cache[file_name] = icon

        for entity, value in entities.items():
            if isinstance(value, basestring):
                xml = '<!ENTITY %s "%s">' % (entity, value)
                icon = re.sub('<!ENTITY %s .*>' % entity, xml, icon)
            else:
                logging.error(
                    'Icon %s, entity %s is invalid.', file_name, entity)

        import rsvg # XXX this is very slow!  why?
        return rsvg.Handle(data=icon)

class _IconInfo(object):
    def __init__(self):
        self.file_name = None
        self.attach_x = 0
        self.attach_y = 0

class _BadgeInfo(object):
    def __init__(self):
        self.attach_x = 0
        self.attach_y = 0
        self.size = 0
        self.icon_padding = 0

class _IconBuffer(object):
    _surface_cache = LRU(50)
    _loader = _SVGLoader()

    def __init__(self):
        self.icon_name = None
        self.icon_size = None
        self.file_name = None
        self.fill_color = None
        self.background_color = None
        self.stroke_color = None
        self.badge_name = None
        self.width = None
        self.height = None
        self.cache = False
        self.scale = 1.0

    def _get_cache_key(self, sensitive):
        if self.background_color is None:
            color = None
        else:
            color = (self.background_color.red, self.background_color.green,
                     self.background_color.blue)
        return (self.icon_name, self.file_name, self.fill_color,
                self.stroke_color, self.badge_name, self.width, self.height,
                color, sensitive)

    def _load_svg(self, file_name):
        entities = {}
        if self.fill_color:
            entities['fill_color'] = self.fill_color
        if self.stroke_color:
            entities['stroke_color'] = self.stroke_color

        return self._loader.load(file_name, entities, self.cache)

    def _get_attach_points(self, info, size_request):
        attach_points = info.get_attach_points()

        if attach_points:
            attach_x = float(attach_points[0][0]) / size_request
            attach_y = float(attach_points[0][1]) / size_request
        else:
            attach_x = attach_y = 0

        return attach_x, attach_y

    def _get_icon_info(self):
        icon_info = _IconInfo()

        if self.file_name:
            icon_info.file_name = self.file_name
        elif self.icon_name:
            theme = gtk.icon_theme_get_default()

            size = 50
            if self.width != None:
                size = self.width

            info = theme.lookup_icon(self.icon_name, size, 0)
            if info:
                attach_x, attach_y = self._get_attach_points(info, size)

                icon_info.file_name = info.get_filename()
                icon_info.attach_x = attach_x
                icon_info.attach_y = attach_y

                del info
            else:
                logging.warning('No icon with the name %s '
                                'was found in the theme.' % self.icon_name)

        return icon_info

    def _draw_badge(self, context, size, sensitive, widget):
        theme = gtk.icon_theme_get_default()
        badge_info = theme.lookup_icon(self.badge_name, size, 0)
        if badge_info:
            badge_file_name = badge_info.get_filename()
            if badge_file_name.endswith('.svg'):
                handle = self._loader.load(badge_file_name, {}, self.cache)

                dimensions = handle.get_dimension_data()
                icon_width = int(dimensions[0])
                icon_height = int(dimensions[1])

                pixbuf = handle.get_pixbuf()
            else:
                pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name)

                icon_width = pixbuf.get_width()
                icon_height = pixbuf.get_height()

            context.scale(float(size) / icon_width,
                          float(size) / icon_height)

            if not sensitive:
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)
            surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf)
            context.set_source_surface(surface, 0, 0)
            context.paint()

    def _get_size(self, icon_width, icon_height, padding):
        if self.width is not None and self.height is not None:
            width = self.width + padding
            height = self.height + padding
        else:
            width = icon_width + padding
            height = icon_height + padding

        return width, height

    def _get_badge_info(self, icon_info, icon_width, icon_height):
        info = _BadgeInfo()
        if self.badge_name is None:
            return info

        info.size = int(_BADGE_SIZE * icon_width)
        info.attach_x = int(icon_info.attach_x * icon_width - info.size / 2)
        info.attach_y = int(icon_info.attach_y * icon_height - info.size / 2)

        if info.attach_x < 0 or info.attach_y < 0:
            info.icon_padding = max(-info.attach_x, -info.attach_y)
        elif info.attach_x + info.size > icon_width or \
             info.attach_y + info.size > icon_height:
            x_padding = info.attach_x + info.size - icon_width
            y_padding = info.attach_y + info.size - icon_height
            info.icon_padding = max(x_padding, y_padding)

        return info

    def _get_xo_color(self):
        if self.stroke_color and self.fill_color:
            return XoColor('%s,%s' % (self.stroke_color, self.fill_color))
        else:
            return None

    def _set_xo_color(self, xo_color):
        if xo_color:
            self.stroke_color = xo_color.get_stroke_color()
            self.fill_color = xo_color.get_fill_color()
        else:
            self.stroke_color = None
            self.fill_color = None

    def _get_insensitive_pixbuf (self, pixbuf, widget):
        if not (widget and widget.style):
            return pixbuf

        icon_source = gtk.IconSource()
        # Special size meaning "don't touch"
        icon_source.set_size(-1)
        icon_source.set_pixbuf(pixbuf)
        icon_source.set_state(gtk.STATE_INSENSITIVE)
        icon_source.set_direction_wildcarded(False)
        icon_source.set_size_wildcarded(False)

        # Please note that the pixbuf returned by this function is leaked
        # with current stable versions of pygtk. The relevant bug is
        # http://bugzilla.gnome.org/show_bug.cgi?id=502871
        #   -- 2007-12-14 Benjamin Berg
        pixbuf = widget.style.render_icon(icon_source, widget.get_direction(),
                                          gtk.STATE_INSENSITIVE, -1, widget,
                                          "sugar-icon")

        return pixbuf

    def get_surface(self, sensitive=True, widget=None):
        cache_key = self._get_cache_key(sensitive)
        if cache_key in self._surface_cache:
            return self._surface_cache[cache_key]

        icon_info = self._get_icon_info()
        if icon_info.file_name is None:
            return None

        is_svg = icon_info.file_name.endswith('.svg')

        if is_svg:
            handle = self._load_svg(icon_info.file_name)
            dimensions = handle.get_dimension_data()
            icon_width = int(dimensions[0])
            icon_height = int(dimensions[1])
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.file_name)
            icon_width = pixbuf.get_width()
            icon_height = pixbuf.get_height()

        badge_info = self._get_badge_info(icon_info, icon_width, icon_height)

        padding = badge_info.icon_padding
        width, height = self._get_size(icon_width, icon_height, padding)
        if self.background_color is None:
            surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
            context = cairo.Context(surface)
        else:
            surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
            context = cairo.Context(surface)
            context = gtk.gdk.CairoContext(context)
            context.set_source_color(self.background_color)
            context.paint()

        context.scale(float(width) / (icon_width + padding * 2),
                      float(height) / (icon_height + padding * 2))
        context.save()

        context.translate(padding, padding)
        if is_svg:
            if sensitive:
                handle.render_cairo(context)
            else:
                pixbuf = handle.get_pixbuf()
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)

                pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf)
                context.set_source_surface(pixbuf_surface, 0, 0)
                context.paint()
        else:
            if not sensitive:
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)
            pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf)
            context.set_source_surface(pixbuf_surface, 0, 0)
            context.paint()

        if self.badge_name:
            context.restore()
            context.translate(badge_info.attach_x, badge_info.attach_y)
            self._draw_badge(context, badge_info.size, sensitive, widget)

        self._surface_cache[cache_key] = surface

        return surface

    xo_color = property(_get_xo_color, _set_xo_color)

class Icon(gtk.Image):
    __gtype_name__ = 'SugarIcon'

    def __init__(self, **kwargs):
        self._buffer = _IconBuffer()
        self._file = None

        gobject.GObject.__init__(self, **kwargs)

    def get_file(self):
        return self._file

    def set_file(self, file_name):
        self._file = file_name
        self._buffer.file_name = file_name

    # XXX we need to override file property to support auto_ptr objects
    # that used to represent temporaly unzipped icons from bundles, see #1175
    file = gobject.property(type=object, setter=set_file, getter=get_file)

    def _sync_image_properties(self):
        if self._buffer.icon_name != self.props.icon_name:
            self._buffer.icon_name = self.props.icon_name

        if self._buffer.file_name != self.props.file:
            self._buffer.file_name = self.props.file

        if self.props.pixel_size == -1:
            width, height = gtk.icon_size_lookup(self.props.icon_size)
        else:
            width = height = self.props.pixel_size
        if self._buffer.width != width or self._buffer.height != height:
            self._buffer.width = width
            self._buffer.height = height

    def _icon_size_changed_cb(self, image, pspec):
        self._buffer.icon_size = self.props.icon_size

    def _icon_name_changed_cb(self, image, pspec):
        self._buffer.icon_name = self.props.icon_name

    def _file_changed_cb(self, image, pspec):
        self._buffer.file_name = self.props.file

    def do_size_request(self, requisition):
        """
        Parameters
        ----------
        requisition :

        Returns
        -------
        None

        """
        self._sync_image_properties()
        surface = self._buffer.get_surface()
        if surface:
            requisition[0] = surface.get_width()
            requisition[1] = surface.get_height()
        elif self._buffer.width and self._buffer.height:
            requisition[0] = self._buffer.width
            requisition[1] = self._buffer.width
        else:
            requisition[0] = requisition[1] = 0

    def do_expose_event(self, event):
        """
        Parameters
        ----------
        event :

        Returns:
        --------
        None

        """
        self._sync_image_properties()
        sensitive = (self.state != gtk.STATE_INSENSITIVE)
        surface = self._buffer.get_surface(sensitive, self)
        if surface is None:
            return

        xpad, ypad = self.get_padding()
        xalign, yalign = self.get_alignment()
        requisition = self.get_child_requisition()
        if self.get_direction() != gtk.TEXT_DIR_LTR:
            xalign = 1.0 - xalign

        allocation = self.get_allocation()
        x = math.floor(allocation.x + xpad +
            (allocation.width - requisition[0]) * xalign)
        y = math.floor(allocation.y + ypad +
            (allocation.height - requisition[1]) * yalign)

        cr = self.window.cairo_create()
        cr.set_source_surface(surface, x, y)
        cr.paint()

    def set_xo_color(self, value):
        """
        Parameters
        ----------
        value :

        Returns
        -------
        None

        """
        if self._buffer.xo_color != value:
            self._buffer.xo_color = value
            self.queue_draw()

    xo_color = gobject.property(
        type=object, getter=None, setter=set_xo_color)

    def set_fill_color(self, value):
        """
        Parameters
        ----------
        value :

        Returns
        -------
        None

        """
        if self._buffer.fill_color != value:
            self._buffer.fill_color = value
            self.queue_draw()

    def get_fill_color(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        fill_color :

        """
        return self._buffer.fill_color

    fill_color = gobject.property(
        type=object, getter=get_fill_color, setter=set_fill_color)

    def set_stroke_color(self, value):
        """
        Parameters
        ----------
        value :

        Returns
        -------
        None

        """
        if self._buffer.stroke_color != value:
            self._buffer.stroke_color = value
            self.queue_draw()

    def get_stroke_color(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        stroke_color :

        """
        return self._buffer.stroke_color

    stroke_color = gobject.property(
        type=object, getter=get_stroke_color, setter=set_stroke_color)

    def set_badge_name(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.badge_name != value:
            self._buffer.badge_name = value
            self.queue_resize()

    def get_badge_name(self):
        return self._buffer.badge_name

    badge_name = gobject.property(
        type=str, getter=get_badge_name, setter=set_badge_name)

class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
    __gtype_name__ = 'CanvasIcon'

    def __init__(self, **kwargs):
        from sugar.graphics.palette import CanvasInvoker

        self._buffer = _IconBuffer()
        self._palette_invoker = CanvasInvoker()

        hippo.CanvasBox.__init__(self, **kwargs)

        self._palette_invoker.attach(self)

        self.connect('destroy', self.__destroy_cb)

    def _emit_paint_needed_icon_area(self):
        surface = self._buffer.get_surface()
        if surface:
            width, height = self.get_allocation()
            s_width = surface.get_width()
            s_height = surface.get_height()

            x = (width - s_width) / 2
            y = (height - s_height) / 2

            self.emit_paint_needed(x, y, s_width, s_height)

    def __destroy_cb(self, icon):
        if self._palette_invoker is not None:
            self._palette_invoker.detach()

    def set_file_name(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        \"\"\"

        """
        if self._buffer.file_name != value:
            self._buffer.file_name = value
            self.emit_paint_needed(0, 0, -1, -1)

    def get_file_name(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        file name :

        """
        return self._buffer.file_name

    file_name = gobject.property(
        type=object, getter=get_file_name, setter=set_file_name)

    def set_icon_name(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.icon_name != value:
            self._buffer.icon_name = value
            self.emit_paint_needed(0, 0, -1, -1)

    def get_icon_name(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        icon name :

        """
        return self._buffer.icon_name

    icon_name = gobject.property(
        type=object, getter=get_icon_name, setter=set_icon_name)

    def set_xo_color(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.xo_color != value:
            self._buffer.xo_color = value
            self._emit_paint_needed_icon_area()

    xo_color = gobject.property(
        type=object, getter=None, setter=set_xo_color)

    def set_fill_color(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.fill_color != value:
            self._buffer.fill_color = value
            self._emit_paint_needed_icon_area()

    def get_fill_color(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        fill color :

        """
        return self._buffer.fill_color

    fill_color = gobject.property(
        type=object, getter=get_fill_color, setter=set_fill_color)

    def set_stroke_color(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.stroke_color != value:
            self._buffer.stroke_color = value
            self._emit_paint_needed_icon_area()

    def get_stroke_color(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        stroke color :

        """
        return self._buffer.stroke_color

    stroke_color = gobject.property(
        type=object, getter=get_stroke_color, setter=set_stroke_color)

    def set_background_color(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.background_color != value:
            self._buffer.background_color = value
            self.emit_paint_needed(0, 0, -1, -1)

    def get_background_color(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        fill color :

        """
        return self._buffer.background_color

    background_color = gobject.property(
        type=object, getter=get_background_color, setter=set_background_color)

    def set_size(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        if self._buffer.width != value:
            self._buffer.width = value
            self._buffer.height = value
            self.emit_request_changed()

    def get_size(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        size :

        """
        return self._buffer.width

    size = gobject.property(
        type=object, getter=get_size, setter=set_size)

    def set_scale(self, value):
        """
        Parameters
        ----------
        value:

        Returns
        -------
        None

        """
        logging.warning(
            'CanvasIcon: the scale parameter is currently unsupported')
        if self._buffer.scale != value:
            self._buffer.scale = value
            self.emit_request_changed()

    def get_scale(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        scale :

        """
        return self._buffer.scale

    scale = gobject.property(
        type=float, getter=get_scale, setter=set_scale)

    def set_cache(self, value):
        """
        Parameters
        ----------
        cache

        Returns
        -------
        None

        """
        self._buffer.cache = value

    def get_cache(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        cache :

        """
        return self._buffer.cache

    cache = gobject.property(
        type=bool, default=False, getter=get_cache, setter=set_cache)

    def set_badge_name(self, value):
        """
        Parameters
        ----------
        value :

        Returns
        -------
        None

        """
        if self._buffer.badge_name != value:
            self._buffer.badge_name = value
            self.emit_paint_needed(0, 0, -1, -1)

    def get_badge_name(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        badge name :

        """
        return self._buffer.badge_name

    badge_name = gobject.property(
        type=object, getter=get_badge_name, setter=set_badge_name)

    def do_paint_below_children(self, cr, damaged_box):
        """
        Parameters
        ----------
        cr :

        damaged_box :

        Returns
        -------
        None

        """
        surface = self._buffer.get_surface()
        if surface:
            width, height = self.get_allocation()

            x = (width - surface.get_width()) / 2
            y = (height - surface.get_height()) / 2

            cr.set_source_surface(surface, x, y)
            cr.paint()

    def do_get_content_width_request(self):
        """
        Parameters
        ----------
        None

        Returns
        -------
        width :

        """
        surface = self._buffer.get_surface()
        if surface:
            size = surface.get_width()
        elif self._buffer.width:
            size = self._buffer.width
        else:
            size = 0

        return size, size

    def do_get_content_height_request(self, for_width):
        surface = self._buffer.get_surface()
        if surface:
            size = surface.get_height()
        elif self._buffer.height:
            size = self._buffer.height
        else:
            size = 0

        return size, size

    def do_button_press_event(self, event):
        if event.button == 1:
            self.emit_activated()
            return True
        else:
            return False

    def create_palette(self):
        return None

    def get_palette(self):
        return self._palette_invoker.palette

    def set_palette(self, palette):
        self._palette_invoker.palette = palette

    palette = gobject.property(
        type=object, setter=set_palette, getter=get_palette)

    def get_palette_invoker(self):
        return self._palette_invoker

    def set_palette_invoker(self, palette_invoker):
        self._palette_invoker.detach()
        self._palette_invoker = palette_invoker

    palette_invoker = gobject.property(
        type=object, setter=set_palette_invoker, getter=get_palette_invoker)

    def set_tooltip(self, text):
        from sugar.graphics.palette import Palette

        self.set_palette(Palette(text))

    palette = property(get_palette, set_palette)

def get_icon_state(base_name, perc, step=5):
    strength = round(perc / step) * step
    icon_theme = gtk.icon_theme_get_default()

    while strength <= 100 and strength >= 0:
        icon_name = '%s-%03d' % (base_name, strength)
        if icon_theme.has_icon(icon_name):
            return icon_name

        strength = strength + step

def get_icon_file_name(icon_name):
    icon_theme = gtk.icon_theme_get_default()
    info = icon_theme.lookup_icon(icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR, 0)
    if not info:
        return None
    filename = info.get_filename()
    del info
    return filename


import boto3
import os

LAMBDA_ARN = os.environ["LAMBDA_ARN"]

s3_client = boto3.client("s3")

def handle_template(request_id, template):
    new_resources = {}

    for name, resource in list(template.get("Resources", {}).items()):
        if resource["Type"] == "AWS::S3::Object":
            props = resource["Properties"]

            if (
                len(
                    [
                        prop
                        for prop in resource["Properties"]
                        if prop in ["Body", "URL", "Base64Body", "Source"]
                    ]
                )
                != 1
            ):
                raise Exception(
                    "You must specify exactly one of: Body, URL, Base64Body, Source"
                )

            target = props["Target"]

            if "ACL" not in target:
                target["ACL"] = "private"

            resource_props = {
                "ServiceToken": LAMBDA_ARN,
                "Target": target,
            }

            if "Body" in props:
                resource_props["Body"] = props["Body"]

            elif "URL" in props:
                resource_props["URL"] = props["URL"]

            elif "Base64Body" in props:
                resource_props["Base64Body"] = props["Base64Body"]

            elif "Source" in props:
                resource_props["Source"] = props["Source"]

            new_resources[name] = {
                "Type": "Custom::S3Object",
                "Version": "1.0",
                "Properties": resource_props,
            }

    for name, resource in list(new_resources.items()):
        template["Resources"][name] = resource

    return template

def handler(event, context):
    try:
        template = handle_template(event["requestId"], event["fragment"])
    except Exception as e:
        return {
            "requestId": event["requestId"],
            "status": "failure",
            "fragment": event["fragment"],
        }

    return {
        "requestId": event["requestId"],
        "status": "success",
        "fragment": template,
    }