import json
from django.conf import settings
from django.urls import reverse

from .models import XMPPAccount

def get_conversejs_settings(settings_dict=None):
    converse_settings = {
        'bosh_service_url': settings.XMPP_BOSH_SERVICE_URL,
        'domain_placeholder': settings.XMPP_DOMAIN,
        'debug': settings.DEBUG,
        'authentication': getattr(settings, 'XMPP_CONVERSEJS_AUTH', 'login'),
        'keepalive': True,
        'auto_login': True,
    }

    try:
        converse_settings.update(settings.XMPP_CONVERSEJS_SETTINGS)
    except AttributeError:
        pass

    if settings:
        converse_settings.update(settings_dict)

    if converse_settings.get('xhr_user_search', None):
        converse_settings['xhr_user_search_url'] = reverse('xmpp_xhr_user_search')

    return converse_settings

def get_conversejs_context(context):
    context['xmpp_enabled'] = settings.XMPP_ENABLED

    if not settings.XMPP_ENABLED:
        # XMPP disabled entirely
        return context

    request = context.get('request')
    if not request.user.is_active:
        # User is not logged in
        return context

    # Setup authentication
    auth_type = getattr(settings, 'XMPP_CONVERSEJS_AUTH', None)
    settings_auth = {}
    if auth_type in ['login', 'prebind']:
        # We need to ensure XMPPAccount for both login and prebind auth
        xmpp_account = XMPPAccount.get_or_create(request.user)
        settings_auth['jid'] = xmpp_account.jid

    if auth_type == 'login':
        settings_auth['password'] = xmpp_account.password
    elif auth_type == 'preauth':
        raise NotImplementedError('preauth is not implemented yet')

    context['conversejs_settings'] = json.dumps(get_conversejs_settings(settings_auth))

    return context


import time

class Player:
    def __init__(self):
        self.gold = 0
        self.gold_per_second = 1
        self.click_gold = 1
        self.upgrades = {
            'Clicking Power': {'cost': 10, 'increment': 1},
            'Gold Per Second': {'cost': 100, 'increment': 1},
            'Auto Clicker': {'cost': 500, 'increment': 2},
            'Gold Rush': {'cost': 1000, 'increment': 5}
        }
        self.autoclickers = 0
        self.gold_rush_active = False
        self.gold_rush_time = 0

    def update(self, dt):
        # Calculate the amount of gold gained in the current tick
        gold_gain = self.gold_per_second * dt

        # Update the gold value
        self.gold += gold_gain

        # Check if Gold Rush is active
        if self.gold_rush_active:
            self.gold += gold_gain * 5

        # Display the current state of the game
        print(f"Gold: {self.gold}")
        print(f"Gold per second: {self.gold_per_second}")
        print(f"Clicking Power: {self.click_gold}")
        print(f"Auto Clickers: {self.autoclickers}")
        print(f"Gold Rush Time Left: {self.gold_rush_time}")

    def click(self):
        # Add gold from clicking
        self.gold += self.click_gold

    def buy_upgrade(self, upgrade_name):
        # Check if the player has enough gold to purchase the upgrade
        if self.gold < self.upgrades[upgrade_name]['cost']:
            print("Not enough gold to purchase upgrade.")
            return

        # Deduct the cost of the upgrade from the player's gold
        self.gold -= self.upgrades[upgrade_name]['cost']

        # Increment the relevant stat by the upgrade increment
        if upgrade_name == 'Clicking Power':
            self.click_gold += self.upgrades[upgrade_name]['increment']
        elif upgrade_name == 'Gold Per Second':
            self.gold_per_second += self.upgrades[upgrade_name]['increment']
        elif upgrade_name == 'Auto Clicker':
            self.autoclickers += 1
        elif upgrade_name == 'Gold Rush':
            self.gold_rush_active = True
            self.gold_rush_time = 10

        # Increment the cost of the upgrade for the next purchase
        self.upgrades[upgrade_name]['cost'] += int(self.upgrades[upgrade_name]['cost'] * 0.1)

    def activate_gold_rush(self):
        # Check if Gold Rush is already active
        if self.gold_rush_active:
            print("Gold Rush is already active.")
            return

        # Check if the player has enough gold to activate Gold Rush
        if self.gold < self.upgrades['Gold Rush']['cost']:
            print("Not enough gold to activate Gold Rush. You can purchase Gold Rush in the shop.")
            return

        # Deduct the cost of Gold Rush from the player's gold
        self.gold -= self.upgrades['Gold Rush']['cost']

        # Activate Gold Rush
        self.gold_rush_active = True
        self.gold_rush_time = 10

    def buy_menu(self):
        print("1. Buy Autoclicker (costs 500 gold)")
        print("2. Upgrade Clicking Power (costs 10 gold)")
        print("3. Upgrade Gold Per Second (costs 100 gold)")
        print("4. Activate Gold Rush (costs 1000 gold)")
        print("5. Exit Buy Menu")
        action = input("Your choice: ")

        if action == '1':
            self.buy_autoclicker()
        elif action == '2':
            self.buy_upgrade('Clicking Power')
        elif action == '3':
            self.buy_upgrade('Gold Per Second')
        elif action == '4':
            self.activate_gold_rush()
        elif action == '5':
            return
        else:
            print("Invalid choice. Please try again.")
            self.buy_menu()

    def run(self):
        last_time = time.time()

        # Define the main game loop
        while True:
            current_time = time.time()
            dt = current_time - last_time
            last_time = current_time

            # Handle input from the player
            print("1. Click (just click enter :)")
            print("2. Buy")
            print("3. Activate Gold Rush")
            print("4. Quit")
            action = input("Your choice:")

            if action == '1':
                self.click()
            elif action == '2':
                self.buy_menu()
            elif action == '3':
                self.activate_gold_rush()
            elif action == '4':
                break

            # Update the game state
            self.update(dt)

            # Check if Gold Rush is active
            if self.gold_rush_active:
                self.gold_rush_time -= dt

                if self.gold_rush_time <= 0:
                    self.gold_rush_active = False

            # Wait for 0.1 seconds before continuing to the next tick
            time.sleep(0.1)

# Create a new instance of the Player class
player = Player()

# Start the game
player.run()


import importlib
import inspect
import os
import pkgutil

import numpy as np
import scipy.sparse
import sklearn
import sklearn.base
import sklearn.datasets

import unittest

def find_sklearn_classes(class_):
    classifiers = set()
    all_subdirectories = []
    sklearn_path = sklearn.__path__[0]
    for root, dirs, files in os.walk(sklearn_path):
        all_subdirectories.append(root)

    for module_loader, module_name, ispkg in pkgutil.iter_modules(all_subdirectories):

        # Work around some issues...
        if module_name in ["hmm", "mixture"]:
            print("Skipping %s" % module_name)
            continue

        module_file = module_loader.__dict__["path"]
        sklearn_module = module_file.replace(sklearn_path, "").replace("/", ".")
        full_module_name = "sklearn" + sklearn_module + "." + module_name

        pkg = importlib.import_module(full_module_name)

        for member_name, obj in inspect.getmembers(pkg):
            if inspect.isclass(obj) and issubclass(obj, class_):
                classifier = obj
                # print member_name, obj
                classifiers.add(classifier)

    print()
    for classifier in sorted([str(cls) for cls in classifiers]):
        print(classifier)

def get_dataset(
    dataset="iris",
    make_sparse=False,
    add_NaNs=False,
    train_size_maximum=150,
    make_multilabel=False,
    make_binary=False,
    return_target_as_string=False,
):
    iris = getattr(sklearn.datasets, "load_%s" % dataset)()
    X = iris.data.astype(np.float32)
    Y = iris.target

    if return_target_as_string:
        if make_binary or make_multilabel or (len(Y.shape) > 1 and Y.shape[1] > 1):
            raise NotImplementedError()
        Y = np.array([iris.target_names[y] for y in Y])

    rs = np.random.RandomState(42)
    indices = np.arange(X.shape[0])
    train_size = min(int(len(indices) / 3.0 * 2.0), train_size_maximum)
    rs.shuffle(indices)
    X = X[indices]
    Y = Y[indices]
    X_train = X[:train_size]
    Y_train = Y[:train_size]
    X_test = X[train_size:]
    Y_test = Y[train_size:]

    if add_NaNs:
        mask = rs.choice([True, False], size=(X_train.shape))
        X_train[mask] = np.NaN

    if make_sparse:
        X_train[:, 0] = 0
        X_train[rs.random_sample(X_train.shape) > 0.5] = 0
        X_train = scipy.sparse.csc_matrix(X_train)
        X_train.eliminate_zeros()
        X_test[:, 0] = 0
        X_test[rs.random_sample(X_test.shape) > 0.5] = 0
        X_test = scipy.sparse.csc_matrix(X_test)
        X_test.eliminate_zeros()

    if make_binary and make_multilabel:
        raise ValueError(
            "Can convert dataset only to one of the two "
            "options binary or multilabel!"
        )

    if make_binary:
        Y_train[Y_train > 1] = 1
        Y_test[Y_test > 1] = 1

    if make_multilabel:
        num_classes = len(np.unique(Y))
        Y_train_ = np.zeros((Y_train.shape[0], num_classes))
        for i in range(Y_train.shape[0]):
            Y_train_[i, Y_train[i]] = 1
        Y_train = Y_train_
        Y_test_ = np.zeros((Y_test.shape[0], num_classes))
        for i in range(Y_test.shape[0]):
            Y_test_[i, Y_test[i]] = 1
        Y_test = Y_test_

    return X_train, Y_train, X_test, Y_test

def _test_classifier(
    classifier,
    dataset="iris",
    sparse=False,
    train_size_maximum=150,
    make_multilabel=False,
    make_binary=False,
):
    X_train, Y_train, X_test, Y_test = get_dataset(
        dataset=dataset,
        make_sparse=sparse,
        train_size_maximum=train_size_maximum,
        make_multilabel=make_multilabel,
        make_binary=make_binary,
    )

    configuration_space = classifier.get_hyperparameter_search_space(
        dataset_properties={"sparse": sparse}
    )
    default_config = configuration_space.get_default_configuration()

    classifier = classifier(random_state=0, **default_config)

    if hasattr(classifier, "iterative_fit"):

        class counter(object):
            def __init__(self, func):
                self.n_calls = 0
                self.func = func

            def __call__(self, *args, **kwargs):
                self.n_calls += 1
                return self.func(*args, **kwargs)

        classifier.iterative_fit = counter(classifier.iterative_fit)

    predictor = classifier.fit(X_train, Y_train)

    if hasattr(classifier, "iterative_fit"):
        n_calls = classifier.iterative_fit.n_calls
    else:
        n_calls = None

    predictions = predictor.predict(X_test)
    return predictions, Y_test, n_calls

def _test_classifier_iterative_fit(classifier, dataset="iris", sparse=False):
    X_train, Y_train, X_test, Y_test = get_dataset(dataset=dataset, make_sparse=sparse)
    configuration_space = classifier.get_hyperparameter_search_space(
        dataset_properties={"sparse": sparse}
    )
    default_config = configuration_space.get_default_configuration()

    classifier = classifier(random_state=0, **default_config)
    classifier.iterative_fit(X_train, Y_train, n_iter=2, refit=True)

    iteration = 2
    while not classifier.configuration_fully_fitted():
        n_iter = int(2**iteration / 2)
        classifier.iterative_fit(X_train, Y_train, n_iter=n_iter)
        iteration += 1

    predictions = classifier.predict(X_test)
    return predictions, Y_test, classifier

def _test_classifier_predict_proba(
    classifier,
    dataset="iris",
    sparse=False,
    train_size_maximum=150,
    make_multilabel=False,
    make_binary=False,
):
    X_train, Y_train, X_test, Y_test = get_dataset(
        dataset=dataset,
        make_sparse=sparse,
        train_size_maximum=train_size_maximum,
        make_multilabel=make_multilabel,
        make_binary=make_binary,
    )
    configuration_space = classifier.get_hyperparameter_search_space()

    default_config = configuration_space.get_default_configuration()
    classifier = classifier(random_state=0, **default_config)

    predictor = classifier.fit(X_train, Y_train)
    predictions = predictor.predict_proba(X_test)
    return predictions, Y_test

def _test_preprocessing(
    Preprocessor, dataset="iris", make_sparse=False, train_size_maximum=150
):
    X_train, Y_train, X_test, Y_test = get_dataset(
        dataset=dataset, make_sparse=make_sparse, train_size_maximum=train_size_maximum
    )
    original_X_train = X_train.copy()
    configuration_space = Preprocessor.get_hyperparameter_search_space()
    default_config = configuration_space.get_default_configuration()

    preprocessor = Preprocessor(random_state=0, **default_config)

    transformer = preprocessor.fit(X_train, Y_train)
    return transformer.transform(X_train), original_X_train

class PreprocessingTestCase(unittest.TestCase):
    def _test_preprocessing_dtype(
        self, Preprocessor, add_NaNs=False, test_sparse=True, dataset="iris"
    ):
        # Dense
        # np.float32
        X_train, Y_train, X_test, Y_test = get_dataset(dataset, add_NaNs=add_NaNs)
        self.assertEqual(X_train.dtype, np.float32)

        configuration_space = Preprocessor.get_hyperparameter_search_space()
        default_config = configuration_space.get_default_configuration()
        preprocessor = Preprocessor(random_state=0, **default_config)

        preprocessor.fit(X_train, Y_train)
        preprocessor.transform(X_train)
        # self.assertEqual(Xt.dtype, np.float32)

        # np.float64
        X_train, Y_train, X_test, Y_test = get_dataset(dataset, add_NaNs=add_NaNs)
        X_train = X_train.astype(np.float64)
        configuration_space = Preprocessor.get_hyperparameter_search_space()
        default_config = configuration_space.get_default_configuration()

        preprocessor = Preprocessor(random_state=0, **default_config)
        preprocessor.fit(X_train, Y_train)
        preprocessor.transform(X_train)
        # self.assertEqual(Xt.dtype, np.float64)

        if test_sparse is True:
            # Sparse
            # np.float32
            X_train, Y_train, X_test, Y_test = get_dataset(
                dataset, make_sparse=True, add_NaNs=add_NaNs
            )
            self.assertEqual(X_train.dtype, np.float32)
            configuration_space = Preprocessor.get_hyperparameter_search_space()
            default_config = configuration_space.get_default_configuration()
            preprocessor = Preprocessor(random_state=0, **default_config)

            preprocessor.fit(X_train, Y_train)
            preprocessor.transform(X_train)
            # self.assertEqual(Xt.dtype, np.float32)

            # np.float64
            X_train, Y_train, X_test, Y_test = get_dataset(
                dataset, make_sparse=True, add_NaNs=add_NaNs
            )
            X_train = X_train.astype(np.float64)
            configuration_space = Preprocessor.get_hyperparameter_search_space()
            default_config = configuration_space.get_default_configuration()

            preprocessor = Preprocessor(random_state=0, **default_config)
            preprocessor.fit(X_train, Y_train)
            preprocessor.transform(X_train)
            # self.assertEqual(Xt.dtype, np.float64)

def _test_regressor(Regressor, dataset="diabetes", sparse=False):
    X_train, Y_train, X_test, Y_test = get_dataset(dataset=dataset, make_sparse=sparse)
    configuration_space = Regressor.get_hyperparameter_search_space()
    default_config = configuration_space.get_default_configuration()

    regressor = Regressor(random_state=0, **default_config)

    # Dumb incomplete hacky test to check that we do not alter the data
    X_train_hash = hash(str(X_train))
    X_test_hash = hash(str(X_test))
    Y_train_hash = hash(str(Y_train))

    if hasattr(regressor, "iterative_fit"):

        class counter(object):
            def __init__(self, func):
                self.n_calls = 0
                self.func = func

            def __call__(self, *args, **kwargs):
                self.n_calls += 1
                return self.func(*args, **kwargs)

        regressor.iterative_fit = counter(regressor.iterative_fit)

    predictor = regressor.fit(X_train, Y_train)

    if hasattr(regressor, "iterative_fit"):
        n_calls = regressor.iterative_fit.n_calls
    else:
        n_calls = None

    predictions = predictor.predict(X_test)
    if (
        X_train_hash != hash(str(X_train))
        or X_test_hash != hash(str(X_test))
        or Y_train_hash != hash(str(Y_train))
    ):
        raise ValueError("Model modified data")
    return predictions, Y_test, n_calls

def _test_regressor_iterative_fit(Regressor, dataset="diabetes", sparse=False):
    X_train, Y_train, X_test, Y_test = get_dataset(dataset=dataset, make_sparse=sparse)
    configuration_space = Regressor.get_hyperparameter_search_space(
        dataset_properties={"sparse": sparse}
    )
    default_config = configuration_space.get_default_configuration()
    regressor = Regressor(random_state=0, **default_config)

    regressor.iterative_fit(X_train, Y_train, n_iter=2, refit=True)
    iteration = 2
    while not regressor.configuration_fully_fitted():
        n_iter = int(2**iteration / 2)
        regressor.iterative_fit(X_train, Y_train, n_iter=n_iter)
        iteration += 1

    predictions = regressor.predict(X_test)
    return predictions, Y_test, regressor

if __name__ == "__main__":
    find_sklearn_classes(sklearn.base.ClassifierMixin)
    find_sklearn_classes(sklearn.base.RegressorMixin)
    find_sklearn_classes(sklearn.base.TransformerMixin)


"""
Module initialize the unfolding.

@title: initialisation
@author: Valentin Louf <valentin.louf@bom.gov.au>
@institutions: Monash University and the Australian Bureau of Meteorology
@date: 16/03/2021

.. autosummary::
    :toctree: generated/

    find_last_good_vel
    flipud
    first_pass
    initialize_unfolding
"""
# Other Libraries
import numpy as np

from numba import jit, jit_module
from numba import uint32, int64, float64

# Custom
from .continuity import take_decision, unfold, is_good_velocity

def find_last_good_vel(j, n, azipos, vflag, nfilter):
    """
    Looking for the last good (i.e. processed) velocity in a slice.

    Parameters:
    ===========
    j: int
        Position in dimension 1
    n: int
        Position in dimension 2
    azipos: array
        Array of available position in dimension 1
    vflag: ndarray <azimuth, range>
        Flag array (-3: missing, 0: unprocessed, 1: processed, 2: processed and unfolded)
    nfilter: int
        Size of filter.

    Returns:
    ========
        idx_ref: int
            Last valid value in slice.
    """
    i = 0
    while i < nfilter:
        i += 1
        idx_ref = j - i
        idx = azipos[idx_ref]
        vflag_ref = vflag[idx, n]
        if vflag_ref > 0:
            return idx_ref
    return -999

def flipud(arr):
    """
    Numpy's flipud function is not supported by numba for some reasons...
    So here it is.
    """
    return arr[::-1, :]  # Soooo complex!

def first_pass(azi_start_pos, velocity, final_vel, vflag, vnyquist, delta_vmax, nfilter=3):
    """
    First pass: continuity check along the azimuth, starting at azi_start_pos.

    Parameters:
    ===========
    azi_start_pos: int
        Starting position in array alongside dimension 0.
    velocity: ndarray <azimuth, range>
        Velocity to dealias
    final_vel: ndarray <azimuth, range>
        Result array
    vflag: ndarray <azimuth, range>
        Flag array (-3: missing, 0: unprocessed, 1: processed, 2: processed and unfolded)
    vnyquist: float
        Nyquist velocity.
    vshift: float
        Shift expected when folding, i.e. 2*vnyquist (in general)
    delta_vmax: float
        Maximum velocity difference tolerated between two contiguous gates.
    nfilter: int
        Size of filtering window

    Returns:
    ========
    final_vel: array <azimuth, range>
        Unfolded velocities.
    flag_vel: array <azimuth, range>
        Flag array for velocity processing (0: unprocessed, 1:processed, 2:unfolded, -3: missing)
    """
    nazi, ngate = velocity.shape
    azipos = np.zeros((2 * nazi), dtype=uint32)
    azipos[:nazi] = np.arange(nazi)
    azipos[nazi:] = np.arange(nazi)

    for mypass in range(2):
        if mypass == 1:
            velocity = flipud(velocity)
            final_vel = flipud(final_vel)
            vflag = flipud(vflag)
            azi_start_pos = nazi - azi_start_pos - 1

        for j in range(azi_start_pos, azi_start_pos + nazi // 2):
            for n in range(ngate):
                # Build slice for comparison
                j_idx = np.arange(j + 1, j + nfilter + 1)
                j_idx[j_idx >= nazi] -= nazi

                idx_selected = vflag[j_idx, n]
                if np.all((idx_selected == -3)):
                    # All values missing in slice.
                    continue
                # Selection of velocity to dealias (j_idx is an array)
                v_selected = velocity[j_idx, n]

                # Searching reference
                idx_ref = j
                # Looking for last processed value for reference, within a nfilter distance.
                if vflag[azipos[j], n] <= 0:
                    idx_ref = find_last_good_vel(j, n, azipos, vflag, nfilter)
                    if idx_ref == -999:
                        continue

                # Reference velocity
                vref = final_vel[azipos[int(idx_ref)], n]

                # Dealiasing slice
                for k in range(len(v_selected)):
                    if idx_selected[k] == -3:
                        continue

                    vk = v_selected[k]
                    dv1 = np.abs(vk - vref)
                    if dv1 < delta_vmax:
                        # No need to dealias
                        final_vel[j_idx[k], n] = vk
                        vflag[j_idx[k], n] = 1
                    else:
                        vk_unfld = unfold(vref, vk, vnyquist)
                        dvk = np.abs(vk_unfld - vref)

                        if dvk < delta_vmax:
                            final_vel[j_idx[k], n] = vk_unfld
                            vflag[j_idx[k], n] = 2

    velocity = flipud(velocity)
    final_vel = flipud(final_vel)
    vflag = flipud(vflag)

    return final_vel, vflag

def initialize_unfolding(azi_start_pos, azi_end_pos, vel, flag_vel, vnyq=13.3):
    """
    Initialize the unfolding procedure and unfold the reference radials..

    Parameters:
    ===========

    Returns:
    ========
    final_vel: array <azimuth, range>
        Unfolded velocities.
    flag_vel: array <azimuth, range>
        Flag array for velocity processing (0: unprocessed, 1:processed, 2:unfolded, -3: missing)
    """
    # Initialize stuff.
    maxazi = vel.shape[0]
    final_vel = np.zeros(vel.shape, dtype=float64)

    iter_radials_init = np.array([azi_start_pos - 1, azi_start_pos, azi_start_pos + 1])
    iter_radials_last = np.array([azi_end_pos - 1, azi_end_pos, azi_end_pos + 1])

    for iter_radials in [iter_radials_init, iter_radials_last]:
        iter_radials[iter_radials >= maxazi] -= maxazi
        iter_radials[iter_radials < 0] += maxazi

        # Magic happens.
        is_bad = 0
        for pos_good in iter_radials:
            myvel = vel[pos_good, :]
            if np.sum(np.abs(myvel) >= 0.6 * vnyq) > 3:
                is_bad += 1
                continue

            for ngate in range(3, len(myvel) - 3):
                velref0 = np.nanmedian(myvel[ngate - 3 : ngate])
                velref1 = np.nanmedian(myvel[ngate + 1 : ngate + 4])
                decision = take_decision(velref0, velref1, vnyq, alpha=0.4)
                if decision != 1:
                    continue

                if np.isnan(velref0):
                    velref = velref1
                elif np.isnan(velref1):
                    velref = velref0
                else:
                    velref = (velref0 + velref1) / 2

                decision = take_decision(velref, myvel[ngate], vnyq, alpha=0.4)
                if decision == 0:
                    continue
                elif decision == 1:
                    final_vel[pos_good, ngate] = myvel[ngate]
                    flag_vel[pos_good, ngate] = 1
                elif decision == 2:
                    vtrue = unfold(myvel[ngate - 1], myvel[ngate], vnyq)
                    if is_good_velocity(myvel[ngate - 1], vtrue, vnyq, alpha=0.4):
                        final_vel[pos_good, ngate] = vtrue
                        flag_vel[pos_good, ngate] = 2

        if is_bad > len(iter_radials) - 1:
            for pos_good in iter_radials:
                myvel = vel[pos_good, :]

                for ngate in range(3, len(myvel) - 3):
                    if np.abs(myvel[ngate]) >= 0.5 * vnyq:
                        continue

                    velref0 = np.nanmedian(myvel[ngate - 3 : ngate])
                    velref1 = np.nanmedian(myvel[ngate + 1 : ngate + 4])
                    decision = take_decision(velref0, velref1, vnyq, alpha=0.4)
                    if decision != 1:
                        continue

                    if np.isnan(velref0):
                        velref = velref1
                    elif np.isnan(velref1):
                        velref = velref0
                    else:
                        velref = (velref0 + velref1) / 2

                    decision = take_decision(velref, myvel[ngate], vnyq, alpha=0.4)
                    if decision == 0:
                        continue
                    elif decision == 1:
                        final_vel[pos_good, ngate] = myvel[ngate]
                        flag_vel[pos_good, ngate] = 1
                    elif decision == 2:
                        vtrue = unfold(myvel[ngate - 1], myvel[ngate], vnyq)
                        if is_good_velocity(myvel[ngate - 1], vtrue, vnyq, alpha=0.4):
                            final_vel[pos_good, ngate] = vtrue
                            flag_vel[pos_good, ngate] = 2

    return final_vel, flag_vel

jit_module(nopython=True, error_model="numpy")


#!/usr/bin/env python2

import time
import os
import pickle
import urllib2

# Timestamp in ms.
def int_time(scale=1):
    return int(time.time()*scale)

def new_deck_data():
    deck_data = {}
    deck_data['lines'] = []
    deck_data['nid2did'] = {}
    deck_data['url2img'] = {}
    deck_data['line2nid'] = {}
    return deck_data

def load_deck_data(deckname):
    if not os.path.isdir(".anki"):
        os.makedirs(".anki")
    filename = os.path.join(".anki", deckname + ".p")
    if os.path.isfile(filename):
       deck_data = pickle.load(open(filename))
    else:
        deck_data = new_deck_data()
    return deck_data

def save_deck_data(deckname, data):
    if not os.path.isdir(".anki"):
        os.makedirs(".anki")
    filename = os.path.join(".anki", deckname + ".p")
    if data != None:
        pickle.dump(data, open(filename, "wb"))

def expand_macro(txt, macro_start, macro_end, f):
    second = 0
    while True:
        first = txt.find(macro_start, second)
        second = txt.find(macro_end, first + len(macro_start))
        if first >= 0 and second >= 0:
            middle = f(txt[first+len(macro_start):second])
            txt = txt[:first] + middle + txt[second+len(macro_end):]
            second = first + len(middle)
        else:
            break
    return txt

def is_prefix(txt, prefix):
    return txt[:len(prefix)].lower() == prefix.lower()

# saves the image to the local media directory, and returns
# the new filename.
def save_image(anki_dir, url):
    media_dir = os.path.join(anki_dir, "collection.media")
    if not os.path.isdir(media_dir):
        os.makedirs(media_dir)

    filename = "img" + str(int_time(1000))
    f = open(os.path.join(media_dir, filename), "wb")
    f.write(urllib2.urlopen(url).read())
    return filename


"""server URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

from newfirst import views

urlpatterns = [
    path('item_list', views.item_list, name='item_list'),  # 项目列表
    path('design_criteria_list', views.design_criteria_list, name='design_criteria_list'),  # 设计准则列表
    path('analysis_rule_list', views.analysis_rule_list, name='analysis_rule_list'),  # 分析规则列表
    path('add_analysis_rule', views.add_analysis_rule, name='add_analysis_rule'),  # 添加分析规则
    path('add_analysis_rule_from_item', views.add_analysis_rule_from_item, name='add_analysis_rule_from_item'),
    path('edit_analysis_rule', views.edit_analysis_rule, name='edit_analysis_rule'),  # 编辑分析规则
    path('delete_analysis_rule', views.delete_analysis_rule, name='delete_analysis_rule'),  # 删除分析规则
    path('add_design_criteria', views.add_design_criteria, name='add_design_criteria'),  # 添加设计准则
    path('add_design_criteria_from_item', views.add_design_criteria_from_item, name='add_design_criteria_from_item'),
    path('edit_design_criteria', views.edit_design_criteria, name='edit_design_criteria'),  # 编辑设计准则
    path('delete_design_criteria', views.delete_design_criteria, name='delete_design_criteria'),  # 删除设计准则
    path('add_item', views.add_item, name='add_item'),  # 添加项目
    path('edit_item', views.edit_item, name='edit_item'),  # 编辑项目
    path('delete_item', views.delete_item, name='delete_item'),  # 删除项目
    path('scenes_list', views.scenes_list, name='scenes_list'),  # 场景列表
    path('add_scenes', views.add_scenes, name='add_scenes'),  # 添加场景
    path('edit_scenes', views.edit_scenes, name='edit_scenes'),  # 编辑场景
    path('delete_scenes', views.delete_scenes, name='delete_scenes'),  # 删除场景
    path('add_rule', views.add_rule, name='add_rule'),  # 添加规则
    path('rules_list', views.rules_list, name='rules_list'),  # 规则集列表
    path('delete_rule', views.delete_rule, name='delete_rule'),  # 删除规则
    path('add_case_list', views.add_case_list, name='add_case_list'),  # 添加实例列表
    path('add_case', views.add_case, name='add_case'),  # 添加实例
    path('case_list', views.case_list, name='case_list'),  # 添加实例列表
    path('delete_case', views.delete_case, name='delete_case'),  # 删除实例
    path('verify_case', views.verify_case, name='verify_case'),  # 验证实例
    path('verify_case_test', views.verify_case_test, name='verify_case_test'),  # 预检验
    path('reset_case', views.reset_case, name='reset_case'),  # 重置实例
    path('fmea_list', views.fmea_list, name='fmea_list'),  # fmea列表
    path('edit_fmea', views.edit_fmea, name='edit_fmea'),  # 编辑fmea
    path('demand_list', views.demand_list, name='demand_list'),  # 需求表
    path('edit_demand', views.edit_demand, name='edit_demand'),  # 编辑需求表
    path('add_design', views.add_design, name='add_design'),  # 添加准则库
    path('designs_list', views.designs_list, name='designs_list'),  # 规则集列表
    path('delete_design', views.delete_design, name='delete_design'),  # 删除规则
    path('check_list', views.check_list, name='check_list'),  # 设计核查
    path('edit_check', views.edit_check, name='edit_check'),  # 编辑设计核查
    path('complete_list', views.complete_list, name='complete_list'),  # 设计完善
    path('edit_complete', views.edit_complete, name='edit_complete'),  # 编辑设计完善
    path('upload_file', views.upload_file, name='upload_file'),  # 上传文件
    path('import_scenes', views.import_scenes, name='import_scenes'),  # 导入场景
    path('scenes_modeling', views.scenes_modeling, name='scenes_modeling'),  # 场景建模
    path('deliver_model_data', views.deliver_model_data, name='deliver_model_data'),  # 传递模型的场景信息
    path('model_list', views.model_list, name='model_list'),  # 模型列表

]


#Hago el upload del archivo, usando el contenido binario del archivo

def upload_file(s3, bucket_name, file_name):

    with open(file_name, 'rb') as data:
        s3.Bucket(bucket_name).put_object(Key= file_name, Body = data) #este file name es el nombre que va
        #tener en el bucket

    #valido que el archivo subio al bucket correspondiente
    my_bucket = s3.Bucket(bucket_name)
    object_exists = any(obj.key == file_name for obj in my_bucket.objects.all())

    if object_exists:
        print(f'file {file_name} uploaded successfully')
    else:
        print(f'file {file_name} could not be uploaded')


from flask import Blueprint, jsonify, request, request
from . import db
from .models import User, Product, Shop, Request
from sqlalchemy import join

main = Blueprint('main', __name__)

@main.route('/users', methods=['GET', 'POST'])
def users():
    if request.method == 'GET':
        user_list = User.query.all()
        users = []

        for user in user_list:
            users.append({'user_name' : user.user_name, 'rating' : user.address})

        return jsonify({'users' : users})
    else:
        user_data = request.get_json()

        new_user = User(user_name=user_data['user_name'], address=user_data['address'])

        db.session.add(new_user)
        db.session.commit()

        return 'Done', 201

@main.route('/shops', methods=['GET', 'POST'])
def shops():
    if request.method == 'GET':
        shop_list = Shop.query.all()
        shops = []

        for shop in shop_list:
            shops.append({'shop_name' : shop.shop_name, 'address' : shop.address, 'sells': shop.sells, 'id': shop.id})

        return jsonify({'shops' : shops})
    else:
        shop_data = request.get_json()

        new_shop = Shop(shop_name=shop_data['shop_name'], address=shop_data['address'], sells=shop_data['sells'])

        db.session.add(new_shop)
        db.session.commit()

        return 'Done', 201

@main.route('/requests', methods=['GET', 'POST'])
def requests():
    if request.method == 'GET':
        request_list = db.session.query(Shop, User, Product, Request).filter(Shop.id == Request.shop_id).filter(User.id == Request.user_id).filter(Product.id == Request.user_id)
        requests = []

        for re in request_list:
            requests.append({'shop_id': re.Shop.id, 'shop_name': re.Shop.shop_name, 'shop_address': re.Shop.address, 'user_id': re.User.id, 'user_name': re.User.user_name, 'user_address': re.User.address, 'product_id': re.Product.id, 'product_name': re.Product.product_name,'product_quantity': re.Product.quantity, 'request_quantity': re.Request.quantity})

        return jsonify({'requests' : requests})

    else:
        request_data = request.get_json()

        new_request = Request(shop_id=request_data['shop_id'], user_id=request_data['user_id'], product_id=request_data['product_id'], quantity=request_data['quantity'])

        db.session.add(new_request)
        db.session.commit()

        return 'Done', 201

@main.route('/products', methods=['GET', 'POST'])
def products():
    if request.method == 'GET':

        product_list =  db.session.query(Shop, Product).filter(Shop.id == Product.shop_id)
        products = []

        for product in product_list:
            products.append({'product_id': product.Product.id,  'product_name': product.Product.product_name, 'quantity': product.Product.quantity, 'shop_id': product.Shop.id, 'shop_name': product.Shop.shop_name, 'addres': product.Shop.address, 'sells': product.Shop.sells})

        return jsonify({'products' : products})
    else:
        product_data = request.get_json()

        new_product = Product(shop_id=product_data['shop_id'], product_name=product_data['product_name'], quantity=product_data['quantity'])

        db.session.add(new_product)
        db.session.commit()

        return 'Done', 201


import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mtick
import matplotlib.ticker as ticker
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from tkinter import filedialog

from core.widget_manager import SliderManager
from matplotlib.path import Path
from matplotlib.patches import PathPatch

OFFSET =0.002
LEFT = 'left'
MIDDLE = "middle"
RIGHT = 'right'

class CustomToolbar(NavigationToolbar2Tk):
    #Custom toolbar class to Save figure with new size and DPI
    def save_figure(self, *args):
        filetypes = self.canvas.get_supported_filetypes().items()
        default_filetype = self.canvas.get_default_filetype()

        fname = filedialog.asksaveasfilename(
            defaultextension=default_filetype,
            filetypes=[*filetypes, ("All Files", "*.*")], )
        if fname:
              # Store original size
            original_size = self.canvas.figure.get_size_inches()
            # Set new size
            self.canvas.figure.set_size_inches(8, 6)
            # Save with new DPI and size
            self.canvas.figure.savefig(fname, dpi=300)
            # Restore original size
            self.canvas.figure.set_size_inches(original_size)

class PlotManager:
    def __init__(self, master, app):
        self.master = master  # Notebook tab should be master
        self.app = app
        self.shared_var = tk.DoubleVar()

        self.ax = None
        self.canvas = None
        self.position_dictionary = {LEFT: 0, MIDDLE: 1, RIGHT: 2}
        self.frames = {LEFT: None, MIDDLE: None, RIGHT: None}
        self.plots = {LEFT: None, MIDDLE: None, RIGHT: None}
        self.toolbars = {LEFT: None, MIDDLE: None, RIGHT: None}
        self.slider_managers = {LEFT: None, MIDDLE: None}
        self.lines = {LEFT: {}, MIDDLE: {},RIGHT: {}}

        self.enable_click_event = False  # No click events on plots by default
        self.selected_points = []

    def create_figure_canvas(self, fig, position):
        tab = self.app.widget_manager.notebook.nametowidget(
            self.app.widget_manager.notebook.select())
        frame = tk.Frame(tab)
        self.frames[position] = frame
        frame.grid(row=7, column=2 * self.position_dictionary[position], columnspan=2)

        canvas = FigureCanvasTkAgg(fig, frame)
        canvas.draw()
        self.canvas = canvas

        toolbar_frame = tk.Frame(frame)
        toolbar = CustomToolbar(canvas, toolbar_frame)
        toolbar.update()

        if position in [LEFT,MIDDLE]:
            slider_manager = SliderManager(
                self.frames[position], self.shared_var, self.app, self.update_plots_with_shift)
            self.slider_managers[position] = slider_manager
            current_tab_id = self.app.widget_manager.notebook.select()
            self.app.variables.set_slider_manager(
                current_tab_id, slider_manager)
            slider_manager.create_slider(frame)

        canvas.get_tk_widget().grid(row=0, column=0, sticky='n')
        toolbar_frame.grid(row=1, column=0, sticky='we')

        self.plots[position] = canvas
        self.toolbars[position] = toolbar

    def update_plots_with_shift(self, shift):
        self.specimen.manual_strain_shift = shift
        self.update_lines()

    def plot_and_draw(self, plot_function, title, position, specimen):
        self.specimen = specimen
        fig, ax = plt.subplots(figsize=(5, 4))

        plot_function(ax)
        ax.set_title(title)
        ax.set_xlabel(r"Strain - $\varepsilon$ (%)")
        ax.set_ylabel(r"Stress - $\sigma$ (MPa)")
        self.ax = ax
        self.fig = fig

        self.legend = self.create_legends(ax, position)

        ax.xaxis.set_major_formatter(mtick.PercentFormatter(1))
        locator = mtick.MaxNLocator(nbins=8)
        ax.xaxis.set_major_locator(locator)
        ax.xaxis.set_major_locator(ticker.MultipleLocator(0.1))
        ax.xaxis.set_minor_locator(ticker.AutoMinorLocator())
        ax.tick_params(axis='x', rotation=25)

        self.plateau_region_start_entry = self.app.widget_manager.prelim_group.range_entry_start
        self.plateau_region_end_entry = self.app.widget_manager.prelim_group.range_entry_end
        plateau_region_start = self.plateau_region_start_entry.get()
        plateau_region_end  = self.plateau_region_end_entry.get()

        if plateau_region_start and plateau_region_end:
            if plateau_region_start ==  self.plateau_region_start_entry.placeholder:
                plateau_region_start =0.2
            if plateau_region_end ==  self.plateau_region_end_entry.placeholder:
                plateau_region_end = 0.4
            # ax.axvspan(float(plateau_region_start), float(plateau_region_end), facecolor='green', alpha=0.1)
            # ax.text((float(plateau_region_start) + float(plateau_region_end))/2, ax.get_ylim()[-1]*0.95, 'Plateau \nRegion', ha='center', va='top', fontsize=8, color='black')

        ax.axhline(0, color='black', linestyle='--')
        ax.axvline(0, color='black', linestyle='--')
        ax.grid()

        if position is not LEFT:
            self.fig.tight_layout()
        self.create_figure_canvas(fig, position)
        self.canvas.mpl_connect('button_press_event', self.on_plot_click)

    def update_lines(self):
        # Update line data rather than recreating plot
        if self.lines[LEFT]["Shifted Stress-Strain Curve"]:
            self.lines[LEFT]["Shifted Stress-Strain Curve"].set_xdata(self.specimen.shifted_strain)
            self.lines[LEFT]["Shifted Stress-Strain Curve"].set_ydata(self.specimen.stress)
            self.plots[LEFT].draw()

        # Middle plot contains lines for all specimens. We need to find and update the line for the current specimen.
        if self.specimen.name in self.lines[MIDDLE]:
            line = self.lines[MIDDLE][self.specimen.name]
            line.set_xdata(self.specimen.shifted_strain)
            line.set_ydata(self.specimen.stress)
            self.plots[MIDDLE].draw()

    def create_legends(self, ax, position):

        self.get_plot_lines(position)

        if position == LEFT:
            #scatter
            legend1_handles = [col for col in ax.collections]
            # lines
            legend2_handles = [line for line in ax.lines]

            legend2 = ax.legend(handles=legend2_handles, loc='upper center', bbox_to_anchor=(0.45, -0.3), ncol=2)
            ax.add_artist(legend2)

            #Lengnd 1 must come after legend 2 to update the legend labels
            legend1 = ax.legend(handles=legend1_handles, )
            ax.add_artist(legend1)

            for text in legend1.get_texts():
                text.set_fontsize(6)
            for text in legend2.get_texts():
                text.set_fontsize(6)
            legend = legend1,legend2
            self.fig.subplots_adjust(bottom=0.32)
        else:
            # for the other positions, use the default legend
            legend = ax.legend()
            for text in legend.get_texts():
                text.set_fontsize(6)

        return legend

    def get_plot_lines(self, position):
        for line in self.ax.get_lines():
            self.lines[position][line.get_label()] = line

    def update_lines_with_selected_points(self, ax):
        self.selected_points.sort()
        _, specimen = self.app.button_actions.get_current_tab()

        # Set the indices
        specimen.graph_manager.first_increase_index = self.selected_points[0]
        specimen.graph_manager.next_decrease_index = self.selected_points[1]

        # Recalculate
        specimen.graph_manager.youngs_modulus = None
        specimen.graph_manager.calculate_youngs_modulus(specimen.stress, specimen.strain)
        specimen.graph_manager.calculate_strength(specimen.stress, specimen.shifted_strain, offset=OFFSET)
        iys_strain, iys_stress = specimen.IYS
        ys_strain, ys_stress = specimen.YS

        # Update the lines
        strain_shifted = specimen.graph_manager.strain_shifted
        if specimen.graph_manager.strain_offset is not None:
            strain_offset = specimen.graph_manager.strain_offset
        if specimen.graph_manager.offset_line is not None:
            offset_line = specimen.graph_manager.offset_line

        ESTIMATED_PLASTIC_INDEX_START = 'Start of Plastic Region'
        ESTIMATED_PLASTIC_INDEX_END = 'End of Plastic Region'

        for artist in ax.get_children()[:]: # create a copy of the list for iteration for removal
            if isinstance(artist, matplotlib.lines.Line2D):
                if artist.get_label() == ESTIMATED_PLASTIC_INDEX_START:
                    artist.set_xdata([strain_shifted[self.selected_points[0]]])
                if artist.get_label() == ESTIMATED_PLASTIC_INDEX_END:
                    artist.set_xdata([strain_shifted[self.selected_points[1]]])
                if artist.get_label() == f"{OFFSET*100}% Offset Stress-Strain Curve":
                    artist.set_xdata(strain_shifted)
                    artist.set_ydata(offset_line)
                # Remove vertical line
                if artist.get_label().startswith('Selected point'):
                    artist.remove()

            # Remove existing IYS scatter plot
            if isinstance(artist, matplotlib.collections.PathCollection) and artist.get_label().startswith('IYS:'):
                artist.remove()
            if isinstance(artist, matplotlib.collections.PathCollection) and artist.get_label().startswith('YS:'):
                artist.remove()

        if iys_strain is not None and iys_stress is not None:
            print("IYS found")
            ax.scatter(iys_strain, iys_stress, c="red",label=f"IYS: ({iys_strain:.3f}, {iys_stress:.3f})")

        if ys_strain is not None and ys_stress is not None:
            print("YS found")
            ax.scatter(ys_strain, ys_stress, c="blue",label=f"YS: ({ys_strain:.3f}, {ys_stress:.3f})")

        # update to work with split legend for left plot

        # TODO: exclue non scatter plots from this

        # Store the old legend's properties
        old_legend = ax.legend_
        loc = old_legend._loc
        bbox_to_anchor = old_legend.get_bbox_to_anchor().transformed(ax.transAxes.inverted())
        fontsize = old_legend.get_texts()[0].get_fontsize()
        framealpha = old_legend.get_frame().get_alpha()

        old_legend.remove()

        # Draw the new legend with the old properties
        ax.legend(loc=loc, bbox_to_anchor=bbox_to_anchor, fontsize=fontsize, framealpha=framealpha)

        # Clear the selected points list
        self.selected_points.clear()
        self.plots[LEFT].draw()

    def on_plot_click(self, event):
        if self.enable_click_event:
            ax = event.inaxes
            if ax is not None:
                # Iterate over lines in axes and find the one labeled 'Shifted Stress-Strain Curve'
                for line in ax.lines:
                    if line.get_label() == 'Shifted Stress-Strain Curve':
                        # Get the nearest index to the clicked point along the x-axis
                        xdata, ydata = line.get_xdata(), line.get_ydata()
                        clicked_point = event.xdata  # Only the x-coordinate matters
                        index = self.find_nearest_x(clicked_point, xdata)
                        print(f"index is {index}")

                        self.selected_points.append(index)

                        # If more than two points are selected, pop the first one (oldest)
                        if len(self.selected_points) > 2:
                            self.selected_points.pop(0)

                        # Visaul guide for user draw a vertical line at the selected point
                        ax.axvline(x=clicked_point, color='black', linestyle=':',
                                linewidth=2.5, label=f'Selected point {len(self.selected_points)}')

                        # Update the lines
                        if len(self.selected_points) == 2:
                            self.update_lines_with_selected_points(ax)

                        break

    @staticmethod
    def find_nearest_x(clicked_x, xdata):
        """Find the index of the nearest x value to 'clicked_x' in 'xdata'."""
        distances = np.abs(xdata - clicked_x)
        return np.argmin(distances)

def draw_error_band_xy(ax, x, y, xerr, yerr, **kwargs):
    # Calculate normals via centered finite differences
    dx = np.concatenate([[x[1] - x[0]], x[2:] - x[:-2], [x[-1] - x[-2]]])
    dy = np.concatenate([[y[1] - y[0]], y[2:] - y[:-2], [y[-1] - y[-2]]])
    l = np.hypot(dx, dy)
    nx = dy / l
    ny = -dx / l

    # End points of errors
    xp = x + nx * xerr
    yp = y + ny * yerr
    xn = x[::-1] - nx[::-1] * xerr[::-1]
    yn = y[::-1] - ny[::-1] * yerr[::-1]

    vertices = np.block([[xp, xn], [yp, yn]]).T
    codes = np.ones(vertices.shape[0], dtype=Path.code_type) * Path.LINETO
    codes[0] = Path.MOVETO

    path = Path(vertices, codes)
    ax.add_patch(PathPatch(path, **kwargs))

def draw_error_band_y(ax, x, y, err, **kwargs):
    xp = np.concatenate([x, x[::-1]])  # Upper band then lower band
    yp = np.concatenate([y + err, y[::-1] - err[::-1]])  # Positive error then negative error

    vertices = np.column_stack([xp, yp])
    codes = np.ones(vertices.shape[0], dtype=Path.code_type) * Path.LINETO
    codes[0] = Path.MOVETO

    path = Path(vertices, codes)
    patch = PathPatch(path, **kwargs)
    ax.add_patch(patch)

def draw_error_band_y_modified(ax, x, upper_y, lower_y, **kwargs):
    xp = np.concatenate([x, x[::-1]])  # Upper band then lower band for x axis
    yp = np.concatenate([upper_y, lower_y[::-1]])  # Upper limit then lower limit

    vertices = np.column_stack([xp, yp])
    codes = np.ones(vertices.shape[0], dtype=Path.code_type) * Path.LINETO
    codes[0] = Path.MOVETO

    path = Path(vertices, codes)
    patch = PathPatch(path, **kwargs)
    ax.add_patch(patch)


# -*- coding: utf8 -*-
# author: Xu Huanrong

import seaborn as sns
from WindPy import w
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import xlrd

plt.rcParams['font.sans-serif'] = ['SimHei']  # display Chinese Character
plt.rcParams['axes.unicode_minus'] = False  # display positive/negative mathematical symbols

def std_bench(dFrame, str_date):
    """processing daily bench_df"""
    dFrame['stock_weight'] = dFrame['stock_weight'] * 0.5 / 100
    dFrame['stock_yield'] = dFrame['stock_yield'] / 100
    new_rows = [str_date, 'Cash','现金', 0.5, "现金", 0.00] # cash weights 50% in benchmark
    dFrame.loc[dFrame.shape[0]] = new_rows
    return dFrame

def std_fund(dFrame, str_date):
    """processing daily fund_df"""
    dFrame['stock_weight'] = dFrame['stock_weight'] / 100
    dFrame['stock_yield'] = dFrame['stock_yield'] / 100
    cash_weight = 1 - dFrame.stock_weight.sum()
    new_rows = [str_date, 'Cash','现金', cash_weight, "现金", 0.00] # cash weights 50% in benchmark
    dFrame.loc[dFrame.shape[0]] = new_rows
    return dFrame

def process_df(dframe):
    "Return fund weight and yield."
    dframe['yield'] = dframe['stock_weight'] * dframe['stock_yield']
    weight_df = dframe.groupby('stock_industry')['stock_weight'].sum()
    yield_df = dframe.groupby('stock_industry')['yield'].sum()
    weight_df = weight_df.to_frame()
    weight_df.columns = ['weight']
    yield_df = yield_df.to_frame()
    weight_df['industry'] = weight_df.index
    yield_df['industry'] = weight_df.index
    weight_df = weight_df.reset_index(drop=True)
    yield_df = yield_df.reset_index(drop=True)
    yield_df['yield'] = yield_df['yield'] / weight_df['weight']
    return weight_df, yield_df

def to_all_key(df_1, df_2, key):
    "change industry numbers of fund as benchmark's "

    df = df_1.copy()
    df.loc[:, key] = np.array([0.0] * len(df.industry))
    new_df = df_2.append(df, ignore_index=True)
    new_df = new_df.drop_duplicates(subset='industry')
    return new_df

def re_index(df):
    "Reindex the df passed"
    df = df.sort_values(by=['industry'])
    df = df.set_index(['industry'])
    return df

def brinson_analysis(fund_weight_df, fund_yield_df, bench_weight_df, bench_yield_df, str_date):
    "Produce three elements of brinson."

    bench_weight_df = re_index(bench_weight_df)
    bench_yield_df = re_index(bench_yield_df)
    fund_weight_df = re_index(fund_weight_df)
    fund_yield_df = re_index(fund_yield_df)

    allocation_result =  (fund_weight_df['weight'] - bench_weight_df['weight']) * bench_yield_df['yield']
    allocation_df =  allocation_result.to_frame(name='result') + 1

    selection_result = (fund_yield_df['yield'] - bench_yield_df['yield']) * bench_weight_df['weight']
    selection_df = selection_result.to_frame(name='result') + 1

    interaction_result = (fund_weight_df['weight'] - bench_weight_df['weight']) * (fund_yield_df['yield'] - bench_yield_df['yield'])
    interaction_df = interaction_result.to_frame(name='result') + 1

    return allocation_df, selection_df, interaction_df

def get_results(allocation_df, selection_df, interaction_df, fund_nav_df, bench_price_df, str_date):
    "Produce result and graph."

    industry_allocation = (allocation_df - 1).sum()[0]
    stock_selection = (selection_df - 1).sum()[0]
    interaction = (interaction_df - 1).sum()[0]

    fund_yield = float(fund_nav_df[fund_nav_df.date == str_date]['fund_yield'])
    bench_yield = float(bench_price_df[bench_price_df.date == str_date]['bench_yield'])
    residual = fund_yield - industry_allocation - stock_selection - interaction - bench_yield

    result_division = [str_date, fund_yield, industry_allocation, stock_selection, interaction, residual ,bench_yield]

    return result_division

if __name__ == '__main__':

    str_date = "2017-12-01"
    bench_df_1 = bench_df[bench_df['date'] == str_date]
    fund_df_1 = fund_df[fund_df['date'] == str_date]
    std_bench_df_1 = std_bench(bench_df_1, str_date)
    std_fund_df_1 = std_fund(fund_df_1, str_date)
    bench_weight_df, bench_yield_df = process_df(std_bench_df_1)
    fund_weight_df, fund_yield_df = process_df(std_fund_df_1)
    fund_weight_df = to_all_key(bench_weight_df, fund_weight_df, 'weight')
    fund_yield_df = to_all_key(bench_yield_df, fund_yield_df, 'yield')
    allocation_df, selection_df, interaction_df = brinson_analysis(fund_weight_df, fund_yield_df, bench_weight_df, bench_yield_df, str_date)
    result_division = get_results(allocation_df, selection_df, interaction_df, fund_nav_df, bench_price_df, str_date)
    print(result_division)


from __future__ import print_function
from pyspark.sql import functions as F

def cal_psi(df1, df2, col_name, n_bin = 20, bin_type ="quantiles", verbose =False):
    """

    :param df1: dataframe
    :param df2: dataframe
    :param col_name: column to calculate psi
    :param n_bin: number bin
    :param bin_type: is "quantiles" or "bins"
    :param verbose: print explaination
    :return: psi
    """
    if bin_type not in ("quantiles", "bins"):
        print("need bin_type = quantiles or bins")
        raise ValueError
        return
    df_union = df1.select(col_name)\
        .unionByName(df2.select(col_name))
    if bin_type == "quantiles":
        delta = 1.0/float(n_bin)
        prob_list = [0.0 + delta * i for i in range(n_bin)]
        point_list = df_union.stat.approxQuantile(col_name, prob_list, 0.001)
    if bin_type == "bins":
        min_max = df_union\
            .select(F.min(col_name).alias("min"), F.max(col_name).alias("max"))\
            .collect()[0]
        min_value = min_max["min"]
        max_value = min_max["max"]
        delta = (max_value - min_value)/ float(n_bin)
        point_list = [min_value + delta * i for i in range(n_bin)]
    bin_expr = ""
    for i in range(len(point_list)):
        if i ==0:
            # first item only compare <
            col_value = "when {0} < {1} then {2} \n "\
                .format(col_name, point_list[i + 1], i + 1)
        elif (i == len(point_list) -1):
            # final item: only compare >=
            col_value = "when {0} > {1} then {2} \n "\
                        .format(col_name, point_list[i], i + 1)
        else:
            col_value = "when {0} between {1} and {2} then {3} \n "\
                .format(col_name, point_list[i], point_list[i + 1], i + 1)
        bin_expr += col_value
    # Null value bin =0, NAN value bin = max_bin.
    bin_expr = "case \n " + bin_expr + " else 0 \n end"
    if verbose:
        print("bin_expr",bin_expr)
        print("point_list",point_list)
    df1_count = df1.count()
    df1_agg = df1.withColumn("bin", F.expr(bin_expr))\
        .groupBy("bin")\
        .agg(
            (F.count("*")/df1_count).alias("count_per1"))
    df2_count = df2.count()
    df2_agg = df2.withColumn("bin", F.expr(bin_expr))\
        .groupBy("bin")\
        .agg(
            (F.count("*")/df2_count).alias("count_per2"))
    df_psi = df1_agg\
        .join(df2_agg, "bin", "outer")\
        .withColumn("psi", (F.expr("count_per1 - count_per2") *F.log(F.expr("count_per1/count_per2"))))
    psi = df_psi.select(F.sum("psi").alias("psi")).collect()[0]["psi"]
    return psi


from __future__ import print_function

import tensorflow as tf
import math
import numpy as np
from matplotlib import pyplot as plt
from modelv import myNeuralNet

# x denotes features, y denotes labels
mnist_train_inp = np.load('./data/mnist/xtrain.npy')
mnist_train_op = np.load('./data/mnist/ytrain.npy')
mnist_val_in = np.load('./data/mnist/xval.npy')
mnist_val_op = np.load('./data/mnist/yval.npy')
mnist_test_in = np.load('./data/mnist/xtest.npy')
max_epochs = 10
batch_size = 100
train_size = len(mnist_train_inp)
#input_data = [[1,1,1],[1,-1,1],[1,2,3]]
nn1 = myNeuralNet(784,10)
nn1.addHiddenLayer(500)
nn1.addFinalLayer()
nn1.setup_training(0.001,"mnist")
nn1.setup_metrics("mnist")

sess = tf.Session()
init = tf.global_variables_initializer()

sess.run(init)
train_lossarr = []
val_accarr =[]
val_lossarr = []
test_out,train_lossarr,val_lossarr,val_accarr = nn1.train(sess,max_epochs,batch_size,train_size,mnist_train_inp,mnist_train_op,mnist_val_in,mnist_val_op,mnist_test_in,train_lossarr = train_lossarr,val_lossarr=val_lossarr,val_accarr=val_accarr,print_step = 50)
np.save('mnist_out.npy',test_out)
np.save('tl1l500n1e3lr10e100bs.npy',train_lossarr)
np.save('vl1l500n1e3lr10e100bs.npy',val_lossarr)
np.save('va1l500n1e3lr10e100bs.npy',val_accarr)
#print (train_lossarr)
#print (val_lossarr)
#print (val_accarr)
sess.close() # fill in other arguments as you modify the train(self, sess, ...) in model.py
	# you will have to pass xtrain, ytrain, etc ... also as arguments so that you can sample batches in train() of model.py

# write code here to store test_pred in relevant file
#


import click

from groups import make_groups

ROSTER_FILE = 'roster.txt'
ABSENT_FILE = 'absent.txt'

absent_nums = list()

@click.group()
def cli():
    """Makes lunch groups."""
    pass

@click.command()
@click.option('--name', prompt=True)
def add(name):
    """Add a name to the lunch roster."""
    with open(ROSTER_FILE, 'a') as f:
        f.write(name + '\n')
        click.echo('Addded %s to the lunch roster.' % name)

@click.command()
def clear():
    """Clear the lunch roster."""
    open(ROSTER_FILE, 'w').close()
    click.echo('Cleared the lunch roster')

def show_roster(roster):
    for i, name in enumerate(roster):
        click.echo("%d: %s" % ((i + 1), name))

def save_absent(row_nums, roster):
    with open(ABSENT_FILE, 'a') as f:
        for row_num in row_nums:
            f.write(roster[row_num] + '\n')

def prompt_row_number(roster_size):
    """Prompts the user for a row number in our roster, and checks that it is valid. If invalid, then prompts the user until a valid input is given. 0 is reserved for letting the user mark that they are done.
    """

    while True:
        row_num = click.prompt('Enter the id of the person who is absent (or 0 to stop)', type=int)

        if row_num <= roster_size:
            return row_num

        click.echo("Invalid id. Please try again.")

@click.command()
def absent():
    """Mark a person as absent."""
    roster = get_roster()
    show_roster(roster)

    roster_size = len(roster)
    while True:
        row_num = prompt_row_number(roster_size)
        if row_num == 0:
            break
        click.echo("Removed %s" % roster[row_num - 1])
        absent_nums.append(row_num - 1)

    save_absent(absent_nums, roster)

def filter_absent(roster):
    try:
        with open(ABSENT_FILE) as f:
            absent_names = f.read().splitlines()
    except FileNotFoundError:
        absent_names = set()

    absent_set = set(absent_names)

    return set(roster).difference(absent_set)

def get_roster(should_filter_absent=False):
    roster = []
    try:
        with open(ROSTER_FILE) as f:
            roster = f.read().splitlines()
    except FileNotFoundError:
        pass

    if should_filter_absent:
        roster = filter_absent(roster)

    return roster

@click.command()
def groups():
    """Generate groups for lunch."""
    roster = get_roster(True)

    if len(roster) < 3:
        click.echo("Roster is currently less than three people. Please use the add command to add more folks.")
        return

    group_list = make_groups(roster)

    click.echo("\nLunch Groups")
    click.echo("------------")
    for i, group in enumerate(group_list):
        group_label = 'Group %d: ' % (i + 1)
        click.echo(group_label + ', '.join(group))

cli.add_command(add)
cli.add_command(groups)
cli.add_command(clear)
cli.add_command(absent)

if __name__ == '__main__':
    cli()


from dataclasses import dataclass, field
from state_machine.StateMachineLexer import StateMachineLexer
from state_machine.StateMachineParser import StateMachineParser
from state_machine.StateMachineListener import StateMachineListener
from antlr4 import InputStream, CommonTokenStream, ParseTreeWalker

@dataclass
class Event:
    code: str
    name: str

@dataclass
class State:
    code: str
    name: str
    transitions: dict = field(default_factory=dict)

    def __add__(self, event: Event):
        return TransitionFactory(self, event)

@dataclass
class Transition:
    source: State
    dest:  State
    event: Event

    def __post_init__(self):
        self.source.transitions[self.event.code] = self.dest.code

class TransitionFactory:
    def __init__(self, state: State, event: Event):
        self.state = state
        self.event = event

    def __rshift__(self, new_state):
        return Transition(self.state, new_state, self.event)

class StateMachine:
    def __init__(self):
        self.states = dict()
        self.events = dict()
        self.transitions = dict()
        self.start = None
        self.reset_events = set()

    def set_start(self, state_code):
        # Starting state to return to after reset events
        self.start = state_code
        return self

    def add_reset_event(self, event_code):
        # Set of events that cause a reset of the state to starting state
        self.reset_events.add(event_code)
        return self

    def add_state(self, code, name):
        self.states[code] = State(code, name)
        return self

    def add_event(self, code, name):
        self.events[code] = Event(code, name)
        return self

    def add_transition(self, transition: str):
        """Use the state and envent codes to define a transition from state to to state in response to event

        :param transition: string 'src event dest'
        :return:
        """
        src, event, dest = transition.split(' ')
        self.transitions[transition] = Transition(self.states[src], self.states[dest], self.events[event] )
        return self

    def __repr__(self):
        out_str = ''
        out_str += 'events\n'
        for event in self.events.values():
            out_str += f'  {event.code} {event.name}\n'
        out_str += 'end\n\n'

        for state in self.states.values():
            out_str += f'state {state.name}\n'
            for event_code, dest_state_code in state.transitions.items():
                out_str += f'  {self.events[event_code].name} => {self.states[dest_state_code].name}\n'
            out_str += 'end\n\n'
        return out_str

    @classmethod
    def from_text(cls, txt):
        return build_state_machine(txt)

def example_state_machine():
    sm = StateMachine()
    sm.add_state(
        's0', 'start'
    ).add_state(
        's1', 'finish'
    ).add_event(
        'e0', 'move'
    ).add_transition(
        's0 e0 s1'
    ).set_start('s0')
    return sm

def example_gothic_controller():
    sm = StateMachine()
    states = 'idle active waiting_for_light waiting_for_drawer unlocked_panel'.split(' ')
    for i, state in enumerate(states):
        sm.add_state(f's{i}', state)
    events = 'door_closed drawer_opened light_on door_opened panel_closed'.split(' ')
    for i, event in enumerate(events):
        sm.add_event(f'e{i}', event)
    # Transitions from state and event codes is a bit ugly - refactor to state and event names?
    sm.add_transition('s0 e0 s1')
    sm.add_transition('s1 e1 s2')
    sm.add_transition('s1 e2 s3')
    sm.add_transition('s2 e2 s4')
    sm.add_transition('s3 e1 s4')
    sm.add_transition('s4 e4 s0')
    sm.set_start('s0')
    sm.add_reset_event('e3')
    return sm

def parse_state_machine(machine_desc):
    input_stream = InputStream(machine_desc)
    lexer = StateMachineLexer(input_stream)
    stream = CommonTokenStream(lexer)
    parser = StateMachineParser(stream)
    tree = parser.file_()
    return tree

def build_state_machine(machine_desc):
    tree = parse_state_machine(machine_desc)
    builder = StateMachineBuilder()
    walker = ParseTreeWalker()
    walker.walk(builder, tree)
    return builder.state_machine

class StateMachineBuilder(StateMachineListener):
    def __init__(self):
        self.states = dict()
        self.events = dict()
        self.transitions = []
        self.state_machine = StateMachine()

    def enterEvent(self, ctx:StateMachineParser.EventContext):
        event = Event(ctx.CODE().getText(), ctx.NAME().getText())
        self.events[event.code] = event
        self.state_machine.add_event(event.code, event.name)
        # print(f'Entering event {event.name}')

    def enterMachine_state(self, ctx:StateMachineParser.Machine_stateContext):
        state = State(f's{len(self.states)}', ctx.NAME().getText())
        self.states[state.code] = state
        self.state_machine.add_state(state.code, state.name)
        # print(f'Entering state {state.name}')

    def enterTransition(self, ctx:StateMachineParser.TransitionContext):
        source_state = ctx.parentCtx.NAME().getText()
        dest_state = ctx.NAME(1).getText()
        event_name = ctx.NAME(0).getText()
        self.transitions.append( (source_state, dest_state, event_name))

    def exitFile(self, ctx:StateMachineParser.FileContext):
        # print(self.transitions)
        # Construct the state machine transitions
        state_lookup = {state.name: state.code for state in self.states.values()}
        event_lookup = {event.name: event.code for event in self.events.values()}
        for source_state, dest_state, event_name in self.transitions:
            self.state_machine.add_transition(
                f'{state_lookup[source_state]} {event_lookup[event_name]} {state_lookup[dest_state]}'
            )


from django.urls import path

from deceases.views import symptoms_autocomplete, diagnostics, deceases_by_symptoms, symptom_tree, \
    doctor_create_update_decease, medical_records, decease_detail, decease_list, decease_autocomplete

urlpatterns = [
    path('medical-records/<int:patient_id>', medical_records, name='medical-records'),
    path('symptom_tree/', symptom_tree, name='symptom-tree'),
    path('diagnostics/', diagnostics, name='diagnostics'),
    path('detail/<int:pk>/', decease_detail, name='decease-detail'),
    path('list/', decease_list, name='decease-list'),
    path('autocomplete/', decease_autocomplete, name='decease-autocomplete'),
    path('symptoms-autocomplete/', symptoms_autocomplete, name='symptoms-autocomplete'),
    path('deceases-by-symptoms/', deceases_by_symptoms, name='deceases-by-symptoms'),
    path('doctor-create-update-patient-decease/', doctor_create_update_decease, name='doctor-create-patient-decease'),
    path('doctor-create-update-patient-decease/<int:pk>/', doctor_create_update_decease,
         name='doctor-update-patient-decease'),

]


from django.test import TestCase
import requests
import socket
import json
import sys

# Create your tests here.
TEST_REPORT_TYPE = (
    (0, 'others'),
    (1, 'pre-submission'),
    (2, 'daily'),
    (3, 'weekly'),
    (4, 'release'),
)

TEST_CASE_RUN_TYPE = (
    (0, 'testrun'),
    (1, 'prepare'),
    (2, 'post'),
)

def catch_exception(func):
    def wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except Exception as e:
            print("Exception in test.py: {}".format(e))
    return wrapper

@catch_exception
def get_testreport(*args):
    report_id = int(args[0])
    apis = "{0}/testreports/?id={1}".format(host_name, report_id)
    res_get = requests.get(url=apis, headers=head, proxies=proxies, timeout=5)
    if res_get.status_code == 200:
        print(res_get.text)
    else:
        print("")

@catch_exception
def create_testreport(*args):
    apis = "{0}/testreports/".format(host_name)
    project_name, project_type, jenkins_url, artifactory_url, requester = \
        args[0], args[1], args[2], args[3], args[4]
    post_data = {"project_name": project_name, "jenkins_url": jenkins_url, "requester_ip": requester_ip,
                 "artifactory_url": artifactory_url, "type": TEST_REPORT_TYPE[project_type], "requester": requester}
    res_post = requests.post(url=apis, headers=head, proxies=proxies,
                        data=json.dumps(post_data), timeout=10)
    if res_post.status_code == 201:
        print("report_id={0}".format(json.loads(res_post.text)["data"]["id"]))
    # create one new report and save report id
    # parse all test case into report
    # Update report status
    # update testcase status

@catch_exception
def update_testreport_step(*args):
    report_id, run_status, run_step = args[0], args[1], args[2]
    apis = "{0}/testreports/{1}".format(host_name, report_id)
    post_data = {"run_step": run_step, "run_status": run_status}
    print("post_data in update_testreport_step:{0}".format(post_data))
    res = requests.patch(url=apis, headers=head, proxies=proxies,
                         data=json.dumps(post_data), timeout=5)
    print(res.status_code)

@catch_exception
def init_testcaselist(*args):
    report_id, test_case_list, gpu_type, server_os = \
        args[0], args[1], args[2], args[3]
    apis = "{0}/testreportDetail/{1}".format(host_name, report_id)
    test_case_list = json.loads(test_case_list)
    post_data = {"test_case_list": test_case_list, "status": 0, "init": True,
                 "gpu_type": gpu_type, "server_os": server_os}
    print("post_data in init_testcaselist:{0}".format(post_data))
    res = requests.post(url=apis, headers=head, proxies=proxies,
                        data=json.dumps(post_data), timeout=5)
    print(res.status_code)

@catch_exception
def update_testcase_run_status(*args):
    report_id, testcasename, status, jenkins_node, serverip, server_os = \
        args[0], args[1], args[2], args[3], args[4], args[5]
    apis = "{0}/testreportDetail/{1}".format(host_name, report_id)
    update_data = {"status": status, "server_os": server_os,
                   "guest_type": guest_type, "hypervisor": hypervisor}
    post_data = {"jenkins_node": jenkins_node, "serverip": serverip,
                 "testcase": testcasename, "update_data": update_data}
    print("post_data in update_testcase_run_status:{0}".format(post_data))
    res = requests.patch(url=apis, headers=head, proxies=proxies,
                         data=json.dumps(post_data), timeout=5)
    print("status_code:{0}".format(res.status_code))

@catch_exception
def update_testcase_report(*args):
    report_id, testcase_name, node_name, servername, serverip, detail_url = \
        args[0], args[1], args[2], args[3], args[4], args[5]
    if detail_url == '""':
        detail_url = None
    apis = "{0}/testreportDetail/{1}".format(host_name, report_id)
    update_data = {"detail_url": detail_url}
    post_data = {"node_name": node_name, "servername": servername, "serverip": serverip,
                 "testcase": testcase_name, "update_data": update_data}
    print("post_data in update_testcase_report:{0}".format(post_data))
    res = requests.patch(url=apis, headers=head, proxies=proxies,
                         data=json.dumps(post_data), timeout=5)
    print("status_code:{0}".format(res.status_code))

@catch_exception
def update_all_case_abort(*args):
    report_id = args[0]
    apis = "{0}/testreports/{1}".format(host_name, report_id)
    post_data = {"all_abort": True}
    res = requests.patch(url=apis, headers=head, proxies=proxies,
                         data=json.dumps(post_data), timeout=5)
    print(res.status_code)

@catch_exception
def update_component(*args):
    report_id, component_name, component_value = args[0], args[1], args[2]
    apis = "{0}/testreports/{1}".format(host_name, report_id)
    post_data = {"components": {component_name: component_value}}
    print("post_data in update_component:{0}".format(post_data))
    res = requests.patch(url=apis, headers=head, proxies=proxies,
                         data=json.dumps(post_data), timeout=5)
    print("status_code:{0}".format(res.status_code))

def some_sql():
    # insert into testreports_reportcomponent(component_name, component_value, test_report_id, create_time, update_time) values("repo_a", "adfasdfa", 1, NOW(), NOW());
    pass

if __name__ == "__main__":
    fun_name = sys.argv[1]
    args = tuple(sys.argv[2:])
    requester_ip = socket.gethostbyname(socket.gethostname())
    token = "Token 123412354wsdrfqawerqasdtr123235412341234"
    proxies = {'http': None, 'https': None}
    host_name = "http://10.21.16.445:8000"
    head = {"Content-Type": "application/json; charset=UTF-8",
            "Authorization": token}
    globals().get(fun_name)(*args)


from gym_foo.model.action_list import ActionList
from gym_foo.model.battlefield_detail import BattleField
from gym_foo.model.action.teleport import Teleport
from gym_foo.model.action.attack import Attack
from gym_foo.model.action.recall_occupied import RecallOccupied
from gym_foo.model.action.scout import Scout
from gym_foo.agent.agent import Agent
from gym_foo.model.tower import Tower
from gym_foo.model.hide_hive import HideHive
from gym_foo.model.action.reinforce import Reinforce
from gym_foo.model.action.rally import Rally
import random
from gym_foo.model.action.speedup import SpeedUp
from gym_foo.model.hive import Hive
from typing import List, Dict
from gym_foo.model.action.recall_march import RecallMarch
from gym_foo.model.march import March
from gym_foo.model.action.join_rally import JoinRally
from gym_foo.model.action.rally_cancel import RallyCancel
from gym_foo.Utils import *
import pickle
import math
import os

class QLearnAgent_V2(Agent):

    def __init__(self, team: object, agent_model_path: object = None) -> object:
        super().__init__(team)
        self.qfunc = dict()
        self.valid_action = ['attack_tower_full',
                             'attack_tower_half',
                             'attack_wonder_full',
                             'attack_wonder_half',
                             'attack_hive_full',
                             'attack_hive_half',
                             'reinforce_tower_full',
                             'reinforce_tower_half',
                             'reinforce_hive',
                             'rally_tower_full',
                             'rally_tower_half',
                             'rally_hive_full',
                             'rally_hive_half',
                             'scout_tower',
                             'scout_hive',
                             'speedup',
                             'teleport_wonder_1',
                             'teleport_wonder_2',
                             'teleport_tower_1',
                             'teleport_tower_2',
                             'recall_march',
                             'recall_occupied',
                             'join_rally_full',
                             'join_rally_half',
                             'cancel_rally'
                             ]
        if agent_model_path:
            self.load_agent_model(agent_model_path)

    # 行军数量是否满
    def is_march_num_full(self, hive):
        return hive.get_using_march_num() == hive.get_max_march_num()

    def is_teleport_left(self, hive):
        return hive.get_teleport_times() > 0

    def get4place(self, cord):
        s = set()
        for x, y in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            s.add((cord[0] + x, cord[1] + y))
        return s

    def get_empty_cord(self, width, height, self_hives: List[Hive], opp_hives: List[Hive], towers: List[Tower]):
        empty_cord = set([(w, h) for w in range(width) for h in range(height)])
        empty_cord -= set([hive.get_cord() for hive in self_hives])
        empty_cord -= set([hive.get_cord() for hive in opp_hives])
        empty_cord -= set([tower.get_cord() for tower in towers])
        return empty_cord

    def greedy(self, state):
        amax = 0
        key = "%s_%s" % (state, self.valid_action[0])
        qmax = self.qfunc.get(key, 0.0)
        for i in range(len(self.valid_action)):  # 扫描动作空间得到最大动作值函数
            key = "%s_%s" % (state, self.valid_action[i])
            q = self.qfunc.get(key, 0.0)
            if qmax < q:
                qmax = q
                amax = i
        return self.valid_action[amax]

    def epsilon_greedy(self, state, epsilon):
        amax = 0
        key = "%s_%s" % (state, self.valid_action[0])
        qmax = self.qfunc.get(key, 0.0)
        for i in range(len(self.valid_action)):  # 扫描动作空间得到最大动作值函数
            key = "%s_%s" % (state, self.valid_action[i])
            q = self.qfunc.get(key, 0.0)
            if qmax < q:
                qmax = q
                amax = i
        # 概率部分
        pro = [0.0 for i in range(len(self.valid_action))]
        pro[amax] += 1 - epsilon
        for i in range(len(self.valid_action)):
            pro[i] += epsilon / len(self.valid_action)

        # #选择动作
        r = random.random()
        s = 0.0
        for i in range(len(self.valid_action)):
            s += pro[i]
            if s >= r: return self.valid_action[i]
        return self.valid_action[len(self.valid_action) - 1]

    def save_agent_model(self, agent_model_path):
        sss = os.path.dirname(agent_model_path)
        if not os.path.exists(sss):
            os.makedirs(sss)
        with open(agent_model_path, "wb") as wf:
            pickle.dump(self.qfunc, wf)

    def load_agent_model(self, agent_model_path):
        with open(agent_model_path, "rb") as rf:
            self.qfunc = pickle.load(rf)
        #print(self.qfunc)

    def generate_action(self, state, score, detail: BattleField):
        action_list = []
        tower = detail.get_towers()
        opp_hives = detail.get_opp_hives()
        empty_cord = self.get_empty_cord(detail.get_width(), detail.get_height(), detail.get_self_hives(), detail.get_opp_hives(), detail.get_towers())
        hive_action_order = []
        for hive in detail.get_self_hives():

            # random_action = random.choice(self.valid_action)
            r, s = get_status_rewards_from_detail_v2(detail, hive)
            # print(s)
            random_action = self.epsilon_greedy(s, 0.2)
            if random_action.startswith('attack_wonder'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(list(filter(lambda x: x.is_wonder(), detail.get_towers())))
                if type(target) == Tower and target.who_occupied() == self._team:
                    continue
                action_list.append(
                    Attack(
                        hive_id=hive.get_id(),
                        target_cord=target.get_cord(),
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2),
                        target_type=Attack.TARGET_TYPE_TOWER,
                        target_id=target.get_id()
                    )
                )

            if random_action.startswith('attack_tower'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(list(filter(lambda x: not x.is_wonder(), detail.get_towers())))
                if type(target) == Tower and target.who_occupied() == self._team:
                    continue
                action_list.append(
                    Attack(
                        hive_id=hive.get_id(),
                        target_cord=target.get_cord(),
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2),
                        target_type=Attack.TARGET_TYPE_TOWER,
                        target_id=target.get_id()
                    )
                )

            if random_action.startswith('attack_hive'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(opp_hives)
                action_list.append(
                    Attack(
                        hive_id=hive.get_id(),
                        target_cord=target.get_cord(),
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2),
                        target_type=Attack.TARGET_TYPE_HIVE,
                        target_id=target.get_id()
                    )
                )
            if random_action.startswith('reinforce_tower'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(tower)
                if type(target) == Tower and target.who_occupied() != self._team:
                    continue
                action_list.append(
                    Reinforce(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Reinforce.TARGET_TYPE_TOWER,
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2)
                    )
                )

            if random_action == 'reinforce_hive':
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(detail.get_self_hives())
                action_list.append(
                    Reinforce(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Reinforce.TARGET_TYPE_HIVE,
                        troops_num=random.randint(1, min(hive.get_max_troops_num(), hive.get_troops_num()))
                    )
                )

            if random_action.startswith('rally_tower'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target =random.choice(tower)
                action_list.append(
                    Rally(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Rally.TARGET_TYPE_TOWER,
                        pending_times=10,
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2)
                    )
                )
            if random_action.startswith('rally_hive'):
                if self.is_march_num_full(hive):
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target =random.choice(detail.get_opp_hives())
                action_list.append(
                    Rally(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Rally.TARGET_TYPE_HIVE,
                        pending_times=10,
                        troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2)
                    )
                )

            if random_action == 'scout_tower':
                if self.is_march_num_full(hive):
                    continue
                target = random.choice(tower)
                if type(target) == Tower and target.who_occupied() is not None and target.who_occupied() != self._team:
                    continue
                action_list.append(
                    Scout(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Scout.TARGET_TYPE_TOWER,
                    )
                )

            if random_action == 'scout_hive':
                if self.is_march_num_full(hive):
                    continue
                target = random.choice(detail.get_opp_hives())
                action_list.append(
                    Scout(
                        hive_id=hive.get_id(),
                        target_id=target.get_id(),
                        target_type=Scout.TARGET_TYPE_HIVE,
                    )
                )

            if random_action == 'speedup':
                if len(detail.get_self_marches()) == 0:
                    continue
                target = random.choice(detail.get_self_marches())
                if target.get_hive_id() != hive.get_id():
                    continue
                action_list.append(
                    SpeedUp(
                        hive_id = hive.get_id(),
                        march_id=target.get_march_id()
                    )
                )
            if random_action == 'teleport_wonder_1':
                if not self.is_teleport_left(hive):
                    continue
                wonder = list(filter(lambda x: x.is_wonder(), detail.get_towers()))
                valid_cord = set()
                for w in wonder:
                    valid_cord |= self.get4place(w.get_cord())
                if len(list(valid_cord & empty_cord)) == 0:
                    continue
                target = random.choice(list(valid_cord & empty_cord))
                action_list.append(
                    Teleport(
                        hive_id=hive.get_id(),
                        new_cord=target
                    )
                )
            if random_action == 'teleport_tower_1':
                if not self.is_teleport_left(hive):
                    continue
                towers = list(filter(lambda x: not x.is_wonder(), detail.get_towers()))
                valid_cord = set()
                for t in towers:
                    valid_cord |= self.get4place(t.get_cord())
                if len(list(valid_cord & empty_cord)) == 0:
                    continue
                target = random.choice(list(valid_cord & empty_cord))
                action_list.append(
                    Teleport(
                        hive_id=hive.get_id(),
                        new_cord=target
                    )
                )
            if random_action == 'teleport_random':
                if not self.is_teleport_left(hive):
                    continue
                if len(list(empty_cord)) == 0:
                    continue
                target = random.choice(list(empty_cord))
                action_list.append(
                    Teleport(
                        hive_id=hive.get_id(),
                        new_cord=target
                    )
                )
            if random_action == 'recall_march':
                if len(detail.get_self_marches()) == 0:
                    continue
                target = random.choice(detail.get_self_marches())
                if target.get_hive_id() != hive.get_id():
                    continue
                action_list.append(
                    RecallMarch(
                        hive_id=hive.get_id(),
                        march_id=target.get_march_id()
                    )
                )

            if random_action == 'recall_occupied':
                target = random.choice(detail.get_towers() + detail.get_self_hives())
                if type(target) == Tower:
                    if (target.get_troops() is None) or (not target.get_troops().is_hive_in(hive_id=hive.get_id())):
                        continue
                if type(target) == Hive and not target.get_rein_troops().is_hive_in(hive_id=hive.get_id()):
                    continue
                action_list.append(RecallOccupied(
                    hive_id=hive.get_id(),
                    target_type=RecallOccupied.TARGET_TYPE_TOWER if type(target) == Tower else RecallOccupied.TARGET_TYPE_HIVE,
                    target_id=target.get_id()
                ))

            if random_action.startswith('join_rally'):
                if self.is_march_num_full(hive):
                    continue
                if len(detail.get_self_rallies()) == 0:
                    continue
                if hive.get_troops_num() == 0:
                    continue
                target = random.choice(detail.get_self_rallies())
                if target.get_troops().is_hive_in(hive_id=hive.get_id()):
                    continue
                is_already_join = False
                for march in detail.get_self_marches():
                    if march.get_hive_id() == hive.get_id() and march.get_target_type() == March.TARGET_TYPE_RALLY and march.get_target_id() == target.get_id():
                        is_already_join = True
                if is_already_join:
                    continue
                action_list.append(JoinRally(
                    hive_id=hive.get_id(),
                    rally_id=target.get_id(),
                    troops_num=min(hive.get_max_troops_num(), hive.get_troops_num()) if random_action.endswith('full') else math.ceil(min(hive.get_max_troops_num(), hive.get_troops_num()) / 2)
                ))

            if random_action == 'cancel_rally':
                if len(detail.get_self_rallies()) == 0:
                    continue
                target = random.choice(detail.get_self_rallies())
                if target.get_hive_id() != hive.get_id():
                    continue
                action_list.append(RallyCancel(
                    hive_id=hive.get_id(),
                    rally_id=target.get_id()
                ))
            hive_action_order.append(random_action)
            # print(hive.get_id(), random_action)
        return hive_action_order, ActionList(team=self._team, action_list=action_list)


from collections import Counter

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:

        L = 0
        result = []
        charMap = {}
        pCharMap = Counter(p)

        for R in range(len(s)):
            # Increment the charMap for each character in the window
            charMap[s[R]] = charMap.get(s[R], 0) + 1

            # Shrink the window until it matches the size of p. The code may seem weird but it makes sense
            # as we make L bigger ( by shifting the L pointer) we are subtracting byt a bigger L and therefore shrinks the window size
            while R - L + 1 > len(p):
                charMap[s[L]] -= 1
                if charMap[s[L]] == 0:
                    del charMap[s[L]]
                L += 1

            # Check if we have an anagram
            if pCharMap == charMap:
                result.append(L)

        return result


def best(W: int, items: list) -> tuple:
    best_values = [0] * (W + 1)
    last_item = [-1] * (W + 1)

    for weight in range(1, W + 1):
        best_value = 0
        for i in range(len(items)):
            if items[i][0] <= weight:
                value = best_values[weight - items[i][0]] + items[i][1]
                if value > best_value:
                    best_value = value
                    last_item[weight] = i

        best_values[weight] = best_value

    picks = [0] * len(items)
    weight = W
    while weight > 0 and last_item[weight] != -1:
        picks[last_item[weight]] += 1
        weight -= items[last_item[weight]][0]

    return (best_values[W], picks)

if __name__ == '__main__':
    print(best(3, [(2, 4), (3, 5)]))
    print(best(3, [(1, 5), (1, 5)]))
    print(best(3, [(1, 2), (1, 5)]))
    print(best(3, [(1, 2), (2, 5)]))
    print(best(58, [(5, 9), (9, 18), (6, 12)]))
    print(best(92, [(8, 9), (9, 10), (10, 12), (5, 6)]))


import pyautogui as pg
import os
import time
import numpy as np

def exc():
    os.system("mv ../../Downloads/prices.csv ./")
    os.system("./tr < prices.csv")
    os.system("./ref < tr.csv > value.txt")
    with open("value.txt", "r") as f:
        data = int(f.read())
    return data

def inNum(A):
    if A == 1 or  A == 0:
        m = 1;
    else:
        m= int(np.log(A-1))
    for i in range(m+4):
        pg.keyDown("backspace")
        pg.keyUp("backspace")
    for s in (str(A)):
        pg.keyDown(s)
        pg.keyUp(s)

n = 1611
best = 711
best_seed = 260375386

pg.moveTo(1670,855)
pg.click()

while (True):
    time.sleep(0.1)
    pg.moveTo(1908,440)
    time.sleep(0.1)
    pg.mouseDown()
    time.sleep(0.1)
    pg.moveTo(1908,600)
    pg.mouseUp()

    time.sleep(0.1)
    pg.moveTo(1315,610)
    pg.click()

    time.sleep(0.1)
    pg.moveTo(1908,611)
    time.sleep(0.1)
    pg.mouseDown()
    time.sleep(0.1)
    pg.moveTo(1908,823)
    pg.mouseUp()

    time.sleep(0.1)
    pg.moveTo(1196,801)
    pg.click()
    #数字入力
    inNum(n+1)

    time.sleep(0.1)
    pg.moveTo(1311,801)
    pg.click()
    temp = exc()
    if temp>best:
        best=temp
        best_seed=n
    print("now")
    print(n)
    print(temp)
    print("best")
    print(best)
    print(best_seed)
    print()
    n+=1