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

# Copyright (c) 2014 Yann GUIBET <yannguibet@gmail.com>.
# All rights reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#
#     2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in
#     the documentation and/or other materials provided with the
#     distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from hashlib import sha512, sha256, sha224
from binascii import hexlify, unhexlify
from .openssl import OpenSSL
from .cipher import Cipher
from .hash import hmac_sha256, equals
from .arithmetic import hash_160
from struct import pack, unpack
from math import ceil
from datetime import datetime, timedelta

class ECC:
    """
    Asymmetric encryption with Elliptic Curve Cryptography (ECC)
    ECDH, ECDSA and ECIES

        import pyelliptic

        alice = pyelliptic.ECC() # default curve: sect283r1
        bob = pyelliptic.ECC(curve='sect571r1')

        ciphertext = alice.encrypt("Hello Bob", bob.get_pubkey())
        print bob.decrypt(ciphertext)

        signature = bob.sign("Hello Alice")
        # alice's job :
        print pyelliptic.ECC(
            pubkey=bob.get_pubkey()).verify(signature, "Hello Alice")

        # ERROR !!!
        try:
            key = alice.get_ecdh_key(bob.get_pubkey())
        except: print("For ECDH key agreement,\
                      the keys must be defined on the same curve !")

        alice = pyelliptic.ECC(curve='sect571r1')
        print alice.get_ecdh_key(bob.get_pubkey()).encode('hex')
        print bob.get_ecdh_key(alice.get_pubkey()).encode('hex')

    """

    def __init__(self, pubkey=None, privkey=None, pubkey_x=None,
                 pubkey_y=None, raw_privkey=None, curve='sect283r1', hash='sha512'):
        """
        For a normal and High level use, specifie pubkey,
        privkey (if you need) and the curve
        """
        # t1 = datetime.now()
        if type(curve) == str:
            self.curve = OpenSSL.get_curve(curve)
        else:
            self.curve = curve

        if type(hash) == str:
            self.hash = globals()[hash]
        else:
            self.hash = hash

        if pubkey_x is not None and pubkey_y is not None:
            self._set_keys(pubkey_x, pubkey_y, raw_privkey)
        elif pubkey is not None:
            pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey)
            if privkey is not None:
                raw_privkey = ECC._decode_privkey(privkey)
            self._set_keys(pubkey_x, pubkey_y, raw_privkey)
        else:
            self.privkey, self.pubkey_x, self.pubkey_y = self._generate()
        # t2 = datetime.now()
        # print 'Pyelliptic ECC:', (t2 - t1).microseconds

    def _set_keys(self, pubkey_x, pubkey_y, privkey):
        if self.raw_check_key(privkey, pubkey_x, pubkey_y) < 0:
            self.pubkey_x = None
            self.pubkey_y = None
            self.privkey = None
            raise Exception("Bad ECC keys ...")
        else:
            self.pubkey_x = pubkey_x
            self.pubkey_y = pubkey_y
            self.privkey = privkey

    @staticmethod
    def get_order(curve):
        try:
            if type(curve) == str:
                curve = OpenSSL.get_curve(curve)

            m = OpenSSL.BN_new()
            OpenSSL.EC_GROUP_get_order(OpenSSL.EC_GROUP_new_by_curve_name(curve), m, 0)
            m_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(m))
            OpenSSL.BN_bn2bin(m, m_bin)
            return m_bin.raw
        finally:
            OpenSSL.BN_free(m)

    @staticmethod
    def get_curves():
        """
        static method, returns the list of all the curves available
        """
        return OpenSSL.curves.keys()

    def get_curve(self):
        return OpenSSL.get_curve_by_id(self.curve)

    def get_curve_id(self):
        return self.curve

    def get_pubkey(self, _format='binary'):
        """
        High level function which returns :
        pubkeyX + pubkeyY
        """
        binary = b''.join((
            self.pubkey_x,
            self.pubkey_y
        ))

        if _format is 'binary':
            pubkey = b'' + unhexlify('04') + binary
        elif _format is 'hex':
            pubkey = b'04' + binary.encode('hex')
        else:
            raise Exception("[ECC] Unsupported pubkey output format ...")

        return pubkey

    def get_privkey(self):
        """
        High level function which returns
        privkey
        """
        return self.privkey

    @staticmethod
    def _decode_pubkey(pubkey, format='binary'):
        if format is 'binary':
            binary_key = pubkey
        elif format is 'hex':
            binary_key = unhexlify(pubkey)
        else:
            raise Exception("[ECC] Unsupported pubkey input format")

        conv_form = binary_key[0:1]
        if hexlify(conv_form) != b'04':
            raise Exception("[ECC] Unsupported pubkey point conversion form")
        i = int(len(binary_key) / 2 + 1)
        pubkey_x = binary_key[1:i]
        pubkey_y = binary_key[i:]
        return pubkey_x, pubkey_y

    @staticmethod
    def _decode_privkey(privkey):
        return privkey

    def _old_get_pubkey(self):
        """
        Old get_pubkey, keeps for compatibility issues.
        """
        return b''.join((pack('!H', self.curve),
                         pack('!H', len(self.pubkey_x)),
                         self.pubkey_x,
                         pack('!H', len(self.pubkey_y)),
                         self.pubkey_y
                         ))

    def _old_get_privkey(self):
        """
        Old get_privkey, keeps for compatibility issues.
        """
        return b''.join((pack('!H', self.curve),
                         pack('!H', len(self.privkey)),
                         self.privkey
                         ))

    @staticmethod
    def _old_decode_pubkey(pubkey):
        """
        Converts old exported pubkey to new format
        """
        i = 0
        curve = unpack('!H', pubkey[i:i + 2])[0]
        i += 2
        tmplen = unpack('!H', pubkey[i:i + 2])[0]
        i += 2
        pubkey_x = pubkey[i:i + tmplen]
        i += tmplen
        tmplen = unpack('!H', pubkey[i:i + 2])[0]
        i += 2
        pubkey_y = pubkey[i:i + tmplen]
        i += tmplen
        return curve, pubkey_x, pubkey_y, i

    @staticmethod
    def _old_decode_privkey(privkey):
        """
        Converts old exported privkey to new format
        """
        i = 0
        curve = unpack('!H', privkey[i:i + 2])[0]
        i += 2
        tmplen = unpack('!H', privkey[i:i + 2])[0]
        i += 2
        privkey = privkey[i:i + tmplen]
        i += tmplen
        return curve, privkey, i

    def _generate(self):
        try:
            pub_key_x = OpenSSL.BN_new()
            pub_key_y = OpenSSL.BN_new()

            key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
            if key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_generate_key(key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_generate_key FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_check_key(key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error())
            priv_key = OpenSSL.EC_KEY_get0_private_key(key)

            group = OpenSSL.EC_KEY_get0_group(key)
            pub_key = OpenSSL.EC_KEY_get0_public_key(key)

            if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key,
                                                            pub_key_x,
                                                            pub_key_y, 0
                                                            )) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())

            field_size = OpenSSL.EC_GROUP_get_degree(OpenSSL.EC_KEY_get0_group(key))
            secret_len = int((field_size + 7) / 8)

            privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key))
            pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x))
            pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y))
            OpenSSL.BN_bn2bin(priv_key, privkey)
            privkey = privkey.raw
            OpenSSL.BN_bn2bin(pub_key_x, pubkeyx)
            pubkeyx = pubkeyx.raw
            OpenSSL.BN_bn2bin(pub_key_y, pubkeyy)
            pubkeyy = pubkeyy.raw

            if len(pubkeyx) < secret_len:
                pubkeyx = pubkeyx.rjust(secret_len, b'\0')
            if len(pubkeyy) < secret_len:
                pubkeyy = pubkeyy.rjust(secret_len, b'\0')

            self.raw_check_key(privkey, pubkeyx, pubkeyy)

            return privkey, pubkeyx, pubkeyy

        finally:
            OpenSSL.EC_KEY_free(key)
            OpenSSL.BN_free(pub_key_x)
            OpenSSL.BN_free(pub_key_y)

    def get_ecdh_key(self, pubkey, kdf, format='binary'):
        """
        High level function. Compute public key with the local private key
        and returns a shared binary key
        """
        pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey, format)
        return self.raw_get_ecdh_key(pubkey_x, pubkey_y)

    def raw_get_ecdh_key(self, pubkey_x, pubkey_y, cofactor=0):
        try:
            ecdh_keybuffer = OpenSSL.malloc(0, 32)

            other_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
            if other_key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
            other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)

            other_group = OpenSSL.EC_KEY_get0_group(other_key)
            other_pub_key = OpenSSL.EC_POINT_new(other_group)
            if (other_pub_key == None):
                raise Exception("[OpenSSl] EC_POINT_new FAIL ... " + OpenSSL.get_error())

            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(other_group,
                                                            other_pub_key,
                                                            other_pub_key_x,
                                                            other_pub_key_y,
                                                            0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..." + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_set_public_key(other_key, other_pub_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_check_key(other_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error())

            own_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
            if own_key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())
            own_priv_key = OpenSSL.BN_bin2bn(
                self.privkey, len(self.privkey), 0)

            # Cofactor Multiplication (required for ECSVDP-DHC)
            if cofactor:
                OpenSSL.EC_KEY_set_flags(own_key, OpenSSL.EC_KEY_get_flags(own_key) | OpenSSL.EC_FLAG_COFACTOR_ECDH)

            if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error())

            OpenSSL.ECDH_set_method(own_key, OpenSSL.ECDH_OpenSSL())
            ecdh_keylen = OpenSSL.ECDH_compute_key(
                ecdh_keybuffer, 32, other_pub_key, own_key, 0)

            if ecdh_keylen != 32:
                raise Exception("[OpenSSL] ECDH keylen FAIL ... " + OpenSSL.get_error())

            return ecdh_keybuffer.raw

        finally:
            OpenSSL.EC_KEY_free(other_key)
            OpenSSL.BN_free(other_pub_key_x)
            OpenSSL.BN_free(other_pub_key_y)
            OpenSSL.EC_POINT_free(other_pub_key)
            OpenSSL.EC_KEY_free(own_key)
            OpenSSL.BN_free(own_priv_key)

    def check_key(self, privkey, pubkey):
        """
        Check the public key and the private key.
        The private key is optional (replace by None)
        """
        pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey)
        if privkey is None:
            raw_privkey = None
        else:
            raw_privkey = ECC._decode_privkey(privkey)
        return self.raw_check_key(raw_privkey, pubkey_x, pubkey_y)

    def raw_check_key(self, privkey, pubkey_x, pubkey_y):
        curve = self.curve
        try:
            key = OpenSSL.EC_KEY_new_by_curve_name(curve)
            if key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())
            if privkey is not None:
                priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0)

            pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
            pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)

            if privkey is not None:
                if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
                    raise Exception(
                        "[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error())

            group = OpenSSL.EC_KEY_get0_group(key)
            pub_key = OpenSSL.EC_POINT_new(group)

            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
                                                            pub_key_x,
                                                            pub_key_y,
                                                            0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_check_key(key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error())
            return 0

        finally:
            OpenSSL.EC_KEY_free(key)
            OpenSSL.BN_free(pub_key_x)
            OpenSSL.BN_free(pub_key_y)
            OpenSSL.EC_POINT_free(pub_key)
            if privkey is not None:
                OpenSSL.BN_free(priv_key)

    @staticmethod
    def Bignum_modulo_add(a, b, curve):
        try:
            if type(curve) == str:
                curve = OpenSSL.get_curve(curve)

            ctx = OpenSSL.BN_CTX_new()
            a = OpenSSL.BN_bin2bn(a, len(a), 0)
            b = OpenSSL.BN_bin2bn(b, len(b), 0)
            m = OpenSSL.BN_new()
            OpenSSL.EC_GROUP_get_order(OpenSSL.EC_GROUP_new_by_curve_name(curve), m, 0)
            r = OpenSSL.BN_new()

            OpenSSL.BN_mod_add(r, a, b, m, ctx)
            r_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(r))
            OpenSSL.BN_bn2bin(r, r_bin)
            return r_bin.raw
        finally:
            OpenSSL.BN_free(a)
            OpenSSL.BN_free(b)
            OpenSSL.BN_free(m)
            OpenSSL.BN_free(r)
            OpenSSL.BN_CTX_free(ctx)

    @staticmethod
    def Bignum_modulo_mul(a, b, curve):
        try:
            if type(curve) == str:
                curve = OpenSSL.get_curve(curve)
            ctx = OpenSSL.BN_CTX_new()
            a = OpenSSL.BN_bin2bn(a, len(a), 0)
            b = OpenSSL.BN_bin2bn(b, len(b), 0)
            m = OpenSSL.BN_new()
            OpenSSL.EC_GROUP_get_order(OpenSSL.EC_GROUP_new_by_curve_name(curve), m, 0)
            r = OpenSSL.BN_new()

            OpenSSL.BN_mod_mul(r, a, b, m, ctx)
            r_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(r))
            OpenSSL.BN_bn2bin(r, r_bin)
            return r_bin.raw
        finally:
            OpenSSL.BN_free(a)
            OpenSSL.BN_free(b)
            OpenSSL.BN_free(m)
            OpenSSL.BN_free(r)
            OpenSSL.BN_CTX_free(ctx)

    @staticmethod
    def point_add(curve, p1_x, p1_y, p2_x, p2_y):
        try:
            p1_x = OpenSSL.BN_bin2bn(p1_x, len(p1_x), 0)
            p1_y = OpenSSL.BN_bin2bn(p1_y, len(p1_y), 0)
            p2_x = OpenSSL.BN_bin2bn(p2_x, len(p2_x), 0)
            p2_y = OpenSSL.BN_bin2bn(p2_y, len(p2_y), 0)
            group = OpenSSL.EC_GROUP_new_by_curve_name(OpenSSL.get_curve(curve))
            if group == 0:
                raise Exception("[OpenSSL] EC_GROUP_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            r = OpenSSL.EC_POINT_new(group)
            a = OpenSSL.EC_POINT_new(group)
            b = OpenSSL.EC_POINT_new(group)
            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, a, p1_x, p1_y, 0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..." + OpenSSL.get_error())
            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, b, p2_x, p2_y, 0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..." + OpenSSL.get_error())

            OpenSSL.EC_POINT_add(group, r, a, b, 0)
            x = OpenSSL.BN_new()
            y = OpenSSL.BN_new()
            if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, r, x, y, 0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())
            x_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(x))
            y_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(y))
            OpenSSL.BN_bn2bin(x, x_bin)
            OpenSSL.BN_bn2bin(y, y_bin)
            return x_bin.raw, y_bin.raw

        finally:
        #    OpenSSL.EC_GROUP_free(group)
            OpenSSL.EC_POINT_free(r)
            OpenSSL.EC_POINT_free(a)
            OpenSSL.EC_POINT_free(b)
            OpenSSL.BN_free(p1_x)
            OpenSSL.BN_free(p1_y)
            OpenSSL.BN_free(p2_x)
            OpenSSL.BN_free(p2_y)
            OpenSSL.BN_free(x)
            OpenSSL.BN_free(y)

    @staticmethod
    def point_mul(curve, n, point_x, point_y):
        try:
            m = OpenSSL.BN_bin2bn(n, len(n), 0)

            point_x = OpenSSL.BN_bin2bn(point_x, len(point_x), 0)
            point_y = OpenSSL.BN_bin2bn(point_y, len(point_y), 0)

            group = OpenSSL.EC_GROUP_new_by_curve_name(OpenSSL.get_curve(curve))
            if group == 0:
                raise Exception("[OpenSSL] EC_GROUP_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            r = OpenSSL.EC_POINT_new(group)
            q = OpenSSL.EC_POINT_new(group)
            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, q, point_x, point_y, 0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..." + OpenSSL.get_error())

            OpenSSL.EC_POINT_mul(group, r, 0, q, m, 0)
            x = OpenSSL.BN_new()
            y = OpenSSL.BN_new()
            if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, r, x, y, 0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())
            x_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(x))
            y_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(y))
            OpenSSL.BN_bn2bin(x, x_bin)
            OpenSSL.BN_bn2bin(y, y_bin)
            return x_bin.raw, y_bin.raw

        finally:
        #    OpenSSL.EC_GROUP_free(group)
            OpenSSL.EC_POINT_free(r)
            OpenSSL.EC_POINT_free(q)
            OpenSSL.BN_free(point_x)
            OpenSSL.BN_free(point_y)
            OpenSSL.BN_free(m)
            OpenSSL.BN_free(x)
            OpenSSL.BN_free(y)

    @staticmethod
    def uncompress_ecpoint(curve, x, y_lsb):
        """
        Derives y coordinate of a compressed ec point using x and y_lsb
        """
        try:
            x = OpenSSL.BN_bin2bn(x, len(x), 0)
            y = OpenSSL.BN_new()

            group = OpenSSL.EC_GROUP_new_by_curve_name(OpenSSL.get_curve(curve))
            if group == 0:
                raise Exception("[OpenSSL] EC_GROUP_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            pub_key = OpenSSL.EC_POINT_new(group)
            if (OpenSSL.EC_POINT_set_compressed_coordinates_GFp(group, pub_key,
                                                                x, y_lsb, 0)) == 0:
                    raise Exception(
                        "[OpenSSL] EC_POINT_set_compressed_coordinates_GFp FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key,
                                                                x, y, 0)) == 0:
                    raise Exception(
                        "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())

            y_bin = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(y))
            OpenSSL.BN_bn2bin(y, y_bin)

            return y_bin.raw

        finally:
            OpenSSL.EC_GROUP_free(group)
            OpenSSL.EC_POINT_free(pub_key)
            OpenSSL.BN_free(x)
            OpenSSL.BN_free(y)

    def sign(self, inputb, der=1):
        """
        Sign the input with ECDSA method and returns the signature
        """
        try:
            size = len(inputb)
            buff = OpenSSL.malloc(inputb, size)
            digest = OpenSSL.malloc(0, 64)
            md_ctx = OpenSSL.EVP_MD_CTX_create()
            dgst_len = OpenSSL.pointer(OpenSSL.c_int(0))
            siglen = OpenSSL.pointer(OpenSSL.c_int(0))
            sig = OpenSSL.malloc(0, 151)

            key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
            if key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0)
            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)

            if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ... " + OpenSSL.get_error())

            group = OpenSSL.EC_KEY_get0_group(key)
            pub_key = OpenSSL.EC_POINT_new(group)

            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
                                                            pub_key_x,
                                                            pub_key_y,
                                                            0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())

            if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_check_key(key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error())

            OpenSSL.EVP_MD_CTX_init(md_ctx)
            if self.hash == sha224:
                OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha224(), None)
            if self.hash == sha256:
                OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha256(), None)

            if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0:
                raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ... " + OpenSSL.get_error())
            OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len)

            if der:
                OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key)
                if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig,
                                         siglen.contents, key)) != 1:
                    raise Exception("[OpenSSL] ECDSA_verify FAIL ... " + OpenSSL.get_error())
                return sig.raw[0:siglen.contents.value]
            else:
                ecdsa_sig = OpenSSL.ECDSA_do_sign(digest, dgst_len.contents, key)
                if (OpenSSL.ECDSA_do_verify(digest, dgst_len.contents, ecdsa_sig, key)) != 1:
                     raise Exception("[OpenSSL] ECDSA_verify FAIL ... " + OpenSSL.get_error())
                # ecdsa_sig = OpenSSL.d2i_ECDSA_SIG(None, OpenSSL.byref(OpenSSL.pointer(sig)), siglen.contents.value)
                sig = OpenSSL.cast(ecdsa_sig, OpenSSL.POINTER(OpenSSL.ECDSA_SIG))
                # print OpenSSL.BN_num_bytes(sig.contents.r), OpenSSL.BN_num_bytes(sig.contents.s)
                R = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(sig.contents.r))
                S = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(sig.contents.s))
                OpenSSL.BN_bn2bin(sig.contents.r, R)
                OpenSSL.BN_bn2bin(sig.contents.s, S)
                return R.raw, S.raw

        finally:
            OpenSSL.EC_KEY_free(key)
            OpenSSL.BN_free(pub_key_x)
            OpenSSL.BN_free(pub_key_y)
            OpenSSL.BN_free(priv_key)
            OpenSSL.EC_POINT_free(pub_key)
            OpenSSL.EVP_MD_CTX_destroy(md_ctx)

    def verify(self, sig, inputb=None, input_digest=None, der=1):
        """
        Verify the signature with the input and the local public key.
        Returns a boolean
        """
        try:
            key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)

            if key == 0:
                raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ... " + OpenSSL.get_error())

            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)
            group = OpenSSL.EC_KEY_get0_group(key)
            pub_key = OpenSSL.EC_POINT_new(group)

            if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
                                                            pub_key_x,
                                                            pub_key_y,
                                                            0)) == 0:
                raise Exception(
                    "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ... " + OpenSSL.get_error())
            if (OpenSSL.EC_KEY_check_key(key)) == 0:
                raise Exception("[OpenSSL] EC_KEY_check_key FAIL ... " + OpenSSL.get_error())

            if input_digest is None:
                binputb = OpenSSL.malloc(inputb, len(inputb))
                digest = OpenSSL.malloc(0, 64)
                dgst_len = OpenSSL.pointer(OpenSSL.c_int(0))
                md_ctx = OpenSSL.EVP_MD_CTX_create()
                OpenSSL.EVP_MD_CTX_init(md_ctx)
                if self.hash == sha224:
                    OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha224(), None)
                if self.hash == sha256:
                    OpenSSL.EVP_DigestInit_ex(md_ctx, OpenSSL.EVP_sha256(), None)

                if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0:
                    raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ... " + OpenSSL.get_error())

                OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len)
            else:
                digest = OpenSSL.malloc(input_digest, len(input_digest))
                dgst_len = OpenSSL.pointer(OpenSSL.c_int(len(input_digest)))

            if der:
                bsig = OpenSSL.malloc(sig, len(sig))
                ret = OpenSSL.ECDSA_verify(
                    0, digest, dgst_len.contents, bsig, len(sig), key)
            else:
                [R, S] = sig
                ecdsa_sig = OpenSSL.ECDSA_SIG()
                r = OpenSSL.BN_bin2bn(OpenSSL.malloc(R, len(R)), len(R), 0)
                s = OpenSSL.BN_bin2bn(OpenSSL.malloc(S, len(S)), len(S), 0)
                ecdsa_sig.r = OpenSSL.cast(r, OpenSSL.POINTER(OpenSSL.BignumType))
                ecdsa_sig.s = OpenSSL.cast(s, OpenSSL.POINTER(OpenSSL.BignumType))
                sig = OpenSSL.byref(ecdsa_sig)
                # bsig = OpenSSL.malloc(0, 151)
                # l = OpenSSL.i2d_ECDSA_SIG(sig, OpenSSL.byref(OpenSSL.pointer(bsig)))
                # print "bsig: ", l, bsig.raw[0:l]
                # ret = OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, bsig, l, key)
                ret = OpenSSL.ECDSA_do_verify(digest, dgst_len.contents, sig, key)

            if ret == -1:
                return False  # Fail to Check
            else:
                if ret == 0:
                    return False  # Bad signature !
                if ret == 1:
                    return True  # Good

            return False

        finally:
            OpenSSL.EC_KEY_free(key)
            OpenSSL.BN_free(pub_key_x)
            OpenSSL.BN_free(pub_key_y)
            OpenSSL.EC_POINT_free(pub_key)
            if not der:
                OpenSSL.BN_free(r)
                OpenSSL.BN_free(s)
            if input_digest is None:
                OpenSSL.EVP_MD_CTX_destroy(md_ctx)

    def encrypt(self, data, pubkey, ephemcurve=None, ciphername='aes-256-cbc'):
        """
        Encrypt data with ECIES method using the public key of the recipient.
        """
        curve = OpenSSL.get_curve_by_id(self.curve)
        pubkey_x, pubkey_y = ECC._decode_pubkey(pubkey)
        return ECC.raw_encrypt(data, pubkey_x, pubkey_y, curve=curve,
                               ephemcurve=ephemcurve, ciphername=ciphername, hash=self.hash)

    @staticmethod
    def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1',
                    ephemcurve=None, ciphername='aes-256-cbc', hash=sha512):
        if type(hash) == str:
            hash = globals()[hash]

        if ephemcurve is None:
            ephemcurve = curve
        # print 'Ephem curve'
        ephem = ECC(curve=ephemcurve, hash=hash)

        pubkey = ephem.get_pubkey()
        if ciphername == 'stream-cipher':
            # Received Data is a Octet String
            l = len(data)/2
            #print 'data: ', data, len(data)
            key = ECC.kdf2(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y, cofactor=1), l + 32, hash)
            key_e, key_m = key[:l], key[l:]
            #print 'key_e ', key_e, ', key_m ', key_mt
            ciphertext = unhexlify(format(int(data, 16) ^ int(hexlify(key_e), 16), '0'+str(len(data))+'x'))
            #print ciphertext
            mac = hmac_sha256(key_m, ciphertext, 160)
            return pubkey + ciphertext + mac
        else:
            key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
            key_e, key_m = key[:32], key[32:]
            iv = Cipher.gen_IV(ciphername)
            ctx = Cipher(key_e, iv, 1, ciphername)
            ciphertext = iv + pubkey + ctx.ciphering(data)
            mac = hmac_sha256(key_m, ciphertext)
            return ciphertext + mac

    def decrypt(self, data, ciphername='aes-256-cbc'):
        """
        Decrypt data with ECIES method using the local private key
        """
        if ciphername != 'stream-cipher':
            blocksize = OpenSSL.get_cipher(ciphername).get_blocksize()
            iv = data[:blocksize]
            i = blocksize
            coord_len = len(self.pubkey_x) * 2 + 1
            pubkey_x, pubkey_y = ECC._decode_pubkey(data[i:i + coord_len])
            i += coord_len
            ciphertext = data[i:len(data) - 32]
            i = len(data) - 32
            mac = data[i:]
            key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
            key_e, key_m = key[:32], key[32:]
            if not equals(hmac_sha256(key_m, data[:i]), mac):
                raise RuntimeError("Fail to verify data")
            ctx = Cipher(key_e, iv, 0, ciphername)
            return ctx.ciphering(ciphertext)
        else:
            i = 0
            coord_len = len(self.pubkey_x) * 2 + 1
            pubkey_x, pubkey_y = ECC._decode_pubkey(data[i:i + coord_len])
            i += coord_len
            ciphertext = data[i:len(data) - 20]
            i = len(data) - 20
            mac = data[i:]
            l = len(ciphertext)
            key = ECC.kdf2(self.raw_get_ecdh_key(pubkey_x, pubkey_y, cofactor=1), l + 32, self.hash)
            key_e, key_m = key[:l], key[l:]
            #print 'key_e ', key_e, ', key_m ', key_m
            #print 'ciphertext ', ciphertext
            if not equals(hmac_sha256(key_m, ciphertext, 160), mac):
                raise RuntimeError("Fail to verify data")

            return unhexlify(format(int(hexlify(ciphertext), 16) ^ int(hexlify(key_e), 16), '0'+str(2*len(ciphertext))+'x'))

    @staticmethod
    def kdf2(z, olen, hash):
        zb= bin(int(hexlify(z), 16))[2:].zfill(256)
        mb = ''
        zbits = len(zb)
        obits = 8*olen
        hbits = 256  # can change based on hash
        cthreshold = ceil(obits/float(hbits))
        counter = 1
        while counter <= cthreshold:
            cb = bin(counter)[2:].zfill(32)
            zcb = unhexlify(format(int(zb+cb, 2), '072x'))  # unhexlify('%x' % int(zb+cb, 2))
            h = hash(zcb).digest()
            hb = bin(int(hexlify(h), 16))[2:].zfill(256)
            mb += hb
            counter += 1
        #print 'mb len ', len(mb)
        kb = mb[:obits]
        k = unhexlify(format(int(kb, 2), '0'+str(obits/4)+'x'))
        # print 'k: ', k, len(k)
        return k


import tensorflow as tf
import numpy as np

# INIT WEIGHT
def init_weight(shape):
    init_random_dist  = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(init_random_dist)

# INIT BIAIS
def init_biais(shape):
    init_const_biais = tf.constant(0.1,shape=shape)
    return tf.Variable(init_const_biais)

# 2D convolution
def conv2D(x, W):
    #x --> [batch, h, w, c]
    #W --> [filter h, filter w, in channels, out channels]
    return tf.nn.conv2d(x,W, strides=[1,1,1,1],padding='SAME')

# POOLING
def max_pool_2by2(x):
    return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1],padding='SAME')

# Convulution layer
def convolution_layer(x, shape):
    W = init_weight(shape)
    b = init_biais([shape[3]])
    return tf.nn.relu(conv2D(x,W) + b)

# fully connected
def fully_layer(x, size):
    input_size = int(x.get_shape()[1])
    W = init_weight([input_size,size])
    b = init_biais([size])
    return tf.matmul(x,W) + b

g = tf.Graph()
with g.as_default():
    x = tf.placeholder(tf.float32, shape=[None, 784])
    y_true = tf.placeholder(tf.float32, shape=[None,10])

    image = tf.reshape(x, [-1,28,28,1])

    conv1 = convolution_layer(image,shape=[5,5, 1, 32])
    conv1_pool = max_pool_2by2(conv1)

    conv2 = convolution_layer(conv1_pool, shape=[5,5,32,64])
    conv2_pool = max_pool_2by2(conv2)
    conv2_flat = tf.reshape(conv2_pool, shape=[-1, 7*7*64])
    fully1 = fully_layer(conv2_flat, size = 1024)

    hold_prob= tf.placeholder(tf.float32)
    fully1_drop = tf.nn.dropout(fully1, keep_prob=hold_prob)

    pred = fully_layer(fully1_drop,10)

    loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_true, logits=pred))

    optimizer = tf.train.AdamOptimizer(learning_rate=0.001)
    train =  optimizer.minimize(loss_function)

    matches = tf.equal(tf.arg_max(pred,1), tf.arg_max(y_true,1))
    precision = tf.reduce_mean(tf.cast(matches,tf.float32))
    saver = tf.train.Saver()

def predict_cnn(x_im):
    with g.as_default():
        with tf.Session() as sess:
            # Save the variables to disk.
            saver.restore(sess, "./model.ckpt")
            sortie = sess.run(pred, feed_dict={x:x_im, hold_prob:1})
            predit = np.argmax(sortie)
    return predit


import argparse
import glob
import os
import shutil
import sys

import cv2
import pandas as pd

from progress.bar import IncrementalBar

from .fcn import img_prep
from .fcn import face_detect
from .fcn import annotate
from .fcn import analyze

CURRENT_PATH = os.getcwd()
mod_path = os.path.dirname(os.path.abspath(__file__))

def create_parser_pfla():
    parser = argparse.ArgumentParser(
        prog='pfla',
        description='Python facial landmark analysis',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    default_test_males = os.path.join(mod_path, 'data', 'test_males')
    parser.add_argument('-g1', '--group1', required=False,
                        help='Path to group 1 image directory',
                        default=default_test_males)
    default_test_females = os.path.join(mod_path, 'data', 'test_females')
    parser.add_argument('-g2', '--group2', required=False,
                        help='Path to group 2 image directory',
                        default=default_test_females)
    return parser

def img_processing(img_id, list_dir):
    """preparation, face detection and landmarking"""

    # begin by creating image object and preparing for processing
    img = img_prep.RawImage(
        os.path.join(list_dir[0], "{}.jpg".format(img_id)),
        os.path.join(list_dir[1], "{}.jpg".format(img_id)),
        img_id
    )
    img.prepare()

    # detect faces in image through Haar Cascade
    fdetector = face_detect.FaceDectector(
        os.path.join(list_dir[1], "{}.jpg".format(img_id)),
        (100, 100),
        (500, 500),
        img_id,
        list_dir[3]
    )
    img_faces = fdetector.run_cascade()
    err = fdetector.to_matrix(img_faces)

    # annotate the detected faces
    fannotator = annotate.FaceAnnotator(
        img_id,
        fdetector.matrix_path,
        list_dir[0],
        list_dir[2]
    )
    mat = fannotator.run_annotator()

    return (mat, err)

def group_process(group, img_dir, list_dir):
    """processing of a group of images"""
    input_dir = img_dir
    img_no = 0
    list_mat = []
    ib = IncrementalBar("Processing Images", max=len(glob.glob(img_dir)))
    errors = []

    for raw_img in sorted(glob.glob(input_dir)):

        # save images to be analyzed in the img_raw directory
        img_id = os.path.join(group, "{}".format(img_no))
        img = cv2.imread(raw_img)
        original_path = os.path.join(
            list_dir[0], "{}.jpg".format(img_id)
        )
        cv2.imwrite(original_path, img)

        ip_ret = img_processing(img_id, list_dir)
        img_no += 1
        mat2 = ip_ret[0]
        if len(ip_ret[1]) > 1:
            errors.append(ip_ret[1])

        list_mat.append(list(mat2.values.flatten()))
        ib.next()

    all_mat = pd.DataFrame(list_mat)
    p = os.path.join(list_dir[3], "ldmks")
    if not os.path.exists(p):
        os.makedirs(p)
    all_mat.to_csv(os.path.join(p, "{}_landmark_matrix.csv".format(group)))
    if len(errors) != 0:
        print("\nWARNING: {} processing completed with errors:".format(group))
        for st in errors:
            print(st)
    else:
        print("\n {} processing completed without errors".format(group))
    ib.finish()

def pfla():
    with open(os.path.join(mod_path, 'art.txt'), 'r') as greet:
        shutil.copyfileobj(greet, sys.stdout)
    parser = create_parser_pfla()
    args = parser.parse_args()

    g1_img_dir = os.path.abspath(os.path.join(args.group1, "*.jpg"))
    g2_img_dir = os.path.abspath(os.path.join(args.group2, "*.jpg"))

    # clean the directories
    img_raw_d = os.path.join(CURRENT_PATH, "img", "img_raw")
    img_prep_d = os.path.join(CURRENT_PATH, "img", "img_prep")
    img_proc_d = os.path.join(CURRENT_PATH, "img", "img_proc")
    data_d = os.path.join(CURRENT_PATH, "data", "faces")
    list_dir = [img_raw_d, img_prep_d, img_proc_d, data_d]
    for dir_ in list_dir:
        shutil.rmtree(dir_, ignore_errors=True)

    groups = ["g1", "g2"]
    for group in groups:
        for dir_ in list_dir:
            d = os.path.join(dir_, group)
            os.makedirs(d)

    group_process('g1', g1_img_dir, list_dir)
    group_process('g2', g2_img_dir, list_dir)
    analyze.main_method(os.path.join(list_dir[3], 'ldmks'))


import os
import cv2
import argparse
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile
from tensorflow.python.framework import graph_util

from architectures.model import model
from architectures.common import SAVE_VARIABLES
import utils
from images.caffe_classes import class_names

parser = argparse.ArgumentParser()
parser.add_argument('--checkpoint_dir', type=str,
                    default='experiments/googlenet/checkpoints')
parser.add_argument('--save_pb_dir', type=str, default='experiments/googlenet/pb')
parser.add_argument('--save_model_filename', type=str, help='Model filename, e.g. epoch-3_2')

args = parser.parse_args()

save_model_filename = args.save_model_filename
checkpoint_path = "{}/{}".format(args.checkpoint_dir, save_model_filename)
save_pb_dir = args.save_pb_dir

os.makedirs(save_pb_dir, exist_ok=True)

# -------------- Prepare images --------------------------

# mean of imagenet dataset in BGR
imagenet_mean = np.array([104., 117., 124.], dtype=np.float32)

image_dir = 'images'

image_files = []
for f in os.listdir(image_dir):
    if f.lower().endswith('.jpeg'):
        image_files.append(os.path.join(image_dir, f))

images = []
for f in image_files:
    img = cv2.imread(f)
    img = cv2.resize(img.astype(np.float32), (224, 224))
    img -= imagenet_mean

    images.append(img)

images = np.array(images)
print("images.shape =", images.shape)

# ---------- Initialize Googlenet -------------------

images_ph = tf.placeholder(tf.float32, shape=(None,) + (224, 224, 3), name='input')
labels_ph = tf.placeholder(tf.int32, shape=(None), name='label')

# is_training always False
is_training_ph = tf.constant(False, dtype=tf.bool, name='is_training')

# epoch number
epoch_number = tf.get_variable('epoch_number', [], dtype=tf.int32, initializer=tf.constant_initializer(0),
                               trainable=False, collections=[tf.GraphKeys.GLOBAL_VARIABLES, SAVE_VARIABLES])
global_step = tf.get_variable('global_step', [], dtype=tf.int32, initializer=tf.constant_initializer(0),
                              trainable=False, collections=[tf.GraphKeys.GLOBAL_VARIABLES, SAVE_VARIABLES])

# Weight Decay policy
wd = utils.get_policy('piecewise_linear', '30, 0.0005, 0.0')

# Learning rate decay policy (if needed)
lr = utils.get_policy('piecewise_linear', '19, 30, 44, 53, 0.01, 0.005, 0.001, 0.0005, 0.0001')

# Create an optimizer that performs gradient descent.
optimizer = utils.get_optimizer('Adam', lr)

dnn_model = model(images_ph, labels_ph, utils.loss, optimizer, wd,
                  architecture='googlenet', num_classes=1000,
                  is_training=is_training_ph, transfer_mode=[0],
                  num_gpus=0, max_to_keep=12)

# convert the model in inference mode
with tf.device('/cpu:0'):
    logits = dnn_model.inference()

# Build an initialization operation to run below.
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())

saver = tf.train.Saver(tf.get_collection(SAVE_VARIABLES))

with tf.Session() as sess:
    sess.run(init)

    saver.restore(sess, checkpoint_path)

    result_logits = sess.run(logits, feed_dict={images_ph: images})

    class_inds = np.argmax(result_logits, axis=-1)

    for class_i in class_inds:
        print(class_names[class_i])

    # dump .pb file
    print("graph def size:", sess.graph_def.ByteSize())
    with gfile.GFile("{}/{}.pb".format(save_pb_dir, save_model_filename), 'wb') as f:
        f.write(sess.graph_def.SerializeToString())
    # convert graph to constants
    output_graph_def = graph_util.convert_variables_to_constants(
      sess,
      sess.graph_def,
      ['output/xw_plus_b'])
    with gfile.GFile("{}/{}_frozen.pb".format(save_pb_dir, save_model_filename), 'wb') as f:
        f.write(output_graph_def.SerializeToString())


import math
import random

from livewires import games, color

games.init(screen_width=640, screen_height=480, fps=50)

class Wrapper(games.Sprite):
    def update(self):
        if self.top > games.screen.height:
            self.bottom = 0
        if self.bottom < 0:
            self.top = games.screen.height
        if self.left > games.screen.width:
            self.right = 0
        if self.right < 0:
            self.left = games.screen.width

    def die(self):
        self.destroy()

class Collider(Wrapper):
    def update(self):
        super(Collider, self).update()
        if self.overlapping_sprites:
            for sprite in self.overlapping_sprites:
                sprite.die()
            self.die()

    def die(self):
        new_explosion = Explosion(self.x, self.y)
        games.screen.add(new_explosion)
        self.destroy()

class Asteroid(Wrapper):
    SMALL = 1
    MEDIUM = 2
    LARGE = 3
    images = {SMALL: games.load_image('asteroid_small.bmp'),
              MEDIUM: games.load_image('asteroid_med.bmp'),
              LARGE: games.load_image('asteroid_big.bmp')}
    SPEED = 2
    SPAWN = 2
    POINTS = 30
    total = 0

    def __init__(self, game, x, y, size):
        super(Asteroid, self).__init__(
            image=Asteroid.images[size],
            x=x,
            y=y,
            dx=random.choice([-1, 1]) * Asteroid.SPEED * random.random() / size,
            dy=random.choice([-1, 1]) * Asteroid.SPEED * random.random() / size)
        self.size = size
        self.game = game
        Asteroid.total += 1

    def die(self):
        Asteroid.total -= 1
        self.game.score.value += Asteroid.POINTS // self.size
        self.game.score.right = games.screen.width - 10

        if self.size != Asteroid.SMALL:
            for i in range(Asteroid.SPAWN):
                new_asteroid = Asteroid(game=self.game, x=self.x, y=self.y, size=self.size - 1)
                games.screen.add(new_asteroid)
        super(Asteroid, self).die()
        if Asteroid.total == 0:
            self.game.advance()

class Ship(Collider):
    image = games.load_image('ship.bmp')
    sound = games.load_sound('thrust.wav')
    ROTATION_SPEED = 3
    VELOCITY_STEP = .05
    MISSILE_DELAY = 25
    VELOCITY_MAX = 3

    def __init__(self, game, x, y):
        super(Ship, self).__init__(image=Ship.image, x=x, y=y)
        self.missile_wait = 0
        self.game = game

    def update(self):
        super(Ship, self).update()

        self.dx = min(max(self.dx, -Ship.VELOCITY_MAX), Ship.VELOCITY_MAX)
        self.dy = min(max(self.dy, -Ship.VELOCITY_MAX), Ship.VELOCITY_MAX)

        if self.missile_wait > 0:
            self.missile_wait -= 1

        if games.keyboard.is_pressed(games.K_w):
            Ship.sound.play()
            self.dy -= Ship.VELOCITY_STEP
        if games.keyboard.is_pressed(games.K_s):
            Ship.sound.play()
            self.dy += Ship.VELOCITY_STEP
        if games.keyboard.is_pressed(games.K_d):
            Ship.sound.play()
            self.dx += Ship.VELOCITY_STEP
        if games.keyboard.is_pressed(games.K_a):
            Ship.sound.play()
            self.dx -= Ship.VELOCITY_STEP
        if games.keyboard.is_pressed(games.K_SPACE) and self.missile_wait == 0:
            new_missile = Missile(self.x, self.y, self.angle, self.dx, self.dy)
            games.screen.add(new_missile)
            self.missile_wait = Ship.MISSILE_DELAY

        if self.dy < 0:
            tan = -self.dx / self.dy
            angle = math.atan(tan)
            self.angle = angle * 180 / math.pi
        elif self.dy > 0:
            tan = -self.dx / self.dy
            angle = math.atan(tan)
            self.angle = angle * 180 / math.pi + 180
        elif self.dx > 0:
            self.angle = 90
        elif self.dx < 0:
            self.angle = 270

        if self.overlapping_sprites:
            for sprite in self.overlapping_sprites:
                sprite.die()
            self.die()

    def die(self):
        super(Ship, self).die()
        self.game.end()

class Missile(Collider):
    image = games.load_image('missile.bmp')
    sound = games.load_sound('missile.wav')
    BUFFER = 45
    VELOCITY_FACTOR = 7
    LIFETIME = 40

    def __init__(self, ship_x, ship_y, ship_angle, ship_dx, ship_dy):
        Missile.sound.play()
        angle = ship_angle * math.pi / 180
        buffer_x = Missile.BUFFER * math.sin(angle)
        buffer_y = Missile.BUFFER * -math.cos(angle)
        x = ship_x + buffer_x
        y = ship_y + buffer_y
        dx = ship_dx + Missile.VELOCITY_FACTOR * math.sin(angle)
        dy = ship_dy + Missile.VELOCITY_FACTOR * -math.cos(angle)
        super(Missile, self).__init__(image=Missile.image,
                                      x=x, y=y,
                                      dx=dx, dy=dy)
        self.lifetime = Missile.LIFETIME

    def update(self):
        super(Missile, self).update()

        self.lifetime -= 1
        if self.lifetime == 0:
            self.destroy()

        if self.overlapping_sprites:
            for sprite in self.overlapping_sprites:
                sprite.die()
            self.die()

class Explosion(games.Animation):
    sound = games.load_sound('explosion.wav')
    images = ['explosion1.bmp',
              'explosion2.bmp',
              'explosion3.bmp',
              'explosion4.bmp',
              'explosion5.bmp',
              'explosion6.bmp',
              'explosion7.bmp',
              'explosion8.bmp',
              'explosion9.bmp']

    def __init__(self, x, y):
        super(Explosion, self).__init__(images=Explosion.images,
                                        x=x, y=y,
                                        repeat_interval=5,
                                        n_repeats=1,
                                        is_collideable=False)
        Explosion.sound.play()

class Game:
    def __init__(self):
        self.level = 0
        self.sound = games.load_sound('level.wav')

        self.score = games.Text(value=0,
                                size=30,
                                color=color.white,
                                top=5,
                                right=games.screen.width - 10,
                                is_collideable=False)
        games.screen.add(self.score)

        self.ship = Ship(game=self,
                         x=games.screen.width / 2,
                         y=games.screen.height / 2)
        games.screen.add(self.ship)

    def play(self):
        games.music.load('theme.mid')
        games.music.play(-1)
        earth_image = games.load_image('earth.jpg', transparent=False)
        games.screen.background = earth_image
        self.advance()
        games.screen.mainloop()

    def advance(self):
        self.level += 1
        BUFFER = 150

        for i in range(self.level):
            x = self.ship.x
            y = self.ship.y
            while (self.ship.x - x) ** 2 + (self.ship.y - y) ** 2 < BUFFER ** 2:
                x = random.randrange(games.screen.width)
                y = random.randrange(games.screen.height)
            new_asteroid = Asteroid(game=self,
                                    x=x, y=y,
                                    size=Asteroid.LARGE)
            games.screen.add(new_asteroid)

        level_message = games.Message(value='Level' + str(self.level),
                                      size=40,
                                      color=color.yellow,
                                      x=games.screen.width / 2,
                                      y=games.screen.height / 10,
                                      lifetime=3 * games.screen.fps,
                                      is_collideable=False)
        games.screen.add(level_message)
        if self.level > 1:
            self.sound.play()

    def end(self):
        end_message = games.Message(value='Game Over',
                                    size=100,
                                    color=color.pink,
                                    x=games.screen.width / 2,
                                    y=games.screen.height / 2,
                                    lifetime=100 * games.screen.fps,
                                    after_death=games.screen.quit,
                                    is_collideable=False)
        games.screen.add(end_message)

def main():
    astrocrash = Game()
    astrocrash.play()

if __name__ == '__main__':
    main()


import time
from collections import deque
def DFS(graph, start, limit):
    stack = deque([start])
    pc = 0
    visited = set()
    visited.add(str(stack))
    while stack:
        current = stack.pop()
        y, x = current
        if y + x == 2 * limit - 2:
            pc += 1
            continue

        w = graph[y][x]

        cns = []
        if limit > y + w and (str(list(stack)+[current,(y+w,x)]) not in visited):
            cns.append((y+w, x))
        elif limit > x + w and (str(list(stack)+[current,(y,x+w)]) not in visited):
            cns.append((y, x+w))

        if not cns:
            continue

        cn = cns.pop(0)
        stack.append(current)
        stack.append(cn)
        visited.add(str(stack))

    return pc

N = int(input())
M = []
for _ in range(N):
    #M.append([int(c) for c in input().split()])
    M.append([1 for _ in range(N)])

t0 = time.clock()
result = DFS(M, (0, 0), N)
t1 = time.clock()
print(result)
print("time consumed", t1-t0)
print("Time / N**2: ", (t1-t0) / N**2)

'''
이 문제를 paraphrasing하면 마지막 종점 노드의 간선의 개수가 몇개인지 묻는 문제
'''


# implement blind regression model to estimate blank entries on the matrix
import math
from heapq import nsmallest
import pickle
import sys
import datetime
import time
import numpy as np

class BlindRegression():
	def __init__(self, data_matrix):
		self._data_matrix = data_matrix
		self._dimension = self._data_matrix.shape
		# calculate "N1(u)" and "N2(i)"
		print(str(self._dimension))
		self._pos_col_entries_set_list = []
		outfile=open('matrix.txt','w')
		for list in data_matrix:
			i=0
			for col in list:
				if i>0:
					outfile.write("\t")
				outfile.write("%s" % col)
				i+=1
			outfile.write("\n")

		outfile.close()
		for row in self._data_matrix:
			self._pos_col_entries_set_list.append(set([i for i in range(len(row)) if row[i] > 0]))

		self._pos_row_entries_set_list = []
		for col in self._data_matrix.T:
			self._pos_row_entries_set_list.append(set([i for i in range(len(col)) if col[i] > 0]))
			#print("self._pos_row_entries_set_list",str(self._pos_row_entries_set_list))

	def estimate_gaussian(self, u, i, beta=2, lam=1, num_points=20):

		if beta < 2:
			print('ERROR: Invalid beta')
			return None

		# calculate "N1(u,v)"
		n1uv = []
		for v in range(self._dimension[0]):
			n1uv.append(self._pos_col_entries_set_list[u].intersection(self._pos_col_entries_set_list[v]))

		# calculate "N2(i,j)"
		n2ij = []
		for j in range(self._dimension[1]):
			n2ij.append(self._pos_row_entries_set_list[i].intersection(self._pos_row_entries_set_list[j]))

		beta_u = set([v for v in self._pos_row_entries_set_list[i] if v != u and len(n1uv[v]) >= beta])
		beta_i = set([j for j in self._pos_col_entries_set_list[u] if j != i and len(n2ij[j]) >= beta])

		beta_ui = sorted([(v, j) for v in beta_u for j in beta_i if self._data_matrix[v][j] > 0], key=lambda x:x[1])

		if len(beta_ui) == 0:
			return None

		if len(beta_ui) > num_points:
			beta_ui = nsmallest(num_points, beta_ui, key=lambda x: abs(x[1]-i))

		print(beta_ui)

		estimate = 0
		total_weight = 0
		for (v, j) in beta_ui:
			s_uv_square = self._suv_square(u, v, n1uv[v])
			s_ij_square = self._sij_square(i, j, n2ij[j])
			w_vj = math.exp(-lam*min(s_uv_square, s_ij_square))
			estimate += w_vj*(self._data_matrix[u][j] + self._data_matrix[v][i] - self._data_matrix[v][j])
			total_weight += w_vj

		return estimate / total_weight

	def estimate_gaussian_cache(self, u, i_vec, beta=2, lam=1, num_points=20):

		if beta < 2:
			print('ERROR: Invalid beta')
			return None

		estimate_result = []
		print('i_vec', i_vec)
		sys.stdout.flush()
		# calculate "N1(u,v)"
		n1uv = []
		for v in range(self._dimension[0]):
			n1uv.append(self._pos_col_entries_set_list[u].intersection(self._pos_col_entries_set_list[v]))

		s_uv_square_cache = {}

		for i in i_vec:
			print(i)
			# calculate "N2(i,j)"
			n2ij = []
			for j in range(self._dimension[1]):
				n2ij.append(self._pos_row_entries_set_list[i].intersection(self._pos_row_entries_set_list[j]))

			beta_u = set([v for v in self._pos_row_entries_set_list[i] if v != u and len(n1uv[v]) >= beta])
			beta_i = set([j for j in self._pos_col_entries_set_list[u] if j != i and len(n2ij[j]) >= beta])

			beta_ui = sorted([(v, j) for v in beta_u for j in beta_i if self._data_matrix[v][j] > 0], key=lambda x: x[1])

			if len(beta_ui) == 0:
				estimate_result.append([i, None])
				continue

			if len(beta_ui) > num_points:
				beta_ui = nsmallest(num_points, beta_ui, key=lambda x: abs(x[1] - i))

			estimate = 0
			total_weight = 0
			for (v, j) in beta_ui:
				if v in s_uv_square_cache:
					s_uv_square = s_uv_square_cache[v]
				else:
					s_uv_square = self._suv_square(u, v, n1uv[v])
					s_uv_square_cache[v] = s_uv_square

				s_ij_square = self._sij_square(i, j, n2ij[j])

				w_vj = math.exp(-lam * min(s_uv_square, s_ij_square))
				estimate += w_vj * (self._data_matrix[u][j] + self._data_matrix[v][i] - self._data_matrix[v][j])
				total_weight += w_vj

			estimate_result.append((i, estimate/total_weight))

		return estimate_result

	def estimate_gaussian_cache_2D(self, u_vec, i_vec, beta=2, lam=1, num_points=20):
		if beta < 2:
			print('ERROR: Invalid beta')
			return None

		s_uv2_cache = {}
		s_ij2_cache = {}
		estimate_result = {}

		counter = 0
		for u in u_vec:
			counter += 1
			if counter % 100 == 0:
				current_ts = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
				print(counter, '/', len(u_vec), 'done', current_ts)
			estimate_result[u] = []
			for i in i_vec:
				# calculate "N1(u,v)"
				n1uv = []
				for v in range(self._dimension[0]):
					n1uv.append(self._pos_col_entries_set_list[u].intersection(self._pos_col_entries_set_list[v]))
				# calculate "N2(i,j)"
				n2ij = []
				for j in range(self._dimension[1]):
					n2ij.append(self._pos_row_entries_set_list[i].intersection(self._pos_row_entries_set_list[j]))

				beta_u = set([v for v in self._pos_row_entries_set_list[i] if v != u and len(n1uv[v]) >= beta])
				beta_i = set([j for j in self._pos_col_entries_set_list[u] if j != i and len(n2ij[j]) >= beta])

				beta_ui = sorted([(v, j) for v in beta_u for j in beta_i if self._data_matrix[v][j] > 0], key=lambda x: x[1])

				if len(beta_ui) == 0:
					estimate_result[u].append([i, None])
					continue

				if len(beta_ui) > num_points:
					beta_ui = nsmallest(num_points, beta_ui, key=lambda x: abs(x[1] - i))

				estimate = 0
				total_weight = 0
				for (v, j) in beta_ui:
					if (u, v) in s_uv2_cache:
						s_uv_square = s_uv2_cache[(u, v)]
					elif (v, u) in s_uv2_cache:
						s_uv_square = s_uv2_cache[(v, u)]
					else:
						s_uv_square = self._suv_square(u, v, n1uv[v])
						s_uv2_cache[(u, v)] = s_uv_square

					if (i, j) in s_ij2_cache:
						s_ij_square = s_ij2_cache[(i, j)]
					elif (j, i) in s_ij2_cache:
						s_ij_square = s_ij2_cache[(j, i)]
					else:
						s_ij_square = self._sij_square(i, j, n2ij[j])
						s_ij2_cache[(i, j)] = s_ij_square

					w_vj = math.exp(-lam * min(s_uv_square, s_ij_square))
					estimate += w_vj * (self._data_matrix[u][j] + self._data_matrix[v][i] - self._data_matrix[v][j])
					total_weight += w_vj

				estimate_result[u].append((i, estimate / total_weight))

		return estimate_result

	def estimate_gaussian_cache_2D_all(self, beta=2, lam=1, num_points=20):
		if beta < 2:
			print('ERROR: Invalid beta')
			return None

		s_uv2_cache = {}
		s_ij2_cache = {}
		estimate_result = -1*np.ones(shape=self._dimension)

		counter = 0
		print("Dimensions:",str(self._dimension[0]),str(self._dimension[1]))
		for row in range(self._dimension[0]):
			print("At row",row)
			counter += 1
			if counter % 10 == 0:
				current_ts = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
				print(counter, '/', self._dimension[0], 'done', current_ts)
			for col in range(self._dimension[1]):
				print("At col",col)
				# calculate "N1(u,v)"
				intersect_col_entries = []
				for v in range(self._dimension[0]):
					#print("Evaluating at row",v)
					intersect_col_entries.append(self._pos_col_entries_set_list[row].intersection(self._pos_col_entries_set_list[v]))
#					print("nonzer _entries is ",str(self._pos_col_entries_set_list[v]))
					#print("intersect_col_entries is ",str(intersect_col_entries[v]))
				# calculate "N2(i,j)"
				intersect_row_entries = []
				for j in range(self._dimension[1]):
					#print("Evaluating at col",j)
					intersect_row_entries.append(self._pos_row_entries_set_list[col].intersection(self._pos_row_entries_set_list[j]))
					#print("intersect_row_entries is ",str(sorted(intersect_row_entries[j])))

				best_row_neighbors = set([other_row for other_row in self._pos_row_entries_set_list[col] if other_row != row and len(intersect_col_entries[other_row]) >= beta])
				#print("beta",beta,"Beta_row",str(sorted(best_row_neighbors)))
				best_col_neighbors = set([other_col for other_col in self._pos_col_entries_set_list[row] if other_col != col and len(intersect_row_entries[other_col]) >= beta])
				#print("beta",beta,"Beta_col",str(sorted(best_col_neighbors)))
				#print("Beta_col",str(best_col_neighbors))

				best_neighbor_tuples = sorted([(v, j) for v in best_row_neighbors for j in best_col_neighbors if self._data_matrix[v][j] > 0], key=lambda x: x[1])

				#print("best neighbor tuples",str(best_neighbor_tuples))
				print("best_neighbor_tuples length",str(len(best_neighbor_tuples)))
				if len(best_neighbor_tuples) == 0:
					continue

				if len(best_neighbor_tuples) > num_points:
					best_neighbor_tuples = nsmallest(num_points, best_neighbor_tuples, key=lambda x: abs(x[1] - col))
				print("num_points",num_points,"length",str(len(best_neighbor_tuples)),"best_neighbor_tuples",str(best_neighbor_tuples))

				estimate = 0
				total_weight = 0
				print("Working on cache")
				for (v, j) in best_neighbor_tuples:
					if (row, v) in s_uv2_cache:
						s_uv_square = s_uv2_cache[(row, v)]
					elif (v, row) in s_uv2_cache:
						s_uv_square = s_uv2_cache[(v, row)]
					else:
						s_uv_square = self._suv_square(row, v, intersect_col_entries[v])
						s_uv2_cache[(row, v)] = s_uv_square

					if (col, j) in s_ij2_cache:
						s_ij_square = s_ij2_cache[(col, j)]
					elif (j, col) in s_ij2_cache:
						s_ij_square = s_ij2_cache[(j, col)]
					else:
						s_ij_square = self._sij_square(col, j, intersect_row_entries[j])
						s_ij2_cache[(col, j)] = s_ij_square

					w_vj = math.exp(-lam * min(s_uv_square, s_ij_square))
					estimate += w_vj * (self._data_matrix[row][j] + self._data_matrix[v][col] - self._data_matrix[v][j])
					total_weight += w_vj

				estimate_result[row][col] = estimate / total_weight
				print("Worked on cache")

		return estimate_result

	def _suv_square(self, u, v, uv_set):

		result = 0

		for i in uv_set:
			for j in uv_set:
				diff = (self._data_matrix[u][i] - self._data_matrix[v][i]) - (self._data_matrix[u][j] - self._data_matrix[v][j])
				result += math.pow(diff, 2)

		return result / (2*len(uv_set)*(len(uv_set)-1))

	def _sij_square(self, i, j, ij_set):

		result = 0

		for u in ij_set:
			for v in ij_set:
				diff = (self._data_matrix[u][i] - self._data_matrix[u][j]) - (self._data_matrix[v][i] - self._data_matrix[v][j])
				result += math.pow(diff, 2)

		return result / (2 * len(ij_set) * (len(ij_set) - 1))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov  8 14:41:52 2017

@author: Ola
"""

from bs4 import BeautifulSoup as Soup
infile = open("result_0.xml","r")
contents = infile.read()
soup = BeautifulSoup(contents,'xml')
#titles = soup.find_all('title')

import xml.etree.ElementTree as ET
import csv

tree = ET.parse("result_0.xml")
root = tree.getroot()

import xml.etree.ElementTree as ET
import csv

tree = ET.parse("resident_data.xml")
root = tree.getroot()

# open a file for writing

Resident_data = open('/tmp/ResidentData.csv', 'w')

# create the csv writer object

csvwriter = csv.writer(Resident_data)
resident_head = []

count = 0
for member in root.findall('Resident'):
	resident = []
	address_list = []
	if count == 0:
		name = member.find('Name').tag
		resident_head.append(name)
		PhoneNumber = member.find('PhoneNumber').tag
		resident_head.append(PhoneNumber)
		EmailAddress = member.find('EmailAddress').tag
		resident_head.append(EmailAddress)
		Address = member[3].tag
		resident_head.append(Address)
		csvwriter.writerow(resident_head)
		count = count + 1

	name = member.find('Name').text
	resident.append(name)
	PhoneNumber = member.find('PhoneNumber').text
	resident.append(PhoneNumber)
	EmailAddress = member.find('EmailAddress').text
	resident.append(EmailAddress)
	Address = member[3][0].text
	address_list.append(Address)
	City = member[3][1].text
	address_list.append(City)
	StateCode = member[3][2].text
	address_list.append(StateCode)
	PostalCode = member[3][3].text
	address_list.append(PostalCode)
	resident.append(address_list)
	csvwriter.writerow(resident)
Resident_data.close()


import san.sanbase_graphql
from san.sanbase_graphql_helper import QUERY_MAPPING
from san.query import get_gql_query
from san.graphql import execute_gql
from san.transform import transform_timeseries_data_query_result
from san.error import SanError

class Batch:
    def __init__(self):
        self.queries = []

    def get(self, dataset, **kwargs):
        self.queries.append([dataset, kwargs])

    def execute(self):
        graphql_string = self.__create_batched_query_string()
        result = execute_gql(graphql_string)
        return self.__transform_batch_result(result)

    def __create_batched_query_string(self):
        batched_queries = []

        for idx, query in enumerate(self.queries):
            [metric, _separator, slug] = query[0].partition('/')
            if metric in QUERY_MAPPING:
                batched_queries.append(
                    get_gql_query(
                        idx, query[0], **query[1]))
            else:
                if slug != '':
                    batched_queries.append(
                        san.sanbase_graphql.get_metric_timeseries_data(
                            idx, metric, slug, **query[1]))
                else:
                    raise SanError('Invalid metric!')
        self.__batch_gql_queries(batched_queries)
        return self.__batch_gql_queries(batched_queries)

    def __transform_batch_result(self, graphql_result):
        result = []

        idxs = sorted([int(k.split('_')[1]) for k in graphql_result.keys()])
        for idx in idxs:
            query = self.queries[idx][0].split("/")[0]
            df = transform_timeseries_data_query_result(idx, query, graphql_result)
            result.append(df)
        return result

    def __batch_gql_queries(self, batched_queries):
        gql_string = "{\n"
        for q in batched_queries:
            gql_string = gql_string + q + "\n"

        gql_string = gql_string + "}"
        return gql_string


#coding=utf-8

import re
import math
import time
import random
import threading

from helper import *

THREADS = 250
pool_sema = threading.BoundedSemaphore(value=THREADS)

today = time.strftime("%Y-%m-%d")

def load_proxy():
	#cachefile = 'proxy_%s.lst' % today
	cachefile = 'proxy.lst'
	proxys = loadconf(cachefile)
	if not proxys:
		proxys = {}
	log_debug("Total %d proxies found." % len(proxys))
	return proxys

class visit_17k(threading.Thread):
	r = re.compile('已有<big>(?P<n>[0-9]+)</big>人读过此书...')
	def __init__ (self, bookid, proxy):
		threading.Thread.__init__(self)
		self.bookid = bookid
		self.proxy = proxy
		self.status = -1

	def run(self):
		url = 'http://www.17k.com/book/%s.html' % self.bookid
		s = http_get(url, self.proxy)
		result = self.r.search(s)
		if result:
			log_debug('counter: %s' % result.group('n'))
		pool_sema.release()

class visit_bj270(threading.Thread):
	r = re.compile('网站累计访问:(?P<n>[0-9]+)人次')
	def __init__ (self, bookid, proxy):
		threading.Thread.__init__(self)
		self.bookid = bookid
		self.proxy = proxy
		self.status = -1

	def run(self):
		url = 'http://www.bj270.18corp.cn/'
		s = http_get(url, self.proxy)
		try:
			s = s.decode('gb2312').encode('utf-8')
		except UnicodeDecodeError:
			pass
		result = self.r.search(s)
		if result:
			log_debug('counter: %s' % result.group('n'))
		pool_sema.release()

class visit_sinablog(threading.Thread):
	r = re.compile('={"pv" : "(?P<n>[0-9]+)"}')
	def __init__ (self, proxy, username, uid):
		threading.Thread.__init__(self)
		self.username = username
		self.uid = uid
		self.proxy = proxy
		self.status = -1

	def run(self):
		reqid = str(int(time.time()*1000000))[-8:]
		url = 'http://hits.blog.sina.com.cn/hits?act=3&uid=%s&varname=requestId_%s' % (self.uid, reqid)
		referer = 'http://blog.sina.com.cn/%s' % self.username
		s = http_get(url, self.proxy, [('Referer', referer)])
		result = self.r.search(s)
		if result:
			log_debug('counter: %s' % result.group('n'))
		pool_sema.release()

class visit_url(threading.Thread):
	r = re.compile('={"pv" : "(?P<n>[0-9]+)"}')
	def __init__ (self, url, proxy, referer=None):
		threading.Thread.__init__(self)
		self.url = url
		self.proxy = proxy
		self.referer = referer

	def run(self):
		if self.referer:
			http_get(self.referer, self.proxy)
		http_get(self.url, self.proxy, [('Referer', self.referer)])
		pool_sema.release()

def task_visit_17k(bookid):
	restr = """
<a title='.*' href="(?P<n>/html/books/.*)" target="_blank">"""
	restr2 = '/html/books/\d+/\d+/\d+/%s/\w+/(?P<n>[0-9]+).shtml' % bookid
	r = re.compile(restr2)
	url = 'http://www.17k.com/list/%s.html' % bookid
	s = http_get(url)
	links = []
	for l in re.findall(restr, s):
		result = r.search(l)
		if result:
			cid = result.group('n')
			d = {}
			d['url'] = 'http://www.17k.com/' + l
			d['clickurl'] = 'http://www.17k.com/main/readbook.do?method=click&bid=%s&cid=%s' % (bookid, cid)
			links.append(d)
	return links

def main():

	proxys = load_proxy()
	proxy_count = len(proxys)
	#return

	links = task_visit_17k('31647')
	max = len(links) - 1

	n = threading.activeCount()

	j = 0
	for i in proxys.keys():
		pool_sema.acquire()
		j += 1
		k = random.randint(0, max)
		log_debug('[%d:%d] url=%s, referer=%s, proxy=%s:%s' % (j, proxy_count, links[k]['clickurl'], links[k]['url'], proxys[i]['ip'], proxys[i]['port']))
		visit_url(url=links[k]['clickurl'], referer=links[k]['url'], proxy=proxys[i]).start()

	while threading.activeCount() != n:
		time.sleep(1)

	return

	####################################

	proxylist = proxys.keys()
	n = len(proxys)
	for iter in range(int(math.ceil(n*1./THREADS))):
		pinglist = []
		for i in proxylist[iter*THREADS:(iter+1)*THREADS]:
			#current = visit_17k(bookid='31647', proxy=proxys[i])
			#current = visit_url(url='http://www.17k.com/html/books/0/3/346/34688/05a1da/1307861.shtml', proxy=proxys[i])
			#current = visit_bj270(bookid=31647, proxy=proxys[i])
			#current = visit_sinablog(proxy=proxys[i], username='fastkylin', uid='5d215861')
			#current = visit_url(url=links[random.randint(0, max)], proxy=proxys[i])
			k = random.randint(0, max)
			current = visit_url(url=links[k]['clickurl'], referer=links[k]['url'], proxy=proxys[i])
			pinglist.append(current)
			current.start()

		log_debug("%d threads running." % len(pinglist))
		for pingle in pinglist:
			pingle.join()
			#print "Status from ",pingle.ip,"is",report[pingle.status]

if __name__ == '__main__':
	main()


class MailAttachmentNotFoundError(Exception):
    def __init__(self, mail_id: str):
        super(MailAttachmentNotFoundError, self).__init__(
            f"No attachments found in mail '{mail_id}'"
        )

class TooManyMailAttachmentsError(Exception):
    def __init__(self, mail_id: str):
        super(TooManyMailAttachmentsError, self).__init__(
            f"Mail '{mail_id}' has more than one attachment"
        )


import unittest
import GPflow
import GPflowOpt
import tensorflow as tf
from GPflow import settings
import numpy as np

float_type = settings.dtypes.float_type
np_float_type = np.float32 if float_type is tf.float32 else np.float64

class DummyTransform(GPflowOpt.transforms.DataTransform):

    def __init__(self, c):
        self.value = c

    def forward(self, X):
        return X * self.value

    def build_forward(self, X):
        return X * self.value

    def __invert__(self):
        return DummyTransform(1/self.value)

    def __str__(self):
        return '(dummy)'

class LinearTransformTests(unittest.TestCase):
    """
    Tests are inspired on GPflow transform tests.
    """

    def setUp(self):
        tf.reset_default_graph()
        self.x = tf.placeholder(float_type)
        self.y = tf.placeholder(float_type)

        self.x_np = np.random.rand(10, 2).astype(np_float_type)
        self.session = tf.Session()
        self.transforms = [DummyTransform(2.0), GPflowOpt.transforms.LinearTransform([2.0, 3.5], [1.2, 0.7])]

    def test_tf_np_forward(self):
        ys = [t.build_forward(self.x) for t in self.transforms]
        ys_tf = [self.session.run(y, feed_dict={self.x: self.x_np}) for y in ys]
        ys_np = [t.forward(self.x_np) for t in self.transforms]
        for y1, y2 in zip(ys_tf, ys_np):
            self.assertTrue(np.allclose(y1, y2))

    def test_forward_backward(self):
        ys_np = [t.forward(self.x_np) for t in self.transforms]
        xs_np = [t.backward(y) for t, y in zip(self.transforms, ys_np)]
        for x in xs_np:
            self.assertTrue(np.allclose(x, self.x_np))

    def test_tf_forward_backward(self):
        ys = [t.build_forward(self.x) for t in self.transforms]
        xs = [t.build_backward(y) for t, y in zip(self.transforms, ys)]
        xs_tf = [self.session.run(x, feed_dict={self.x: self.x_np}) for x in xs]
        for x in xs_tf:
            self.assertTrue(np.allclose(x, self.x_np))

    def test_invert_np(self):
        ys_np = [t.forward(self.x_np) for t in self.transforms]
        xs_np = [t.backward(y) for t, y in zip(self.transforms, ys_np)]
        xsi_np = [(~t).forward(y) for t, y in zip(self.transforms, ys_np)]

        for x in zip(xs_np, xsi_np):
            self.assertTrue(np.allclose(x[0], self.x_np))
            self.assertTrue(np.allclose(x[1], self.x_np))
            self.assertTrue(np.allclose(x[0], x[1]))

    def test_invert_tf(self):
        ys = [t.build_forward(self.x) for t in self.transforms]
        xs = [t.build_backward(y) for t, y in zip(self.transforms, ys)]
        xsi = [(~t).build_forward(y) for t, y in zip(self.transforms, ys)]
        xs_tf = [self.session.run(x, feed_dict={self.x: self.x_np}) for x in zip(xs, xsi)]

        for x in xs_tf:
            self.assertTrue(np.allclose(x[0], self.x_np))
            self.assertTrue(np.allclose(x[1], self.x_np))
            self.assertTrue(np.allclose(x[0], x[1]))


import torch
from torch.nn import functional as f
import random

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
theta = torch.randn(1, 1503, device=device, requires_grad=True)

def logestic_model(x):
    a = torch.mm(theta, x)
    return torch.sigmoid(a)

def get_loss(y_p, y_t):
    return -torch.mean(y_t * torch.log(y_p) + (1 - y_t) * torch.log(1 - y_p))

def getx(triplets, i):
    x1_pre = torch.tensor([triplets[i][0]], device=device)
    x1 = f.one_hot(x1_pre, 501)
    x2_pre = torch.tensor([triplets[i][1]], device=device)
    x2 = f.one_hot(x2_pre, 501)
    x3_pre = torch.tensor([triplets[i][2]], device=device)
    x3 = f.one_hot(x3_pre, 501)
    return torch.cat([x1, x2, x3], 1).t().float()

def OneHotProcessing(infile1, infile2, outfile):
    infopen1 = open(infile1, 'r', encoding='utf-8')
    infopen2 = open(infile2, 'r', encoding='utf-8')
    outfopen = open(outfile, 'w', encoding='utf-8')
    lines = infopen1.readlines()
    triplets_train = []
    ys_train = []
    for line in lines:
        nums = line.split()
        triplets_train.append([int(nums[0]), int(nums[1]), int(nums[2])])
        ys_train.append(int(nums[-1]))

    lines = infopen2.readlines()
    triplets_verification = []
    ys_verification = []
    for line in lines:
        nums = line.split()
        triplets_verification.append([int(nums[0]), int(nums[1]), int(nums[2])])
        ys_verification.append(int(nums[-1]))
    print("read in completed")

    alpha = 0.02
    i = random.randint(0, len(triplets_train) - 1)
    # sum = torch.zeros(1, 1503, device=device)
    # for i in range(len(triplets_train)):
    x = getx(triplets_train, i)
    y_p = logestic_model(x)
    y = torch.tensor([ys_train[i]], device=device)
    # sum = sum + torch.mm(y_p - y, x.t())
    # theta.data = theta.data - alpha * sum.data
    loss = get_loss(y_p, y)
    # print(loss)
    loss.backward()
    # print(theta.grad)
    theta.data = theta.data - alpha * theta.grad.data
    print("go in training")

    # epoch
    # for e in range(len(triplets_train)):
    for e in range(100000):
        #     for i in range(len(triplets_train)):
        #         x = getx(triplets_train, i)
        #         y_p = logestic_model(x)
        #         y = torch.tensor([ys_train[i]], device=device)
        #         sum = sum + torch.mm(y_p - y, x.t())
        # theta.data = theta.data - alpha * sum.data
        i = random.randint(0, len(triplets_train) - 1)
        x = getx(triplets_train, i)
        y_p = logestic_model(x)
        y = torch.tensor([ys_train[i]], device=device)
        theta.grad.zero_()
        loss = get_loss(y_p, y)
        theta.data = theta.data - alpha * theta.grad.data

    # print('epoch: {}, loss: {}'.format(e * 500, loss.data.item()))

    for data in theta.cpu().detach().numpy().tolist():
        out = str(data) + ' '
        outfopen.write(out)
    outfopen.write('\n')

    # print(theta)
    print("learning completed")

    true_pridictions = 0  # 预测1正确
    one_predictions = 0  # 预测1的个数
    true_origional = 0  # 原有1的个数

    for i in range(len(triplets_verification)):
        x = getx(triplets_verification, i)
        y_p = logestic_model(x)
        y = torch.tensor([ys_verification[i]], device=device)

        loss = get_loss(y_p, y)

        out = str(i) + ' y_p:' + str(y_p.item()) + ' y:' + str(y.item()) + ' T/F:'
        if ((y_p.item() >= 0.5) and (y.item() == 1)) or ((y_p.item() < 0.5) and (y.item() == 0)):
            out += 'T\n'
        else:
            out += 'F\n'
        outfopen.write(out)

        if (y_p.item() >= 0.5) & (y.item() == 1):
            true_pridictions += 1
        if (y_p.item() >= 0.5):
            one_predictions += 1
        if (y.item() == 1):
            true_origional += 1

    print("total:", len(triplets_verification))
    print("true pridictions:", true_pridictions)
    print("one pridictions:", one_predictions)
    print("true oritional:", true_origional)
    recall_rate = float(true_pridictions) / float(true_origional)
    precision_rate = float(true_pridictions) / float(one_predictions)
    f1_measure = 2 * (recall_rate * precision_rate) / (recall_rate + precision_rate)
    print("recall rate:", recall_rate)
    print("precision_rate", precision_rate)
    print("f1 measure:", f1_measure)

if __name__ == '__main__':
    OneHotProcessing("./sets/pre_onehot_train_set.txt",
                     "./sets/pre_onehot_verification_set.txt",
                     "./sets/verification_out.txt")


"""
RFarm Model Processing Tool

__date__ = '20190902'
__version__ = '4.0.0'
__author__ = 'Fabio Delogu            (fabio.delogu@cimafoundation.org,
              Simone Gabellani        (simone.gabellani@cimafoundation.org)
              Francesco Silvestro     (francesco.silvestro@cimafoundation.org)
              Nicola Rebora           (nicola.rebora@cimafoundation.org)'
__library__ = 'hyde'

General command line:
python3 HYDE_Model_RFarm.py -settings_file configuration.json -time YYYYMMDDHHMM

Version(s):
20190902 (4.0.0) --> Porting in Hyde package and python 3.x
20171114 (3.5.1) --> Fix bugs (accumulated and istantaneous rain)
20170530 (3.5.0) --> Update version
20150924 (3.0.2) --> Final release for FP Marche project
20150823 (3.0.0) --> Final release for DRIHM project
20140408 (2.0.1) --> Final release based on Rainfarm 1.0
"""

# ----------------------------------------------------------------------------------------------------------------------
# Library
import time
import argparse

from src.common.log.lib_logging import setLoggingFile

from src.hyde.algorithm.settings.model.rfarm.lib_rfarm_args import logger_formatter, logger_handle, logger_name

from src.hyde.driver.configuration.generic.drv_configuration_algorithm import DataAlgorithm
from src.hyde.driver.configuration.model.rfarm.drv_configuration_time_rfarm import DataTime

from src.hyde.driver.model.rfarm.drv_model_rfarm_geo import DataGeo
from src.hyde.driver.model.rfarm.drv_model_rfarm_base import ModelTime, ModelRunner
# ----------------------------------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------------------------------
# Method to get script argument(s)
def getArgs():
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument('-settings_file', action="store", dest="settings_file")
    args_parser.add_argument('-time', action="store", dest="time_arg")
    args_values = args_parser.parse_args()

    script_name = args_parser.prog

    if 'settings_file' in args_values:
        settings_file = args_values.settings_file
    else:
        settings_file = 'configuration.json'

    if 'time_arg' in args_values:
        time_arg = args_values.time_arg
    else:
        time_arg = None

    return script_name, settings_file, time_arg
# ----------------------------------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------------------------------
# Script Main
def main():

    # -------------------------------------------------------------------------------------
    # Version and algorithm information
    project_name = 'HYDE'
    alg_version = '4.0.0'
    alg_type = 'Model'
    alg_name = 'RFarm Processing Tool'
    # Time algorithm information
    alg_start_time = time.time()
    # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------
    # Get script argument(s)
    [script_name, file_setting, time_arg] = getArgs()

    # Set algorithm configuration
    driver_algorithm_settings = DataAlgorithm(file_setting)
    [data_algorithm_settings, data_algorithm_path,
     data_algorithm_flags, data_algorithm_colormap] = driver_algorithm_settings.getDataSettings()

    # Set logging file
    log_stream = setLoggingFile(data_algorithm_path['log'], logger_name, logger_handle, logger_formatter)
    # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------
    # Start Program
    log_stream.info('[' + project_name + ' ' + alg_type + ' - ' + alg_name + ' (Version ' + alg_version + ')]')
    log_stream.info('[' + project_name + '] Start Program ... ')
    # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------
    # Get data time
    log_stream.info(' --> Set algorithm time ... ')
    driver_algorithm_time = DataTime(
        time_arg,
        time_settings=data_algorithm_settings['time']['time_now'],
        time_period_past=int(data_algorithm_settings['time']['time_period']),
        time_frequency=data_algorithm_settings['time']['time_frequency'],
        time_rounding=data_algorithm_settings['time']['time_rounding'])
    data_algorithm_time = driver_algorithm_time.getDataTime()
    log_stream.info(' --> Set algorithm time ... DONE')
    # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------
    # Get data geo
    log_stream.info(' --> Set grid data ... ')
    data_algorithm_geo = DataGeo(
        data_algorithm_path['terrain_data'], data_algorithm_path['grid_data'],
        file_updating=data_algorithm_flags['cleaning_static_data'])
    data_geo = data_algorithm_geo.getDataGeo()
    log_stream.info(' --> Set grid data ... DONE')
    # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------
    # Iterate over time steps
    for time_step in data_algorithm_time['time_steps']:

        # -------------------------------------------------------------------------------------
        # Compute dynamic time
        log_stream.info(' --> Compute time ... ')
        driver_dynamic_time = ModelTime(
            time_step=time_step,
            time_run=data_algorithm_time['time_run'],
            time_settings=data_algorithm_settings['data']['dynamic']['time'])
        data_dynamic_time = driver_dynamic_time.computeModelTime()
        log_stream.info(' --> Compute time ... DONE')
        # -------------------------------------------------------------------------------------

        # -------------------------------------------------------------------------------------
        # Configure and execute model
        log_stream.info(' --> Initialize model ... ')
        driver_model_runner = ModelRunner(
            time_step=data_dynamic_time.time_step,
            time_range=data_dynamic_time.time_range,
            variable_in=data_algorithm_settings['variables']['input']['rain_data'],
            variable_out=data_algorithm_settings['variables']['outcome']['rain_data'],
            data_geo=data_geo,
            template=data_algorithm_settings['data']['dynamic']['template'],
            parameters=data_algorithm_settings['algorithm']['parameters'],
            file_ancillary_in=data_algorithm_path['rain_input_ancillary'],
            file_ancillary_out=data_algorithm_path['rain_outcome_ancillary'],
            file_in=data_algorithm_path['rain_input_data'],
            file_out=data_algorithm_path['rain_outcome_data'],
            file_ancillary_in_updating=data_algorithm_flags['cleaning_dynamic_ancillary_in'],
            file_ancillary_out_updating=data_algorithm_flags['cleaning_dynamic_ancillary_out'],
            file_out_updating=data_algorithm_flags['cleaning_dynamic_out'],
            file_out_zipping=data_algorithm_flags['zipping_dynamic_out'],
            file_write_engine=data_algorithm_settings['algorithm']['ancillary']['write_engine']
        )
        log_stream.info(' --> Initialize model ... DONE')

        # Collect data
        log_stream.info(' --> Collect model data ... ')
        data_dynamic = driver_model_runner.collect(data_dynamic_time)
        log_stream.info(' --> Collect model data ... DONE!')

        # Configure model
        log_stream.info(' --> Configure model ... ')
        driver_model_runner.configure(data_dynamic)
        log_stream.info(' --> Configure model ... DONE!')

        # Execute model
        log_stream.info(' --> Execute model ... ')
        data_run = driver_model_runner.exec()
        log_stream.info(' --> Execute model ... DONE')

        # Finalize model
        log_stream.info(' --> Save model result ... ')
        driver_model_runner.save(data_run)
        log_stream.info(' --> Save model result ... DONE')

        # Clean tmp file(s)
        driver_model_runner.clean(cleaning_dynamic_tmp=data_algorithm_flags['cleaning_dynamic_tmp'])
        # -------------------------------------------------------------------------------------

    # -------------------------------------------------------------------------------------

    # ----------------------------------------------------------------------------------------------------------------------
    # Note about script parameter(s)
    log_stream.info('NOTE - Algorithm parameter(s)')
    log_stream.info('Script: ' + str(script_name))
    # ----------------------------------------------------------------------------------------------------------------------

    # ----------------------------------------------------------------------------------------------------------------------
    # End Program
    alg_time_elapsed = round(time.time() - alg_start_time, 1)

    log_stream.info('[' + project_name + ' ' + alg_type + ' - ' + alg_name + ' (Version ' + alg_version + ')]')
    log_stream.info('End Program - Time elapsed: ' + str(alg_time_elapsed) + ' seconds')
    # ----------------------------------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------------------------------
# Call script from external library
if __name__ == "__main__":
    main()
# ----------------------------------------------------------------------------------------------------------------------


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

import pandas as pd
from atomic.frame import minimal_frame
from atomic import Editor as AtomicEditor
from atomic import Universe, Isotope, Atom
from gaussian.basis import shell_order

from datetime import datetime

class Editor(AtomicEditor):
    '''
    '''
    shell_order = shell_order
    _to_universe = AtomicEditor.to_universe

class Fchk(Editor):

    @property
    def frame(self):
        if self._frame is None:
            self.parse_frame()
        return self._frame

    @property
    def atom(self):
        if self._atom is None:
            self.parse_atom()
        return self._atom

    @property
    def momatrix(self):
        if self._momatrix is None:
            self.parse_momatrix()

    def parse_frame(self):
        self._frame = minimal_frame(self.atom)

    def parse_atom(self):
        nat = self._last_num_from_regex(self._regex[self._renat])
        znum = self._patterned_array(self._regex[self._reznum], nat, 6)
        positions = self._patterned_array(self._regex[self._reposition], nat * 3, 5).reshape((nat, 3))
        atdf = pd.DataFrame()
        atdf['Z'] = znum
        atdf['symbol'] = atdf['Z'].map(Isotope.Z_to_symbol()).astype('category')
        atdf['x'] = positions[:,0]
        atdf['y'] = positions[:,1]
        atdf['z'] = positions[:,2]
        atdf['frame'] = [0] * nat
        self._atom = Atom(atdf)

    def parse_momatrix(self):
        basdim = self._last_num_from_regex(self._regex[self._rebasdim])
        amomatrix = self._patterned_array(self._regex[self._reamomatrix], basdim ** 2, 5).reshape((basdim, basdim))
        self._momatrix = amomatrix

    def parse_orbital(self):
        #pass
        # Primitives and Mocoef DataFrames
        basdim = self._last_num_from_regex(self._regex[self._rebasdim])
        primdim = self._last_num_from_regex(self._regex[self._reprimdim])
        contdim = self._last_num_from_regex(self._regex[self._recontdim])
        shell = self._patterned_array(self._regex[self._reshelltype], contdim, 6)
        prim = self._patterned_array(self._regex[self._reprimitive], contdim, 6)
        stoatom = self._patterned_array(self._regex[self._reshelltoatom], contdim, 6)
        primexp = self._patterned_array(self._regex[self._reprimexp], primdim, 5)
        contcoef = self._patterned_array(self._regex[self._recontcoef], primdim, 5)
        crdshell = self._patterned_array(self._regex[self._recrdshell], contdim * 3, 5)
        alphaen = self._patterned_array(self._regex[self._realphaen], basdim, 5)

    def parse(self):
        self._renat = 'Number of atoms'
        self._reznum = 'Atomic numbers'
        self._rebasdim = 'Number of basis functions'
        self._reposition = 'Current cartesian coordinates'
        self._recontdim = 'Number of contracted shells'
        self._reprimdim = 'Number of primitive shells'
        self._reshelltype = 'Shell types'
        self._reprimitive = 'Number of primitives per shell'
        self._reshelltoatom = 'Shell to atom map'
        self._reprimexp = 'Primitive exponents'
        self._recontcoef = 'Contraction coefficients'
        self._recrdshell = 'Coordinates of each shell'
        self._realphaen = 'Alpha Orbital Energies'
        self._reamomatrix = 'Alpha MO coefficients'

        t0 = datetime.now()
        self._regex = self.regex(self._renat, self._reznum,
                                 self._rebasdim, self._reposition,
                                 self._recontdim, self._reprimdim,
                                 self._reshelltype, self._reprimitive,
                                 self._reshelltoatom, self._reprimexp,
                                 self._recontcoef, self._recrdshell,
                                 self._realphaen, self._reamomatrix,)
        t1 = datetime.now()
        print('Calling Editor.regex with {} args'.format(len(self._regex)))
        print('Seconds : {}'.format((t1 - t0).total_seconds()))

        self.parse_atom()
        t2 = datetime.now()
        print('Calling parse_atom')
        print('Seconds : {}'.format((t2 - t1).total_seconds()))

        self.parse_frame()
        t3 = datetime.now()
        print('Calling parse_frame')
        print('Seconds : {}'.format((t3 - t2).total_seconds()))

        self.parse_orbital()
        t4 = datetime.now()
        print('Calling parse_orbital')
        print('Seconds : {}'.format((t4 - t3).total_seconds()))

        self.parse_momatrix()
        t5 = datetime.now()
        print('Calling parse_momatrix')
        print('Seconds : {}'.format((t5 - t4).total_seconds()))

    def to_universe(self):
        return self._to_universe(**{'momatrix': self._momatrix})

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.meta = {'program': 'gaussian'}
        self.parse()


#!/usr/bin/python3
from sys import stdin

for i in range(int(stdin.readline().strip())):
  digits = [int(x) for x in reversed(stdin.readline().strip())]
  value = [x for x in digits]
  if len([x for x in digits if x != 0]) == 0:
    print("Case #%d: INSOMNIA" %(i+1))
    continue

  seen = [(1 if x in value else 0) for x in range(10)]
  while not all(seen):
    carry = 0
    for j in range(len(value)):
      val = value[j] + carry + (digits[j] if j < len(digits) else 0)
      value[j] = int(val%10)
      seen[value[j]] = 1
      carry = int(val/10)
    if carry != 0:
      value.append(carry)
      seen[carry] = 1
  print("Case #%d: %s" %(i+1, "".join(map(str, reversed(value)))))


# 归档日志文件

# 创建本月目录
import time
import os,shutil

# 获取当前时间
localtime = time.strftime('%Y-%m',time.localtime(time.time()))

# 目录
old_file_dir = r'..\LOG'
new_file_dir = old_file_dir + str('\\' + localtime)

# 如果目录不存在 则创建目录
if os.path.exists(new_file_dir) is False:
        os.makedirs(new_file_dir)

# 文件归档
old_file_list = os.walk(old_file_dir)
for path, dirs, filelist in old_file_list:
    for filename in filelist:
        if 'log.'+ localtime in filename:
            full_path = os.path.join(path, filename)  # 旧地址 + 文件名
            despath = new_file_dir + '\\'+filename  # 新地址 +文件名
            shutil.move(full_path, despath)


#-------------------------------------------------------------------------------
# Introduction to Programming in Python by Sedgewick
#
# Author:        Christopher Martinez
# Date:          08/25/2016
# Description:
#
# Three-sort. Compose a program that takes three integers from the command line
# and writes them in ascending order. Use the built-in min() and max()
# functions.
#-------------------------------------------------------------------------------
import sys
import stdio

n1 = int(sys.argv[1])
n2 = int(sys.argv[2])
n3 = int(sys.argv[3])

minimum = min(n1, n2, n3)
maximum = max(n1, n2, n3)
middle = min(max(n1, n2), max(n1, n3), max(n2, n3))

stdio.writeln('')
stdio.writeln(str(minimum))
stdio.writeln(str(middle))
stdio.writeln(str(maximum))
stdio.writeln('')