from builtins import range
import numpy as np

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)
    """
    N = x.shape[0]
    M = w.shape[1]
    D = np.prod(x.shape[1:])
    xShaped = np.reshape(x, (N, D))
    b = b.reshape(M,)
    out = np.dot(xShaped, w) + b
    cache = (x, 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)

    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
    M = dout.shape[1]
    N = x.shape[0]
    D = np.prod(x.shape[1:])

    dx = dout.dot(w.T).reshape(x.shape)
    dw = x.reshape(N, D).T.dot(dout)
    db = np.sum(dout, 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
    dx = np.array(dout, copy=True)

    dx[x < 0] = 0

    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 paremeter 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':
        # taken from :
        # https://kratzert.github.io/2016/02/12/understanding-the-gradient-flow-through-the-batch-normalization-layer.html
        #step1: calculate mean
        mu = 1./N * np.sum(x, axis = 0)

        #step2: subtract mean vector of every trainings example
        xmu = x - mu

        #step3: following the lower branch - calculation denominator
        sq = xmu ** 2

        #step4: calculate variance
        var = 1./N * np.sum(sq, axis = 0)

        #step5: add eps for numerical stability, then sqrt
        sqrtvar = np.sqrt(var + eps)

        #step6: invert sqrtwar
        ivar = 1./sqrtvar

        #step7: execute normalization
        xhat = xmu * ivar

        #step8: Nor the two transformation steps
        gammax = gamma * xhat

        #step9
        out = gammax + beta

        #store intermediate
        cache = (xhat,gamma,xmu,ivar,sqrtvar,var,eps)
        running_mean = momentum * running_mean + (1 - momentum) * mu
        running_var = momentum * running_var + (1 - momentum) * var

    elif mode == 'test':
        # substract meaan
        xzeroed = x - running_mean

        # divide by the variance, mul with gamma and add beta
        out = gamma * xzeroed / np.sqrt(running_var + eps) + 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,)
    """
    dx, dgamma, dbeta = None, None, None

    #unfold the variables stored in cache
    xhat,gamma,xmu,ivar,sqrtvar,var,eps = cache

    #get the dimensions of the input/output
    N,D = dout.shape

    # taken from:
    # https://kratzert.github.io/2016/02/12/understanding-the-gradient-flow-through-the-batch-normalization-layer.html
    #step9
    dbeta = np.sum(dout, axis=0)
    dgammax = dout #not necessary, but more understandable

    #step8
    dgamma = np.sum(dgammax*xhat, axis=0)
    dxhat = dgammax * gamma

    #step7
    divar = np.sum(dxhat*xmu, axis=0)
    dxmu1 = dxhat * ivar

    #step6
    dsqrtvar = -1. /(sqrtvar**2) * divar

    #step5
    dvar = 0.5 * 1. /np.sqrt(var+eps) * dsqrtvar

    #step4
    dsq = 1. /N * np.ones((N,D)) * dvar

    #step3
    dxmu2 = 2 * xmu * dsq

    #step2
    dx1 = (dxmu1 + dxmu2)
    dmu = -1 * np.sum(dxmu1+dxmu2, axis=0)

    #step1
    dx2 = 1. /N * np.ones((N,D)) * dmu

    #step0
    dx = dx1 + dx2

    return dx, dgamma, dbeta

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
    """
    dx, dgamma, dbeta = None, None, None
    ###########################################################################
    # TODO: Implement the backward pass for batch normalization. Store the    #
    # results in the dx, dgamma, and dbeta variables.                         #
    #                                                                         #
    # After computing the gradient with respect to the centered inputs, you   #
    # should be able to compute gradients with respect to the inputs in a     #
    # single statement; our implementation fits on a single 80-character line.#
    ###########################################################################
    pass
    ###########################################################################
    #                             END OF YOUR CODE                            #
    ###########################################################################

    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: 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 # first dropout mask. Notice /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 = dout * mask
    elif mode == 'test':
        dx = dout
    return dx

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)
    """
    out = None

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

    # pad the image with zeros as defined in the conv_param
    paddedX = np.pad(x, ((0,), (0,), (pad,),(pad, )), 'constant')
    N, C, H, W = x.shape
    F, C, filterH, filterW = w.shape

    # calculate the output size of image after conv
    hTag = int(1 + (H + 2 * pad - filterH) / stride)
    wTag = int(1 + (W + 2 * pad - filterW) / stride)
    out = np.zeros((N, F, hTag, wTag))

    # Run for each [image,filter, pixel hight, pixel width]
    for n in range(N):
        for f in range(F):
            for i in range(hTag):
                for j in range(wTag):
                    # compute the activation of a given pixel in image n using filter f by dot product of the patch with the
                    # filter and add the bias term to the filter
                    out[n, f, i, j] = np.sum(paddedX[n,:, i*stride:i*stride + filterH, j*stride:j*stride + filterW] * w[f,:]) + b[f]

    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
    F, C, hFilter, wFilter = w.shape
    N, nChannels, hOut, wOut = dout.shape
    stride = conv_param['stride']
    pad = conv_param['pad']
    x_pad = np.pad(x, [(0, 0), (0, 0), (pad, pad), (pad, pad)],'constant')
    dw, db, dx = np.zeros_like(w), np.zeros_like(b), np.zeros_like(x_pad)

    # Run for each image
    for n in range(N):
        #Get the padded input image that we passed throw this layer
        image = x_pad[n, :, :, :]

        # Run for each channel we calculated, e.g filter
        for channel in range(nChannels):

            # Scan the entire image
            for i in range(hOut):
                for j in range(wOut):

                    # Get the current patch we want to use for caclulating the gradient
                    image_patch = image[:, (i*stride):(i*stride + hFilter), (j*stride):(j*stride + wFilter)]

                    # The gradient with respect to W(channel, i,j) is the sum of image patches(X) multypled with the upstream derevarive
                    dw[channel, :, :, :] += image_patch * dout[n, channel, i, j]

                    # The gradient with respect to b(channel) is the sum  upstream gradients of filter f
                    db[channel] += dout[n, channel, i, j]
                    # The gradient with respect to x is a multiplication of the f W filter with the upstram gradient of this channel
                    dx[n, :, (i*stride):(i*stride + hFilter), (j*stride):(j*stride + wFilter)] += w[channel, :, :, :] * dout[n, channel, i,j]

    dx = dx[:, :, pad:-pad, pad:-pad] # delete padding
    ###########################################################################
    #                             END OF YOUR CODE                            #
    ###########################################################################
    return dx, dw, db

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)
    """
    N, C, H, W = x.shape
    hPool = pool_param['pool_height']
    wPool = pool_param['pool_width']
    stridePool = pool_param['stride']
    hTag = int(1 + (H - hPool) / stridePool)
    wTag = int(1 + (W - wPool) / stridePool)
    out = np.zeros((N, C, hTag, wTag))

    # Run for each [image,filter, pixel hight, pixel width]
    for n in range(N):
        for c in range(C):
            for i in range(hTag):
                for j in range(wTag):
                    # Take the max value from this patch
                    out[n, c, i, j] = np.max(x[n,c, i*stridePool:i*stridePool + hPool, j*stridePool:j*stridePool + wPool])
    cache = (x, pool_param)
    return out, 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
    N, C, H, W = x.shape
    N, nChannels, hOut, wOut = dout.shape
    hPool = pool_param['pool_height']
    wPool = pool_param['pool_width']
    stridePool = pool_param['stride']
    hTag = int(1 + (H - hPool) / stridePool)
    wTag = int(1 + (W - wPool) / stridePool)
    dx = np.zeros((N,C,H,W))

    for n in range(N):
        for c in range(C):
            for i in range(hTag):
                for j in range(wTag):
                        # Find the index of the max value from the patch, and put stream the gradient of the max pooling
                        # through this index
                    arrInd = np.argmax(x[n,c, i*stridePool:i*stridePool + hPool, j*stridePool:j*stridePool + wPool])
                    cordInd = np.unravel_index(arrInd, (hPool, wPool))
                    dx[n,c, i*stridePool + cordInd[0], j*stridePool + cordInd[1]] = dout[n, c, i, j]

    return dx

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

    ###########################################################################
    # 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.                            #
    ###########################################################################
    N, C, H, W = x.shape
    x_reshaped = x.transpose(0,2,3,1).reshape(N*H*W, C)
    out_tmp, cache = batchnorm_forward(x_reshaped, gamma, beta, bn_param)
    out = out_tmp.reshape(N, H, W, C).transpose(0, 3, 1, 2)

    return out, 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

    ###########################################################################
    # 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.                            #
    ###########################################################################
    N, C, H, W = dout.shape
    dout_reshaped = dout.transpose(0,2,3,1).reshape(N*H*W, C)
    dx_tmp, dgamma, dbeta = batchnorm_backward(dout_reshaped, cache)
    dx = dx_tmp.reshape(N, H, W, C).transpose(0, 3, 1, 2)

    return dx, 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
    """
    shifted_logits = x - np.max(x, axis=1, keepdims=True)
    Z = np.sum(np.exp(shifted_logits), axis=1, keepdims=True)
    log_probs = shifted_logits - np.log(Z)
    probs = np.exp(log_probs)
    N = x.shape[0]
    loss = -np.sum(log_probs[np.arange(N), y]) / N
    dx = probs.copy()
    dx[np.arange(N), y] -= 1
    dx /= N
    return loss, dx


import numpy as np
import pytest
import torch

from tsbatteries import preprocessing
from tsbatteries.preprocessing.pipeline import (PipelineCompiler,
                                                PipelineDataset)
from tsbatteries.tests.helpers import make_classification_problem

@pytest.fixture()
def static_pipeline():
    pipeline = preprocessing.Pipeline(
        [
            ("negative_impute", preprocessing.NegativeFilter()),
            ("stdsc", preprocessing.TensorScaler(method="mms")),
        ]
    )
    return pipeline

@pytest.fixture()
def temporal_pipeline():
    pipeline = preprocessing.Pipeline(
        [
            ("pad", preprocessing.PadRaggedTensors()),
            ("negative_impute", preprocessing.NegativeFilter()),
            ("stdsc", preprocessing.TensorScaler(method="stdsc")),
            ("interpolation", preprocessing.Interpolation(method="linear")),
            ("backfill", preprocessing.ForwardFill(backwards=True)),
        ]
    )
    return pipeline

@pytest.fixture()
def label_pipeline():
    pipeline = preprocessing.LabelProcessor(problem="oneshot")
    return pipeline

def test_pipeline(temporal_pipeline):
    # Create random tensor data
    data = [torch.randn(5, 2) for _ in range(5)]
    assert torch.isnan(temporal_pipeline.fit_transform(data)).sum() == 0

@pytest.mark.parametrize(
    "static_dim, batch_size",
    [
        (None, None),
        (None, 32),
        (5, None),
        (5, 32),
    ],
)
def test_preprocessing_pipeline(
    static_pipeline, temporal_pipeline, label_pipeline, static_dim, batch_size
):
    # Check the preprocessing pipeline can be run effectively with and without static data
    train_data, _ = make_classification_problem(static_dim=5)
    static_data, temporal_data, labels = train_data
    temporal_data = np.array([x for x in temporal_data], dtype=object)
    if static_dim is None:
        static_data = None
        static_pipeline = None

    # Check fit transform works with full data
    dataset = PipelineDataset(static_data, temporal_data, labels)
    main_pipeline = PipelineCompiler(
        static_pipeline, temporal_pipeline, label_pipeline, batch_size=batch_size
    )
    output = main_pipeline.fit_transform(dataset)

    # Check fit transform works with and without static
    assert len(output) == 3


class Solution(object):
    def pivotIndex(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return -1
        total = sum(nums)
        leftSum = 0
        for i in range(len(nums)):
            if 2*leftSum == total - nums[i]:
                return i
            leftSum += nums[i]
        return -1


from typing import Optional, List
import collections
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root: return []
        queue = collections.deque([root])
        children = 1
        res = []
        temp = []

        while queue:
            node = queue.popleft()
            temp.append(node.val)
            children -= 1
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

            if not children:
                children = len(queue)
                res.append(temp.copy())
                temp.clear()

        return reversed(res)


import pytest

from sabnzbd.newsunpack import *

class TestNewsUnpack:
    @pytest.mark.parametrize(
        "test_input, expected_output",
        [
            (["cmd1", 9, "cmd3"], '"cmd1" "9" "cmd3"'),  # sending all commands as valid string
            (["", "cmd1", "5"], '"" "cmd1" "5"'),  # sending blank string
            (["cmd1", None, "cmd3", "tail -f"], '"cmd1" "" "cmd3" "tail -f"'),  # sending None in command
            (["cmd1", 0, "ps ux"], '"cmd1" "" "ps ux"'),  # sending 0
        ],
    )
    def test_list_to_cmd(self, test_input, expected_output):
        """ Test to convert list to a cmd.exe-compatible command string """

        res = list2cmdline(test_input)
        # Make sure the output is cmd.exe-compatible
        assert res == expected_output

    def test_is_sfv_file(self):
        assert is_sfv_file("tests/data/good_sfv_unicode.sfv")
        assert is_sfv_file("tests/data/one_line.sfv")
        assert not is_sfv_file("tests/data/only_comments.sfv")
        assert not is_sfv_file("tests/data/random.bin")


from typing import List
class Solution:
    def maxArea(self, height: List[int]) -> int:
        left=0
        right = len(height)-1
        max_area = 0
        while left < right:
            min_height = min(height[left], height[right])
            area = (right - left) * min_height
            max_area = max(area, max_area)
            if min_height == height[left]:
                left += 1
            else:
                right -= 1
        return max_area


# ben simms is a kook
import readline
import math
import random
import time
# Welcome to APBP! bruh.
# We will rule the world.

print("""
+---------++       +------------+       ++-------------+         +-----------+
|         |        |            |        |             |         |           |
|         |        |            |        |             |         |           |
|         |        |            |        |             |         |           |
|         |        +------------+        +------------++         +-----------+
+---------+        |                     |            |          |
|         |        |                     |            |          |
|         |        |                     |            |          |
|         |        |                     |            |          |
+         +        +                     +------------++         +
""") #There we go.

def armorfxn(item): #Chances for certain armor, describes the amount of health that is protected from certain armor.
    num = 0
    bbn = []
    while num <= 3:
        if item[num] == 0:
            bbn.insert(num, "no")
        elif item[num] == 5:
            bbn.insert(num, "cardboard")
        elif item[num] == 10:
            bbn.insert(num, "leather")
        elif item[num] == 15:
            bbn.insert(num, "bronze")
        elif item[num] == 20:
            bbn.insert(num, "iron")
        elif item[num] == 25:
            bbn.insert(num, "chainmail")
        num += 1
    return bbn

#### This is the main global variable setup we have here.  ###
class setup():  # chest config[0:4]: 0 = Nothing 1 = AP , 2 = sword, 3 = shotgun, 4 =  pistol # Monsters =
    def __init__(self):
    # Global and important variables
        self.bossposition = ([(random.randint(5, 10) * random.choice([-1,1]) ), random.randint(-1, 1), ( random.randint(5, 10) * random.choice([-1,1]) ) ])
        self.player_health = 200
        self.inCombat = False
        self.roomposition = [ 0 , 0 , 0 ] # x, y, z
        self.chestconfig = [10, 2, 1, 1, 2, 1] # same as inventory
        self.chestnames = ["1 sword", "2 bullets", "1 shotgun", "1 pistol", "2 shotgun shells", "1 AP"]
        self.monsterconfig = [[30, 40, 50, 60, 70], [15, 23, 30, 38, 45], [70, 90, 110, 130, 150]] # chance, damage, health
        self.rooms = [[[0 , 0 , 0 ], False , False, None, [0, 0]]] # coords, chest, monster, fallenitems, chestinv
        self.inventory = [10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0] # 0 = sword, 1 = bullets 2 = shotgun 3 = pistol 4 = shells 5 = ap 6 = keys 7 = compass 8 = helmet 9 = torso 10 = pants 11 = boots
        self.monsters = [[0, 0, 0]]
        self.exit = False
        self.fallenitems = []
        self.defense = (int(self.inventory[8] + self.inventory[9] + self.inventory[10] + self.inventory[11])/100)
        self.armorr = ["no", "cardboard", "leather", "bronze", "iron", "chainmail"]
        self.armor3 = ["helmet", "torso", "pants", "boots"]
        self.armor = [self.inventory[8], self.inventory[9], self.inventory[10], self.inventory[11]]
        self.armor2 = armorfxn(self.armor)

z1 = setup() # Makes it easier to access in the program.
z1.rooms.append([z1.bossposition, False, True]) # Sets up the boss level

def reset_def(): # This resets the inventory at the beginning of the game and also whenever you call upon it.
    z1.armor = [z1.inventory[8], z1.inventory[9], z1.inventory[10], z1.inventory[11]]
    z1.armor2 = armorfxn(z1.armor)
    z1.defense = (int(z1.inventory[8] + z1.inventory[9] + z1.inventory[10] + z1.inventory[11])/100)

# 0 = sword, 1 = bullets 2 = shotgun 3 = pistol 4 = shells 5 = ap 6 = keys 7 = compass 8 = helmet 9 = torso 10 = pants 11 = boots
def chestgen(): # This is the main code for the chest generation program. There are different items that the chests give to the player ( it gives two items from this list below)
    num = 0
    n = random.randint(8, 11)
    chestlist = [[250, [5, random.randint(1, 2)], " AP"], [375, [n, 5-z1.inventory[n]], " 1 cardboard " + z1.armor3[n-8]], [438, [n, 10-z1.inventory[n]], " 1 leather  " + z1.armor3[n-8]],
    [470, [n, 15-z1.inventory[n]], " 1 bronze  " + z1.armor3[n-8]], [490, [n, 20-z1.inventory[n]], " 1 iron " + z1.armor3[n-8]], [500, [n, 25-z1.inventory[n]], " 1 chainmail " + z1.armor3[n-8]],
    [625, [0, 1], " sword"], [688, [3, 1], " pistol"], [750, [2, 1], " shotgun"], [875, [1, random.randint(1, 10)], " bullets"], [1000, [4, random.randint(2, 5)], " shotgun shells"] ]
    a = random.randint(0, 999)
    while True:
        if a < chestlist[num][0]:
            b = chestlist[num][1]
            if a < 500 and a > 249:
                c = chestlist[num][2]
            else:
                c = str(chestlist[num][1][1]) + chestlist[num][2]
            break
        else:
            num += 1
    if b[1] > 0:
        return[b, c]
    else:
        return None

def chestgen1(): # when you open a chest it randomly gives you certain items
    a = 1
    while a != None:
        n = chestgen()
        if n == None:
            pass
        else:
            return n
### made before the whole donald trump president thing.... :p
# Drawn by me :D Donald Trump Face *it is our trump card*
trump = """
                                           XXXXXXXXX XX
                           XX X XX X XX XXXX       XX  XXX XXXXX XXXXX
                     X XXX    X    XX       X       XX       XX       XXXXXX
                XXXXX  XXX    XX    XX      XX       XX        XX          XXXX
             XXX         XX     XX    X       X        X          XX        XX XXXXX
            XX  XX         XX    XX    XX       X        X          X        XX    XX
         XXX       XX        X     X      X       X        X          X X     XXX    XX
       XXX           X X      XX   XX      X       X         X X         XXXX   XXXXXXXXXX
      XX              XX  X    X      X     XXXX    X            XX          XXXXXXXXXXXXXX
     XX                X    X X XXX    X        XXX XXX     XX     XXX XXXXXXXXXX          X
     X                XX        X  XXX  X X          XXXXXXXX   X XXXXX    XX              X
    X               XX           XXX XX    XX X         X XXXXXX             XX            X
   XX              X                XX XX      XX X      XXX                  XX            X
   X           XXX                    XX XX         XXX X                      XX           X
   X         XXX                       XXX XX  XX XX   XX                       X
  X           X                          XXXXXX                                  X          X
 XXX          X                          XX                                      X
   XXX        X                                                                   X         X
   XX          X                                              XXX                 XX
   X           X              X XXXX                         XX XXXXXXXXXXX        X       X
   X           X      XXXXXXXXXXX  XX                        X             XX      X       X
  XX          XX          X         X                        XXXX X X XX            X
  X           X     XXX XX X  X  X X X XXXX             XXXXX      XXXX XXXX        X      X
  X           X    X            XXXXXXXX   XXX         XX X    XXXXXXXX     X       X      X
  X           X    XXXXXXXXX     XX XXX      X            XXXXXXXX    X     X        X     X
  X          XX             XXXXXXXXXXXX XXXXX                   XXXX                X     X
   X         X                           XXX                                         X     X
   X        XX                         XX                                            XXXXXXX
   X        X                                                                              XXXXX
   XX      XX                                                                                XX
  XXX      XX                            XXX XXX         XXXX                          X        X
 XX         X                            X  XX  X    XXX   XX                          XXXX      X
XX          X                             XXX   X      XX XX                              XXX    X
X           X                                                                             XXX  XXX
X           X                                                                        XXXXXXXXXXX
XX          X                                                                    XXXXX XXX   X
 XX         X                            XXXXXXXXXXXX XX                         XX          XX
  XX        X                       XXXXXX               XX XXXXXX               X            X
    XXXX    X                       X     XXXXXXXXXXXXXXXXX      XX              X            XX                               X
       XX   XX                                                                   X             XX
        X    XXXX                                                                 X             X
        X      XXX                                                               XXX            XX
        X     XX  XX                                                             X  X     X       XXX
        XX  XXX    XXXX            XXX                                           X  XXXXXXXX    XXXX
         XXXX         XXXX XXXXXXXXX XX            XXXX                        XXX          XXXX
                         XXX          XXXXXX XXXXXX   XXXXXXXXX           XXXXXX
                                        XX XXX                XXXXXXXXXXXXX

"""

def open_chest(): # Basic display when opening a certain chest.
    a = chestgen1()
    z1.inventory[a[0][0]] += a[0][1]
    reset_def()
    print("You have received " + a[1] + " from the chest!")

class database(): # This is the help command database that we draw certain info from. not super necesary but fun.
    helpgame = ["help", "command", "help: gives info on a certain command or argument(item in game, direction of motion, etc.)", ""]
    use = ["use", "command", "use: attempts to use selected item or object\nSubcommands: sword, shotgun, key, pistol, compass", ""]
    move = ["move", "command", "move: moves in specified direction (north, south, east, west)", ""]
    east = ["east", "argument", "east: move east one room", ""]
    west = ["west", "argument", "west: move west one room", ""]
    north = ["north", "argument", "north: move north one room", ""]
    south = ["south", "argument", "south: move south one room", ""]
    AP = ["AP", "argument", "AP: Arnold Palmer. Drink of the Gods. Restores 25 health per use.", "drink"]
    health = ["health", "argument", "health: your total health. can be restored with certain items.", "attribute"]
    sword = ["sword", "argument", "sword: a rusty old iron sword. doesn't look like it will be very effective in combat, but its better than nothing.", "weapon"]
    shotgun = ["shotgun", "argument", "shotgun: a double barreled shotgun. looks pretty effective.", "weapon"]
    pistol = ["pistol", "argument", "pistol: a service issue m9 pistol. looks fairly good. holds 6 bullets per magazine.", "weapon"]
    compass = ["compass", "argument", "compass: tells distance from BEN SIMMS"]

x = database()

database_total = [x.helpgame, x.use, x.move, x.west, x.north, x.south, x.AP, x.health,
                    x.sword, x.shotgun, x.pistol, x.compass]

row0 = [item[0] for item in database_total]

#Definition of functions in the thing
def addlists(list1, list2): # adds lists together for other programs we have around.
    new_list =[]
    counter1 = 0
    while counter1 < len(list1) and counter1 < len(list2):
        new_list.append(int(list1[counter1]) + int(list2[counter1]))
        counter1 += 1
    return(new_list)

def isempty(listuno): # returns whether or not a given list is empty
    if len(listuno) == 0:
        return True
    else:
        return False

def indexmulti(val, list1): # This looks through multiple lists and returns items.
    list2 = list1[:]
    new_vals = []
    while list2.count(val) > 0:
        new_vals.append(list2.index(val))
        temp_val = list2.index(val)
        list2.remove(val)
        list2.insert(temp_val, '0')
    return (new_vals)

def slicemulti(indexes, list3): # This slices lists into given indexes, I beleive there is a thing that comes w/ python that does it.
    list_new = []
    num1 = 0
    while num1 < len(indexes):
        list_new.append(list3[indexes[num1]])
        num1 = int(num1) + 1
    return list_new

def combatstatus(): # when run, gives the player their status in combat.
    print("You have " + str(z1.player_health) + " health, and the monster has " + str(z1.monsters[-1][2]) + " health.")

def mondead(): # Gives items in a chest when you kill a monster. post combat function basicallly.
    if z1.monsters[-1][2] <= 0:
        z1.rooms[room_number()][2] = False
        z1.inCombat = False
        print("You have slain the monster and recieved a chest key!")
        z1.inventory[6] += 1
        a = random.randint(0, 3)
        if a == 0:
            changehealth(50)
            print("You have won the dice roll and have gained 50 health!")
        else:
            print("You lost the dice roll and did not gain 50 health.")
        if z1.rooms[1][2] == False: #once you beat the boss the game is boring, but you can go and defeat all the other monsters, this allows for our game to be easily edited for more editions.
            print(trump)
            print("You have defeated the boss! You win! You may continue wandering the dungeons at your leisure.")
        return True
    else:
        return False

def changehealth(input2): # Changes a players health.
    z1.player_health += input2
    if z1.player_health > 200:
        z1.player_health = 200

def helpgame(input1): # More help function
    if input1 == "EMPTY":
        print("Main Commands: use, move, inspect, exit\nUse 'help (subcommand)' for more info")
    else:
        print(database_total[row0.index(input1)][2])

def use(item, on, directobject): # The main function of our program. Lets the user use items.
    if item == "sword" or item == "pistol" or item == "hands" or item == "shotgun": # combat items, options
        if directobject == "self" or directobject == "myself":
            attack_monster = False
            act_on_self = True
        else:
            attack_monster = True
            act_on_self = False
    else:
        attack_monster = False
        act_on_self = False

    if item == "sword": #Gives different chances and damage info for each of the items, not very concise but it works.
        chance = 75
        damage = 40
        dist = 6
        if z1.inventory[0] > 0:
            ammo = True
        else:
            ammo = False
    elif item == "pistol":
        chance = 65
        damage = 100
        dist = 7
        if z1.inventory[1] > 0 and z1.inventory[3] > 0:
            ammo = True
            z1.inventory[1] = z1.inventory[1] - 1
        else:
            ammo = False
    elif item == "shotgun":
        chance = 100
        damage = 75
        dist = 7
        if z1.inventory[4] > 0 and z1.inventory[2] > 0:
            ammo = True
            z1.inventory[4] = z1.inventory[4] - 1
        else:
            ammo = False
    elif item == "AP": # Gives variant health to a player from AP
            if z1.inventory[5] > 0:
                ap = random.choice([["homemade", 100], ["arizona", 75], ["snapple", 50], ["jank", 25]])
                changehealth(ap[1])
                print("You chugged some " + ap[0] + " AP and gained " + str(ap[1]) + " health! #khaked")
                z1.inventory[5] -= 1
            else:
                print("You don't have enough AP you fool")
    elif item == "hands": # You can fight the monster with your hands if you don't have anything. Not suggested.
        damage = 5
        chance = 50
        dist = 1
        ammo = True
    else:
        damage = 0
        chance = 0
        dist = 0
        ammo = True
    if z1.inCombat == True: # options for when a player is "in combat"
        n2 = True
        n3 = mondead()
        while n3 == False and n2 == True:
            rng_player_damage = int(random.gauss(damage, dist))
            rng_monster_damage = round(((1-z1.defense)*int(random.gauss(z1.monsters[-1][1], 3))))
            if attack_monster == True: # Attacks a monster
                if ammo == False:
                    print("This weapon is all used up!")
                elif random.randint(0, 100) <= chance:
                    z1.monsters[-1][2] -= rng_player_damage
                    print("You did " + str(rng_player_damage) + " damage!")
                else:
                    print("You missed")
            elif act_on_self == True: # kills yourself (mostly for testing)
                if ammo == False:
                    print("You do not have enough ammo!")
                elif random.randint(0, 100) <= chance:
                    changehealth(-rng_player_damage)
                    print("You did " + str(rng_player_damage) + " damage! The original value was " + str(rng_player_damage) + " but you blocked " + str((z1.defense)*(rng_player_damage)) + " damage!")
                else:
                    print("You missed")
            else: # if you aren't lucky, you can miss the monster fully.
                print("you did nothing. get RKO'ed")

            n3 = mondead() # This explains how much damage the monster does and howm much your armor helps.
            if z1.monsters[-1][2] > 0:
                time.sleep(.5)
                if random.randint(0, 100) <= z1.monsters[-1][0]:
                    changehealth(-rng_monster_damage)
                    print("The monster did " + str(rng_monster_damage) + " damage! The original value was " + str(rng_monster_damage + (round(rng_monster_damage/(1-z1.defense))*z1.defense)) + " but you blocked " + str(round(rng_monster_damage/(1-z1.defense))*z1.defense) + " damage!")
                else:
                    print("The monster missed!")
                n2 = False
    else:
        if act_on_self == True:
            rng_player_damage = int(random.gauss(damage, dist))
            if ammo == False:
                print("You do not have enough ammo!")
            elif random.randint(0, 100) <= chance:
                changehealth(-rng_player_damage)
                print("You did " + str(rng_player_damage) + " damage! The original value was " + str(rng_player_damage) + " but you blocked " + str((z1.defense)*(rng_player_damage)) + " damage!")
            else:
                print("You missed")
        elif item == "compass": # Shows how far away you are from the boss room with a little twist ;)
            print("You are about " + str(int(math.pow(int(math.pow(abs(z1.roomposition[0] - z1.bossposition[0]), 2) + math.pow(abs(z1.roomposition[2] - z1.bossposition[2]), 2)), .5))) + " rooms away from the boss.")
            try:
                print("You are about " + str(int(math.pow(int(math.pow(abs(z1.roomposition[0] - z1.rooms[(item[3] for item in z1.rooms).index(True)][0][0]), 2) + math.pow(abs(z1.roomposition[2] - z1.rooms[(item[3] for item in z1.rooms).index(True)][0][0]), 2)), .5))) + " rooms away from your fallen inventory.")
            except:
                pass
        elif item == "key" and directobject == "chest" and ( z1.rooms[room_number()][1] ): # opens the chest. gives peopel things if they have keys.
            if z1.inventory[6] > 0:
                z1.inventory[6] -= 1
                open_chest()
                open_chest()
                z1.rooms[room_number()][1] = False
            else:
                print("You don't have enough keys! Kill monsters!")

# Gives information on a given subject.
def inspect(object1): #unnecessary when we have to still make things work.
    if object1 == "monster" or object1 == "boss" or object1 == "ben simms":
        if z1.monsters[-1][0] > 0:
            return("The monster has " + str(z1.monsters[-1][2]) + " health, a " + str(z1.monsters[-1][0]) + " percent chance to hit, and does " + str(z1.monsters[-1][1]) + " damage per successful hit.")
        else:
            print("There is no monster here!")
    elif object1 == "self":
        return("You have " + str(z1.player_health) + " health! Your current defense value is " + str(z1.defense*100) + ". You are wearing " + z1.armor2[0] + " helmet, " + z1.armor2[1] + " breastplate, " + z1.armor2[2] + " pants, " + z1.armor2[3] + " boots.")
    elif object1 == "door":
        return("There are four rusty doors around you, one in each direction.")
    elif object1 == "inventory":
        return("In your inventory you have " + str(int(int(z1.inventory[0]/10 - .1) + 1)) + " swords, " + str(z1.inventory[1]) + " bullets, " + str(z1.inventory[2]) + " shotguns, " + str(z1.inventory[3]) + " pistols, " + str(z1.inventory[4]) + " shells, " + str(z1.inventory[5]) + " APs, " + str(z1.inventory[6]) + " keys and " + str(z1.inventory[7]) + " compass.")
    elif object1 == "room":
        fff = []
        if z1.rooms[room_number()][2]:
            fff.append("a monster")
        if z1.rooms[room_number()][1]:
            fff.append("a chest")
        if isempty(fff):
            fff.append("nothing")
        return("you are in " + str(z1.rooms[room_number()][0]) + " with " + " and ".join(fff) + " in it.")

# Tells us what number room the player is in from the database of rooms
def room_number():
    counter = 0
    while counter != (len(z1.rooms)):
        if z1.rooms[counter][0] == z1.roomposition:
            return(counter)
        counter += 1
    return(None)

#This changes the postiton of the room.  And creates a new room if needed.
def changeposition(x,y,z):
    z1.roomposition = [ ( z1.roomposition[0] + x ) , ( z1.roomposition[1] + y ) , ( z1.roomposition[2] + z ) ]
    if room_number() == None:
        z1.rooms.append([z1.roomposition, random.choice([False, True]), random.choice([False, True]), None, False])
    print("You have changed rooms. Now, " + inspect("room"))
    if z1.rooms[1][0] == z1.roomposition:
        print("You have entered the boss battle!")
    if z1.rooms[room_number()][3]:
        print("You have reacquired the items you dropped on death!")
        z1.inventory = addlists(z1.inventory, z1.fallenitems)
        z1.fallenitems = []
        z1.rooms[room_number()][3] = False
    if z1.rooms[room_number()][2]:
        if input("Do you want to fight? ").lower() == "yes":
            print("Welcome to combat! Type 'use [weapon] on monster' to attack! But be careful, monsters are dangerous.")
            z1.inCombat = True
            if z1.roomposition == z1.bossposition:
                z1.monsters.append([70, 50, 500])
            else:
                z1.monsters.append([z1.monsterconfig[0][random.randint(0, 4)], z1.monsterconfig[1][random.randint(0, 4)], z1.monsterconfig[2][random.randint(0, 4)]])
        else:
            z1.inCombat = False
            z1.roomposition = [ ( z1.roomposition[0] - x ) , ( z1.roomposition[1] - y ) , ( z1.roomposition[2] - z ) ]
            print("You have gone back to your previous room")

# Moves the player between rooms.
def move(direction):
    if direction == "east":
        changeposition(1,0,0)
    elif direction == "west":
        changeposition(-1,0,0)
    elif direction == "north":
        changeposition(0,0,1)
    elif direction == "south":
        changeposition(0,0,-1)
    elif direction == "up":
        if z1.roomposition[0] == 0 and z1.roomposition[2] == 0:
            changeposition(0,1,0)
        else:
            print("You cannot move up. Go to the home room w/ the stairs")
    elif direction == "down":
        if z1.roomposition[0] == 0 and z1.roomposition[2] == 0:
            changeposition(0,-1,0)
        else:
            print("You cannot move down. Go to the home room w/ the stairs")
    else:
        print("Unknown move command, Use'move north/south/east/west/up/down' to move.")

# Is the main movement of the program

def rungame(): # This is the function that runs the commands if you are alive.
    if z1.inCombat:
        print("It is your turn!")
        combatstatus()
    userinput = input("> ")
    user_input = userinput.split()
    cmd = user_input[0]
    args = user_input[1:int(len(user_input))]
    while isempty(user_input) == False:
        if isempty(args):
            args = ["EMPTY"]
        if cmd == "help":
            helpgame(args[0])
        elif cmd == "move":
            if not z1.inCombat:
                move(args[0])
            else:
                print("You can't flee from Combat!")
        elif cmd in ["east", "west", "north", "south"]:
            if not z1.inCombat:
                move(cmd)
            else:
                print("You can't flee from Combat!")
        elif cmd == "open" and args[0] == "chest":
            use("key", "on", "chest")
        elif cmd == "health":
            print("Your health is " + z1.player_health )
        elif cmd == "use":
            if len(args) == 1:
                args.append(0)
                args.append(0)
            use(args[0], args[1], args[2])
        elif cmd == "inspect":
            print(inspect(args[0]))
        elif cmd == "trump":
            print(trump)
        elif cmd == "inventory":
            inspect(cmd)
        elif cmd == "exit" or cmd == "suicide":
            if cmd == "exit":
                z1.exit = True
            z1.player_health = 0
        else:
            print("Unknown command. Use 'help' for a list of commands")
        user_input = []
reset_def()
print("Welcome to the most kookie of the APBP games\nYou are in the home room. - Start by moving around with command 'move'\nUse 'help' if you need help\nThe goal is to find the boss level and slay\nUse your compass to find the boss 'use compass'")
print("Here are some basic tips: use the move command to move between rooms, ie move east, move west, etc.\nby using the inspect command, you can take a look at things such as your inventory, health, and armor values.")
while True:
    if z1.player_health > 0:
        try:
            rungame()
        except:
            print("Error!")
    elif z1.exit:
        break
    else:
        print("You died!") # if you die you have options to respawn or to exit the game.
        if input("Do you want to respawn? ").lower() == "yes":
            z1.rooms[room_number()][3] = z1.inventory
            z1.player_health = 200
            z1.fallenitems = z1.inventory
            z1.inventory = [0, 0, 0, 0, 0, 0, 0, 1]
            z1.inCombat = False
            changeposition(-z1.roomposition[0], -z1.roomposition[1], -z1.roomposition[2])
        else:
            print("Thank you for playing!")
            break


'''
Title     : functions_file
Objective : Functions to process and transform TCGA data from https://portal.gdc.cancer.gov/ with R
Created by: Kevin Brinneman for UTSA Electrical & Computer Engineering
Created on: 2022-01-23

This script will recursively iterate over all folder to decompress GZ files.Once decompressed, all RNA_seq files are
opened as .COUNTS format and processed as JSON files. JSON format is preferible over .TXT files to prevent data
corruption.
'''

'''
Directory tree only showing three samples. The same architecture continues for the list showed below.
Directory originally in Data_processing/preprocessed_data/GDC. Files too large to share.

----TCGA
    |----GDC_Data
    |    |----TCGA-ACC
              |----harmonized
                   |----Transcriptome_Profiling
                        |----Gene_Expression_Quantification
                            |----[folders with txt files]
                   |----Clinical
                        |----Clinical_Supplement
                            |----[folders with txt files]
    |    |----TCGA-BLCA
              |----harmonized
                   |----Transcriptome_Profiling
                        |----Gene_Expression_Quantification
                            |----[folders with txt files]
                   |----Clinical
                        |----Clinical_Supplement
                            |----[folders with txt files]
    |    |----TCGA-BRCA
              |----harmonized
                   |----Transcriptome_Profiling
                        |----Gene_Expression_Quantification
                            |----[folders with txt files]
                   |----Clinical
                        |----Clinical_Supplement
                            |----[folders with txt files]

    .
    .
    .

    [           ...          ...        ... TCGA-CESC,TCGA-CHOL,TCGA-COAD,
    TCGA-DLBC, TCGA-ESCA,TCGA-GBM,TCGA-HNSC,TCGA-KICH,TCGA-KIRC,TCGA-KIRP,
    TCGA-LGG, TCGA-LIHC,TCGA-LUAD,TCGA-LUSC,TCGA-MESO,TCGA-OV,TCGA-PAAD,
    TCGA-PCPG, TCGA-PRAD,TCGA-READ,TCGA-SARC,TCGA-SKCM,TCGA-STAD,TCGA-TGCT,
    TCGA-THCA,TCGA-THYM,TCGA-UCEC,TCGA-UCS,TCGA-UVM,TCGA-LAML]
'''

#import libraries
import gzip, pathlib, shutil, json, re

#Where the directory is located
base_dir = "D:/GDCdata"

#Function to open .COUNTS files, proccess them as JSON, and deletion of processed files.

def unpack_all_in_dir(_dir):
    path = pathlib.Path(_dir)
    for gzfilepath in path.rglob('*.gz'):
        with gzip.open(gzfilepath) as f, gzfilepath.with_suffix('').open('wb') as fw:
            shutil.copyfileobj(f, fw)
        os.remove(gzfilepath)

unpack_all_in_dir(base_dir)

#Function used to find clinical-to-rna match. Creates two dictionaries of clinical and rna data
# and is compared to find a match between samples with same ID alphanumeric string

def merge_data_files(_dir):
    path = pathlib.Path(_dir)
    tcga_type = [item for item in path.iterdir() if item.is_dir()] #make the folder a mutable object list
    GDC_data = {}
    for tcga in tcga_type:
        GDC_data[tcga.name] = {}
        for clinical in tcga.glob('Clinical_Supplement'):
            Clinical_Supplement = {}
            for case in clinical.iterdir():
                Clinical_Supplement[case.name] = case
        for rna_cases in tcga.glob('Gene_Expression_Quantification'):
            Gene_Expression_Quantification = {}
            for sample in rna_cases.iterdir():
                Gene_Expression_Quantification[sample.name] = sample
        ({f for f in Clinical_Supplement} & {f for f in Gene_Expression_Quantification})
    print(GDC_data)

#Function to iterate over all folders to save samples as JSON files and convert each .COUNT file
#to JSON format. Each JSON formart file is processed as a dictionary.

def header_check_df (_dir):
    path = pathlib.Path(_dir)
    for headers in path.rglob('*.htseq.counts'):
        object_gene= {}
        feature_rna_string = {}
        with open(headers) as f:
            for line in f:
                gene, count = line.strip().split(None,1)
                feature_rna_string.update({gene: int(count)})
            object_gene[str(re.sub(r'.htseq.counts', '', headers.name))] = feature_rna_string
        file_regexd = re.sub(r'.htseq.counts','',headers.name) + '.json'
        out_file = open(headers.parent.joinpath(file_regexd), 'w')
        json.dump(object_gene, out_file, indent = 4, sort_keys= False)
        out_file.close()

header_check_df(base_dir)


from collections import namedtuple
from pathlib import Path

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pytest

from mne import Epochs, compute_proj_evoked, read_cov, read_events
from mne.channels import read_layout
from mne.io import read_raw_fif
from mne.time_frequency.tfr import AverageTFR
from mne.utils import _record_warnings
from mne.viz import (
    _get_presser,
    mne_analyze_colormap,
    plot_evoked_topo,
    plot_topo_image_epochs,
)
from mne.viz.evoked import _line_plot_onselect
from mne.viz.topo import _imshow_tfr, _plot_update_evoked_topo_proj, iter_topography
from mne.viz.utils import _fake_click

base_dir = Path(__file__).parents[2] / "io" / "tests" / "data"
evoked_fname = base_dir / "test-ave.fif"
raw_fname = base_dir / "test_raw.fif"
event_name = base_dir / "test-eve.fif"
cov_fname = base_dir / "test-cov.fif"
event_id, tmin, tmax = 1, -0.2, 0.2
layout = read_layout("Vectorview-all")

def _get_events():
    """Get events."""
    return read_events(event_name)

def _get_picks(raw):
    """Get picks."""
    return [0, 1, 2, 6, 7, 8, 306, 340, 341, 342]  # take a only few channels

def _get_epochs():
    """Get epochs."""
    raw = read_raw_fif(raw_fname)
    raw.add_proj([], remove_existing=True)
    events = _get_events()
    picks = _get_picks(raw)
    # bad proj warning
    epochs = Epochs(raw, events[:10], event_id, tmin, tmax, picks=picks)
    return epochs

def _get_epochs_delayed_ssp():
    """Get epochs with delayed SSP."""
    raw = read_raw_fif(raw_fname)
    events = _get_events()
    picks = _get_picks(raw)
    reject = dict(mag=4e-12)
    with pytest.warns(RuntimeWarning, match="projection"):
        epochs_delayed_ssp = Epochs(
            raw,
            events[:10],
            event_id,
            tmin,
            tmax,
            picks=picks,
            proj="delayed",
            reject=reject,
        )
    return epochs_delayed_ssp

def test_plot_joint():
    """Test joint plot."""
    evoked = _get_epochs().average()
    evoked.plot_joint(ts_args=dict(time_unit="s"), topomap_args=dict(time_unit="s"))

    def return_inds(d):  # to test function kwarg to zorder arg of evoked.plot
        return list(range(d.shape[0]))

    evoked.plot_joint(
        title="test",
        topomap_args=dict(contours=0, res=8, time_unit="ms"),
        ts_args=dict(spatial_colors=True, zorder=return_inds, time_unit="s"),
    )
    with pytest.raises(ValueError, match="If one of `ts_args` and"):
        evoked.plot_joint(ts_args=dict(axes=True, time_unit="s"))

    axes = plt.subplots(nrows=3)[-1].flatten().tolist()
    evoked.plot_joint(
        times=[0],
        picks=[6, 7, 8],
        ts_args=dict(axes=axes[0]),
        topomap_args={"axes": axes[1:], "time_unit": "s"},
    )
    with pytest.raises(ValueError, match="of length 4"):
        evoked.plot_joint(
            picks=[6, 7, 8],
            ts_args=dict(axes=axes[0]),
            topomap_args=dict(axes=axes[2:]),
        )
    plt.close("all")

    # test proj options
    assert len(evoked.info["projs"]) == 0
    evoked.pick(picks="meg")
    evoked.add_proj(compute_proj_evoked(evoked, n_mag=1, n_grad=1, meg="combined"))
    assert len(evoked.info["projs"]) == 1
    with pytest.raises(ValueError, match="must match ts_args"):
        evoked.plot_joint(ts_args=dict(proj=True), topomap_args=dict(proj=False))
    evoked.plot_joint(
        ts_args=dict(proj="reconstruct"), topomap_args=dict(proj="reconstruct")
    )
    plt.close("all")

    # test sEEG (gh:8733)
    evoked.del_proj().pick("mag")  # avoid overlapping positions error
    mapping = {ch_name: "seeg" for ch_name in evoked.ch_names}
    evoked.set_channel_types(mapping, on_unit_change="ignore")
    evoked.plot_joint()

    # test DBS (gh:8739)
    evoked = _get_epochs().average().pick("mag")
    mapping = {ch_name: "dbs" for ch_name in evoked.ch_names}
    evoked.set_channel_types(mapping, on_unit_change="ignore")
    evoked.plot_joint()
    plt.close("all")

def test_plot_topo():
    """Test plotting of ERP topography."""
    # Show topography
    evoked = _get_epochs().average()
    # should auto-find layout
    plot_evoked_topo([evoked, evoked], merge_grads=True, background_color="w")

    plot_evoked_topo(
        [evoked, evoked], merge_grads=True, background_color="w", color="blue"
    )

    # test legend colors
    colors = ["red", "blue"]
    fig = plot_evoked_topo([evoked, evoked], merge_grads=True, color=colors)
    legend = fig.axes[0].get_legend()
    legend_colors = [
        line.properties()["markeredgecolor"] for line in legend.get_lines()
    ]
    assert legend_colors == colors

    with pytest.raises(ValueError, match="must be .*tuple, list, str,.*"):
        plot_evoked_topo(
            [evoked, evoked], merge_grads=True, color=np.array(["blue", "red"])
        )

    picked_evoked = evoked.copy().pick(evoked.ch_names[:3])
    picked_evoked_eeg = evoked.copy().pick(picks="eeg")
    picked_evoked_eeg.pick(picked_evoked_eeg.ch_names[:3])

    # test scaling
    for ylim in [dict(mag=[-600, 600]), None]:
        plot_evoked_topo([picked_evoked] * 2, layout, ylim=ylim)

    for evo in [evoked, [evoked, picked_evoked]]:
        pytest.raises(ValueError, plot_evoked_topo, evo, layout, color=["y", "b"])

    evoked_delayed_ssp = _get_epochs_delayed_ssp().average()
    ch_names = evoked_delayed_ssp.ch_names[:3]  # make it faster
    picked_evoked_delayed_ssp = evoked_delayed_ssp.pick(ch_names)
    fig = plot_evoked_topo(picked_evoked_delayed_ssp, layout, proj="interactive")
    func = _get_presser(fig)
    event = namedtuple("Event", ["inaxes", "xdata", "ydata"])
    func(
        event(
            inaxes=fig.axes[0],
            xdata=fig.axes[0]._mne_axs[0].pos[0],
            ydata=fig.axes[0]._mne_axs[0].pos[1],
        )
    )
    func(event(inaxes=fig.axes[0], xdata=0, ydata=0))
    params = dict(
        evokeds=[picked_evoked_delayed_ssp],
        times=picked_evoked_delayed_ssp.times,
        fig=fig,
        projs=picked_evoked_delayed_ssp.info["projs"],
    )
    bools = [True] * len(params["projs"])
    with pytest.warns(RuntimeWarning, match="projection"):
        _plot_update_evoked_topo_proj(params, bools)

    # should auto-generate layout
    plot_evoked_topo(
        picked_evoked_eeg.copy(),
        fig_background=np.zeros((4, 3, 3)),
        proj=True,
        background_color="k",
    )
    # Test RMS plot of grad pairs
    picked_evoked.plot_topo(merge_grads=True, background_color="w")
    plt.close("all")
    for ax, idx in iter_topography(evoked.info, legend=True):
        ax.plot(evoked.data[idx], color="red")
        # test status bar message
        if idx != -1:
            assert evoked.ch_names[idx] in ax.format_coord(0.5, 0.5)
    assert idx == -1
    plt.close("all")
    cov = read_cov(cov_fname)
    cov["projs"] = []
    evoked.pick(picks="meg").plot_topo(noise_cov=cov)
    plt.close("all")

    # Test exclude parameter
    exclude = ["MEG 0112"]
    fig = picked_evoked.plot_topo(exclude=exclude)
    n_axes_expected = len(picked_evoked.info["ch_names"]) - len(exclude)
    n_axes_found = len(fig.axes[0].lines)
    assert n_axes_found == n_axes_expected

    # test plot_topo
    evoked.plot_topo()  # should auto-find layout
    _line_plot_onselect(0, 200, ["mag", "grad"], evoked.info, evoked.data, evoked.times)
    plt.close("all")

    for ax, idx in iter_topography(evoked.info):  # brief test with false
        ax.plot([0, 1, 2])
        break
    plt.close("all")

def test_plot_topo_nirs(fnirs_evoked):
    """Test plotting of ERP topography for nirs data."""
    fnirs_evoked.pick(picks="hbo")
    fig = plot_evoked_topo(fnirs_evoked)
    assert len(fig.axes) == 1
    plt.close("all")

def test_plot_topo_single_ch():
    """Test single channel topoplot with time cursor."""
    evoked = _get_epochs().average()
    evoked2 = evoked.copy()
    # test plotting several evokeds on different time grids
    evoked.crop(-0.19, 0)
    evoked2.crop(0.05, 0.19)
    fig = plot_evoked_topo([evoked, evoked2], background_color="w")
    # test status bar message
    ax = plt.gca()
    assert "MEG 0113" in ax.format_coord(0.065, 0.63)
    num_figures_before = len(plt.get_fignums())
    _fake_click(fig, fig.axes[0], (0.08, 0.65))
    assert num_figures_before + 1 == len(plt.get_fignums())
    fig = plt.gcf()
    ax = plt.gca()
    _fake_click(fig, ax, (0.5, 0.5), kind="motion")  # cursor should appear
    assert isinstance(ax._cursorline, matplotlib.lines.Line2D)
    _fake_click(fig, ax, (1.5, 1.5), kind="motion")  # cursor should disappear
    assert ax._cursorline is None
    plt.close("all")

def test_plot_topo_image_epochs():
    """Test plotting of epochs image topography."""
    title = "ERF images - MNE sample data"
    epochs = _get_epochs()
    epochs.load_data()
    cmap = mne_analyze_colormap(format="matplotlib")
    data_min = epochs._data.min()
    plt.close("all")
    fig = plot_topo_image_epochs(
        epochs, sigma=0.5, vmin=-200, vmax=200, colorbar=True, title=title, cmap=cmap
    )
    assert epochs._data.min() == data_min
    num_figures_before = len(plt.get_fignums())
    _fake_click(fig, fig.axes[0], (0.08, 0.64))
    assert num_figures_before + 1 == len(plt.get_fignums())
    # test for auto-showing a colorbar when only 1 sensor type
    ep = epochs.copy().pick(picks="eeg")
    fig = plot_topo_image_epochs(ep, vmin=None, vmax=None, colorbar=None, cmap=cmap)
    ax = [x for x in fig.get_children() if isinstance(x, matplotlib.axes.Axes)]
    # include inset axes (newer MPL)
    ax.extend(
        y for x in ax for y in x.get_children() if isinstance(y, matplotlib.axes.Axes)
    )
    qm_cmap = [
        y.cmap
        for x in ax
        for y in x.get_children()
        if isinstance(y, matplotlib.collections.QuadMesh)
    ]
    assert len(qm_cmap) >= 1
    assert qm_cmap[0] is cmap

def test_plot_tfr_topo():
    """Test plotting of TFR data."""
    epochs = _get_epochs()
    n_freqs = 3
    nave = 1
    data = np.random.RandomState(0).randn(
        len(epochs.ch_names), n_freqs, len(epochs.times)
    )
    tfr = AverageTFR(epochs.info, data, epochs.times, np.arange(n_freqs), nave)
    plt.close("all")
    fig = tfr.plot_topo(
        baseline=(None, 0), mode="ratio", title="Average power", vmin=0.0, vmax=14.0
    )

    # test complex
    tfr.data = tfr.data * (1 + 1j)
    plt.close("all")
    fig = tfr.plot_topo(
        baseline=(None, 0), mode="ratio", title="Average power", vmin=0.0, vmax=14.0
    )

    # test opening tfr by clicking
    num_figures_before = len(plt.get_fignums())
    # could use np.reshape(fig.axes[-1].images[0].get_extent(), (2, 2)).mean(1)
    with pytest.warns(RuntimeWarning, match="not masking"):
        _fake_click(fig, fig.axes[0], (0.08, 0.65))
    assert num_figures_before + 1 == len(plt.get_fignums())
    plt.close("all")

    tfr.plot([4], baseline=(None, 0), mode="ratio", show=False, title="foo")
    pytest.raises(ValueError, tfr.plot, [4], yscale="lin", show=False)

    # nonuniform freqs
    freqs = np.logspace(*np.log10([3, 10]), num=3)
    tfr = AverageTFR(epochs.info, data, epochs.times, freqs, nave)
    fig = tfr.plot([4], baseline=(None, 0), mode="mean", vmax=14.0, show=False)
    assert fig[0].axes[0].get_yaxis().get_scale() == "log"

    # one timesample
    tfr = AverageTFR(epochs.info, data[:, :, [0]], epochs.times[[1]], freqs, nave)
    with _record_warnings():  # matplotlib equal left/right
        tfr.plot([4], baseline=None, vmax=14.0, show=False, yscale="linear")

    # one frequency bin, log scale required: as it doesn't make sense
    # to plot log scale for one value, we test whether yscale is set to linear
    vmin, vmax = 0.0, 2.0
    fig, ax = plt.subplots()
    tmin, tmax = epochs.times[0], epochs.times[-1]
    with pytest.warns(RuntimeWarning, match="not masking"):
        _imshow_tfr(
            ax,
            3,
            tmin,
            tmax,
            vmin,
            vmax,
            None,
            tfr=data[:, [0], :],
            freq=freqs[[-1]],
            x_label=None,
            y_label=None,
            colorbar=False,
            cmap=("RdBu_r", True),
            yscale="log",
        )
    fig = plt.gcf()
    assert fig.axes[0].get_yaxis().get_scale() == "linear"

    # ValueError when freq[0] == 0 and yscale == 'log'
    these_freqs = freqs[:3].copy()
    these_freqs[0] = 0
    with pytest.warns(RuntimeWarning, match="not masking"):
        pytest.raises(
            ValueError,
            _imshow_tfr,
            ax,
            3,
            tmin,
            tmax,
            vmin,
            vmax,
            None,
            tfr=data[:, :3, :],
            freq=these_freqs,
            x_label=None,
            y_label=None,
            colorbar=False,
            cmap=("RdBu_r", True),
            yscale="log",
        )


import pygame
pygame.font.init()

def mostrar_texto_centrado(screen,texto,center_x,center_y,color,fuente):
    render = fuente.render(texto,True,color)
    rect_text = render.get_rect(center = (center_x,center_y))
    #rect_text_saludar.center = rect_saludar.center
    screen.blit(render,rect_text)

def crear_boton(screen,texto,bg_color,bg_color_hover,rect_boton:pygame.Rect,font_color,fuente = pygame.font.SysFont
                (None,36)):
    if rect_boton.collidepoint(pygame.mouse.get_pos()):
        pygame.draw.rect(screen,bg_color_hover,rect_boton,border_radius=5)
    else:
        pygame.draw.rect(screen,bg_color,rect_boton,border_radius=5)

    mostrar_texto_centrado(screen,texto,*rect_boton.center,font_color,fuente)


""" Bayesian Determinisitc Policy Gradient evaluated on th
didactic "chain" environment
"""

import tensorflow as tf
from gym import Wrapper
from tensorflow.python.layers.utils import smart_cond
from tensorflow.python.ops.variable_scope import get_local_variable

import chi
from chi import Experiment
from chi import experiment, model
from chi.rl import ReplayMemory

# chi.chi.tf_debug = True
from chi.rl.bdpg import BdpgAgent
from chi.rl.ddpg import DdpgAgent
from chi.rl.util import print_env

@experiment
def bdpg_chains2(self: Experiment, logdir=None, env=1, heads=3, n=50, bootstrap=False, sr=50000):
  from tensorflow.contrib import layers
  import gym
  from gym import spaces
  from gym import wrappers
  import numpy as np
  from tensorflow.contrib.framework import arg_scope

  def gym_make(id) -> gym.Env:
    return gym.make(id)

  chi.set_loglevel('debug')

  if env == 0:
    import gym_mix
    from chi.rl.wrappers import PenalizeAction
    env = gym_mix.envs.ChainEnv(n)
    env = PenalizeAction(env, .001, 1)
  elif env == 1:
    # env = gym.make('Pendulum-v0')
    env = gym.make('MountainCarContinuous-v0')

  if bootstrap:
    class Noise(Wrapper):
      def __init__(self, env):
        super().__init__(env)
        self.n = 3
        self.observation_space = gym.spaces.Box(
          np.concatenate((self.observation_space.low, np.full([self.n], -1))),
          np.concatenate((self.observation_space.high, np.full([self.n], 1))))

      def _reset(self):
        s = super()._reset()
        self.noise = np.random.uniform(-1, 1, [self.n])
        s = np.concatenate([s, self.noise])
        return s

      def _step(self, action):
        s, r, d, i = super()._step(action)
        s = np.concatenate([s, self.noise])
        return s, r, d, i

    env = Noise(env)

  print_env(env)

  def pp(x):
    # v = get_local_variable('noise', [x.shape[0], 100], initializer=tf.random_normal_initializer)
    # y = tf.concat(x, v)
    return x

  def ac(x):
    with tf.name_scope('actor_head'):
      x = layers.fully_connected(x, 50, biases_initializer=layers.xavier_initializer())
      x = layers.fully_connected(x, 50, biases_initializer=layers.xavier_initializer())
      # a = layers.fully_connected(x, env.action_space.shape[0], None, weights_initializer=tf.random_normal_initializer(0, 1e-4))
      a = layers.fully_connected(x, env.action_space.shape[0], None)
      return a

  def cr(x, a):
    with tf.name_scope('critic_head'):
      x = layers.fully_connected(x, 50, biases_initializer=layers.xavier_initializer())
      x = tf.concat([x, a], axis=1)
      x = layers.fully_connected(x, 50, biases_initializer=layers.xavier_initializer())
      # q = layers.fully_connected(x, 1, None, weights_initializer=tf.random_normal_initializer(0, 1e-4))
      q = layers.fully_connected(x, 1, None)
      return tf.squeeze(q, 1)

  if bootstrap:
    agent = DdpgAgent(env, ac, cr, replay_start=sr, noise=lambda a: a)
  else:
    agent = DdpgAgent(env, ac, cr, replay_start=sr)
  threshold = getattr(getattr(env, 'spec', None), 'reward_threshold', None)

  for ep in range(100000):

    R, info = agent.play_episode()

    if ep % 20 == 0:
      head = info.get('head')
      print(f'Return of episode {ep} after timestep {agent.t}: {R} (head = {head}, threshold = {threshold})')

    if ep % 100 == 0 and bootstrap:
      pass

  #
  # @chi.function(logging_policy=lambda _: True)
  # def plot():
  #   # obsp = env.observation_space
  #   # h = obsp.high
  #   # l = obsp.low
  #   # x, y = tf.meshgrid(tf.linspace(l[0], h[0], 100), tf.linspace(l[1], h[1], 100))
  #   # x = tf.reshape(x, [-1])
  #   # y = tf.reshape(y, [-1])
  #   # inp = tf.stack(x, y, axis=1)
  #
  #   x = tf.linspace(0, 30, 100)
  #   x = tf.py_func(env.batch_features, x, tf.float32, stateful=False)
  #   s = pp(x)
  #   a0 = actor(s)
  #   tf.image


#!/usr/bin/python3

import os
import sys

import pandas as pd

def get_size(path):
    total = 0
    for entry in os.scandir(path):
        try:
            if entry.is_dir(follow_symlinks=False):
                total += get_size(entry.path)

            else:
                total += entry.stat(follow_symlinks=False).st_size

        except Exception as e:
            print("Exception: ", e)
            total += 0

    return total

if __name__ == "__main__":
    # if you're running this in linux, change the default path to "/home"
    # also run the code as "sudo python3 Disk_usage.py" or "sudo ./Disk_usage.py"
    # i.e, with super user permissions

    path = "C:/Users/"
    print("Total arguments passed: ", len(sys.argv))

    directory = sys.argv[1] if len(sys.argv) >= 2 else path
    usage = []
    paths = []

    for entry in os.scandir(directory):
        if entry.is_dir(follow_symlinks=False):
            print(entry.path + " is a directory.")
            print(get_size(entry.path))
            total = get_size(entry.path)
            paths.append(entry.path)
            usage.append(total)

        usage_dict = {"directory": paths, "usage": usage}
        df = pd.DataFrame(usage_dict)

        print(df)
        df.to_csv("disk_home_usage.csv")