import pickle
import time
from unittest import SkipTest
import sys
import os

import numpy as np
import pytest

import randomstate.entropy as entropy
from randomstate.prng.mlfg_1279_861 import mlfg_1279_861
from randomstate.prng.mrg32k3a import mrg32k3a
from randomstate.prng.mt19937 import mt19937
from randomstate.prng.pcg32 import pcg32
from randomstate.prng.pcg64 import pcg64
from randomstate.prng.xorshift1024 import xorshift1024
from randomstate.prng.xorshift128 import xorshift128
from randomstate.prng.xoroshiro128plus import xoroshiro128plus
from randomstate.prng.dsfmt import dsfmt
from randomstate.prng.sfmt import sfmt
from numpy.testing import assert_almost_equal, assert_equal, assert_raises, assert_, assert_array_equal

@pytest.fixture(scope='module', params=(np.bool, np.int8, np.int16, np.int32, np.int64,
                                        np.uint8, np.uint16, np.uint32, np.uint64))
def dtype(request):
    return request.param

def params_0(f):
    val = f()
    assert_(np.isscalar(val))
    val = f(10)
    assert_(val.shape == (10,))
    val = f((10, 10))
    assert_(val.shape == (10, 10))
    val = f((10, 10, 10))
    assert_(val.shape == (10, 10, 10))
    val = f(size=(5, 5))
    assert_(val.shape == (5, 5))

def params_1(f, bounded=False):
    a = 5.0
    b = np.arange(2.0, 12.0)
    c = np.arange(2.0, 102.0).reshape(10, 10)
    d = np.arange(2.0, 1002.0).reshape(10, 10, 10)
    e = np.array([2.0, 3.0])
    g = np.arange(2.0, 12.0).reshape(1, 10, 1)
    if bounded:
        a = 0.5
        b = b / (1.5 * b.max())
        c = c / (1.5 * c.max())
        d = d / (1.5 * d.max())
        e = e / (1.5 * e.max())
        g = g / (1.5 * g.max())

    # Scalar
    f(a)
    # Scalar - size
    f(a, size=(10, 10))
    # 1d
    f(b)
    # 2d
    f(c)
    # 3d
    f(d)
    # 1d size
    f(b, size=10)
    # 2d - size - broadcast
    f(e, size=(10, 2))
    # 3d - size
    f(g, size=(10, 10, 10))

def comp_state(state1, state2):
    identical = True
    if isinstance(state1, dict):
        for key in state1:
            identical &= comp_state(state1[key], state2[key])
    elif type(state1) != type(state2):
        identical &= type(state1) == type(state2)
    else:
        if (isinstance(state1, (list, tuple, np.ndarray)) and isinstance(state2, (list, tuple, np.ndarray))):
            for s1, s2 in zip(state1, state2):
                identical &= comp_state(s1, s2)
        else:
            identical &= state1 == state2
    return identical

def warmup(rs, n=None):
    if n is None:
        n = 11 + np.random.randint(0, 20)
    rs.standard_normal(n, method='bm')
    rs.standard_normal(n, method='zig')
    rs.standard_normal(n, method='bm', dtype=np.float32)
    rs.standard_normal(n, method='zig', dtype=np.float32)
    rs.randint(0, 2 ** 24, n, dtype=np.uint64)
    rs.randint(0, 2 ** 48, n, dtype=np.uint64)
    rs.standard_gamma(11.0, n)
    rs.standard_gamma(11.0, n, dtype=np.float32)
    rs.random_sample(n, dtype=np.float64)
    rs.random_sample(n, dtype=np.float32)

class RNG(object):
    @classmethod
    def _extra_setup(cls):
        cls.vec_1d = np.arange(2.0, 102.0)
        cls.vec_2d = np.arange(2.0, 102.0)[None, :]
        cls.mat = np.arange(2.0, 102.0, 0.01).reshape((100, 100))
        cls.seed_error = TypeError

    def _reset_state(self):
        self.rs.set_state(self.initial_state)

    def test_init(self):
        rs = self.mod.RandomState()
        state = rs.get_state()
        rs.standard_normal(1, method='bm')
        rs.standard_normal(1, method='zig')
        rs.set_state(state)
        new_state = rs.get_state()
        assert_(comp_state(state, new_state))

    def test_advance(self):
        state = self.rs.get_state()
        if hasattr(self.rs, 'advance'):
            self.rs.advance(self.advance)
            assert_(not comp_state(state, self.rs.get_state()))
        else:
            raise SkipTest

    def test_jump(self):
        state = self.rs.get_state()
        if hasattr(self.rs, 'jump'):
            self.rs.jump()
            jumped_state = self.rs.get_state()
            assert_(not comp_state(state, jumped_state))
            self.rs.random_sample(2*3*5*7*11*13*17)
            self.rs.set_state(state)
            self.rs.jump()
            rejumped_state = self.rs.get_state()
            assert_(comp_state(jumped_state, rejumped_state))
        else:
            raise SkipTest

    def test_random_uintegers(self):
        assert_(len(self.rs.random_uintegers(10)) == 10)

    def test_random_raw(self):
        assert_(len(self.rs.random_raw(10)) == 10)
        assert_(self.rs.random_raw((10, 10)).shape == (10, 10))

    def test_uniform(self):
        r = self.rs.uniform(-1.0, 0.0, size=10)
        assert_(len(r) == 10)
        assert_((r > -1).all())
        assert_((r <= 0).all())

    def test_uniform_array(self):
        r = self.rs.uniform(np.array([-1.0] * 10), 0.0, size=10)
        assert_(len(r) == 10)
        assert_((r > -1).all())
        assert_((r <= 0).all())
        r = self.rs.uniform(np.array([-1.0] * 10), np.array([0.0] * 10), size=10)
        assert_(len(r) == 10)
        assert_((r > -1).all())
        assert_((r <= 0).all())
        r = self.rs.uniform(-1.0, np.array([0.0] * 10), size=10)
        assert_(len(r) == 10)
        assert_((r > -1).all())
        assert_((r <= 0).all())

    def test_random_sample(self):
        assert_(len(self.rs.random_sample(10)) == 10)
        params_0(self.rs.random_sample)

    def test_standard_normal_zig(self):
        assert_(len(self.rs.standard_normal(10, method='zig')) == 10)

    def test_standard_normal(self):
        assert_(len(self.rs.standard_normal(10)) == 10)
        params_0(self.rs.standard_normal)

    def test_standard_gamma(self):
        assert_(len(self.rs.standard_gamma(10, 10)) == 10)
        assert_(len(self.rs.standard_gamma(np.array([10] * 10), 10)) == 10)
        params_1(self.rs.standard_gamma)

    def test_standard_exponential(self):
        assert_(len(self.rs.standard_exponential(10)) == 10)
        params_0(self.rs.standard_exponential)

    def test_standard_cauchy(self):
        assert_(len(self.rs.standard_cauchy(10)) == 10)
        params_0(self.rs.standard_cauchy)

    def test_standard_t(self):
        assert_(len(self.rs.standard_t(10, 10)) == 10)
        params_1(self.rs.standard_t)

    def test_binomial(self):
        assert_(self.rs.binomial(10, .5) >= 0)
        assert_(self.rs.binomial(1000, .5) >= 0)

    def test_reset_state(self):
        state = self.rs.get_state()
        int_1 = self.rs.random_raw(1)
        self.rs.set_state(state)
        int_2 = self.rs.random_raw(1)
        assert_(int_1 == int_2)

    def test_entropy_init(self):
        rs = self.mod.RandomState()
        rs2 = self.mod.RandomState()
        s1 = rs.get_state()
        s2 = rs2.get_state()
        assert_(not comp_state(rs.get_state(), rs2.get_state()))

    def test_seed(self):
        rs = self.mod.RandomState(*self.seed)
        rs2 = self.mod.RandomState(*self.seed)
        assert_(comp_state(rs.get_state(), rs2.get_state()))

    def test_reset_state_gauss(self):
        rs = self.mod.RandomState(*self.seed)
        rs.standard_normal()
        state = rs.get_state()
        n1 = rs.standard_normal(size=10)
        rs2 = self.mod.RandomState()
        rs2.set_state(state)
        n2 = rs2.standard_normal(size=10)
        assert_array_equal(n1, n2)

    def test_reset_state_uint32(self):
        rs = self.mod.RandomState(*self.seed)
        rs.randint(0, 2 ** 24, 120, dtype=np.uint32)
        state = rs.get_state()
        n1 = rs.randint(0, 2 ** 24, 10, dtype=np.uint32)
        rs2 = self.mod.RandomState()
        rs2.set_state(state)
        n2 = rs2.randint(0, 2 ** 24, 10, dtype=np.uint32)
        assert_array_equal(n1, n2)

    def test_reset_state_uintegers(self):
        rs = self.mod.RandomState(*self.seed)
        rs.random_uintegers(bits=32)
        state = rs.get_state()
        n1 = rs.random_uintegers(bits=32, size=10)
        rs2 = self.mod.RandomState()
        rs2.set_state(state)
        n2 = rs2.random_uintegers(bits=32, size=10)
        assert_((n1 == n2).all())

    def test_shuffle(self):
        original = np.arange(200, 0, -1)
        permuted = self.rs.permutation(original)
        assert_((original != permuted).any())

    def test_permutation(self):
        original = np.arange(200, 0, -1)
        permuted = self.rs.permutation(original)
        assert_((original != permuted).any())

    def test_tomaxint(self):
        vals = self.rs.tomaxint(size=100000)
        maxsize = 0
        if os.name == 'nt':
            maxsize = 2 ** 31 - 1
        else:
            try:
                maxsize = sys.maxint
            except:
                maxsize = sys.maxsize
        if maxsize < 2 ** 32:
            assert_((vals < sys.maxsize).all())
        else:
            assert_((vals >= 2 ** 32).any())

    def test_beta(self):
        vals = self.rs.beta(2.0, 2.0, 10)
        assert_(len(vals) == 10)
        vals = self.rs.beta(np.array([2.0] * 10), 2.0)
        assert_(len(vals) == 10)
        vals = self.rs.beta(2.0, np.array([2.0] * 10))
        assert_(len(vals) == 10)
        vals = self.rs.beta(np.array([2.0] * 10), np.array([2.0] * 10))
        assert_(len(vals) == 10)
        vals = self.rs.beta(np.array([2.0] * 10), np.array([[2.0]] * 10))
        assert_(vals.shape == (10, 10))

    def test_bytes(self):
        vals = self.rs.bytes(10)
        assert_(len(vals) == 10)

    def test_chisquare(self):
        vals = self.rs.chisquare(2.0, 10)
        assert_(len(vals) == 10)
        params_1(self.rs.chisquare)

    def test_complex_normal(self):
        st = self.rs.get_state()
        vals = self.rs.complex_normal(2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='zig')
        assert_(len(vals) == 10)

        self.rs.set_state(st)
        vals2 = [self.rs.complex_normal(2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='zig') for _ in range(10)]
        np.testing.assert_allclose(vals, vals2)

        self.rs.set_state(st)
        vals3 = self.rs.complex_normal(2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='zig')
        np.testing.assert_allclose(vals, vals3)

        self.rs.set_state(st)
        norms = self.rs.standard_normal(size=20, method='zig')
        norms = np.reshape(norms, (10, 2))
        cov = 0.5 * (-5.0)
        v_real = 7.5
        v_imag = 2.5
        rho = cov / np.sqrt(v_real * v_imag)
        imag = 7 + np.sqrt(v_imag) * (rho * norms[:, 0] + np.sqrt(1 - rho ** 2) * norms[:, 1])
        real = 2 + np.sqrt(v_real) * norms[:, 0]
        vals4 = [re + im * (0 + 1.0j) for re, im in zip(real, imag)]

        np.testing.assert_allclose(vals4, vals)

    def test_complex_normal_bm(self):
        st = self.rs.get_state()
        vals = self.rs.complex_normal(2.0 + 7.0j, 10.0, 5.0 - 5.0j, size=10, method='bm')
        assert_(len(vals) == 10)

        self.rs.set_state(st)
        vals2 = [self.rs.complex_normal(2.0 + 7.0j, 10.0, 5.0 - 5.0j, method='bm') for _ in range(10)]
        np.testing.assert_allclose(vals, vals2)

        self.rs.set_state(st)
        vals3 = self.rs.complex_normal(2.0 + 7.0j * np.ones(10), 10.0 * np.ones(1), 5.0 - 5.0j, method='bm')
        np.testing.assert_allclose(vals, vals3)

    def test_complex_normal_zero_variance(self):
        st = self.rs.get_state()
        c = self.rs.complex_normal(0, 1.0, 1.0)
        assert_almost_equal(c.imag, 0.0)
        self.rs.set_state(st)
        n = self.rs.standard_normal()
        np.testing.assert_allclose(c, n, atol=1e-8)

        st = self.rs.get_state()
        c = self.rs.complex_normal(0, 1.0, -1.0)
        assert_almost_equal(c.real, 0.0)
        self.rs.set_state(st)
        self.rs.standard_normal()
        n = self.rs.standard_normal()
        assert_almost_equal(c.real, 0.0)
        np.testing.assert_allclose(c.imag, n, atol=1e-8)

    def test_exponential(self):
        vals = self.rs.exponential(2.0, 10)
        assert_(len(vals) == 10)
        params_1(self.rs.exponential)

    def test_f(self):
        vals = self.rs.f(3, 1000, 10)
        assert_(len(vals) == 10)

    def test_gamma(self):
        vals = self.rs.gamma(3, 2, 10)
        assert_(len(vals) == 10)

    def test_geometric(self):
        vals = self.rs.geometric(0.5, 10)
        assert_(len(vals) == 10)
        params_1(self.rs.exponential, bounded=True)

    def test_gumbel(self):
        vals = self.rs.gumbel(2.0, 2.0, 10)
        assert_(len(vals) == 10)

    def test_laplace(self):
        vals = self.rs.laplace(2.0, 2.0, 10)
        assert_(len(vals) == 10)

    def test_logitic(self):
        vals = self.rs.logistic(2.0, 2.0, 10)
        assert_(len(vals) == 10)

    def test_logseries(self):
        vals = self.rs.logseries(0.5, 10)
        assert_(len(vals) == 10)

    def test_negative_binomial(self):
        vals = self.rs.negative_binomial(10, 0.2, 10)
        assert_(len(vals) == 10)

    def test_rand(self):
        state = self.rs.get_state()
        vals = self.rs.rand(10, 10, 10)
        self.rs.set_state(state)
        assert_((vals == self.rs.random_sample((10, 10, 10))).all())
        assert_(vals.shape == (10, 10, 10))
        vals = self.rs.rand(10, 10, 10, dtype=np.float32)
        assert_(vals.shape == (10, 10, 10))

    def test_randn(self):
        state = self.rs.get_state()
        vals = self.rs.randn(10, 10, 10)
        self.rs.set_state(state)
        assert_equal(vals, self.rs.standard_normal((10, 10, 10)))
        assert_equal(vals.shape, (10, 10, 10))

        state = self.rs.get_state()
        vals = self.rs.randn(10, 10, 10, method='bm')
        self.rs.set_state(state)
        assert_equal(vals, self.rs.standard_normal((10, 10, 10), method='bm'))

        state = self.rs.get_state()
        vals_inv = self.rs.randn(10, 10, 10, method='bm')
        self.rs.set_state(state)
        vals_zig = self.rs.randn(10, 10, 10, method='zig')
        assert_((vals_zig != vals_inv).any())

        vals = self.rs.randn(10, 10, 10, dtype=np.float32)
        assert_(vals.shape == (10, 10, 10))

    def test_noncentral_chisquare(self):
        vals = self.rs.noncentral_chisquare(10, 2, 10)
        assert_(len(vals) == 10)

    def test_noncentral_f(self):
        vals = self.rs.noncentral_f(3, 1000, 2, 10)
        assert_(len(vals) == 10)
        vals = self.rs.noncentral_f(np.array([3] * 10), 1000, 2)
        assert_(len(vals) == 10)
        vals = self.rs.noncentral_f(3, np.array([1000] * 10), 2)
        assert_(len(vals) == 10)
        vals = self.rs.noncentral_f(3, 1000, np.array([2] * 10))
        assert_(len(vals) == 10)

    def test_normal(self):
        vals = self.rs.normal(10, 0.2, 10)
        assert_(len(vals) == 10)

    def test_pareto(self):
        vals = self.rs.pareto(3.0, 10)
        assert_(len(vals) == 10)

    def test_poisson(self):
        vals = self.rs.poisson(10, 10)
        assert_(len(vals) == 10)
        vals = self.rs.poisson(np.array([10] * 10))
        assert_(len(vals) == 10)
        params_1(self.rs.poisson)

    def test_poisson_lam_max(self):
        vals = self.rs.poisson_lam_max
        assert_almost_equal(vals, np.iinfo('l').max - np.sqrt(np.iinfo('l').max) * 10)

    def test_power(self):
        vals = self.rs.power(0.2, 10)
        assert_(len(vals) == 10)

    def test_randint(self):
        vals = self.rs.randint(10, 20, 10)
        assert_(len(vals) == 10)

    def test_random_integers(self):
        vals = self.rs.random_integers(10, 20, 10)
        assert_(len(vals) == 10)

    def test_rayleigh(self):
        vals = self.rs.rayleigh(0.2, 10)
        assert_(len(vals) == 10)
        params_1(self.rs.rayleigh, bounded=True)

    def test_vonmises(self):
        vals = self.rs.vonmises(10, 0.2, 10)
        assert_(len(vals) == 10)

    def test_wald(self):
        vals = self.rs.wald(1.0, 1.0, 10)
        assert_(len(vals) == 10)

    def test_weibull(self):
        vals = self.rs.weibull(1.0, 10)
        assert_(len(vals) == 10)

    def test_zipf(self):
        vals = self.rs.zipf(10, 10)
        assert_(len(vals) == 10)
        vals = self.rs.zipf(self.vec_1d)
        assert_(len(vals) == 100)
        vals = self.rs.zipf(self.vec_2d)
        assert_(vals.shape == (1, 100))
        vals = self.rs.zipf(self.mat)
        assert_(vals.shape == (100, 100))

    def test_hypergeometric(self):
        vals = self.rs.hypergeometric(25, 25, 20)
        assert_(np.isscalar(vals))
        vals = self.rs.hypergeometric(np.array([25] * 10), 25, 20)
        assert_(vals.shape == (10,))

    def test_triangular(self):
        vals = self.rs.triangular(-5, 0, 5)
        assert_(np.isscalar(vals))
        vals = self.rs.triangular(-5, np.array([0] * 10), 5)
        assert_(vals.shape == (10,))

    def test_multivariate_normal(self):
        mean = [0, 0]
        cov = [[1, 0], [0, 100]]  # diagonal covariance
        x = self.rs.multivariate_normal(mean, cov, 5000)
        assert_(x.shape == (5000, 2))
        x_zig = self.rs.multivariate_normal(mean, cov, 5000, method='zig')
        assert_(x.shape == (5000, 2))
        x_inv = self.rs.multivariate_normal(mean, cov, 5000, method='bm')
        assert_(x.shape == (5000, 2))
        assert_((x_zig != x_inv).any())

    def test_multinomial(self):
        vals = self.rs.multinomial(100, [1.0 / 3, 2.0 / 3])
        assert_(vals.shape == (2,))
        vals = self.rs.multinomial(100, [1.0 / 3, 2.0 / 3], size=10)
        assert_(vals.shape == (10, 2))

    def test_dirichlet(self):
        s = self.rs.dirichlet((10, 5, 3), 20)
        assert_(s.shape == (20, 3))

    def test_pickle(self):
        pick = pickle.dumps(self.rs)
        unpick = pickle.loads(pick)
        assert_((type(self.rs) == type(unpick)))
        assert_(comp_state(self.rs.get_state(), unpick.get_state()))

        pick = pickle.dumps(self.rs)
        unpick = pickle.loads(pick)
        assert_((type(self.rs) == type(unpick)))
        assert_(comp_state(self.rs.get_state(), unpick.get_state()))

    def test_version(self):
        state = self.rs.get_state()
        assert_('version' in state)
        assert_(state['version'] == 0)

    def test_seed_array(self):
        if self.seed_vector_bits is None:
            raise SkipTest

        if self.seed_vector_bits == 32:
            dtype = np.uint32
        else:
            dtype = np.uint64
        seed = np.array([1], dtype=dtype)
        self.rs.seed(seed)
        state1 = self.rs.get_state()
        self.rs.seed(1)
        state2 = self.rs.get_state()
        assert_(comp_state(state1, state2))

        seed = np.arange(4, dtype=dtype)
        self.rs.seed(seed)
        state1 = self.rs.get_state()
        self.rs.seed(seed[0])
        state2 = self.rs.get_state()
        assert_(not comp_state(state1, state2))

        seed = np.arange(1500, dtype=dtype)
        self.rs.seed(seed)
        state1 = self.rs.get_state()
        self.rs.seed(seed[0])
        state2 = self.rs.get_state()
        assert_(not comp_state(state1, state2))

        seed = 2 ** np.mod(np.arange(1500, dtype=dtype), self.seed_vector_bits - 1) + 1
        self.rs.seed(seed)
        state1 = self.rs.get_state()
        self.rs.seed(seed[0])
        state2 = self.rs.get_state()
        assert_(not comp_state(state1, state2))

    def test_seed_array_error(self):
        if self.seed_vector_bits == 32:
            out_of_bounds = 2 ** 32
        else:
            out_of_bounds = 2 ** 64

        seed = -1
        assert_raises(ValueError, self.rs.seed, seed)

        seed = np.array([-1], dtype=np.int32)
        assert_raises(ValueError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, -5], dtype=np.int32)
        assert_raises(ValueError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, out_of_bounds])
        assert_raises(ValueError, self.rs.seed, seed)

    def test_uniform_float(self):
        rs = self.mod.RandomState(12345)
        warmup(rs)
        state = rs.get_state()
        r1 = rs.random_sample(11, dtype=np.float32)
        rs2 = self.mod.RandomState()
        warmup(rs2)
        rs2.set_state(state)
        r2 = rs2.random_sample(11, dtype=np.float32)
        assert_array_equal(r1, r2)
        assert_equal(r1.dtype, np.float32)
        assert_(comp_state(rs.get_state(), rs2.get_state()))

    def test_gamma_floats(self):
        rs = self.mod.RandomState()
        warmup(rs)
        state = rs.get_state()
        r1 = rs.standard_gamma(4.0, 11, dtype=np.float32)
        rs2 = self.mod.RandomState()
        warmup(rs2)
        rs2.set_state(state)
        r2 = rs2.standard_gamma(4.0, 11, dtype=np.float32)
        assert_array_equal(r1, r2)
        assert_equal(r1.dtype, np.float32)
        assert_(comp_state(rs.get_state(), rs2.get_state()))

    def test_normal_floats(self):
        rs = self.mod.RandomState()
        warmup(rs)
        state = rs.get_state()
        r1 = rs.standard_normal(11, method='bm', dtype=np.float32)
        rs2 = self.mod.RandomState()
        warmup(rs2)
        rs2.set_state(state)
        r2 = rs2.standard_normal(11, method='bm', dtype=np.float32)
        assert_array_equal(r1, r2)
        assert_equal(r1.dtype, np.float32)
        assert_(comp_state(rs.get_state(), rs2.get_state()))

    def test_normal_zig_floats(self):
        rs = self.mod.RandomState()
        warmup(rs)
        state = rs.get_state()
        r1 = rs.standard_normal(11, method='zig', dtype=np.float32)
        rs2 = self.mod.RandomState()
        warmup(rs2)
        rs2.set_state(state)
        r2 = rs2.standard_normal(11, method='zig', dtype=np.float32)
        assert_array_equal(r1, r2)
        assert_equal(r1.dtype, np.float32)
        assert_(comp_state(rs.get_state(), rs2.get_state()))

    def test_output_fill(self):
        rs = self.rs
        state = rs.get_state()
        size = (31, 7, 97)
        existing = np.empty(size)
        rs.set_state(state)
        rs.standard_normal(out=existing)
        rs.set_state(state)
        direct = rs.standard_normal(size=size)
        assert_equal(direct, existing)

        existing = np.empty(size, dtype=np.float32)
        rs.set_state(state)
        rs.standard_normal(out=existing, dtype=np.float32)
        rs.set_state(state)
        direct = rs.standard_normal(size=size, dtype=np.float32)
        assert_equal(direct, existing)

    def test_output_filling_uniform(self):
        rs = self.rs
        state = rs.get_state()
        size = (31, 7, 97)
        existing = np.empty(size)
        rs.set_state(state)
        rs.random_sample(out=existing)
        rs.set_state(state)
        direct = rs.random_sample(size=size)
        assert_equal(direct, existing)

        existing = np.empty(size, dtype=np.float32)
        rs.set_state(state)
        rs.random_sample(out=existing, dtype=np.float32)
        rs.set_state(state)
        direct = rs.random_sample(size=size, dtype=np.float32)
        assert_equal(direct, existing)

    def test_output_filling_exponential(self):
        rs = self.rs
        state = rs.get_state()
        size = (31, 7, 97)
        existing = np.empty(size)
        rs.set_state(state)
        rs.standard_exponential(out=existing)
        rs.set_state(state)
        direct = rs.standard_exponential(size=size)
        assert_equal(direct, existing)

        existing = np.empty(size, dtype=np.float32)
        rs.set_state(state)
        rs.standard_exponential(out=existing, dtype=np.float32)
        rs.set_state(state)
        direct = rs.standard_exponential(size=size, dtype=np.float32)
        assert_equal(direct, existing)

    def test_output_filling_gamma(self):
        rs = self.rs
        state = rs.get_state()
        size = (31, 7, 97)
        existing = np.zeros(size)
        rs.set_state(state)
        rs.standard_gamma(1.0, out=existing)
        rs.set_state(state)
        direct = rs.standard_gamma(1.0, size=size)
        assert_equal(direct, existing)

        existing = np.zeros(size, dtype=np.float32)
        rs.set_state(state)
        rs.standard_gamma(1.0, out=existing, dtype=np.float32)
        rs.set_state(state)
        direct = rs.standard_gamma(1.0, size=size, dtype=np.float32)
        assert_equal(direct, existing)

    def test_output_filling_gamma_broadcast(self):
        rs = self.rs
        state = rs.get_state()
        size = (31, 7, 97)
        mu = np.arange(97.0) + 1.0
        existing = np.zeros(size)
        rs.set_state(state)
        rs.standard_gamma(mu, out=existing)
        rs.set_state(state)
        direct = rs.standard_gamma(mu, size=size)
        assert_equal(direct, existing)

        existing = np.zeros(size, dtype=np.float32)
        rs.set_state(state)
        rs.standard_gamma(mu, out=existing, dtype=np.float32)
        rs.set_state(state)
        direct = rs.standard_gamma(mu, size=size, dtype=np.float32)
        assert_equal(direct, existing)

    def test_output_fill_error(self):
        rs = self.rs
        size = (31, 7, 97)
        existing = np.empty(size)
        assert_raises(TypeError, rs.standard_normal, out=existing, dtype=np.float32)
        assert_raises(ValueError, rs.standard_normal, out=existing[::3])
        existing = np.empty(size, dtype=np.float32)
        assert_raises(TypeError, rs.standard_normal, out=existing, dtype=np.float64)

        existing = np.zeros(size, dtype=np.float32)
        assert_raises(TypeError, rs.standard_gamma, 1.0, out=existing, dtype=np.float64)
        assert_raises(ValueError, rs.standard_gamma, 1.0, out=existing[::3], dtype=np.float32)
        existing = np.zeros(size, dtype=np.float64)
        assert_raises(TypeError, rs.standard_gamma, 1.0, out=existing, dtype=np.float32)
        assert_raises(ValueError, rs.standard_gamma, 1.0, out=existing[::3])

    def test_randint_broadcast(self, dtype):
        if dtype == np.bool:
            upper = 2
            lower = 0
        else:
            info = np.iinfo(dtype)
            upper = int(info.max) + 1
            lower = info.min
        self._reset_state()
        a = self.rs.randint(lower, [upper] * 10, dtype=dtype)
        self._reset_state()
        b = self.rs.randint([lower] * 10, upper, dtype=dtype)
        assert_equal(a, b)
        self._reset_state()
        c = self.rs.randint(lower, upper, size=10, dtype=dtype)
        assert_equal(a, c)
        self._reset_state()
        d = self.rs.randint(np.array([lower] * 10), np.array([upper], dtype=np.object), size=10, dtype=dtype)
        assert_equal(a, d)
        self._reset_state()
        e = self.rs.randint(np.array([lower] * 10), np.array([upper] * 10), size=10, dtype=dtype)
        assert_equal(a, e)

        self._reset_state()
        a = self.rs.randint(0, upper, size=10, dtype=dtype)
        self._reset_state()
        b = self.rs.randint([upper] * 10, dtype=dtype)
        assert_equal(a, b)

    def test_randint_numpy(self, dtype):
        high = np.array([1])
        low = np.array([0])

        out = self.rs.randint(low, high, dtype=dtype)
        assert out.shape == (1,)

        out = self.rs.randint(low[0], high, dtype=dtype)
        assert out.shape == (1,)

        out = self.rs.randint(low, high[0], dtype=dtype)
        assert out.shape == (1,)

    def test_randint_broadcast_errors(self, dtype):
        if dtype == np.bool:
            upper = 2
            lower = 0
        else:
            info = np.iinfo(dtype)
            upper = int(info.max) + 1
            lower = info.min
        with pytest.raises(ValueError):
            self.rs.randint(lower, [upper + 1] * 10, dtype=dtype)
        with pytest.raises(ValueError):
            self.rs.randint(lower - 1, [upper] * 10, dtype=dtype)
        with pytest.raises(ValueError):
            self.rs.randint([lower - 1], [upper] * 10, dtype=dtype)
        with pytest.raises(ValueError):
            self.rs.randint([0], [0], dtype=dtype)

class TestMT19937(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = mt19937
        cls.advance = None
        cls.seed = [2 ** 21 + 2 ** 16 + 2 ** 5 + 1]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 32
        cls._extra_setup()
        cls.seed_error = ValueError

    def test_numpy_state(self):
        nprs = np.random.RandomState()
        nprs.standard_normal(99)
        state = nprs.get_state()
        self.rs.set_state(state)
        state2 = self.rs.get_state()
        assert_((state[1] == state2['state'][0]).all())
        assert_((state[2] == state2['state'][1]))
        assert_((state[3] == state2['gauss']['has_gauss']))
        assert_((state[4] == state2['gauss']['gauss']))

class TestPCG32(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = pcg32
        cls.advance = 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1
        cls.seed = [2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1, 2 ** 21 + 2 ** 16 + 2 ** 5 + 1]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = None
        cls._extra_setup()

    def test_seed_array_error(self):
        # GH #82 for eror type changes
        if self.seed_vector_bits == 32:
            out_of_bounds = 2 ** 32
        else:
            out_of_bounds = 2 ** 64

        seed = -1
        assert_raises(ValueError, self.rs.seed, seed)

        seed = np.array([-1], dtype=np.int32)
        assert_raises(TypeError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, -5], dtype=np.int32)
        assert_raises(TypeError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, out_of_bounds])
        assert_raises(TypeError, self.rs.seed, seed)

class TestPCG64(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = pcg64
        cls.advance = 2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1
        cls.seed = [2 ** 96 + 2 ** 48 + 2 ** 21 + 2 ** 16 + 2 ** 5 + 1,
                    2 ** 21 + 2 ** 16 + 2 ** 5 + 1]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = None
        cls._extra_setup()

    def test_seed_array_error(self):
        # GH #82 for eror type changes
        if self.seed_vector_bits == 32:
            out_of_bounds = 2 ** 32
        else:
            out_of_bounds = 2 ** 64

        seed = -1
        assert_raises(ValueError, self.rs.seed, seed)

        seed = np.array([-1], dtype=np.int32)
        assert_raises(TypeError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, -5], dtype=np.int32)
        assert_raises(TypeError, self.rs.seed, seed)

        seed = np.array([1, 2, 3, out_of_bounds])
        assert_raises(TypeError, self.rs.seed, seed)

class TestXorShift128(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = xorshift128
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 64
        cls._extra_setup()

class TestXoroShiro128Plus(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = xoroshiro128plus
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 64
        cls._extra_setup()

class TestXorShift1024(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = xorshift1024
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 64
        cls._extra_setup()

class TestSFMT(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = sfmt
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 32
        cls._extra_setup()

class TestMLFG(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = mlfg_1279_861
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls.seed_vector_bits = 64
        cls._extra_setup()

class TestMRG32k3A(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = mrg32k3a
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls._extra_setup()
        cls.seed_vector_bits = 64

class TestDSFMT(RNG):
    @classmethod
    def setup_class(cls):
        cls.mod = dsfmt
        cls.advance = None
        cls.seed = [12345]
        cls.rs = cls.mod.RandomState(*cls.seed)
        cls.initial_state = cls.rs.get_state()
        cls._extra_setup()
        cls.seed_vector_bits = 32

class TestEntropy(object):
    def test_entropy(self):
        e1 = entropy.random_entropy()
        e2 = entropy.random_entropy()
        assert_((e1 != e2))
        e1 = entropy.random_entropy(10)
        e2 = entropy.random_entropy(10)
        assert_((e1 != e2).all())
        e1 = entropy.random_entropy(10, source='system')
        e2 = entropy.random_entropy(10, source='system')
        assert_((e1 != e2).all())

    def test_fallback(self):
        e1 = entropy.random_entropy(source='fallback')
        time.sleep(0.1)
        e2 = entropy.random_entropy(source='fallback')
        assert_((e1 != e2))


import requests
from bs4 import BeautifulSoup
from pylibz import log, deepcopy
from pylibz.func import base64_encode
from .config import get_javdb_host, get_local
from .func import get_cache, write_cache

def get_values(item):
    values = []
    contents = item.select("a")
    for i in range(len(contents)):
        values.append(contents[i].text)
    return values

def get_data(session: requests.Session, vid: str, vmsg: dict):
    vmsg = deepcopy(vmsg)
    url = "%s/v/%s" % (get_javdb_host(), vid)
    r = session.get(url)
    r = r.content.decode("utf-8")
    soup = BeautifulSoup(r, 'lxml')
    title = soup.select(".title")[0].select("strong")[0].text.strip()
    vmsg["title"] = title
    contents = soup.select(".panel-block")
    for i in range(len(contents) - 1):
        if len(contents[i].select("strong")) < 1:
            continue
        tag = contents[i].select("strong")[0].text
        tag = tag.strip().strip(":")
        if tag == '片商':
            t = get_values(contents[i])
            if isinstance(t, list):
                vmsg["writer"] += t
            else:
                vmsg["writer"].append(t)
        elif tag == '發行':
            t = get_values(contents[i])
            if isinstance(t, list):
                vmsg["writer"] += t
            else:
                vmsg["writer"].append(t)
        elif tag == '系列':
            tagline = get_values(contents[i])
            if isinstance(tagline, list):
                if len(tagline) > 0:
                    tagline = tagline[0]
                else:
                    tagline = ""
            vmsg["director"] = [tagline]
        elif tag == '日期':
            vmsg["release_date"] = contents[i].select('.value')[0].text
        elif tag == '類別':
            vmsg["genre"] = get_values(contents[i])
        elif tag == '演員':
            vmsg["actor"] = get_values(contents[i])
    backdrop = soup.select('.video-cover')[0].get("src")
    if backdrop.find("http") == -1:
        backdrop = "https:" + backdrop
    backdrop = "%s/javdb/img/%s" % (get_local(), base64_encode(backdrop))
    vmsg["extra"]["com.zanjo.javdb"]["backdrop"].append(backdrop)
    return vmsg

def search_javdb(query: str):
    query = query
    cache = get_cache("javdb", query)
    if cache is not None:
        return cache
    url = "%s/search?f=all&q=" % get_javdb_host()
    session = requests.session()
    session.headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36 Edg/100.0.1185.39"
    }
    r = session.get(url + query)
    r = r.content.decode("utf-8")
    try:
        soup = BeautifulSoup(r, "lxml")
    except Exception as e:
        log().warning(r)
        raise e
    contents = soup.select("#videos .grid-item.column")
    res = []
    for i in range(len(contents)):
        if i > 5:
            break
        vid = contents[i].select("a")[0].get('href').replace("/v/", "")
        title = contents[i].select(".uid")[0].text.strip()
        sub_title = contents[i].select(".video-title")[0].text.strip()
        original_available = contents[i].select(".meta")[0].text.strip()
        poster = contents[i].select(".item-image > img")[0].get("data-src")
        if poster.find("http") == -1:
            poster = "https:" + poster
        poster = "%s/javdb/img/%s" % (get_local(), base64_encode(poster))
        vmsg = {
            "title": "%s %s" % (title, sub_title),
            "tagline": sub_title,
            "original_available": original_available,
            "original_title": title,
            "summary": sub_title,
            "certificate": "",
            "genre": [
            ],
            "actor": [],
            "director": "",
            "writer": [],
            "extra": {
                "com.zanjo.javdb": {
                    "poster": [poster],
                    "backdrop": []
                }
            }
        }
        tt = title.lower().strip()
        if i < 1 or tt == query or tt in query or query in tt:
            try:
                vmsg = get_data(session, vid, vmsg)
            except:
                log().trace()
        res.append(vmsg)
    resp = {

        "success": True,
        "result": res
    }
    write_cache("javdb", query, resp)
    return resp


def solve(data, matrix):
    for i in matrix:
        if i[0] == 99:
            return data[0]
        if i[0] == 1:
            data[i[3]] = data[i[1]] + data[i[2]]
        if i[0] == 2:
            data[i[3]] = data[i[1]] * data[i[2]]
    return data[0]

def get_matrix(data):
    matrix = []
    secondary = []
    for index, i in enumerate(data):
        if index % 4 == 0:
            if secondary:
                matrix.append(secondary)
            secondary = []
        secondary.append(i)

    matrix.append(data[-4:])
    return matrix

def find_first_value(data, expected_res):
    last_result = 0
    i = 0
    while True:
        data[1] = i
        data[2] = 0
        # 19690720
        matrix = get_matrix(data.copy())
        result = solve(data.copy(), matrix)

        if result <= expected_res:
            last_result = result
        else:
            return last_result, i
        i += 1

if __name__ == '__main__':
    with open('input.txt') as f:
        data = [int(i) for i in f.read().split(',')]
    expected_result = 19690720
    result, x = find_first_value(data.copy(), expected_result)
    y = expected_result - result
    print(100 * x + y)


from selenium import webdriver
from bs4 import BeautifulSoup
import time

base_url ="https://search.naver.com/search.naver?where=view&sm=tab_jum&query="
keyword=input("검색어 입력하세요 : ")

url =base_url + keyword

driver = webdriver.Chrome()

driver.get(url)
time.sleep(3)
#page불러오는데 시간이 걸리므로 time을 자주 사용하게 된다

'''
자바스크립트 기능을 사용해서 '스크롤'기능을 이용함. 현재 x축 이동은 필요없으므로
y축 이동만 2000으로 설정해서 해봄
document.body.scrollHeight사용하면 화면 가장 밑까지 스크롤 됨
반복문을 쓰면 스크롤을 몇번 반복할지 정할 수 있음
'''
for i in range(5):
    driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
    time.sleep(2)

naver_html = driver.page_source

soup = BeautifulSoup(naver_html, "html.parser")
items = soup.select(".api_ani_send")

rank_num=1
for area in items:
    ad = area.select_one(".link_ad")
    if ad:
        # print("광고입니다")
        continue
        # continue사용하면 아래 코드는 실행x 위로 다시 돌아감

    print(f"<<{rank_num}>>")
    names = area.select_one(".sub_txt.sub_name")
    titles = area.select_one(".api_txt_lines.total_tit")
    print(names.text)
    print(titles.text)
    print(titles['href'])
    print()

    rank_num+= 1


from functools import reduce

def read_input():
    with open('input') as f:
        lines = f.read().splitlines()
    return lines

def main1(right=3, down=1):
    lines = read_input()
    tree = '#'
    pos = right
    found = 0
    for line in lines[down::down]:
        if line[pos] == tree:
            found += 1
        pos = (pos + right) % len(line)
    return found

def main2():
    params = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
    res = [main1(*p) for p in params]
    return reduce((lambda x, y: x * y), res)

def main(task):
    return {1: main1, 2: main2}[task]()

if __name__ == '__main__':
    print(main(2))


"""
A utility for building a QM config file (which is a highly nested Python dict)
from the attributes of Quantum Element objects. We use the QM config schema
(available at https://qm-docs.s3.amazonaws.com/v0.8/config/index.html) to first
create a schema dict from whose structure the config file for the given
elements is built step by step.

This module is designed for convenience, and is not meant to be a comprehensive
utility for building a config file for all possible use cases. But it can be
extended easily to cover more cases. Global defaults, wherever used, are
explicitly declared before defining public methods.

Dc offsets are set to 0.0 and and mixer correction matrix is set to identity by
default. These values are instead to be changed during mixer tuning via the QM
API.

Here's where this module is not comprehensive:
1. No support for building digital_outputs in controllers config
2. No support for building digitalInputs, singleInputCollection,
outputPulseParameters, hold_offset, measurement_qe, frequency in elements
config.
3.
"""
from copy import deepcopy
from pathlib import Path
import yaml

from codebase.instruments import QuantumElement
from codebase.utils.pulselib import (
    Pulse,
    MeasurementPulse,
    Waveform,
    ConstantWaveform,
    ArbitraryWaveform,
)

# --------------------------------- Globals ------------------------------------
CONTROLLER = "con1"
MAX_ANALOG_OUTPUTS = 10
MAX_ANALOG_INPUTS = 2
DEFAULT_DC_OFFSET_DICT = {"offset": 0.0}
DEFAULT_MIXER_CORRECTION = (1.0, 0.0, 0.0, 1.0)
DEFAULT_TIME_OF_FLIGHT = 180
DEFAULT_SMEARING = 0
MIXER_PREFIX = "mixer_"  # mixer naming convention is MIXER_PREFIX + element.name
NUM_MIXERS_PER_ELEMENT = 1
DEFAULT_DIGITAL_MARKER = "ON"
DEFAULT_DIGITAL_ON_SAMPLES = [(1, 0)]  # must be list of tuples
DEFAULT_SAMPLING_RATE = 1  # for arbitrary waveforms, in gigacycles per second
DEFAULT_MAX_ALLOWED_ERROR = 1e3  # for auto-compression of arbitrary waveforms

# ------------------------------- Base config ----------------------------------
# base config must be in the same directory as this module
CONFIG_SCHEMA_FILENAME = "qm_config_schema.yaml"
CONFIG_SCHEMA_PATH = Path(__file__).resolve().parent / CONFIG_SCHEMA_FILENAME
with open(CONFIG_SCHEMA_PATH, "r") as base_config_file:
    QM_CONFIG_SCHEMA = yaml.safe_load(base_config_file)

# ------------------------------ Public method ---------------------------------
def build_qm_config(elements: set[QuantumElement]) -> dict:
    """
    Builds qm config from a base config file. The qm config to be built is
    passed on to helper methods, which build it step by step. This works
    because dicts are mutable and passed by reference in Python.
    """
    qm_config = dict()  # the config to be built
    qm_config["version"] = QM_CONFIG_SCHEMA["version"]  # is currently 1
    _build_elements_config(elements, qm_config)
    _build_controllers_config(elements, qm_config)
    _build_mixers_config(elements, qm_config)
    _build_pulses_and_waveforms_config(elements, qm_config)
    _build_digital_waveforms_config(qm_config)
    return qm_config

# ------------------------- Private helper methods -----------------------------
def _build_elements_config(elements: set, qm_config: dict):
    elements_config = dict()
    for element in elements:
        element_schema = deepcopy(QM_CONFIG_SCHEMA["elements"]["element_name"])
        _build_element_config(element, element_schema)
        elements_config[element.name] = element_schema
    qm_config["elements"] = elements_config

def _build_element_config(element: QuantumElement, element_schema: dict):
    _build_element_ports_config(element, element_schema)
    _build_element_freq_config(element, element_schema)
    _build_element_ops_config(element, element_schema)

    if hasattr(element, "time_of_flight") or hasattr(element, "smearing"):
        _build_readout_element_config(element, element_schema)
    else:
        del element_schema["time_of_flight"], element_schema["smearing"]

def _build_element_ports_config(element: QuantumElement, element_schema: dict):
    # TODO make this error handling more robust
    if not hasattr(element, "ports"):
        raise RuntimeError("No ports defined for element " + element.name)

    if "in" in element.ports:  # single input
        element_schema["singleInput"]["port"] = (CONTROLLER, element.ports["in"])
        del element_schema["mixInputs"]
    elif "I" in element.ports and "Q" in element.ports:  # mixed inputs
        element_schema["mixInputs"]["I"] = (CONTROLLER, element.ports["I"])
        element_schema["mixInputs"]["Q"] = (CONTROLLER, element.ports["Q"])
        del (element_schema["singleInput"], element_schema["singleInputCollection"])

    # output port, if available
    if "out" in element.ports:
        element_schema["outputs"]["out1"] = (CONTROLLER, element.ports["out"])
    else:
        del element_schema["outputs"]

def _build_element_freq_config(element: QuantumElement, element_schema: dict):
    # TODO error handling if element does not have lo_freq, int_freq attributes
    # TODO decide if 'frequency' in elements config is to be updated with omega
    element_schema["mixInputs"]["lo_frequency"] = element.lo_freq
    element_schema["intermediate_frequency"] = element.int_freq

def _build_element_ops_config(element: QuantumElement, element_schema: dict):
    # TODO make this error handling more robust
    if not hasattr(element, "operations"):
        raise RuntimeError("No operations defined for element " + element.name)

    for op_name, pulse in element.operations.items():
        element_schema["operations"][op_name] = pulse.name

def _build_readout_element_config(element: QuantumElement, element_schema: dict):
    tof = (
        element.time_of_flight
        if element.time_of_flight is not None
        else DEFAULT_TIME_OF_FLIGHT
    )
    element_schema["time_of_flight"] = tof

    smearing = element.smearing if element.smearing is not None else DEFAULT_SMEARING
    element_schema["smearing"] = smearing

def _build_controllers_config(elements: set, qm_config: dict):
    controller_schema = deepcopy(QM_CONFIG_SCHEMA["controllers"])
    for element in elements:
        for port_name, port_num in element.ports.items():
            if port_name == "out":  # build analog inputs config
                ai_config = controller_schema[CONTROLLER]["analog_inputs"]
                ai_config[port_num] = DEFAULT_DC_OFFSET_DICT
            else:  # build analog outputs config
                ao_config = controller_schema[CONTROLLER]["analog_outputs"]
                ao_config[port_num] = DEFAULT_DC_OFFSET_DICT
    qm_config["controllers"] = controller_schema

def _build_mixers_config(elements: set, qm_config: dict):
    # also updates mixer name in elements config
    mixers_config = dict()
    for element in elements:
        # build mixer config only if mixed inputs found
        if "I" in element.ports and "Q" in element.ports:
            mixer_schema = deepcopy(QM_CONFIG_SCHEMA["mixers"]["mixer_name"])
            mixer_name = MIXER_PREFIX + element.name
            # update mixer_name in elements' mixed inputs config
            mix_inputs_config = qm_config["elements"][element.name]["mixInputs"]
            mix_inputs_config["mixer"] = mixer_name
            _build_mixer_config(element, mixer_schema)
            mixers_config[mixer_name] = mixer_schema
    qm_config["mixers"] = mixers_config

def _build_mixer_config(element: QuantumElement, mixer_schema: dict):
    for i in range(NUM_MIXERS_PER_ELEMENT):
        mixer_schema[i]["intermediate_frequency"] = element.int_freq
        mixer_schema[i]["lo_frequency"] = element.lo_freq
        mixer_schema[i]["correction"] = DEFAULT_MIXER_CORRECTION

def _build_pulses_and_waveforms_config(elements: set, qm_config: dict):
    pulses_config = dict()
    waveforms_config = dict()
    for element in elements:
        for pulse in element.operations.values():
            if pulse.name not in pulses_config:  # only add unique pulses
                pulse_schema = deepcopy(QM_CONFIG_SCHEMA["pulses"]["pulse_name"])
                _build_pulse_config(pulse, pulse_schema, qm_config)
                pulses_config[pulse.name] = pulse_schema
                for waveform in pulse.waveforms.values():
                    if waveform.name not in waveforms_config:
                        _build_waveform_config(waveform, waveforms_config)
    qm_config["pulses"] = pulses_config
    qm_config["waveforms"] = waveforms_config

def _build_pulse_config(pulse: Pulse, pulse_schema: dict, qm_config: dict):
    if not hasattr(pulse, "waveforms"):
        raise RuntimeError("No waveforms defined for pulse " + pulse.name)

    _build_pulse_waveform_config(pulse, pulse_schema)
    pulse_schema["length"] = pulse.length

    if isinstance(pulse, MeasurementPulse):
        pulse_schema["operation"] = "measurement"
        _build_meas_pulse_config(pulse, pulse_schema, qm_config)
    else:
        pulse_schema["operation"] = "control"
        del pulse_schema["digital_marker"], pulse_schema["integration_weights"]

def _build_pulse_waveform_config(pulse: Pulse, pulse_schema: dict):
    if "single" in pulse.waveforms:  # single input
        pulse_schema["waveforms"]["single"] = pulse.waveforms["single"].name
        del pulse_schema["waveforms"]["I"], pulse_schema["waveforms"]["Q"]
    elif "I" in pulse.waveforms and "Q" in pulse.waveforms:  # mixed inputs
        pulse_schema["waveforms"]["I"] = pulse.waveforms["I"].name
        pulse_schema["waveforms"]["Q"] = pulse.waveforms["Q"].name
        del pulse_schema["waveforms"]["single"]

def _build_meas_pulse_config(pulse: Pulse, pulse_schema: dict, qm_config: dict):
    pulse_schema["digital_marker"] = DEFAULT_DIGITAL_MARKER
    for iw_name in pulse.integration_weights.keys():
        pulse_schema["integration_weights"][iw_name] = iw_name
    _build_integration_weights_config(pulse, qm_config)

def _build_integration_weights_config(pulse: MeasurementPulse, qm_config: dict):
    qm_config["integration_weights"] = pulse.integration_weights

def _build_waveform_config(waveform: Waveform, waveforms_config: dict):
    if isinstance(waveform, ConstantWaveform):
        const_wf_schema = deepcopy(QM_CONFIG_SCHEMA["waveforms"]["constant_wf"])
        const_wf_schema["type"] = "constant"
        const_wf_schema["sample"] = waveform.get_samples()
        waveforms_config[waveform.name] = const_wf_schema
    elif isinstance(waveform, ArbitraryWaveform):
        arb_wf_schema = deepcopy(QM_CONFIG_SCHEMA["waveforms"]["arbitrary_wf"])
        arb_wf_schema["type"] = "arbitrary"

        # we cannot set max_allowed_error and sampling_rate at the same time
        # for now, we'll simply not set these and follow qm's default behaviour
        # arb_wf_schema['max_allowed_error'] = DEFAULT_MAX_ALLOWED_ERROR
        # arb_wf_schema['sampling_rate'] = DEFAULT_SAMPLING_RATE

        arb_wf_schema["samples"] = waveform.get_samples()
        waveforms_config[waveform.name] = arb_wf_schema

def _build_digital_waveforms_config(qm_config: dict):
    # for now, assume only one default digital waveform 'ON'
    # this method can be extended if we require multiple digital waveforms
    # simply make the element remember its digital waveforms
    digital_waveforms_config = dict()
    digital_waveform_schema = QM_CONFIG_SCHEMA["digital_waveforms"][
        "digital_wf_name"
    ].copy()
    digital_waveform_schema["samples"] = DEFAULT_DIGITAL_ON_SAMPLES
    digital_waveforms_config[DEFAULT_DIGITAL_MARKER] = digital_waveform_schema
    qm_config["digital_waveforms"] = digital_waveforms_config


# various cost functions and testing functions.
"""
d x^T A x = x^T(A+A^T)
          = 2x^T A if A is symmetry

d_xx x^TAx = A + A^T or 2A if A is symmetry
"""
import numpy as np

def cost_fk(dX, dU, u, type='x'):
    assert type in 'xu'
    # 1/2(x-u)**2 = 1/2x**2 - xu + 1/2u^2
    # l_xx = 1
    # l_x = u
    l_uu = np.zeros((dX + dU, dX + dU))
    l_u = np.zeros((dX + dU))

    idx = slice(dX) if type == 'x' else slice(dX, dX + dU)

    l_uu[idx, idx] = np.eye(dX if type == 'x' else dU)
    l_u[idx] = -np.array(u)
    return l_uu, l_u


from django.urls import path
from . import views

urlpatterns = [
    #for the login page
    path('login/', views.admin_login, name='login'),
    #for the logout page
    path('logout/', views.admin_logout, name='logout'),
    #for the dashboard page
    path('', views.dash, name='dash'),
    #for the documentation page
    path('documentation/', views.documentation, name='documentation'),
]


import numpy as np
import sys
from aggregate_sl.utilities import Utils

class AggregateLocalSL(object):

    def _update_centroid(self, node):
        node.update_centroid(np.mean(self.data[node.get_index(),:], axis=0))

    def _warm_up(self, list_objects, sub_n=100):
        for node in list_objects:
            self._update_centroid(node)
            x_s = self.sampling_function(node.get_centroid(), sub_n)
            y_s = self.black_box_model(x_s)
            sub_coefs, err, min_ls = Utils.select_feature_lr_wrapper(self.k_sparse, x_s, y_s, 'bs', self.fit_intercept)
            if self.fit_intercept:
                coefs = np.zeros((self.n_feature+1, ))
                coefs[min_ls+1] = sub_coefs
            else:
                coefs = np.zeros((self.n_feature, ))
                coefs[min_ls] = sub_coefs
            node.update_coefs(coefs)

    def __init__(self, data, list_objects, sampling_function, black_box_model, k_sparse, fit_intercept = False,  k_neighbor=1):

        '''
        :param list_objects: list of objects to be clustered, each node only contains index domain
        :param sampling_function: sampling function: given a point and number of sample points, return n
        :param black_box_model : black_box_model to return label for a given point
        :param k : search nearest k neighbors to aggregate
        '''

        self.similarity_scores = {} #similarity_scores
        self.distance_map = {} #key: node; value: sorted list of pairs: (node, distance from centroid)
        self.nearest_k = k_neighbor #every time we only aggromate k nearest neighbors which default value is 1
        self.sampling_function = sampling_function
        self.black_box_model = black_box_model
        self.k_sparse = k_sparse
        self.fit_intercept = fit_intercept
        self.n_feature = len(list_objects.get_centroid())
        self.data = data

        for i in range(len(list_objects)):
            for j in range(i, len(list_objects)):
                self.similarity_scores[(list_objects[i], list_objects[j])] = float("inf")

        for i in range(len(list_objects)):
            self.distance_map[list_objects[i]] = []
            for j in range(len(list_objects)):
                if i == j:
                    continue
                self.distance_map[list_objects[i]]\
                    .append((list_objects[j], np.norm(list_objects[i].get_centroid(), list_objects[j].get_centroid())))
            self.distance_map[list_objects[i]] = sorted(self.distance_map[list_objects[i]], key=lambda x: x[1])

    def _extract_nearest_k(self, node):

        neighbors = self.distance_map[node]
        res = neighbors[:min(len(neighbors),self.nearest_k)]
        return [x[0] for x in res]

    def _contains(self, key_tuple, obj):

        '''
        :param tuple:
        :param obj:
        :return:
        '''

        for item in key_tuple:
            if item == obj:
                return True
        return False

    def remove_cluster(self, cluster):
        for key_tuple in self.similarity_pairs:
            if self._contains(key_tuple, cluster):
                del self.similarity_pairs[key_tuple]

    def add_elem(self, key_tuple, value):
        self.similarity_pairs[key_tuple] = value

    def find_minimal_pair(self):
        minimal_similarity_score = float('inf')
        final_tuple  = None
        for tuple, similarity_score in self.similarity_pairs.items():
            if minimal_similarity_score < similarity_score:
                minimal_similarity_score = similarity_score
                final_tuple = tuple
        return final_tuple

    def set_similarity_score(self, cluster1, cluster2, score):
        self.similarity_pairs[(cluster1, cluster2)] = score


#!/usr/bin/env python3

import queue, datetime, re

try:
  from tkinter import *
  from tkinter.ttk import *
  import tkinter.font as tkFont
except:
  from Tkinter import *
  import Tkinter.font as tkFont
  from Tkinter.ttk import *

def time(s):#this was defined somewhere already
  if re.search('^\\d\\d:\\d\\d$', s):
    return datetime.datetime.strptime(datetime.date.today().isoformat()+s+':00',
                             '%Y-%m-%d%H:%M:%S')
  else:
    return datetime.datetime.strptime(datetime.date.today().isoformat()+s,
                             '%Y-%m-%d%H:%M:%S')

class MultiColumnListbox(Frame):
  """use a TreeView as a multicolumn ListBox"""
  #Preface:
  #  do NOT edit this class,
  #  or ANYTHING related to this class

  def __init__(self, root, header):
    Frame.__init__(self, root)
    self.tree      = None
    self.header    = header
    self.info_list = []
    self._setup_widgets()
    self._build_tree()

  def _setup_widgets(self):
    s = """\click on header to sort by that column
to change width of column drag boundary
    """
    # create a treeview with dual scrollbars
    self.tree = Treeview(self, columns=self.header, show="headings")
    vsb = Scrollbar(self, orient="vertical",
                          command=self.tree.yview)
    hsb = Scrollbar(self, orient="horizontal",
                          command=self.tree.xview)
    self.tree.configure(yscrollcommand=vsb.set,
                        xscrollcommand=hsb.set)
    self.tree.grid(column=0, row=0, sticky='nsew')
    vsb.grid(column=1, row=0, sticky='ns')
    hsb.grid(column=0, row=1, sticky='ew')
    self.grid_columnconfigure(0, weight=1)
    self.grid_rowconfigure(0, weight=1)

  def update(self, new_list):
    self.info_list = new_list
    self._build_tree()

  def _build_tree(self):
    self.tree.delete(*self.tree.get_children())
    for col in self.header:
      self.tree.heading(col, text=col.title(),
        command=lambda c=col: self.sortby(self.tree, c, 0))
      # adjust the column's width to the header string
      self.tree.column(col,
        width=tkFont.Font().measure(col.title()))

    for item in self.info_list:
      self.tree.insert('', 'end', values=item)
      # adjust column's width if necessary to fit each value
      for ix, val in enumerate(item):
        col_w = tkFont.Font().measure(val)
        if self.tree.column(self.header[ix],width=None)<col_w:
          self.tree.column(self.header[ix], width=col_w)

  def sortby(self, tree, col, descending):
    """sort tree contents when a column header is clicked on"""
    # grab values to sort
    data = [(tree.set(child, col), child) \
      for child in tree.get_children('')]
    # if the data to be sorted is numeric change to float
    #data =  change_numeric(data)
    # now sort the data in place
    data.sort(reverse=descending)
    for ix, item in enumerate(data):
      tree.move(item[1], '', ix)
    # switch the heading so it will sort in the opposite direction
    tree.heading(col, command=lambda col=col: sortby(tree, col, \
      int(not descending)))

class App:
  def __init__(self, observer, queue, done, end, g):
    self.queue    = queue
    self.observer = observer
    self.done     = done
    self.end      = end
    self.grader   = g
    self.root = Tk()
    self.root.wm_title("DHS-HSPC Grader")
    self.root.geometry("900x304+200+200")
    self.root.bind_class("Text",  "<Control-a>", self.display_selectall)
    self.root.bind_class("Entry", "<Control-a>", self.entry_selectall)

    self.mainframe = Frame(self.root)
    self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
    self.mainframe.columnconfigure(0, weight=1)
    self.mainframe.rowconfigure(0, weight=1)

    header = ['Team Name', 'Problem Number', 'Attempt', 'Grade']

    #table of queued submissions(should be empty most of the time(mysql)
    self.queue_table = MultiColumnListbox(self.mainframe, header[:3])
    self.queue_table.grid(row=1, column=0, rowspan=5)

    #table of things that are done
    self.done_table = MultiColumnListbox(self.mainframe, header)
    self.done_table.grid(row=1, column=4, rowspan=5)

    #button that kills everything, or something like that
    self.btn1 = Button(self.mainframe, text="Stop",
                       command=lambda: self.clicked('stop'))
    self.btn1.grid(row=6, column=4)

    #that thing that says how much time is left
    self.timer_text  = StringVar()
    self.timer_text.set('Time Remaining: 00:00:00')
    self.timer_label = Label(self.mainframe, textvariable=self.timer_text)
    self.timer_label.grid(row=0, column=1, columnspan=3)

    #for your viewing pleasure
    self.separator1 = Separator(self.mainframe, orient='horizontal')
    self.separator1.grid(row=2, column=3, sticky='ew')

    #the place where the things that get graded appear
    self.grader_text  = StringVar()
    self.grader_text.set('Waiting')
    self.grader_label = Label(self.mainframe, width=25, anchor='center',
                              textvariable=self.grader_text)
    self.grader_label.grid(row=3, column=3)

    #for your viewing pleasure
    self.separator2 = Separator(self.mainframe, orient='horizontal')
    self.separator2.grid(row=4, column=3, sticky='ew')

    messages = 'Values for result:\n0: not graded\n1: good(complete)\n' \
               '2: formatting error\n3: compile error\n' \
               '4: no main class found or syntax error\n5: run time error\n' \
               '6: ran for too long\n7: outputs do not match\n' \
               'other: very very bad error\n'

    #key for humans to understand grades
    self.grade_values = Label(self.mainframe, anchor='center', text=messages)
    self.grade_values.grid(row=5, column=3)

    #humans be human, in case SOMEONE tells you that the competition will
    #  go into overtime, use this
    self.time_frame = Frame(self.mainframe)
    self.time_frame.grid(row=6, column=0)
    self.time_input = StringVar()
    self.time_input.set('{:02}:{:02}:{:02}'.format(self.end.hour,
                                                   self.end.minute,
                                                   self.end.second))
    self.time_entry =Entry(self.time_frame,width=8,textvariable=self.time_input)
    self.time_entry.grid(row=0, column=0)

    #the button in case someone tells you that you have to be here longer
    self.btn2 = Button(self.time_frame, text="Set End Time",
                       command=lambda: self.clicked('time'))
    self.btn2.grid(row=0, column=1)

    self.update()#should trigger constant updates, until the end of time

  def entry_selectall(self, event):
    event.widget.select_range(0, END)

  def display_selectall(self, event):
    event.widget.tag_add(SEL, '1.0', END)

  def clicked(self, button):
    if 'stop' in button.lower():
      self.end = datetime.datetime.now()
      self.observer.stop()
      self.observer.join()
    elif 'time' in button.lower():
      try:
        tmp = time(self.time_input.get())
        if self.end > datetime.datetime.now():
          self.end = tmp
      except ValueError:#we learn time in 1st grade, right?
        print("please go back to 1st grade and learn how to represent time")
    self.update()

  def update(self):
    tmp = [(i[1]['team_name'], i[1]['problem_id'],
            i[1]['attempts']) for i in self.queue.queue]
    self.queue_table.update(tmp)

    tmp = [(i['team_name'], i['problem_id'],
            i['attempts'],  i['result']) for i in self.done]
    self.done_table.update(tmp)

    if self.end < datetime.datetime.now():
      h = 0
      m = 0
      s = 0
      self.observer.stop()#if time has ended(the end is here), stop
      self.observer.join()
    else:#it seems humans deal better with time when it's-a split up
      sec = (self.end - datetime.datetime.now()).seconds
      h   = int(sec / 3600)
      m   = int(sec / 60) % 60
      s   = int(sec % 60)

    self.timer_text.set('Time Remaining: {:02}:{:02}:{:02}'.format(h, m, s))

    if self.grader and self.grader.status():
      self.grader_text.set('Grading\n'+self.grader.status())
    else:
      self.grader_text.set('Waiting')

    self.root.after(500, self.update)#update again after half-a asecond

  def mainloop(self):#run forest, run!
    self.root.mainloop()

  def quit(self):#kill stuff
    if not self.queue.empty() or (self.grader and self.grader.status()):
      return
    self.observer.stop()
    self.observer.join()
    self.root.quit()

#This is here to test the gui, should remain commented
'''
obs = None
q = queue.Queue()
q.put(('a', {'team_name':'team_1', 'problem_id':3, 'attempts':2}))
done = [{'team_name':'another team', 'problem_id':2, 'attempts':1, 'result':5}]
g = None
end = datetime.datetime.strptime(datetime.date.today().isoformat()+'23:00:00',
                                 '%Y-%m-%d%H:%M:%S')
app = App(obs, q, done, end, g)
app.mainloop()
print('I got Here')
'''


import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import TimeSeriesSplit
from statsmodels.tsa.arima.model import ARIMA
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

#Using oop
class TemperatureData:
    def __init__(self):
        self.data = None
        self.top_hot_years = TopHotYears()
    ##fulfilling the requirement of handling file and error
    def TemperatureFileLoad(self, fileName):
        try:
            self.data = pd.read_csv(fileName)
        except FileNotFoundError:
            print("File not found!")
        except pd.errors.EmptyDataError:
            print("Empty data file!")
        except pd.errors.ParserError:
            print("Error parsing the data file!")

    def filter_data(self, start_year=None, end_year=None):
        if start_year and end_year:
            self.data = self.data[(self.data[' Year'] >= start_year) & (self.data[' Year'] <= end_year)]

    def plotChart(self):
        if self.data is not None:
            plt.plot(self.data[' Year'], self.data['Temperature - (Celsius)'])
            plt.xlabel('Year')
            plt.ylabel('Temperature (Celsius)')
            plt.title('Temperature Change Over Time')
            plt.show()
        else:
            print("No data to plot!")

    def generate_statistical_summary(self):
        if self.data is not None:
            summary = self.data['Temperature - (Celsius)'].describe()
            print(summary)
        else:
            print("No data available!")

    def train_arima_model(self):
        if self.data is not None:
            tscv = TimeSeriesSplit(n_splits=3)
            for train_index, test_index in tscv.split(self.data):
                train_data = self.data.iloc[train_index]
                test_data = self.data.iloc[test_index]
                model = ARIMA(train_data['Temperature - (Celsius)'], order=(1, 0, 0))
                model_fit = model.fit()

                # Forecasting
                forecast = model_fit.predict(start=test_index[0], end=test_index[-1])
                print("Forecast:")
                print(forecast)
                plt.plot(test_data[' Year'], test_data['Temperature - (Celsius)'], label='Actual')
                plt.plot(test_data[' Year'], forecast, label='Forecast')
                plt.xlabel('Year')
                plt.ylabel('Temperature (Celsius)')
                plt.title('ARIMA Forecast')
                plt.legend()
                plt.show()

        else:
            print("No data available!")

    def train_lstm_model(self):
        if self.data is not None:
            # Prepare input and output data
            train_X = self.data['Temperature - (Celsius)'].shift(1).fillna(0).values.reshape(-1, 1)
            train_y = self.data['Temperature - (Celsius)'].values.reshape(-1, 1)

            # Create LSTM model
            model = Sequential()
            model.add(LSTM(128, activation='relu', input_shape=(1, 1)))
            model.add(Dense(1))
            model.compile(optimizer='adam', loss='mse')

            # Train the model
            model.fit(train_X, train_y, epochs=10)
            # Generate forecast
            forecast = model.predict(train_X[-10:])
            print("Forecast:")
            print(forecast)

        else:
            print("No data available!")

class TopHotYears:
    def __init__(self):
        self.top_temperatures = pd.DataFrame(columns=[' Year', 'Temperature - (Celsius)'])
    def find_top_hot_years(self, data, n=10):
        if data is not None:
            sorted_df = data.sort_values('Temperature - (Celsius)', ascending=False)
            top_n_years = sorted_df[' Year'].unique()[:n]
            for year in top_n_years:
                max_temperature_year = sorted_df[sorted_df[' Year'] == year].iloc[0]
                self.top_temperatures = pd.concat([self.top_temperatures, max_temperature_year.to_frame().T])
            return self.top_temperatures[[' Year', 'Temperature - (Celsius)']]
        else:
            print("No data available!")

temp_data = TemperatureData()
temp_data.TemperatureFileLoad('Tempreture_1901_2016_Pakistan.csv')
temp_data.filter_data(1910, 2010)
temp_data.plotChart()
temp_data.generate_statistical_summary()
temp_data.train_arima_model()
temp_data.train_lstm_model()
# Find the top 10 hot years
top_hot_years = temp_data.top_hot_years.find_top_hot_years(temp_data.data, 10)
print(top_hot_years)


# the list
known_users = ["Alice", "Bob", "Claire", "Dan", "Emma", "Fred", "George", "Harry"]

while True:
    print("Hi! I am Travis")
    name = input("What is your name? ").strip().capitalize()

# this checks if the name entered exists in the list above
    if name in known_users:
        print(f"Welcome back {name}!")
        remove = input("Do you want to be removed from the Matrix (y/n)?: ").strip().lower()
# this will then ask the user if they want to be removed
        if remove == "y":
            known_users.remove(name)
            print("You've been removed from the Matrix!")
        elif remove == "n":
            print("No problem, I didn't want you to go")

# this will then ask the user if they wish to be added to the list
    else:
        print(f"Sorry, don't know who you are {name}!")
        add_me = input("Do you want to be added TO THE MATRIX? (y/n)?: ").strip().lower()
        if add_me == "y":
            known_users.append(name)
            print(f"You are now in the Matrix {name}!")
        elif add_me == "n":
            print("No worries then")


from tkinter import *
root=Tk()

mymenu=Menu(root)
root.config(menu=mymenu)

def fun1():
    print("this is new project")
def fun2():
    print("this is new ")
    root.quit()
submenu=Menu(mymenu)
mymenu.add_cascade(label="file",menu=submenu)
submenu.add_command(label="New Project",command=fun1)
submenu.add_command(label="New",command=fun2 )

toolbar=Frame(root,bg="pink")
inbutton=Button(toolbar,text="crop")
inbutton.pack(side=LEFT,padx=2,pady=2)
toolbar.pack(side=TOP,fill=X)
statusbar=Label(root,text="this is status bar" ,anchor=W)
statusbar.pack(side=BOTTOM,fill=X)
root.mainloop()


from random import randint

rps_dict = {
    '1': 'ROCK',
    '2': 'PAPER',
    '3': 'SCISSOR'
}

def compair(a, b):
    if a == b: return 'DRAW'
    if a == 'ROCK':
        if b == 'PAPER':
            return b
        else:  # 'SCISSOR'
            return a
    elif a == 'PAPER':
        if b == 'ROCK':
            return a
        else:  # 'SCISSOR'
            return b
    else:
        if b == 'ROCK':
            return b
        else:  # 'PAPER'
            return a

def get_player_choice():
    choice = input('1-ROCK 2-PAPER 3-SCISSOR: ')
    if choice in '123':
        return rps_dict[choice]
    else:
        print('Not available; Choose between 1, 2 and 3.')
        return get_player_choice()

def get_computer_choice():
    choice = str(randint(1, 3))
    return rps_dict[choice]

def display_choices(player, computer):
    print('Player\'s choice: {c}'.format(c=player))
    print('Computer\'s choice: {c}'.format(c=computer))

def play_again():
    choice = input('Play again? (y: yes)')
    if choice != 'y':
        quit()

def main():
    while True:
        player = get_player_choice()
        computer = get_computer_choice()
        print()

        display_choices(player, computer)
        res = compair(player, computer)
        print()

        print('{winner} wins.'.format(winner=res) if res != 'DRAW' else 'DRAW')

        play_again()
        print()

if __name__ == '__main__':
    main()


# Adjust to the number of reagents you would like in your reagents bag
restockTo = 50
if Player.Name == 'TheWarMage':
    restockTo = 150
    #pass
# Adjust to whether to not you want to remove reagents from your bag if you have more than the desired amount
removeReagentsIfOverRestockToAmount = True

houseReagentsChestSerial = 0x43923CEA
houseTopLeftCornerX = 975
houseTopLeftCornerY = 452
houseBottomRightCornerX = 987
houseBottomRightCornerY = 469

from Scripts.utilities.items import FindItem, MoveItem, FindNumberOfItems
from Scripts.glossary.items.reagents import reagents
from Scripts.glossary.colors import colors
from Scripts import config

def RestockReagents():
    global restockTo
    global removeReagentsIfOverRestockToAmount

    reagentsBagSharedValue = 'reagentsBag'

    if not Misc.CheckSharedValue( reagentsBagSharedValue ):
        reagentsBag = Target.PromptTarget( 'Select bag to move the reagents into' )
        Misc.SetSharedValue( reagentsBagSharedValue, reagentsBag )

    reagentsBag = Misc.ReadSharedValue( reagentsBagSharedValue )
    if reagentsBag == None or Items.FindBySerial( reagentsBag ) == None:
        Player.HeadMessage( colors[ 'red' ], 'Can\'t find reagents bag! Clearing stored bag, please run again' )
        Misc.RemoveSharedValue( reagentsBagSharedValue )
        return

    reagentsBag = Items.FindBySerial( reagentsBag )

    if ( Player.Position.X >= houseTopLeftCornerX and Player.Position.Y >= houseTopLeftCornerY and
            Player.Position.X <= houseBottomRightCornerX and Player.Position.Y <= houseBottomRightCornerY ):
        reagentsSource = Items.FindBySerial( houseReagentsChestSerial )
    else:
        reagentsSource = Target.PromptTarget( 'Select container to restock from' )
        reagentsSource = Items.FindBySerial( reagentsSource )
        if reagentsSource == None or not reagentsSource.IsContainer:
            Player.HeadMessage( colors[ 'red' ], 'Invalid source container' )

    Items.UseItem( reagentsSource )
    Misc.Pause( config.dragDelayMilliseconds )

    reagentItemIDs = [ reagents[ reagent ].itemID for reagent in reagents ]
    reagentsInBag = FindNumberOfItems( reagentItemIDs, reagentsBag )

    for reagent in reagents:
        currentReagent = reagents[ reagent ]
        if reagentsInBag[ currentReagent.itemID ] == restockTo:
            continue
        elif reagentsInBag[ currentReagent.itemID ] < restockTo:
            reagentStackFromReagentsBag = FindItem( currentReagent.itemID, reagentsBag )
            reagentStackFromSourceContainer = FindItem( currentReagent.itemID, reagentsSource )
            if reagentStackFromReagentsBag == None:
                MoveItem( Items, Misc, reagentStackFromSourceContainer, reagentsBag, restockTo )
            else:
                MoveItem( Items, Misc, reagentStackFromSourceContainer, reagentsBag, restockTo - reagentStackFromReagentsBag.Amount )
        elif removeReagentsIfOverRestockToAmount:
            reagentStackFromReagentsBag = FindItem( currentReagent.itemID, reagentsBag )
            Misc.SendMessage( 'Removing %i %s' % ( reagentStackFromReagentsBag.Amount - restockTo, currentReagent.name ) )
            MoveItem( Items, Misc, reagentStackFromReagentsBag, reagentsSource, reagentStackFromReagentsBag.Amount - restockTo )

RestockReagents()


# -*- coding: utf-8 -*-
"""
Created on Fri Feb 10 14:34:25 2023

@author: MICRO
"""

import cv2
from matplotlib import pyplot as plt
import numpy as np

x=np.arange(256)
y=np.sin(2*np.pi*x/50)

y+=max(y)

y_img=np.array([[y[j]*127 for j in range(256)] for i in range(256)],dtype=np.uint8)

plt.imshow(y_img)

img=cv2.imread('images/onion.png',0)

dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)

dft=np.fft.fftshift(dft) #shift to center

magnitude_spectrum = 20*np.log((cv2.magnitude(dft[:,:,0],dft[:,:,1]))+1) #to rise negative value

fig=plt.figure(figsize=(12,12))
ax1=fig.add_subplot(2,2,1)
ax1.imshow(img)
ax1.title.set_text('Input image')

ax2=fig.add_subplot(2,2,2)
ax2.imshow(magnitude_spectrum)
ax2.title.set_text('FFT image')


"""
Crop image randomly based on original size
"""
import os
import cv2
import numpy as np
import random
from torchvision import transforms

class RandomCropDramaticlly(object):
    def __init__(self, minimum_percent=0.7, maximum_percent=0.85, p=0.5):
        """
        random crop input image by percent, returned image have same size with input image

        the cropped image is between minimum percent and maximum percent
        """
        self.minimum_percent = minimum_percent
        self.maximum_percent = maximum_percent
        self.w_orig = None
        self.h_orig = None
        self.bbox_img = None    # is image in bbox type
        self.p = p

    def __call__(self, input_img):
        """
        crop image randomly
        """
        if random.random() < self.p: return input_img

        self.h_orig = input_img.shape[0]
        self.w_orig = input_img.shape[1]

        img = self.find_bbox_img(input_img)
        h, w = img.shape[0], img.shape[1]

        # crop image randomly by percent
        crop_img = self.random_crop_by_percent(img, w, h)

        # resize image
        if self.w_orig >= self.h_orig:
            resize = self.w_orig - 2 * 10
        else:
            resize = self.h_orig - 2 * 10
        crop_img = self.resize_by_scale(crop_img, resize, interpolation=None)

        # padding
        pad_img = self.padding(crop_img, input_img)

        # # visual
        # show_img = pad_img[:, :, 0:3]
        # show_sketch = pad_img[:, :, 3:]
        # cv2.imshow('process', show_img)
        # cv2.imshow('show_sketch', show_sketch)
        # cv2.waitKey(0)

        return pad_img

    def is_bbox_img(self, img):
        if (img[0][0][:] == [255, 255, 255]).all():
            return True
        else:
            return False

    def find_bbox_img(self, img):

        def find_bbox(img):
            if img.shape[2] == 3:
                indexs = np.where(img != [255, 255, 255])
            elif img.shape[2] == 1:
                indexs = np.where(img != 255)
            else:       # multi-channel
                rgb_img = img[:, :, 0:3]
                indexs = np.where(rgb_img != 255)
            min_x, max_x = min(indexs[0]), max(indexs[0])
            min_y, max_y = min(indexs[1]), max(indexs[1])
            return min_x, max_x, min_y, max_y
        min_x, max_x, min_y, max_y = find_bbox(img)
        bbox_img = img[min_x:max_x, min_y:max_y]
        return bbox_img

    def random_crop_by_percent(self, bbox_img, w, h):
        ratio_wh = w / h
        # extrem ratio condition
        if ratio_wh >= 5:
            cropped_size = int(w * self.minimum_percent)
            b_vertical = True
        elif ratio_wh <= 0.2:
            cropped_size = int(h * self.minimum_percent)
            b_vertical = False
        else:
            random_percent = random.randint(int(self.minimum_percent * 100), int(self.maximum_percent * 100)) * 0.01
            if random.random() < 0.5:
                cropped_size = int(w * random_percent)
                b_vertical = True
            else:
                cropped_size = int(h * random_percent)
                b_vertical = False

        if b_vertical:  # crop
            if random.random() < 0.5:
                crop_img = bbox_img[:, 0:cropped_size]
            else:
                crop_img = bbox_img[:, w - cropped_size:w]
        else:
            if random.random() < 0.5:
                crop_img = bbox_img[0:cropped_size, :]
            else:
                crop_img = bbox_img[h - cropped_size: h, :]
        return crop_img

    def resize_by_scale(self, img, size, interpolation=None):
        """
        interpolation: INTER_NEAREST, INTER_LINEAR, INTER_AREA
        """
        h, w = img.shape[0], img.shape[1]
        if (w >= h and w == size) or (h >= w and h == size):
            return img
        if w > h:
            ow = size
            oh = int(size * h / w)
        else:
            oh = size
            ow = int(size * w / h)
        return cv2.resize(img, (ow, oh), interpolation)

    def padding(self, crop_img, input_img):
        # padding
        h_diff = int((self.h_orig - crop_img.shape[0]) / 2)
        w_diff = int((self.w_orig - crop_img.shape[1]) / 2)
        if h_diff < 0: h_diff = 10
        if w_diff < 0: h_diff = 10

        replicate = crop_img
        for i in range(crop_img.shape[2]):
            padding_img = cv2.copyMakeBorder(crop_img[:, :, i], h_diff, h_diff, w_diff, w_diff, cv2.BORDER_CONSTANT,
                                             value=[255])
            padding_img = np.expand_dims(padding_img, axis=2)
            if i == 0:
                replicate = padding_img
            else:
                replicate = np.concatenate((replicate, padding_img), axis=2)

        if replicate.shape != input_img.shape: #img.shape:
            replicate = cv2.resize(replicate, (self.w_orig, self.h_orig))
        return replicate

def __repr__(self):
    return self.__class__.__name__ + '(size={0}, padding={1})'.format(self.size, self.padding)

if __name__ == '__main__':
    img_dir = '/Users/shunming/data/3D/maijiaxiu/online/train/images'
    # img_dir = '/Users/shunming/data/3D/xilin_online_test/xiling_images'
    img_files = os.listdir(img_dir)
    random_crop = RandomCropDramaticlly()
    for img_file in img_files:
        img = cv2.imread(os.path.join(img_dir, img_file))
        norm = cv2.imread(os.path.join(img_dir, img_file))
        # img = cv2.imread('/Users/shunming/data/3D/render_shape_images/new_process/render/3c0c52b6-84c8-465b-9d86-9f195c99f6d9/_r_000_albedo.png0001.png')
        # norm = cv2.imread('/Users/shunming/data/3D/render_shape_images/new_process/render/3c0c52b6-84c8-465b-9d86-9f195c99f6d9/_r_000_normal.png0001.png')
        img = cv2.resize(img, (448, 448))
        norm = cv2.resize(norm, (448, 448))
        img = np.concatenate((img, norm), axis=2)
        t = transforms.Compose([
            RandomCropDramaticlly()
        ])
        t(img)


##parameters=REQUEST=None, **kw

if REQUEST is not None:
    kw.update(REQUEST.form)

tmtool = context.portal_themes
src_theme, src_page = tmtool.getEffectiveThemeAndPageName(editing=1)
theme_container = tmtool.getThemeContainer(theme=src_theme)

xpos = kw.get('xpos', 0)
ypos = kw.get('ypos', 0)
direction = kw.get('direction')
dest_block = kw.get('dest_block')
dest_theme = kw.get('dest_theme')
dest_page = kw.get('dest_page')

# if the destination theme is not specified assume that
# it is the current theme
if dest_theme is None:
    dest_theme = src_theme

dest_theme_container = tmtool.getThemeContainer(dest_theme)
if dest_theme_container is None:
    return

# if the destination page is not specified choose the requested page
if not dest_page:
    req_theme, req_page = tmtool.getRequestedThemeAndPageName(editing=1)
    dest_page_container = dest_theme_container.getPageContainer(page=req_page)
    if dest_page_container is None:
        dest_page_container = dest_theme_container.getDefaultPage()
    if dest_page_container is None:
        dest_page_container = dest_theme_container.addThemePage()
    dest_page = dest_page_container.getId()

# content will be duplicated
if dest_theme != src_theme or dest_page != src_page:
    newobj = context.copy_to_theme(dest_theme, dest_page)
    for category in context.getApplicableStyles():
        style_propid = category['id']
        style = getattr(context, style_propid, None)
        if not style:
            continue
        # do not copy styles between the pages of a same theme.
        if dest_theme == src_theme:
            continue
        styles = tmtool.findStylesFor(category=category['meta_type'], \
                                      object=context, title=style)
        if len(styles) > 0:
            if len(styles['object']) > 0:
                style_to_copy = styles['object'][0]
                newstyle = style_to_copy.copy_to_theme(dest_theme)
                prop_dict = {style_propid:newstyle.getTitle()}
                newobj.edit(**prop_dict)
    # switch to the destination theme and page
    tmtool.setViewMode(theme=dest_theme, page=dest_page)
else:
    if direction:
        newobj = context.move(direction=direction)
    else:
        newobj = context.move_to_block(dest_block=dest_block, xpos=xpos, ypos=ypos)

if newobj is None:
    return

url = context.portal_url() + '/cpsskins_theme_manage_form'

# set the content as selected
tmtool.setViewMode(selected_content=newobj.getId())

if REQUEST is None:
    return newobj
else:
    REQUEST.RESPONSE.redirect(url)


from flask import Blueprint, render_template, request

from app import db
from products.models import TV, Fridge

products = Blueprint('products', __name__, template_folder='templates', static_folder='static')

def sort(data):
    # Сортируем по параметру выбранном пользователем
    if request.form["sort"] == "click_amount":
        data.sort(key=lambda product: product.click_count, reverse=True)
    else:
        data.sort(key=lambda product: product.name)

@products.route("/tvs", methods=['GET', 'POST'])
def tvs_page():
    all_tvs = TV.query.all()

    # Проверяем есть ли запрос на сортировку с формы
    if "sort" in request.form:
        sort(all_tvs)
    else:
        # Если с формы запрос не отправлен, то сортируем по имени
        all_tvs.sort(key=lambda tv: tv.name)

    return render_template("products.html", products=all_tvs, type="tvs")

@products.route("/fridges", methods=['GET', 'POST'])
def fridges_page():
    all_fridges = Fridge.query.all()

    # Проверяем есть ли запрос на сортировку с формы
    if "sort" in request.form:
        sort(all_fridges)
    else:
        # Если с формы запрос не отправлен, то сортируем по имени
        all_fridges.sort(key=lambda fridges: fridges.name)

    return render_template("products.html", products=all_fridges, type="fridges")

@products.route('/click', methods=['POST'])
def product_click():
    """
    Функция вызываемая, когда AJAX делает запрос, сигнализируя, что был сделан клик
    """
    data = eval(request.data)

    if data['type'] == "fridges":
        product = Fridge.query.filter(Fridge.name == data['name']).first()
        all_products = Fridge.query.all()
    else:
        product = TV.query.filter(TV.name == data['name']).first()
        all_products = TV.query.all()

    product.click_count += 1
    db.session.commit()

    return render_template("products.html", products=all_products, type=data['type'])


import pandas as pd
import numpy as np
import tensorflow as tf
from sklearn import preprocessing, model_selection

def get_data():
    bc = pd.read_csv('data/wdbc.data',
                     header=None)
    print(bc)
    bc.info()

    enc = preprocessing.LabelEncoder()
    y = enc.fit_transform(bc[1])
    y = y.reshape(-1, 1)
    y = np.float32(y)           # int -> float

    bc.drop([0, 1], axis=1, inplace=True)
    bc.info()

    x = bc.values
    print(x.shape, y.shape)     # (569, 30) (569, 1)
    return model_selection.train_test_split(x,y,train_size=0.7)
def show_accuracy(preds, labels):
    preds = preds.reshape(-1)

    bools = np.int32(preds > 0.5)
    y_bools = np.int32(labels.reshape(-1))

    print('acc :', np.mean(bools == y_bools))

def BreastCancer(x_train, x_test, y_train, y_test):
    ph_x = tf.placeholder(tf.float32)
    ph_y = tf.placeholder(tf.float32)
    n_features = x_train.shape[1]
    n_classes = y_train.shape[1]
    w = tf.get_variable('w', shape=[n_features, n_classes],
                        initializer=tf.glorot_uniform_initializer)
    b = tf.Variable(tf.zeros([n_classes]))
    z = tf.matmul(ph_x, w) + b
    hx = tf.sigmoid(z)

    loss_i = tf.nn.sigmoid_cross_entropy_with_logits(labels=y_train, logits=z)
    loss = tf.reduce_mean(loss_i)

    optimizer = tf.train.RMSPropOptimizer(learning_rate=0.01)
    train = optimizer.minimize(loss=loss)

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

    for i in range(1000):
        sess.run(train,{ph_x:x_train, ph_y: y_train})
        # if i % 100 == 0:
        #     print(i, sess.run(loss, {ph_x: x_train}))

    preds_test = sess.run(hx, {ph_x:x_test})
    show_accuracy(preds_test, y_test)
    sess.close()
    return preds_test

x_train, x_test, y_train, y_test = get_data()

results = np.zeros(y_test.shape)
for i in range(7):
    with tf.variable_scope(str(i)):
        preds = BreastCancer(x_train, x_test, y_train, y_test)
        results += preds
print('-'*30)
show_accuracy(results/7, y_test)


from marshmallow import Schema, fields, EXCLUDE

class BookSchema(Schema):
    title = fields.Str()
    author = fields.Str()
    description = fields.Str()

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

incoming_book_data = {
    "title": "Clean Code",
    "author": "Bob Martin",
}

book_schema = BookSchema()
book = book_schema.load(incoming_book_data)
book_obj = Book(**book)

print(book_obj)


#Class to calculate precision and recall

import random

class precision_recall_calculator():

    def __init__(self, test_data, train_data, pm, is_model):
        self.test_data = test_data
        self.train_data = train_data
        self.user_test_sample = None
        self.model1 = pm
        self.model2 = is_model

        self.ism_training_dict = dict()
        self.pm_training_dict = dict()
        self.test_dict = dict()

    #Method to return random percentage of values from a list
    def remove_percentage(self, list_a, percentage):
        k = int(len(list_a) * percentage)
        random.seed(0)
        indicies = random.sample(range(len(list_a)), k)
        new_list = [list_a[i] for i in indicies]

        return new_list

    #Create a test sample of users for use in calculating precision
    #and recall
    def create_user_test_sample(self, percentage):
        #Find users common between training and test set
        users_test_and_training = list(set(self.test_data['user_id'].unique()).intersection(set(self.train_data['user_id'].unique())))
        print("Length of user_test_and_training:%d" % len(users_test_and_training))

        #Take only random user_sample of users for evaluations
        self.users_test_sample = self.remove_percentage(users_test_and_training, percentage)

        print("Length of user sample:%d" % len(self.users_test_sample))

    #Method to generate recommendations for users in the user test sample
    def get_test_sample_recommendations(self):
        #For these test_sample users, get top 10 recommendations from training set
        #self.ism_training_dict = {}
        #self.pm_training_dict = {}

        #self.test_dict = {}

        for user_id in self.users_test_sample:
            #Get items for user_id from item similarity model
            print("Getting recommendations for user:%s" % user_id)
            user_sim_items = self.model2.recommend(user_id)
            self.ism_training_dict[user_id] = list(user_sim_items["song"])

            #Get items for user_id from popularity model
            user_sim_items = self.model1.recommend(user_id)
            self.pm_training_dict[user_id] = list(user_sim_items["song"])

            #Get items for user_id from test_data
            test_data_user = self.test_data[self.test_data['user_id'] == user_id]
            self.test_dict[user_id] = set(test_data_user['song'].unique() )

    #Method to calculate the precision and recall measures
    def calculate_precision_recall(self):
        #Create cutoff list for precision and recall calculation
        cutoff_list = list(range(1,11))

        #For each distinct cutoff:
        #    1. For each distinct user, calculate precision and recall.
        #    2. Calculate average precision and recall.

        ism_avg_precision_list = []
        ism_avg_recall_list = []
        pm_avg_precision_list = []
        pm_avg_recall_list = []

        num_users_sample = len(self.users_test_sample)
        for N in cutoff_list:
            ism_sum_precision = 0
            ism_sum_recall = 0
            pm_sum_precision = 0
            pm_sum_recall = 0
            ism_avg_precision = 0
            ism_avg_recall = 0
            pm_avg_precision = 0
            pm_avg_recall = 0

            for user_id in self.users_test_sample:
                ism_hitset = self.test_dict[user_id].intersection(set(self.ism_training_dict[user_id][0:N]))
                pm_hitset = self.test_dict[user_id].intersection(set(self.pm_training_dict[user_id][0:N]))
                testset = self.test_dict[user_id]

                pm_sum_precision += float(len(pm_hitset))/float(N)
                pm_sum_recall += float(len(pm_hitset))/float(len(testset))

                ism_sum_precision += float(len(ism_hitset))/float(len(testset))
                ism_sum_recall += float(len(ism_hitset))/float(N)

            pm_avg_precision = pm_sum_precision/float(num_users_sample)
            pm_avg_recall = pm_sum_recall/float(num_users_sample)

            ism_avg_precision = ism_sum_precision/float(num_users_sample)
            ism_avg_recall = ism_sum_recall/float(num_users_sample)

            ism_avg_precision_list.append(ism_avg_precision)
            ism_avg_recall_list.append(ism_avg_recall)

            pm_avg_precision_list.append(pm_avg_precision)
            pm_avg_recall_list.append(pm_avg_recall)

        return (pm_avg_precision_list, pm_avg_recall_list, ism_avg_precision_list, ism_avg_recall_list)

    #A wrapper method to calculate all the evaluation measures
    def calculate_measures(self, percentage):
        #Create a test sample of users
        self.create_user_test_sample(percentage)

        #Generate recommendations for the test sample users
        self.get_test_sample_recommendations()

        #Calculate precision and recall at different cutoff values
        #for popularity mode (pm) as well as item similarity model (ism)

        return self.calculate_precision_recall()
        #return (pm_avg_precision_list, pm_avg_recall_list, ism_avg_precision_list, ism_avg_recall_list)