import numpy as np
from scipy.signal import fftconvolve, convolve
from itertools import product

def affine_forward(x, w, b):
    """
    Computes the forward pass for an affine (fully-connected) layer.

    The input x has shape (N, d_1, ..., d_k) and contains a minibatch of N
    examples, where each example x[i] has shape (d_1, ..., d_k). We will
    reshape each input into a vector of dimension D = d_1 * ... * d_k, and
    then transform it to an output vector of dimension M.

    Inputs:
    - x: A numpy array containing input data, of shape (N, d_1, ..., d_k)
    - w: A numpy array of weights, of shape (D, M)
    - b: A numpy array of biases, of shape (M,)

    Returns a tuple of:
    - out: output, of shape (N, M)
    - cache: (x, w, b)
    """
    cache = (x, w, b)
    x = x.reshape(x.shape[0], -1)  # NxD
    out = x.dot(w) + b
    return out, cache

def affine_backward(dout, cache):
    """
    Computes the backward pass for an affine layer.

    Inputs:
    - dout: Upstream derivative, of shape (N, M)
    - cache: Tuple of:
      - x: Input data, of shape (N, d_1, ... d_k)
      - w: Weights, of shape (D, M)
      - b: biases, of shape (M,

    Returns a tuple of:
    - dx: Gradient with respect to x, of shape (N, d1, ..., d_k)
    - dw: Gradient with respect to w, of shape (D, M)
    - db: Gradient with respect to b, of shape (M,)
    """
    x, w, b = cache

    dx = dout.dot(w.T).reshape(x.shape)
    dw = x.reshape(x.shape[0], -1).T.dot(dout)
    db = dout.sum(axis=0)

    return dx, dw, db

def relu_forward(x):
    """
    Computes the forward pass for a layer of rectified linear units (ReLUs).

    Input:
    - x: Inputs, of any shape

    Returns a tuple of:
    - out: Output, of the same shape as x
    - cache: x
    """
    out = np.maximum(0, x)
    cache = x
    return out, cache

def relu_backward(dout, cache):
    """
    Computes the backward pass for a layer of rectified linear units (ReLUs).

    Input:
    - dout: Upstream derivatives, of any shape
    - cache: Input x, of same shape as dout

    Returns:
    - dx: Gradient with respect to x
    """
    dx, x = None, cache
    dout[np.where(x <= 0.)] = 0.
    dx = dout

    return dx

def batchnorm_forward(x, gamma, beta, bn_param):
    """
    Forward pass for batch normalization.

    During training the sample mean and (uncorrected) sample variance are
    computed from minibatch statistics and used to normalize the incoming data.
    During training we also keep an exponentially decaying running mean of the mean
    and variance of each feature, and these averages are used to normalize data
    at test-time.

    At each timestep we update the running averages for mean and variance using
    an exponential decay based on the momentum parameter:

    running_mean = momentum * running_mean + (1 - momentum) * sample_mean
    running_var = momentum * running_var + (1 - momentum) * sample_var

    Note that the batch normalization paper suggests a different test-time
    behavior: they compute sample mean and variance for each feature using a
    large number of training images rather than using a running average. For
    this implementation we have chosen to use running averages instead since
    they do not require an additional estimation step; the torch7 implementation
    of batch normalization also uses running averages.

    Input:
    - x: Data of shape (N, D)
    - gamma: Scale parameter of shape (D,)
    - beta: Shift parameter of shape (D,)
    - bn_param: Dictionary with the following keys:
      - mode: 'train' or 'test'; required
      - eps: Constant for numeric stability
      - momentum: Constant for running mean / variance.
      - running_mean: Array of shape (D,) giving running mean of features
      - running_var Array of shape (D,) giving running variance of features

    Returns a tuple of:
    - out: of shape (N, D)
    - cache: A tuple of values needed in the backward pass
    """
    mode = bn_param['mode']
    eps = bn_param.get('eps', 1e-5)
    momentum = bn_param.get('momentum', 0.9)

    N, D = x.shape
    running_mean = bn_param.get('running_mean', np.zeros(D, dtype=x.dtype))
    running_var = bn_param.get('running_var', np.zeros(D, dtype=x.dtype))

    out, cache = None, None
    if mode == 'train':
        var = np.var(x, axis=0)
        mean = x.mean(axis=0)
        x_shift = x - mean
        x_norm = x_shift/np.sqrt(var + eps)

        out = gamma*x_norm
        out += beta

        scale = (1. - momentum)
        running_mean *= momentum
        running_mean += scale*mean

        running_var *= momentum
        running_var += scale*var

        cache = (x_shift, x_norm, var+eps, gamma)
        # cache = (x, mean, var+eps, gamma)

    elif mode == 'test':
        out = (x - running_mean)/np.sqrt(running_var + eps)
        out *= gamma
        out += beta

    else:
        raise ValueError('Invalid forward batchnorm mode "%s"' % mode)

    # Store the updated running means back into bn_param
    bn_param['running_mean'] = running_mean
    bn_param['running_var'] = running_var

    return out, cache

def batchnorm_backward(dout, cache):
    """
    Backward pass for batch normalization.

    For this implementation, you should write out a computation graph for
    batch normalization on paper and propagate gradients backward through
    intermediate nodes.

    Inputs:
    - dout: Upstream derivatives, of shape (N, D)
    - cache: Variable of intermediates from batchnorm_forward.

    Returns a tuple of:
    - dx: Gradient with respect to inputs x, of shape (N, D)
    - dgamma: Gradient with respect to scale parameter gamma, of shape (D,)
    - dbeta: Gradient with respect to shift parameter beta, of shape (D,)
    """

    # I just did the alt version...vanilla was dumb

    return batchnorm_backward_alt(dout, cache)

def batchnorm_backward_alt(dout, cache):
    """
    Alternative backward pass for batch normalization.

    For this implementation you should work out the derivatives for the batch
    normalizaton backward pass on paper and simplify as much as possible. You
    should be able to derive a simple expression for the backward pass.

    Note: This implementation should expect to receive the same cache variable
    as batchnorm_backward, but might not use all of the values in the cache.

    Inputs / outputs: Same as batchnorm_backward
    """
    x_shift, x_norm, var_eps, gamma = cache
    dx_norm = gamma*dout

    dgamma = np.einsum('ij,ij->j', dout, x_norm)
    dbeta = np.sum(dout, axis=0)

    dx = dx_norm - np.mean(dx_norm, axis=0)
    dx -= x_shift*np.einsum('ij,ij->j', dx_norm, x_shift)/(var_eps*dx_norm.shape[0])
    dx /= np.sqrt(var_eps)

    return dx, dgamma, dbeta

def dropout_forward(x, dropout_param):
    """
    Performs the forward pass for (inverted) dropout.

    Inputs:
    - x: Input data, of any shape
    - dropout_param: A dictionary with the following keys:
      - p: Dropout parameter. We drop each neuron output with probability p.
      - mode: 'test' or 'train'. If the mode is train, then perform dropout;
        if the mode is test, then just return the input.
      - seed: Seed for the random number generator. Passing seed makes this
        function deterministic, which is needed for gradient checking but not in
        real networks.

    Outputs:
    - out: Array of the same shape as x.
    - cache: A tuple (dropout_param, mask). In training mode, mask is the dropout
      mask that was used to multiply the input; in test mode, mask is None.
    """
    p, mode = dropout_param['p'], dropout_param['mode']
    if 'seed' in dropout_param:
        np.random.seed(dropout_param['seed'])

    mask = None
    out = None

    if mode == 'train':
        mask = (np.random.rand(*x.shape) < p)/p
        out = x*mask
    elif mode == 'test':
        out = x

    cache = (dropout_param, mask)
    out = out.astype(x.dtype, copy=False)

    return out, cache

def dropout_backward(dout, cache):
    """
    Perform the backward pass for (inverted) dropout.

    Inputs:
    - dout: Upstream derivatives, of any shape
    - cache: (dropout_param, mask) from dropout_forward.
    """
    dropout_param, mask = cache
    mode = dropout_param['mode']

    dx = None
    if mode == 'train':
        dx = mask*dout
    elif mode == 'test':
        dx = dout
    return dx

def flip_ndarray(x):
    """ Reverse the positions of the entries of the input array along all of its axes.

        Parameters
        ----------
        x : numpy.ndarray

        Returns
        -------
        out : numpy.ndarray
            A view of x with all of its axes reversed. Since a view is returned, this operation is O(1).

        Example
        ------
        x = array([[1, 2, 3],
                   [6, 5, 6]])
        flip_ndarray(x))
        >> array([[6, 5, 4],
                  [3, 2, 1]])"""
    loc = tuple(slice(None, None, -1) for i in xrange(x.ndim))
    return x[loc]

def nd_convolve(dat, conv_kernel, stride, outshape=None):
    """ Perform a convolution of two ndarrays, using a specified stride.

        Parameters
        ----------
        data : numpy.ndarray
            Array to be convolved over.
        kernel : numpy.ndarray
            Kernel used to perform convolution.
        stride : Union[Iterable[int, ...], Dict[int, int], int]
            Step sizes used while sliding the kernel during the convolution.
             - If a dictionary is provided, then it is used to map (axis-index -> stride-value). If an
               axis is not specified in the dictionary keys, then a stride of 1 is used along that axis.
             - If an iterable is provided, it must provide an explicit stride value for each axis (in order
               of ascending axis-index).
             - If a single stride value is specified, that value is used for every axis.

        outshape : Optional[Tuple[int, ...]]
            Provide the known output shape of the convolution, allowing the function to bypass
            sanity checks and some initial computations.

        Returns
        -------
        out : numpy.ndarray
            An array of the resulting convolution.
        """
    if np.max(dat.shape) >= 500:
        conv = fftconvolve
    else:
        conv = convolve

    if type(stride) is dict:
        stride_gen = (stride.get(key, 1) for key in range(dat.ndim))
    elif hasattr(stride, '__iter__'):
        stride_gen = stride
    else:
        stride_gen = (stride for i in range(dat.ndim))
    stride = np.fromiter(stride_gen, dtype=int)

    if outshape is None:
        outshape = get_outshape(dat.shape, conv_kernel.shape, stride)

    full_conv = conv(dat, conv_kernel, mode='valid')

    if np.all(stride == 1):
        return full_conv

    # all index positions to down-sample the convolution, given stride > 1
    all_pos = zip(*product(*(stride[n]*np.arange(i) for n,i in enumerate(outshape))))
    out = np.zeros(outshape, dtype=dat.dtype)
    out.flat = full_conv[all_pos]
    return out

def get_outshape(dat_shape, kernel_shape, stride):
    """ Returns the shape of the ndarray resulting from the convolution, using specified stride,
        of two ndarrays whose shapes are specified.

        Parameters
        ----------
        dat_shape : Iterable[int, ...]
            Shape of array to be convolved over.
        kernel_shape : Iterable[int, ...]
            Shape of kernel used to perform convolution.
        stride : Union[int, Iterable[int, ...]] ( > 0)
            Step size used while sliding the kernel during the convolution.

        Returns
        -------
        out : numpy.ndarray([int, ...])
            Shape of the array resulting from the convolution."""

    dat_shape = np.array(dat_shape)
    kernel_shape = np.array(kernel_shape)

    if hasattr(stride, '__iter__'):
        stride = np.fromiter(stride, dtype=float)
        assert len(stride) == len(dat_shape), 'The stride iterable must provide a stride value for each dat axis.'
    else:
        stride = float(stride)
    assert len(dat_shape) == len(kernel_shape), "kernel and data must have same number of dimensions"

    outshape = (dat_shape-kernel_shape)/stride+1.
    for num in outshape:
        assert num.is_integer(), num
    outshape = np.rint(outshape).astype(int)

    return outshape

def padder(dat, pad, skip_axes=[0]):
    """ Returns an array padded with zeros with specified depth on both sides of each axis. A list of
        axes can be specified, which will not receive any padding.

        Parameters
        ----------
        dat : numpy.ndarray
            Array to be padded
        pad : int ( >= 0)
            Padding depth to be used on each end of a padding axis.
        skip_axes : Union[int, Iterable[int, ...]]
            The indices corresponding to axes that will not be padded.

        Returns
        -------
        out : numpy.ndarray
            Array padded with zeros."""
    assert pad >= 0 and type(pad) == int
    if pad == 0:
        return dat

    if type(skip_axes) == int:
        skip_axes = [skip_axes]
    assert hasattr(skip_axes, '__iter__')
    padding = [(pad, pad) for i in xrange(dat.ndim)]

    for ax in skip_axes:
        padding[ax] = (0, 0)

    return np.pad(dat, padding, mode='constant').astype(dat.dtype)

def conv_forward_naive(x, w, b, conv_param):
    """
    A naive implementation of the forward pass for a convolutional layer.

    The input consists of N data points, each with C channels, height H and width
    W. We convolve each input with F different filters, where each filter spans
    all C channels and has height HH and width HH.

    Input:
    - x: Input data of shape (N, C, H, W)
    - w: Filter weights of shape (F, C, HH, WW)
    - b: Biases, of shape (F,)
    - conv_param: A dictionary with the following keys:
      - 'stride': The number of pixels between adjacent receptive fields in the
        horizontal and vertical directions.
      - 'pad': The number of pixels that will be used to zero-pad the input.

    Returns a tuple of:
    - out: Output data, of shape (N, F, H', W') where H' and W' are given by
      H' = 1 + (H + 2 * pad - HH) / stride
      W' = 1 + (W + 2 * pad - WW) / stride
    - cache: (x, w, b, conv_param)
    """

    pad_x = padder(x, conv_param['pad'], skip_axes=[0, 1])
    conv_out_shape = get_outshape(pad_x[0].shape, w[0].shape, conv_param['stride'])
    out = np.zeros((x.shape[0], w.shape[0], conv_out_shape[-2], conv_out_shape[-1]))

    for nk, kernel in enumerate(w):
        # note: we are actually computing a correlation, not a convolution
        conv_kernel = flip_ndarray(kernel)
        for nd, dat in enumerate(pad_x):
            out[nd, nk, :, :] = nd_convolve(dat, conv_kernel, conv_param['stride'], conv_out_shape)
        out[:, nk:nk+1, :, :] += b[nk]

    cache = (x, w, b, conv_param)
    return out, cache

def conv_backward_naive(dout, cache):
    """
    A naive implementation of the backward pass for a convolutional layer.

    Inputs:
    - dout: Upstream derivatives.
    - cache: A tuple of (x, w, b, conv_param) as in conv_forward_naive

    Returns a tuple of:
    - dx: Gradient with respect to x
    - dw: Gradient with respect to w
    - db: Gradient with respect to b
    """

    x, w, b, conv_param = cache

    dx = np.zeros_like(x, dtype=x.dtype)
    dw = np.zeros_like(w, dtype=w.dtype)
    db = np.sum(dout, axis=(0, 2, 3))

    pad = conv_param['pad']
    stride = conv_param['stride']

    npad = np.array([0]+[pad for i in xrange(x[0].ndim-1)])
    outshape = (np.array(x[0].shape)-np.array(w[0].shape)+2.*npad)/float(stride)+1.
    outshape = np.round(outshape).astype(int)

    # all positions to place the kernel
    all_pos = list(product(*[stride*np.arange(i) for i in outshape]))
    all_slices = [tuple(slice(start, start+w[0].shape[i]) for i,start in enumerate(j)) for j in all_pos]

    if pad:
        pad_ax = [(0, 0)] + [(pad, pad) for i in xrange(x[0].ndim-1)]

    for nk, kernel in enumerate(w):  # iterate over all kernels
        dx_kernel = np.zeros(x.shape, dtype=x.dtype)
        dkernel = np.zeros_like(kernel, dtype=kernel.dtype)
        for nd, dat in enumerate(x):  # iterate over each piece of data to be convolved
            if pad:
                dat = np.pad(dat, pad_ax, mode='constant').astype(dat.dtype)

            dy = dout[nd, nk][np.newaxis, :, :]
            ddat = np.zeros((x[0].shape[0], x[0].shape[1]+2*pad, x[0].shape[2]+2*pad), dtype=x[0].dtype)

            for i, slices in enumerate(all_slices):
                loc = np.unravel_index(i, outshape)
                dy_val = dy[loc]
                ddat[slices] += dy_val*kernel
                dkernel += dy_val*dat[slices]

            if pad:
                ddat = ddat[:, pad:-pad, pad:-pad]

            dx_kernel[nd] = ddat[:]
        dw[nk:nk+1] = dkernel
        dx += dx_kernel

    return dx, dw, db

def max_pool(x, pool_shape, stride, pooling_axes, backprop=False, dout=None):
    """ Pool the values of an ndarray, by taking the max over a specified pooling
        filter volume that rasters across the specified axes of x with a given stride.

        A backprop flag can be toggled to, instead, perform back-propagation through the
        maxpool layer (i.e. pass gradient values through of the array elements that
        contributed to the forward pooling).

        Parameters
        ----------
        x : numpy.ndarray
            Input array to be pooled.
        pool_shape : Iterable[int, ...]
            Shape of the pooling_filter along each specified pooling axis, listed
            in ascending axis order. No entries are provided for non-pooling axes.
        stride : int ( > 0)
            Step size used while rastering the pooling filter across x.
        pooling_axes : Union[int, Iterable[int, ...]]
            The axes along which the values of x will be max-pooled.
        backprop : bool, optional
            Indicates whether or not max_pool performs back propagation
            instead of pooling.
        dout : Union[NoneType, numpy.ndarray]
            "Upstream" array, whose values will be back propagated through
             the max-pool layer. This must be specified if backprop is True.

        Returns
        -------
        if backprop is False
            out : numpy.ndarray
                An array of the max-pooled values of x.

        if backprop is True
            dx : numpy.ndarray (shape=x.shape)
                An array of values from dout back-propagated through the pooling layer.
        """

    if type(pooling_axes) is int:
        pooling_axes = (pooling_axes)
    pooling_axes = tuple(sorted(pooling_axes))

    pool_only_slice = tuple(slice(None, None) if i in pooling_axes else 0 for i in range(x.ndim))
    outshape = get_outshape(x[pool_only_slice].shape, pool_shape, stride)

    if backprop:
        assert dout is not None, "dout must be provided during backprop"
        mask_view = tuple(np.newaxis if i in pooling_axes else slice(None, None) for i in range(x.ndim))
        dx = np.zeros_like(x, dtype=x.dtype)

    else:
        tmp_shape = list(x.shape)
        for i, ax in enumerate(pooling_axes):
            tmp_shape[ax] = outshape[i]
        out = np.zeros(tmp_shape, dtype=x.dtype)

    all_slices = [slice(None, None) for i in range(x.ndim)]

    # iterate over positions to place the pooling filter
    for i, pos in enumerate(product(*[stride*np.arange(i) for i in outshape])):

        slices = all_slices[:]
        # generate slices to make pooling filter views of x
        for j, start in enumerate(pos):
            slices[pooling_axes[j]] = slice(start, start + pool_shape[j])
        slices = tuple(slices)

        # generate slices of output array to update
        inds = np.unravel_index(i, outshape)
        loc = all_slices[:]
        for cnt, ax in enumerate(pooling_axes):
            loc[ax] = inds[cnt]

        maxes = np.amax(x[slices], axis=pooling_axes)

        if not backprop:
            out[loc] = maxes
        else:
            dx[slices][np.where(x[slices] == maxes[mask_view])] = dout[loc].flat

    if not backprop:
        return out
    else:
        return dx

def max_pool_forward_naive(x, pool_param):
    """
    A naive implementation of the forward pass for a max pooling layer.

    Inputs:
    - x: Input data, of shape (N, C, H, W)
    - pool_param: dictionary with the following keys:
      - 'pool_height': The height of each pooling region
      - 'pool_width': The width of each pooling region
      - 'stride': The distance between adjacent pooling regions

    Returns a tuple of:
    - out: Output data
    - cache: (x, pool_param)
    """

    pool_shape = (pool_param['pool_height'], pool_param['pool_width'])
    cache = (x, pool_param)
    return max_pool(x, pool_shape, pool_param['stride'], (2, 3)), cache

def max_pool_backward_naive(dout, cache):
    """
    A naive implementation of the backward pass for a max pooling layer.

    Inputs:
    - dout: Upstream derivatives
    - cache: A tuple of (x, pool_param) as in the forward pass.

    Returns:
    - dx: Gradient with respect to x
    """
    x, pool_param = cache
    pool_shape = (pool_param['pool_height'], pool_param['pool_width'])
    return max_pool(x, pool_shape, pool_param['stride'], (2, 3), backprop=True, dout=dout)

def spatial_batchnorm_forward(x, gamma, beta, bn_param):
    """
    Computes the forward pass for spatial batch normalization.

    Inputs:
    - x: Input data of shape (N, C, H, W)
    - gamma: Scale parameter, of shape (C,)
    - beta: Shift parameter, of shape (C,)
    - bn_param: Dictionary with the following keys:
      - mode: 'train' or 'test'; required
      - eps: Constant for numeric stability
      - momentum: Constant for running mean / variance. momentum=0 means that
        old information is discarded completely at every time step, while
        momentum=1 means that new information is never incorporated. The
        default of momentum=0.9 should work well in most situations.
      - running_mean: Array of shape (D,) giving running mean of features
      - running_var Array of shape (D,) giving running variance of features

    Returns a tuple of:
    - out: Output data, of shape (N, C, H, W)
    - cache: Values needed for the backward pass
    """
    out, cache = None, None

    N, C, H, W = x.shape
    out, cache = batchnorm_forward(x.reshape(-1, C), gamma, beta, bn_param)

    #############################################################################
    # TODO: Implement the forward pass for spatial batch normalization.         #
    #                                                                           #
    # HINT: You can implement spatial batch normalization using the vanilla     #
    # version of batch normalization defined above. Your implementation should  #
    # be very short; ours is less than five lines.                              #
    #############################################################################
    pass
    #############################################################################
    #                             END OF YOUR CODE                              #
    #############################################################################

    return out.reshape(N, C, H, W), cache

def spatial_batchnorm_backward(dout, cache):
    """
    Computes the backward pass for spatial batch normalization.

    Inputs:
    - dout: Upstream derivatives, of shape (N, C, H, W)
    - cache: Values from the forward pass

    Returns a tuple of:
    - dx: Gradient with respect to inputs, of shape (N, C, H, W)
    - dgamma: Gradient with respect to scale parameter, of shape (C,)
    - dbeta: Gradient with respect to shift parameter, of shape (C,)
    """
    dx, dgamma, dbeta = None, None, None
    N, C, H, W = dout.shape

    dx, dgamma, dbeta = batchnorm_backward_alt(dout.reshape(-1, C), cache)
    #############################################################################
    # TODO: Implement the backward pass for spatial batch normalization.        #
    #                                                                           #
    # HINT: You can implement spatial batch normalization using the vanilla     #
    # version of batch normalization defined above. Your implementation should  #
    # be very short; ours is less than five lines.                              #
    #############################################################################
    pass
    #############################################################################
    #                             END OF YOUR CODE                              #
    #############################################################################

    return dx.reshape(N, C, H, W), dgamma, dbeta

def svm_loss(x, y):
    """
    Computes the loss and gradient using for multiclass SVM classification.

    Inputs:
    - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
      for the ith input.
    - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
      0 <= y[i] < C

    Returns a tuple of:
    - loss: Scalar giving the loss
    - dx: Gradient of the loss with respect to x
    """
    N = x.shape[0]
    correct_class_scores = x[np.arange(N), y]
    margins = np.maximum(0, x - correct_class_scores[:, np.newaxis] + 1.0)
    margins[np.arange(N), y] = 0
    loss = np.sum(margins) / N
    num_pos = np.sum(margins > 0, axis=1)
    dx = np.zeros_like(x)
    dx[margins > 0] = 1
    dx[np.arange(N), y] -= num_pos
    dx /= N
    return loss, dx

def softmax_loss(x, y):
    """
    Computes the loss and gradient for softmax classification.

    Inputs:
    - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
      for the ith input.
    - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
      0 <= y[i] < C

    Returns a tuple of:
    - loss: Scalar giving the loss
    - dx: Gradient of the loss with respect to x
    """
    probs = np.exp(x - np.max(x, axis=1, keepdims=True))
    probs /= np.sum(probs, axis=1, keepdims=True)
    N = x.shape[0]
    loss = -np.sum(np.log(probs[np.arange(N), y])) / N
    dx = probs.copy()
    dx[np.arange(N), y] -= 1
    dx /= N
    return loss, dx


import requests
import base64
class OpenHab:

    def __init__(self):
        self.openhab_host = "localhost"
        self.openhab_port = "8080"

    def post_command(self, key, value):
        print("appel de post_command(" + key +","+ value +")")
        """ Post a command to OpenHAB - key is item, value is command """
        url = 'http://%s:%s/rest/items/%s'%(self.openhab_host,
                                    self.openhab_port, key)
        try:
            req = requests.post(url, data=value,
                                    headers=self.basic_header())
        except requests.ConnectionError:
            print (" Erreur dans l'adressage du serveur openHab")

    def put_status(self, key, value):
        """ Put a status update to OpenHAB  key is item, value is state """
        url = 'http://%s:%s/rest/items/%s/state'%(self.openhab_host,
                                    self.openhab_port, key)
        req = requests.put(url, data=value, headers=self.basic_header())
        if req.status_code != requests.codes.ok:
            req.raise_for_status()

    def get_status(self, name):
        """ Request updates for any item in group NAME from OpenHAB.
         Long-polling will not respond until item updates.
        """
        # When an item in Group NAME changes we will get all items in the group
        # and need to determine which has changed
        url = 'http://%s:%s/rest/items/%s'%(self.openhab_host,
                                        self.openhab_port, name)
        payload = {'type': 'json'}
        try:
            req = requests.get(url, params=payload,
                                headers=self.polling_header())
            if req.status_code != requests.codes.ok:
                req.raise_for_status()
            # Try to parse JSON response
            # At top level, there is type, name, state, link and members array
            members = req.json()["members"]
            for member in members:
                # Each member has a type, name, state and link
                name = member["name"]
                state = member["state"]
                do_publish = True
                # Pub unless we had key before and it hasn't changed
                if name in self.prev_state_dict:
                    if self.prev_state_dict[name] == state:
                        do_publish = False
                self.prev_state_dict[name] = state
                if do_publish:
                    self.publish(name, state)
        except:
            print("error located in openhab.py")

    def basic_header(self):
        """ Header for OpenHAB REST request - standard """
        """self.auth = base64.encodestring('%s:%s'
                           %(self.username, self.password)
                           ).replace('\n', '')"""
        return {
                #"Authorization" : "Basic %s" %self.auth,
                "Content-type": "text/plain"}


"""
The wrapper over the spaCy's Tokenizer for `English`,`German`,`Spanish`,`Portuguese`,`French`,`Italian`, and `Dutch`.
 Based on the library's documentation website, the tokenization algorithm can be summarized as follows:
    1. Iterate over space-separated substrings
    2. Check whether we have an explicitly defined rule for this substring. If we do, use it.
    3. Otherwise, try to consume a prefix.
    4. If we consumed a prefix, go back to the beginning of the loop, so that special-cases always get priority.
    5. If we didn't consume a prefix, try to consume a suffix.
    6. If we can't consume a prefix or suffix, look for "infixes" — stuff like hyphens etc.
    7. Once we can't consume any more of the string, handle it as a single token.
For more info regarding the tokenizer please see the "Tokenization" part of https://spacy.io/usage/linguistic-features
A valid use case of the tokenizer wrapper class could be:
    SpaCyTokenizer().tokenize("This is a test", LanguageIdentifier.en)
"""
from typing import List

import spacy

from translate.readers.constants import LanguageIdentifier as LId

__author__ = "Hassan S. Shavarani"

class SpaCyTokenizer:
    def __init__(self):
        """
        The tokenizer performs lazy instantiation of the models. You don't need multiple instances of this class for
         tokenization of sentences from different languages.
        """
        self._models = {}
        self._supported_languages = [LId.en, LId.de, LId.es, LId.pt, LId.fr, LId.it, LId.nl]

    def tokenize(self, text: str, lang_identifier: LId, lower_case: bool = False) -> List[str]:
        """
        :param text: the string to be tokenized
        :param lang_identifier: one of the langugage values defined in `translate.readers.constants.LanguageIdentifier`
        :param lower_case: the flag indicating whether the resulting tokens need to be lower-cased or not.
        :return: the list of tokenized strings
        """
        if lang_identifier not in self._supported_languages:
            raise ValueError("SpaCyTokenizer cannot tokenize utterances in \"{}\"".format(lang_identifier.name))
        if lang_identifier not in self._models:
            try:
                self._models[lang_identifier] = spacy.load(lang_identifier.name)
            except OSError:
                raise EnvironmentError("The spaCy resources for \"{0}\" might not be installed correctly, please try "
                                       "running the following command in your comman-line before running this project\n"
                                       "python -m spacy download {0}".format(lang_identifier.name))
        tokenized_document = self._models[lang_identifier].tokenizer(text)
        if lower_case:
            return [token.text.lower() for token in tokenized_document]
        else:
            return [token.text for token in tokenized_document]


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time    : 2020/6/3 11:10
@Author  : WangHuan
@Contact : hi_chengzi@126.com
@File    : data.py
@Software: PyCharm
@description: 读取excel中的数据方便testcase直接使用
"""

import os
import json
import xlrd

class ReadData(object):

    def __init__(self, filename):
        scr_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        data_path = os.path.join(scr_path, "data", filename)
        data_open = xlrd.open_workbook(data_path)
        self.data_excel = data_open.sheet_by_index(0)

    def get_url(self):
        '''
        获取请求的url
        :return:
        '''
        url = self.data_excel.cell(1, 3).value
        return url

    def get_method(self, case_name):
        '''
        获取请求类型
        :param case_name:
        :return:
        '''
        return self.get_case(case_name=case_name)[4]

    def get_data(self, case_name):
        '''
        获取请求数据，转化为字典格式
        :param case_name:
        :return:
        '''
        return json.loads(self.get_case(case_name)[6])

    def get_expect(self, case_name):
        '''
        期望结果
        :param case_name:
        :return:
        '''
        return self.get_case(case_name)[7]

    def get_case(self, case_name):
        '''
        根据case_name找到对应用例行
        :param case_name:
        :return: 用例所在行
        '''

        for i in range(1, self.data_excel.nrows):
            if self.data_excel.cell(i, 1).value == case_name:
                return self.data_excel.row_values(i)

        print("用例名称未找到")
        return None

if __name__ == '__main__':
    data = ReadData("test_login_data.xlsx")
    url = data.get_url()
    method = data.get_method("test_login_normal")
    json = data.get_data("test_login_normal")
    expect = data.get_expect("test_login_normal")
    print(url, method)
    print(type(json))
    print(json)
    print(expect)


# Importamos los módulos y bibliotecas necesarios para realizar este programa
import http.client
import json

# Empleamos un código que utiliza la biblioteca http.client que hemos importado para leer repositorios
headers = {'User-Agent': 'http-client'}
conn = http.client.HTTPSConnection("api.fda.gov")
conn.request("GET", "/drug/label.json?limit=10", None, headers) # Con limit=10 encontraremos 10 medicamentos distintos
r1 = conn.getresponse()
print(r1.status, r1.reason)
repos_raw = r1.read().decode("utf-8")
conn.close()
informacion = json.loads(repos_raw)

# sabemos que en la página a la que accedemos el contenido es json y json se encuentra en forma de diccionario por tanto utilizamos las funciones de un diccionario para encontrar los diferentes elementos
medicamento_info=informacion["results"]

# Indexamos entre los distintos elementos de la página para imprimir los diez que hay en ella
for i in range(len(medicamento_info)):
    info = medicamento_info[i]
    print("Id del medicamento:",info["id"])


from PyQt5.QtCore import QThread, pyqtSignal
import socket
import errno

class ClientThread(QThread):
    oppo = pyqtSignal(str)
    rply = pyqtSignal(str)
    error = pyqtSignal(str)
    rematch = pyqtSignal(str)
    draw = pyqtSignal(str)

    def __init__(self, username, ip, parent=None):
        super(ClientThread, self).__init__(parent)
        self.username = username
        self.ip = ip

    def run(self):
        rcv = False
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.s.connect((self.ip, 1234))
            self.s.sendall(bytes(self.username, 'utf-8'))
        except ConnectionRefusedError as e:
            self.error.emit("nTarget Refused to Connect")

        try:
            while True:
                msg = self.s.recv(10)
                msg = msg.decode('utf-8')

                if not rcv:
                    self.oppo.emit(msg)
                    rcv = True

                elif msg == "D":
                    self.draw.emit(msg)

                elif msg == "R":
                    self.rematch.emit(msg)

                else:
                    self.rply.emit(msg)

        except IOError as e:
            if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
                if rcv:
                    self.error.emit("yOpponent Disconnected")

        except Exception as e:
            self.error.emit('yUnknown Error: {}'.format(str(e)))

    def send(self, data):
        self.s.sendall(bytes(data, "utf-8"))


# Macros and libararies
from math import isinf
from numpy import array, zeros, full, argmin, inf, ndim
import numpy as np
import torch as T
import torch.nn as nn
import torch.nn.functional as F

def _traceback(D):
    i, j = array(D.shape) - 2
    p, q = [i], [j]
    while (i > 0) or (j > 0):
        tb = argmin((D[i, j], D[i, j + 1], D[i + 1, j]))
        if tb == 0:
            i -= 1
            j -= 1
        elif tb == 1:
            i -= 1
        else:  # (tb == 2):
            j -= 1
        p.insert(0, i)
        q.insert(0, j)
    return array(p), array(q)

def dtw(x, y, dist, warp=1, w=inf, s=1.0):
    """
    Computes Dynamic Time Warping (DTW) of two sequences.
    :param array x: N1*M array
    :param array y: N2*M array
    :param func dist: distance used as cost measure
    :param int warp: how many shifts are computed.
    :param int w: window size limiting the maximal distance between indices of matched entries |i,j|.
    :param float s: weight applied on off-diagonal moves of the path. As s gets larger, the warping path is increasingly biased towards the diagonal
    Returns the minimum distance, the cost matrix, the accumulated cost matrix, and the wrap path.
    """
    assert len(x)
    assert len(y)
    assert isinf(w) or (w >= abs(len(x) - len(y)))
    assert s > 0
    r, c = len(x), len(y)
    if not isinf(w):
        D0 = full((r + 1, c + 1), inf)
        for i in range(1, r + 1):
            D0[i, max(1, i - w):min(c + 1, i + w + 1)] = 0
        D0[0, 0] = 0
    else:
        D0 = zeros((r + 1, c + 1))
        D0[0, 1:] = inf
        D0[1:, 0] = inf
    D1 = D0[1:, 1:]  # view
    for i in range(r):
        for j in range(c):
            if (isinf(w) or (max(0, i - w) <= j <= min(c, i + w))):
                D1[i, j] = dist(x[i], y[j])
    C = D1.copy()
    jrange = range(c)
    for i in range(r):
        if not isinf(w):
            jrange = range(max(0, i - w), min(c, i + w + 1))
        for j in jrange:
            min_list = [D0[i, j]]
            for k in range(1, warp + 1):
                i_k = min(i+k, r)
                j_k = min(j+k, c)
                min_list += [D0[i_k, j] * s, D0[i, j_k] * s]
            D1[i, j] += min(min_list)
    if len(x) == 1:
        path = zeros(len(y)), range(len(y))
    elif len(y) == 1:
        path = range(len(x)), zeros(len(x))
    else:
        path = _traceback(D0)
    return D1[-1, -1], C, D1, path

# We define two sequences x, y as numpy array
# where y is actually a sub-sequence from x
x = np.array([2, 0, 1, 1, 2, 4, 2, 1, 2, 0]).reshape(-1, 1)
y = np.array([1, 1, 2, 4, 2, 1, 2, 0]).reshape(-1, 1)

euclidean_norm = lambda x, y: np.abs(x - y)

d, cost_matrix, acc_cost_matrix, path = dtw(x, y, dist=euclidean_norm)

# You can also visualise the accumulated cost and the shortest path
import matplotlib.pyplot as plt

plt.imshow(acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest')
plt.plot(path[0], path[1], 'w')
#plt.show()

# this cannot handle inf, -\rho * x too big, e^{- \rho * x} close to 0
def smooth_min(x, rho=10):
  eps = 1e-12
  val =  -1/rho * T.log(T.mean(T.exp(x * (-rho))) + eps)
  assert val!=float('inf'), T.mean(T.exp(x * (-rho)))
  return val

rho = 10
x = T.tensor([100.0,  2.0231, 100.0])
print (smooth_min(x,rho))

# 1d min func is 1

# this will serve as a loss function
def _traceback(D):
    i, j = array(D.shape) - 2
    p, q = [i], [j]
    while (i > 0) or (j > 0):
        tb = argmin((D[i, j], D[i, j + 1], D[i + 1, j]))
        if tb == 0:
            i -= 1
            j -= 1
        elif tb == 1:
            i -= 1
        else:  # (tb == 2):
            j -= 1
        p.insert(0, i)
        q.insert(0, j)
    return array(p), array(q)

def diff_dtw_loss(x, y, dist, warp=1, w=inf, s=1.0, rho=40):
    """ differentiable dtw, takes two sequences and
    compute the distance under the metric
    x, y is a tensor seq_len x dim
    dist is a bi-variate function
    """

    assert x.shape[0]
    assert y.shape[0]
    assert isinf(w) or (w >= abs(len(x) - len(y)))
    assert s > 0

    MAX_VAL = 1e2

    r, c = x.shape[0], y.shape[0]
    if not isinf(w):
        D0 = T.full((r + 1, c + 1), MAX_VAL)
        for i in range(1, r + 1):
            D0[i, max(1, i - w):min(c + 1, i + w + 1)] = 0
        D0[0, 0] = 0
    else:
        D0 = T.zeros(r + 1, c + 1)
        D0[0, 1:] = MAX_VAL
        D0[1:, 0] = MAX_VAL
    D1 = D0[1:, 1:]  # view
    for i in range(r):
        for j in range(c):
            #print("dtw size", x.size(), y.size())
            if (isinf(w) or (max(0, i - w) <= j <= min(c, i + w))):
                D1[i, j] = dist(x[0][i], y[0][j])
    C = D1.clone()
    jrange = range(c)
    for i in range(r):
        if not isinf(w):
            jrange = range(max(0, i - w), min(c, i + w + 1))
        for j in jrange:
            min_list = D0[i, j]
            for k in range(1, warp + 1):
                #                 print(i+k, r)
                i_k = min(i + k, r)
                j_k = min(j + k, c)
                min_list = T.cat((T.tensor([min_list], requires_grad=True), \
                                  T.tensor([D0[i_k, j] * s], requires_grad=True), \
                                  T.tensor([D0[i, j_k] * s], requires_grad=True)))
                # Softmin is NOT a smooth min function
            min_val = smooth_min(min_list, rho)
            # print('min:', i, j, min_val, min_list)
            D1[i, j] = D1[i, j] + min_val
    if len(x) == 1:
        path = zeros(len(y)), range(len(y))
    elif len(y) == 1:
        path = range(len(x)), zeros(len(x))
    else:
        path = _traceback(D0)
    return D1[-1, -1], C, D1, path

x = np.array([2, 0, 1, 1, 2, 4, 2, 1, 2, 0], dtype=np.float32).reshape(-1, 1)
y = np.array([1, 1, 2, 4, 2, 1, 2, 0], dtype=np.float32).reshape(-1, 1)

tensor_x = T.tensor(T.from_numpy(x), requires_grad=True)
tensor_y = T.tensor(T.from_numpy(y), requires_grad=True)

euclidean_norm = lambda x, y: T.abs(x - y)

#diff_d, diff_cost_matrix, diff_acc_cost_matrix, diff_path = diff_dtw_loss(tensor_x, tensor_y, dist=euclidean_norm)

#print('distance', diff_d, 'diff distance:', diff_d.detach().numpy())
#diff_acc_cost_matrix = diff_acc_cost_matrix.detach().numpy()
# print(acc_cost_matrix)

# You can also visualise the accumulated cost and the shortest path
import matplotlib.pyplot as plt

#fig, (ax1, ax2) = plt.subplots(1, 2)
#fig.suptitle('Original and Differentiable Accumated Cost Matrix')
#ax1.imshow(acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest')
#ax1.plot(path[0], path[1], 'w')
#ax2.imshow(diff_acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest')
#ax2.plot(diff_path[0], diff_path[1], 'w')

# plt.imshow(acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest')
# plt.plot(path[0], path[1], 'w')
# plt.show()

import torch as T
from torch.nn import functional as F

from torch.nn.modules import Module

class _Loss(Module):
    def __init__(self, size_average=None, reduce=None, reduction='mean', _Reduction=None):
        super(_Loss, self).__init__()
        if size_average is not None or reduce is not None:
            self.reduction = _Reduction.legacy_get_string(size_average, reduce)
        else:
            self.reduction = reduction

class DTW_Loss(_Loss):
  def __init__(self, rho=10, size_average=None, reduce=None, reduction='mean'):
    super(DTW_Loss, self).__init__(size_average, reduce, reduction)
    self.rho = rho

  def forward(self, output, target):
    # batch x seq_len x dim
    if ndim(output)==3:
      dist = []
      for b in range(output.size(0)):
          #print("sizes", output.size(), target.size())
          d_b, cost_matrix, diff_acc_cost_matrix, diff_path = diff_dtw_loss(output[b], target[b], dist=euclidean_norm, rho=rho)
          dist.append(d_b)
      d = T.mean(T.stack(dist))
    else:
      d, cost_matrix, diff_acc_cost_matrix, diff_path = diff_dtw_loss(output, target, dist=euclidean_norm, rho=rho)
    #F.mse_loss(output, target, reduction=self.reduction)
    loss_val =  d #.detach().numpy()
    return loss_val

x = np.array([2, 0, 1, 1, 2, 4, 2, 1, 2, 0], dtype=np.float32).reshape(1, -1, 1)
y = np.array([1, 1, 2, 4, 2, 1, 2, 0], dtype=np.float32).reshape(1, -1, 1)

tensor_x = T.tensor(T.from_numpy(x),requires_grad=True)
tensor_y = T.tensor(T.from_numpy(y),requires_grad=True)
loss_vals = []

rhos = np.linspace(1, 10,10)
#for rho in rhos:
  #print(rho)
  #my_loss = DTW_Loss(rho)
  #loss_vals.append(my_loss(tensor_x, tensor_y))


import cPickle
import gzip
import os.path
import sys
from subprocess import PIPE, Popen
from warnings import warn

import yaml

from koert.gnucash.xmlformat import SaxHandler

def open_gcf_in_git_repo(repopath, filepath, cachepath=None, scheme=None):
    from git import Repo

    repo = Repo(repopath)
    commit = repo.head.commit
    mtime = commit.authored_date
    f = commit.tree[filepath].data_stream

    result = parse_gcf(f, mtime, cachepath=cachepath, scheme=scheme)

    f.read()

    return result

def open_pos_gzipped(filepath):
    f = None
    try:
        # Only after a byte is read,  is the check whether filepath
        # points to a gzipped file performed.
        f = gzip.open(filepath)
        f.read(1)
        f.rewind()
    except IOError:
        # message should read: "Not a gzipped file"
        f = open(filepath)
    return f

def saxparse(f, handler):
    from xml.sax import parse as saxparse
    saxparse(f, handler)

def lxmlparse(f, handler):
    from lxml.etree import parse as lxmlparse
    from lxml.sax import saxify
    etree = lxmlparse(f)
    saxify(etree, handler)

def cache_path(filepath):
    return filepath + ".pickled"

def get_commit_name():
    directory = os.path.dirname(__file__)
    p = Popen('git rev-parse HEAD',
              stdout=PIPE, shell=True, cwd=directory)
    outp, err = p.communicate()
    return outp

def load_cache(cachepath, mtime):
    if not os.path.exists(cachepath):
        return False
    # Do not use the cache if the gnucash file is newer
    if mtime >= os.path.getmtime(cachepath):
        return False
    with open(cachepath, "r") as f:
        current_commit_name = get_commit_name()
        try:
            cached_commit_name, gcf = cPickle.load(f)
            if cached_commit_name != current_commit_name:
                return False
            print("loaded cache %s" % cachepath)
            return gcf
        except Exception as e:
            warn("Failed to load pickled cache of Gnucash file "
                 "'%s': %s" % (cachepath, repr(e)))
            return False

def update_cache(cachepath, gcf):
    if sys.getrecursionlimit() < 2000:
        sys.setrecursionlimit(2000)
    with open(cachepath, "w") as f:
        try:
            cPickle.dump((get_commit_name(), gcf), f)
        except RuntimeError as e:
            warn("""Failed to dump a pickled version of the \
gnucash file "%s" due to the RuntimeError below.  If this is a stack \
overflow, you might want to increase the maximum recursion depth by \
sys.setrecursionlimit.""")
            raise e

def parse_gcf(f, mtime, scheme=None, parse=saxparse, cachepath=None):
    if cachepath is not None:
        result = load_cache(cachepath, mtime)
        if result:
            return result
    handler = SaxHandler(scheme)
    parse(f, handler)
    result = handler.result
    result.mtime = mtime
    update_cache(cachepath, result)
    return result

def open_gcf(filepath, scheme=None, parse=saxparse, cachepath=None):
    if cachepath is None:
        cachepath = cache_path(filepath)
    with open(filepath) as f:
        return parse_gcf(f, os.path.getmtime(filepath),
                         scheme=scheme, parse=parse, cachepath=cachepath)

def open_yaml(path):
    with open(path) as f:
        d = yaml.load(f)

    dirname = os.path.dirname(path)
    gcf_path = os.path.join(dirname, d['path'])
    cache_path = None
    if "cache" in d:
        cache_path = os.path.join(dirname, d['cache'])
    gcf = None
    if 'repo' in d:
        repo_path = os.path.join(dirname, d['repo'])
        gcf = open_gcf_in_git_repo(repo_path, d['path'], cachepath=cache_path)
    else:
        gcf = open_gcf(gcf_path, cachepath=cache_path)
    if 'meta' in d:
        gcf.meta = d['meta']

    return gcf


import sys
import json
from splunklib.searchcommands import dispatch, StreamingCommand, Configuration, Option
from splunklib.searchcommands.validators import Fieldname
import environment_data

@Configuration(local=True)
class EnvironmentInstancesUpdateState(StreamingCommand):

    state_field = Option(validate=Fieldname())
    name_field = Option(validate=Fieldname())

    def stream(self, instances):
        for instance in instances:
            environment_id = instance["environment_id"]
            instance_state = instance[self.state_field]
            instance_name = instance[self.name_field]

            self.service.post("/services/msaas/environments/%s/instances/%s" % (environment_id, instance_name), body=json.dumps({
                "state": instance_state,
            }))
            # environment_data.update_instance(
            # self.service, environment_id, instance_name,
            # instance_state=instance_state)
            yield instance

dispatch(EnvironmentInstancesUpdateState,
         sys.argv, sys.stdin, sys.stdout, __name__)


import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = './config/My Project-bd8af4dfa881.json'
from google.cloud import texttospeech
import base64
import subprocess
from pydub import AudioSegment
from pydub.playback import play
import io

def create_google_sst(text):
    client = texttospeech.TextToSpeechClient()
    synthesis_input = texttospeech.types.SynthesisInput(text=text)
    voice = texttospeech.types.VoiceSelectionParams(
            name="en-US-Wavenet-F",
            language_code='en-US',
            ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE
        )
    audio_config = texttospeech.types.AudioConfig(
            audio_encoding=texttospeech.enums.AudioEncoding.MP3,
            pitch=2.0,
            speaking_rate=1.26
        )

    response = client.synthesize_speech(synthesis_input, voice, audio_config)
    audio = base64.b64decode(response.audio_content)

    song = AudioSegment.from_file(io.BytesIO(audio), format="mp3")
    play(song)

create_google_sst("how can I help you ?")


import sys, subprocess
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QTreeWidget, QTreeWidgetItem, QGroupBox, QPushButton, QApplication
from PyQt5 import QtCore

class MyApp(object):
    def __init__(self):
        super(MyApp, self).__init__()
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)

        self.hLayout = QHBoxLayout()
        self.mainLayout.insertLayout(0, self.hLayout)

        self.listA=QTreeWidget()
        self.listA.setColumnCount(3)
        self.listA.setHeaderLabels(['Checkbox','Name','Data'])
        for i in range(3):
            item=QTreeWidgetItem()
            item.setCheckState(0, 2)
            item.setText(1, 'Item '+str(i))
            item.setData(2, 256, id(item) )
            item.setText(2, str(id(item) ) )
            self.listA.addTopLevelItem(item)

        self.hLayout.addWidget(self.listA)

        self.buttonGroupbox = QGroupBox()
        self.buttonlayout = QVBoxLayout()
        self.buttonGroupbox.setLayout(self.buttonlayout)

        okButton = QPushButton('Remove Selected')
        okButton.clicked.connect(self.removeSel)
        self.buttonlayout.addWidget(okButton)

        getDataButton = QPushButton('Get Items Data')
        getDataButton.clicked.connect(self.getItemsData)
        self.buttonlayout.addWidget(getDataButton)

        self.mainLayout.addWidget(self.buttonGroupbox)
        self.mainWidget.show()
        sys.exit(app.exec_())

    def removeSel(self):
        listItems = []
        for i in range(self.listA.topLevelItemCount()):
            item=self.listA.topLevelItem(i)
            print("item", item)
            if (item.checkState(0) == 2):
                listItems.append(item)

        print("listItems: ",listItems)

        for item in listItems:
            print("item: ", item)
            itemIndex=self.listA.indexOfTopLevelItem(item)
            print("itemIndex", itemIndex)
            self.listA.takeTopLevelItem(itemIndex)
        print('\n\t Number of items remaining', self.listA.topLevelItemCount())

    def getItemsData(self):
        for i in range(self.listA.topLevelItemCount()):
            item=self.listA.topLevelItem(i)
            itmData=item.data(2, 256)
            print('\n\t Item Id Stored as Item Data:', itmData, 'Item Checkbox State:', item.checkState(0))

if __name__ == '__main__':
    what = subprocess.Popen(['adb', 'devices',  '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, errs = what.communicate()
    out = str(out, 'utf-8')
    outs = out.split()
    del outs[0:4]
    length = len(outs)
    n = length/6
    struct = [[] for i in range(int(n))]
    for i in range(int(n)):
        print(n, i)
        struct[i] = outs[i*6:(i+1)*6]
        print(struct[i])
    app = QApplication(sys.argv)
    MyApp()


import tornado.ioloop
import tornado.web
import psycopg2.extras
import notorm
import tornado.autoreload

class Game(notorm.record):
    _fields = {'id':None,
               'name':None
    }

    insert_qry = """
    insert into game (name)
    values(%(name)s)
    returning id
    """

    update_qry = """
    update game set name=%(name)s where id = %(id)s
    """

    @classmethod
    def get(cls, game_id):
        cursor = notorm.db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
        cursor.execute("""select game.*::game from game where id = %(game_id)s""",
                                 {'game_id': game_id})

        results = cursor.fetchall()
        games = notorm.build_relationships(results, 'game')
        if not games:
            return None
        return games[0]

    @classmethod
    def get_all(cls):
        cursor = notorm.db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
        cursor.execute("""select game.*::game from game order by name""")

        results = cursor.fetchall()
        games = notorm.build_relationships(results, 'game')
        return games

class GameComposite(psycopg2.extras.CompositeCaster):
    def make(self, values):
        d = dict(zip(self.attnames, values))
        return Game(**d)

class ExampleRequestHandler(tornado.web.RequestHandler):
    def on_finish(self):
        notorm.db.commit()

    def log_exception(self, typ, value, tb):
        print("Exception")
        notorm.db.rollback()
        return super(ExampleRequestHandler, self).log_exception(typ, value, tb)

class MainHandler(ExampleRequestHandler):
    def get(self):
        games = Game.get_all()
        self.render("../main.html", games=games)

class GameHandler(ExampleRequestHandler):
    def get(self, game_id=None):
        if game_id:
            game = Game.get(game_id)
        else:
            game = Game()
        self.render("../edit.html", game=game)

    def post(self, game_id=None):
        if game_id:
            game = Game.get(game_id)
        else:
            game = Game()
        game.name = self.get_argument('name')
        game.save()
        self.redirect("/")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
        (r"/game/new", GameHandler),
        (r"/game/([0-9]+)", GameHandler)
    ])

if __name__ == "__main__":
    notorm.db = psycopg2.connect("dbname=notorm_example user=dbuser")

    cursor = notorm.db.cursor()
    psycopg2.extras.register_composite('game', cursor, globally=True, factory = GameComposite)
    app = make_app()
    app.listen(8888)
    tornado.autoreload.start(tornado.ioloop.IOLoop.current())
    tornado.ioloop.IOLoop.current().start()


import random
from datetime import datetime, timedelta

from Person import Person

class Place:

    def __init__(self, place_info):
        self.population = set()
        self.place_info = place_info  # (40.760265, -73.989105, 'Italian', '217', '291', 'Ristorante Da Rosina')
        self.time_to_recover = 14
        self.total_infected_number = 0
        self.immune_population = set()

    def get_population(self):
        return self.population

    def get_total_infected(self):
        return self.total_infected_number

    def set_population(self, new_population):
        self.population = new_population

    def set_total_movements(self, number):
        self.total_movements = number
        self.init_population(self.total_movements)  # initilise population according to place popularity

    def init_population(self, number):
        start_time = datetime(2010, 12, 21, 20, 0, 0)
        for i in range(number):
            person = Person()
            # infect with a certain probability
            if random.random() <= 0.001:
                person.set_infected(start_time)
            self.add_person(person)

    def get_total_movements(self):
        return self.total_movements

    def add_person(self, person):
        self.population.add(person)

    def incubate_cycle(self, current_time_o):
        ''' Process local population at a place and yield a new cycle of infections '''

        # set recovered timedelta(days=1): set time_to_recover, current_time
        infected_pop = [p for p in self.population if p.get_status() == 1]
        recovered_pop = [p.set_immune(current_time_o) for p in infected_pop if
                         current_time_o - p.get_time_infected() > timedelta(days=self.time_to_recover)]
        infected_pop = set(infected_pop).difference(recovered_pop)  # infected pop - recovered
        # print (len(infected_pop))
        # print (len(recovered_pop))
        # print (len(self.population))
        # print ('----')

        # calculate number of infected people
        total_infected = len(infected_pop)
        # if total_infected == 0:
        # 	#if there is no infected person at place, no one else can be infected (ie do not execute code below)
        # 	return

        total_pop = len(self.population)

        # calculate susceptible to infection
        susceptible_pop = self.population.difference(infected_pop)
        susceptible_pop = susceptible_pop.difference(self.immune_population)
        self.immune_population = self.immune_population.union(recovered_pop)

        # calculate probability of infection
        if total_pop == 0:
            prob_infection = 0.0
        else:
            prob_infection = total_infected / total_pop

        # calculate newly infected number
        newly_infected_num = int(len(susceptible_pop) * prob_infection)

        # set newly infected persons accordingly
        newly_infected_pop = random.choices(tuple(susceptible_pop), k=newly_infected_num)
        for i in range(newly_infected_num):
            newly_infected_pop[i].set_infected(current_time_o)

        # count number infected
        self.total_infected_number = len(infected_pop) + newly_infected_num

    def set_recovered(self):
        ''' Process local population and yield a new cycle of recoveries (death case will be added later)'''
        pass


from Acquisition import aq_parent
from ftw.solr.interfaces import ISolrSearch
from ftw.solr.query import make_filters
from opengever.base.browser.navigation import make_tree_by_url
from opengever.base.interfaces import IOpengeverBaseLayer
from opengever.base.solr import OGSolrDocument
from opengever.repository.interfaces import IRepositoryFolder
from opengever.repository.repositoryfolder import REPOSITORY_FOLDER_STATE_INACTIVE
from opengever.repository.repositoryroot import IRepositoryRoot
from plone.app.contentlisting.interfaces import IContentListingObject
from plone.restapi.interfaces import IExpandableElement
from plone.restapi.serializer.converters import json_compatible
from plone.restapi.services import Service
from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot
from zExceptions import BadRequest
from zope.component import adapter
from zope.component import getUtility
from zope.dottedname.resolve import resolve
from zope.interface import implementer
from zope.interface import Interface

@implementer(IExpandableElement)
@adapter(Interface, IOpengeverBaseLayer)
class Navigation(object):

    FIELDS = [
        'UID',
        'path',
        'portal_type',
        'review_state',
        'Title',
        'title_de',
        'title_en',
        'title_fr',
        'Description',
        'filename',
        'has_sametype_children',
        'is_subdossier',
        'dossier_type',
    ]

    def __init__(self, context, request):
        self.context = context
        self.request = request
        self.solr = getUtility(ISolrSearch)

    def __call__(self, expand=False):
        root_interface = self.get_root_interface()
        content_interfaces = self.get_content_interfaces()

        if self.request.form.get('include_root'):
            content_interfaces.append(root_interface)

        result = {
            'navigation': {
                '@id': '{}/@navigation'.format(self.context.absolute_url()),
            },
        }

        if not expand:
            return result

        root = self.find_root(root_interface, content_interfaces)
        solr_docs = self.query_solr(root, content_interfaces)

        nodes = map(self.solr_doc_to_node, solr_docs)
        result['navigation']['tree'] = make_tree_by_url(nodes)

        return result

    def find_root(self, root_interface, content_interfaces):
        context = self.context

        if root_interface not in content_interfaces:
            while (not root_interface.providedBy(context)
                   and not IPloneSiteRoot.providedBy(context)):
                context = aq_parent(context)
        else:
            # This happens i.e. on lookup a dossier tree from a subdossier.
            #
            # The current context is the subdossier which is also
            # providing the root_interface. We have to get sure, that we return
            # the most upper object providing the given root_interface if
            # the root_interface is within `content_interfaces`
            current = context
            while (not IPloneSiteRoot.providedBy(current)):
                if root_interface.providedBy(current):
                    context = current
                current = aq_parent(current)

        if root_interface.providedBy(context):
            root = context
        else:
            response = self.solr.search(
                filters=make_filters(
                    object_provides=root_interface.__identifier__),
                sort='path asc',
                fl=["path"],
            )
            roots = [OGSolrDocument(d) for d in response.docs]

            if roots:
                root = roots[0].getObject()
            else:
                raise BadRequest("No root found for interface: {}".format(
                    root_interface.__identifier__))
        return root

    def query_solr(self, root, content_interfaces):
        query = {
            'object_provides': [i.__identifier__ for i in content_interfaces],
            'path_parent': '/'.join(root.getPhysicalPath()),
            'trashed': 'false',
        }

        review_states = self.request.form.get('review_state', [])
        if review_states:
            query['review_state'] = review_states

        filters = make_filters(**query)

        if self.request.form.get('include_context'):
            # Include context branch's UIDs in the query, by adding them as
            # a filter that is OR'ed with the main filters (which themselves
            # are AND'ed together). This is necessary because restrictions
            # from the main filters must not be applied to the context branch.
            context_uids = list(self.get_context_branch_uids(root))
            if context_uids:
                context_filter = make_filters(UID=context_uids)[0]
                main_filters = self._join_filters(make_filters(**query), 'AND')
                filters = self._join_filters([main_filters, context_filter], 'OR')

        resp = self.solr.search(
            filters=filters,
            sort='sortable_title asc',
            rows=10000,
            fl=self.FIELDS)

        return [OGSolrDocument(doc) for doc in resp.docs]

    def get_context_branch_uids(self, root):
        """Return UIDs of the current context's chain up to the root.
        """
        for item in self.context.aq_chain:
            item_uid = item.UID()
            if item_uid == root.UID():
                break
            yield item_uid

    def _lookup_iface_by_identifier(self, identifier):
        return resolve(identifier) if identifier else None

    def _join_filters(self, filters, op):
        op = ' %s ' % op
        return op.join(['(%s)' % flt for flt in filters])

    def get_root_interface(self):
        """Lookups the root_interface provided within the request parameter.

        This interface is used as the navigation root identifier.
        """
        interface = self.request.form.get('root_interface')
        try:
            return self._lookup_iface_by_identifier(
                interface) or IRepositoryRoot
        except ImportError:
            raise BadRequest("The provided `root_interface` could not be "
                             "looked up: {}".format(interface))

    def get_content_interfaces(self):
        """Lookups the content_interfaces provided within the request parameter.

        The interfaces provided in `content_interfaces` are used as navigation
        items.
        """
        interfaces = self.request.form.get('content_interfaces')
        if not interfaces:
            return [IRepositoryFolder]

        if not isinstance(interfaces, list):
            interfaces = [interfaces]

        content_interfaces = []
        for interface in interfaces:
            try:
                content_interfaces.append(
                    self._lookup_iface_by_identifier(interface))
            except ImportError:
                raise BadRequest("The provided `content_interfaces` could not be "
                                 "looked up: {}".format(interface))
        return content_interfaces

    def solr_doc_to_node(self, solr_doc):
        wrapper = IContentListingObject(solr_doc)
        context_url = self.context.absolute_url()

        node = {
            '@type': wrapper.portal_type,
            'text': wrapper.Title(),
            'description': wrapper.Description(),
            'url': wrapper.getURL(),
            'uid': wrapper.UID,
            'active': wrapper.review_state() != REPOSITORY_FOLDER_STATE_INACTIVE,
            'current': context_url == wrapper.getURL(),
            'current_tree': context_url.startswith(wrapper.getURL()),
            'is_leafnode': None,
            'is_subdossier': wrapper.is_subdossier,
            'review_state': wrapper.review_state(),
            'dossier_type': wrapper.dossier_type,
        }
        if wrapper.portal_type == 'opengever.repository.repositoryfolder':
            node['is_leafnode'] = not wrapper.has_sametype_children
        return json_compatible(node)

class NavigationGet(Service):

    def reply(self):
        navigation = Navigation(self.context, self.request)
        return navigation(expand=True)['navigation']


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

import base64
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Hash import SHA256
import pylzma
import os
import sys
sys.path.insert(0, os.path.abspath('./encrepo'))
import hash_helper
import pack
import time

BS = 32
AES_KEY_SIZE = 32 #Key is 256 bit
pad = lambda s : s if len(s) % AES_KEY_SIZE == 0 else \
        s + (AES_KEY_SIZE - len(s) % AES_KEY_SIZE) \
            * chr(AES_KEY_SIZE - len(s) % AES_KEY_SIZE)

unpad = lambda s : s if len(s) % AES_KEY_SIZE == 0 else \
        s[:-ord(s[len(s)-1])]

class AESCipher:
    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

raw_info = """awsome text goes here,
        U cannot see me,
        One good turn deserves another"""

with open('/home/xin/iprule') as input_file:
    raw_info = input_file.read()

key = 'abcdefghijklmnopqrstuvwxyz123456'

key = pad(key)

AES_KEY = 'asdfas2"%H:%M:%'

def test_compressed():
    print("key=%s  length:%d"%(key,len(key)))
    print("Original length of data:%d"%len(raw_info))

    raw_hash = hash_helper.hash_str(raw_info)
    print("Original hash:%s"%raw_hash)
    h = SHA256.new()
    h.update(raw_info)
    print("Original hashA:%s"%h.hexdigest())

    compressed_info = pylzma.compress(raw_info)

    print("compressed length of data:%d"%len(compressed_info))

    cf = AESCipher(key)
    encrypted = cf.encrypt(compressed_info)
    decrypted = cf.decrypt(encrypted)
    print("encrypted length of data:%d"%len(encrypted))
    decompressed = pylzma.decompress(decrypted)
    print("Decrypted hash:%s"%hash_helper.hash_str(decompressed))

def test_run1():
    print("Original length of data:%d"%len(raw_info))
    raw_hash = hash_helper.hash_str(raw_info)
    print("Original hash:%s"%raw_hash)

    cf = AESCipher(key)
    encrypted = cf.encrypt(raw_info)
    print("length of encrypted data:%d"%len(encrypted))
    compressed_info = pylzma.compress(encrypted)
    print("compressed length of encrypted data:%d"%len(compressed_info))

    decompressed = pylzma.decompress(compressed_info)
    decrypted = cf.decrypt(decompressed)
    print("Decrypted hash:%s"%hash_helper.hash_str(decrypted))

def test_run2():
    info = "the red fox jumps over the lazy dog\n"
    more_info = lambda i : '' if i ==0 else \
            more_info(i-1) + 'Line {0:10d} : {1}'.format(i, info) * 100
    with open('/tmp/test.txt','w') as afile:
        afile.write(more_info(100))
    t0 = time.time()
    print(t0)
    t1 = t0
    t2 = t1
    print('{0}:....total={1:20f}, step={2:20f}'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))

def noautorun_test_pack_large():
    t0 = time.time()
    print(t0)
    t1 = t0
    t2 = t1

    print('{0}:....total={1:12f}, step={2:12f}..starting'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))

    #test_file = '/tmp/Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4'
    test_file = '/home/xin/下载/头脑特工队.Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4'
    with open(test_file) as afile:
        dgst_original = hash_helper.hash_file(afile)
    #dgst_original ='370cbba5943b5ba6ab868e9f0e098d8ccb8aa5f7396f82ebe22ac6a072c001f8'
    print("Original SHA256:%s"%dgst_original)
    t2 = time.time()
    print('{0}:....total={1:12f}, step={2:12f}..dgst original'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))
    t1 = t2
    packed_file_name = '/tmp/Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4.pack'
    unpacked_file_name = '/tmp/Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.unpack.mp4'
    pack.pack_file(AES_KEY, test_file, packed_file_name)
    t2 = time.time()
    print('{0}:....total={1:12f}, step={2:12f}..packing..'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))
    t1 = t2
    pack.unpack_file(AES_KEY, packed_file_name, unpacked_file_name)
    t2 = time.time()
    print('{0}:....total={1:12f}, step={2:12f}..Unpacking..'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))
    t1 = t2
    with open(unpacked_file_name) as newfile:
        dgst_new = hash_helper.hash_file(newfile)

    t2 = time.time()
    print('{0}:....total={1:12f}, step={2:12f}..dgst result..'.format(
                time.strftime("%H:%M:%S", time.localtime(t0)),
                t2 - t0,
                t2 - t1))
    t1 = t2
    print("New SHA256:%s"%dgst_new)
    assert dgst_original == dgst_new

def noautorun_test_pad():
    with open('/tmp/3.mp4') as afile:
        s = afile.read()
        print(hash_helper.hash_str(s))
        encrypted = pack.encrypt(AES_KEY, s)
        decrypted = pack.decrypt1(AES_KEY, encrypted)
        print(hash_helper.hash_str(decrypted))
        print(unpad(hash_helper.hash_str(decrypted)))

def split_file_writer(file_name, split_size=32):
    file_size = split_size * 2 ** 20
    sum_len = [0]
    def write_file(buf):
        sum_len[0] += len(buf)
        file_no = sum_len[0] // file_size
        new_filename = file_name if file_no==0 else file_name+'.'+('0000'+str(file_no))[-4:]
        with open(new_filename,'a') as afile:
            afile.write(buf)
    return write_file

def split_file_reader(file_name):
    files = [open(file_name,'r')]
    file_no = [0]
    def read_file(buf_size):
        buf = files[0].read(buf_size)
        if len(buf) == 0:
            file_no[0] += 1
            files[0].close()
            try:
                files[0] = open(file_name+'.'+('0000'+str(file_no[0]))[-4:])
                return read_file(buf_size)
            except IOError:
                return ''
        else:
            return buf
    return read_file

def tester_split():
    original_file_name = '/home/xin/下载/头脑特工队.Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4'
    splited_file_name = '/tmp/new/inside.out.mp4'
    recombined_file_name = '/tmp/inside.out.recombined.mp4'
    writer = split_file_writer(splited_file_name)

    with open(original_file_name) as afile:
        buf = afile.read(65536)
        while len(buf) >0 :
            writer(buf)
            buf = afile.read(65536)

def tester_combine():
    original_file_name = '/home/xin/下载/头脑特工队.Inside.Out.2015.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4'
    splited_file_name = '/tmp/new/inside.out.mp4'
    recombined_file_name = '/tmp/inside.out.recombined.mp4'
    reader = split_file_reader(splited_file_name)
    with open(recombined_file_name,'w') as afile:
        buf = reader(65536)
        while len(buf)>0:
            afile.write(buf)
            buf = reader(65536)

    dgst1 = hash_helper.hash_file(open(original_file_name))
    dgst2 = hash_helper.hash_file(open(recombined_file_name))

    assert dgst1 == dgst2

tester_combine()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from commons import logger
import os

import yaml
from appium import webdriver

logger = logger.Logger().getLogger()

def appium_desired():
    dirname = os.path.dirname(os.path.dirname(__file__))
    filename = os.path.join(dirname, 'config/kyb_caps.yaml')
    with open(filename, 'r', encoding='utf-8') as file:
        data = yaml.load(file)

    base_dir = os.path.dirname(os.path.dirname(__file__))
    app_path = os.path.join(base_dir, 'app', data['appname'])
    desired_caps = {
        "platformName": data['platformName'],
        "platformVersion": data['platformVersion'],

        "deviceName": data['deviceName'],
        "udid": data['udid'],

        "app": app_path,
        "appPackage": data['appPackage'],
        "appActivity": data['appActivity'],

        "automationName": data['automationName'],
        "noReset": data['noReset'],

        "unicodeKeyboard": data['unicodeKeyboard'],
        "resetKeyboard": data['resetKeyboard']
    }
    logger.info('start app......')

    driver = webdriver.Remote('http://' + str(data['ip']) + ':' + str(data['port']) + '/wd/hub', desired_caps)
    driver.implicitly_wait(3)
    return driver

if __name__ == '__main__':
    appium_desired()


#!/usr/bin/python3

import spaceking.net as net
import spaceking.common as com
import spaceking.log as log
import spaceking.event as ev

import shutil
import atexit
import os
import tempfile
import asyncio
import socket

EVT_SERVER_RUNNING = 15000
EVT_SERVER_QUIT = 15001
EVT_SERVER_CONNECTED = 15002
EVT_SERVER_DISCONNECTED = 15003
EVT_SERVER_FAILED_JOIN = 15004
EVT_SERVER_FAILED_CLIENT = 15005
EVT_SERVER_NEW_CLIENT = 15006
EVT_SERVER_DISCONNECTED_CLIENT = 15007

class ServerClient:

    __slots__ = ["uid", "addr", "reader", "writer"]

    def __init__(self, uid, addr, reader, writer):
        self.uid = uid
        self.addr = addr
        self.reader = reader
        self.writer = writer

    def __str__(self):
        return "client: uid={0}, addr={1}".format(self.uid, self.addr)

class ServerConnection(net.Connection):
    """Game server"""

    MAX_CLIENTS = 16

    def __init__(self,
                 bind_to=None,
                 loop=asyncio.get_event_loop(),
                 socket_type="tcp"):
        """NOTE: with socket_type = unix, the bind_to needs to be None or a
           temporary directory. This directory is removed on exit."""
        super().__init__()
        self.clients = []
        self.server = None
        self._uid_cursor = 0  # ringbuf cur.
        self.loop = loop

        self.proto_map = {
            "tcp": self._start_tcp_server,
            "unix": self._start_unix_server
        }
        if socket_type not in self.proto_map:
            raise ValueError("socket type: {0} not valid.".format(socket_type))
        self.socket_type = socket_type

        if bind_to is None:
            if socket_type == "unix":
                self.bind_to = self._unique_unix_socket_path()
            else:
                self.bind_to = "localhost"
        else:
            self.bind_to = bind_to

        self.register_handler(net.EVT_PACKET_SEND, self.handle_packet_send)

    def _unique_unix_socket_path(self):
        directory = tempfile.mkdtemp(prefix="sock-serv", dir=com.CONFIG_HOME)
        sock_name = "socket"
        return os.path.join(directory, "socket")

    def _create_client(self, uid, *args, **kwargs):
        client = ServerClient(uid, *args, **kwargs)
        self._add_client(client)

        def create_evt(pkt):
            return net.NetEvent(net.EVT_PACKET_RECV, uid, pkt)

        # Server listens for client packets
        coro = self.listen_packets(client.reader, create_evt)
        task = asyncio.Task(coro, loop=self.loop)
        # Cleanup on socket death
        task.add_done_callback(lambda t: self.disconnect_client(client, t))
        return client

    def _add_client(self, client):
        self.clients.append(client)

    def _remove_client_by_uid(self, uid):
        for idx, client in enumerate(self.clients):
            if idx == uid:
                del self.clients[idx]

    def _get_client_by_uid(self, uid):
        for idx, client in enumerate(self.clients):
            if client.uid == uid:
                return self.clients[idx]

    def _next_uid(self):
        # Spawn new unique client ID. ring used for simplicity.
        uid = self._uid_cursor
        self._uid_cursor = (uid + 1) % ServerConnection.MAX_CLIENTS
        return uid

    def get_client_count(self):
        return len(self.clients)

    @asyncio.coroutine
    def accept_client(self, reader, writer):
        uid = self._next_uid()

        remote_addr = self._get_addr(writer)
        if remote_addr is None:
            log.warn("Error on client uid={0} connect.".format(uid))
            return

        client = self._create_client(uid, remote_addr, reader, writer)

        yield from self.notify(net.NetEvent(EVT_SERVER_NEW_CLIENT, uid))
        log.info("{0} connected.".format(client))

    @asyncio.coroutine
    def handle_packet_send(self, event):
        client = self._get_client_by_uid(event.uid)
        if client is None:
            return
        try:
            yield from self.send_packets(client.writer, event.pkt)
        except socket.error as err:
            log.debug("Error while sending packets to {0}".format(client))
            self.disconnect_client(client)
            return

    def disconnect_client_by_uid(self, uid):
        # task of disconnect notification is returned
        self._remove_client_by_uid(uid)
        event = net.NetEvent(EVT_SERVER_DISCONNECTED_CLIENT, uid)

        task = asyncio.Task(self.notify(event), loop=self.loop)
        return task

    def disconnect_client(self, client, client_task=None):
        if client_task:
            try:
                result = client_task.result()
            except Exception as err:
                msg = "{0} completed with an error. {1}".format(client, err)
                log.debug(msg)

        log.info("{0} disconnected.".format(client))
        self.disconnect_client_by_uid(client.uid)

    def _start_server(self, coro):
        try:
            self.server = self.loop.run_until_complete(coro)
        except Exception as err:
            log.error("server connection crashed on startup")
            raise err

    def _start_tcp_server(self):
        self._start_server(asyncio.start_server(self.accept_client,
                                                loop=self.loop,
                                                host=self.bind_to,
                                                port=net.SERVER_PORT,
                                                reuse_address=True))

    def _start_unix_server(self):
        def socket_cleanup():
            shutil.rmtree(os.path.dirname(self.bind_to))
            log.debug("UNIX socket {0} cleaned up.".format(self.bind_to))

        atexit.register(socket_cleanup)
        self._start_server(asyncio.start_unix_server(self.accept_client,
                                                     path=self.bind_to,
                                                     loop=self.loop))

    def start_server(self):
        self.proto_map[self.socket_type]()

        log.info("spaceking server listening.")
        self.notify(net.NetEvent(EVT_SERVER_RUNNING, None))

    def quit(self):
        log.debug("spaceking server connection shutting down.")
        if self.server:
            self.server.close()
            self.server = None
            self.notify(net.NetEvent(EVT_SERVER_QUIT, None))
        else:
            log.debug("Calling quit on a dead server")


# coding:utf-8

import logging
import psutil
import time
import json
import winreg
import requests
import os
import subprocess
import globalvar as gl
from urllib.parse import parse_qs

logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
#logging.disable(logging.CRITICAL)   # 加这句话，就是log全部禁止，不加，就可以log打印了

# 定义函数，两个参数，都是python本身定义的，默认就行了。
def application(environ, start_response):

    recordLog('start in webapi')
    # 定义文件请求的类型和当前请求成功的code
    try:
        start_response('200 OK', [('Content-Type', 'application/json;charset=utf-8')])
        d = parse_qs(environ['QUERY_STRING'])
        recordLog(environ['QUERY_STRING'])
        key = d.get('key', [''])[0] # 返回第一个age值.
        recordLog(key)
    except Exception as err:
        recordLog('web err!')
        recordLog(str(err))

    # 获取服务器的硬件运行信息
    if key=='getinfo':
        info=sysInfo()
        json_str = json.dumps(info,ensure_ascii=False,indent=4)
        recordLog('record getinfo')
        recordLog(json.dumps(json_str))
        return [json_str.encode('utf-8')]

    # 主动触发服务器下载最新版的热更新
    elif key=='download':
        info = {"status": "download"}
        try:
            res =requests.get(r'http://47.75.120.191:83/PCInfoService.exe',timeout=30)
        except Exception as err:
            info = {"status":str(err)}
            recordLog(str(err))

        down=os.path.join(getPath(),'PCInfoService.exe')

        try:
            downloadFile = open(down,'wb')
            for chunk in res.iter_content(100000):
                downloadFile.write(chunk)
            #recordLog(os.path.getsize(downloadFile))
            downloadFile.close()
            info = {"status":"download finish"}

            recordLog("download finish")

            WriteRestartCmd()
            recordLog("update Start")
            recordLog("shutdown")

        except Exception as err:
            recordLog(str(err))
            info = {"status":str(err)}

        finally:
            return [json_str.encode('utf-8')]

    else:
        logging.debug('Noget')
        info = {"status": "none"}
        json_str = json.dumps(info,ensure_ascii=False,indent=4)
        return [json_str.encode('utf-8')]

#编写bat脚本，删除旧程序，运行新程序
def WriteRestartCmd():
    os.chdir(getPath())
    b = open("upgrade.bat",'w')
    TempList = "@echo off\n";   #关闭bat脚本的输出
    TempList += "if not exist pcinfoservice.exe exit \n";    #新文件不存在,退出脚本执行
    TempList += "sc stop pcinfo \n"
    TempList += "ping /n 5 127.1>nul \n"   #5秒后删除旧程序（3秒后程序已运行结束，不延时的话，会提示被占用，无法删除）
    TempList += "del PCInfo.exe /q \n"
    TempList += "ren PCInfoService.exe PCInfo.exe \n"
    TempList += "pcinfo.exe install \n"
    TempList += "sc start pcinfo \n"
    TempList += "sc config pcinfo start= auto"
    b.write(TempList)
    b.close()
    subprocess.Popen("upgrade.bat")

def recordLog(strmsg): #把strmsg写入日志

    os.chdir(getPath())
    try:
        logFile = open(r'web.log','a')
        logFile.write(get_time_stamp()+'  ') #写入日志
        logFile.write(strmsg+'\n')
    except Exception as err:
        logFile.write(get_time_stamp()+'  ') #写入日志
        logFile.write('write web.log err!\n')
        pass
    finally:
        logFile.close()
    return

def sysInfo():
    info={}

    line={}
    try:
        line.setdefault('CPU核心',str(psutil.cpu_count()))
        line.setdefault('CPU利用率',str(int(psutil.cpu_percent())) + '%')
        info['CPU']=line

        line={}
        line.setdefault('空闲内存G',str(round(psutil.virtual_memory().free/(1024.0*1024.0*1024.0), 2)))
        line.setdefault('总内存G',str(int(round(psutil.virtual_memory().total/(1024.0*1024.0*1024.0)))))
        line.setdefault('内存利用率',str(int((psutil.virtual_memory().total-psutil.virtual_memory().free)/float(psutil.virtual_memory().total)*100))+ '%')
        info['Memory'] =line

        line={}

        io = psutil.disk_partitions()
        j=0
    except Exception as err:
        recordLog(str(err))

    for i in io:
        diskstr=[]
        try:
            o = psutil.disk_usage(i.device)
        except Exception as err:
            recordLog(str(err))
            j=j+1
            continue

        disk=io[j][0].strip(r':\\')
        diskstr.append(str(int(o.free/(1024.0*1024.0*1024.0)))+"G")
        diskstr.append(str(int(o.total/(1024.0*1024.0*1024.0)))+"G")
        line.setdefault(disk,diskstr)
        del(diskstr)
        j=j+1

    info['Disk']=line
    try:
        info.setdefault('version',gl.getvalue('version'))
    except Exception as err:
        recordLog("version write err")

    return info

def getPath():
    #获取服务执行程序的路径
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,r"SYSTEM\CurrentControlSet\Services\PCInfo")
        downloadPath =winreg.QueryValueEx(key,"ImagePath")
        path=os.path.dirname(downloadPath[0][1:])
    except Exception as err:
        path=r'c:\windows\system32'
        recordLog('Path change err: '+ str(err))
    return path

def get_time_stamp():
    ct = time.time()
    local_time = time.localtime(ct)
    data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
    data_secs = (ct - int(ct)) * 1000
    time_stamp = "%s.%03d" % (data_head, data_secs)
    return time_stamp