"""
Bing Zhai's step count implementation (https://github.com/bzhai/AFAR)
of the Verisense Step Count algorithm (https://github.com/ShimmerEngineering/Verisense-Toolbox/tree/master/Verisense_step_algorithm)
modifications by Dan Jackson.
"""

# --- HACK: Allow the test to run standalone as specified by a file in the repo (rather than only through the module)
if __name__ == '__main__' and __package__ is None:
    import sys; import os; sys.path.append(os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__)))), '..')))
# ---

import numpy as np
import pandas as pd
import math

## TODO: Move steps to own code in 'process'
## TODO: Automatically resample to 15 Hz if required
## TODO: Analysis should preserve given timestamps

def find_peak(acc, peak_win_len=3):
    """
    :param acc: accelerometer raw data
    :param peak_win_len: window len to detect peak
    :return: peak_info: a matrix with shape: (len(acc)/peak_win_len, 5)
            # peak_info[,0] - peak location
            # peak_info[,1] - acc magnitude
            # peak_info[,2] - periodicity (samples)
            # peak_info[,3] - similarity
            # peak_info[,4] - continuity
    """
    half_k = np.round(peak_win_len / 2).astype(int)
    segments = np.floor(acc.shape[0] / peak_win_len).astype(int)
    peak_info = np.empty((segments, 5))
    peak_info[:] = np.inf
    for i in np.arange(segments):
        start_idx = i * peak_win_len
        end_idx = start_idx + peak_win_len - 1
        tmp_loc_a = np.argmax(acc[start_idx:end_idx+1])
        tmp_loc_b = i * peak_win_len + tmp_loc_a
        start_idx_ctr = tmp_loc_b - half_k
        if start_idx_ctr < 0:
            start_idx_ctr = 0
        end_idx_ctr = tmp_loc_b + half_k
        if end_idx_ctr > len(acc):
            end_idx_ctr = len(acc)
        check_loc = np.argmax(acc[start_idx_ctr:end_idx_ctr+1])
        if check_loc == half_k:
            peak_info[i, 0] = tmp_loc_b
            peak_info[i, 1] = np.max(acc[start_idx:end_idx+1])
    peak_info = peak_info[~np.in1d(peak_info[:, 0], np.inf)]
    return peak_info

def filter_magnitude(peak_info, mag_thres=1.2):
    peak_info = peak_info[peak_info[:, 1] > mag_thres]
    return peak_info

def calc_periodicity(peak_info, period_min=5, period_max=15):
    """
    calculate the period
    :param peak_info:
    :param period_min:
    :param period_max:
    :return:
    """
    num_peaks = peak_info.shape[0]
    # calculate periodicity
    peak_info[:num_peaks-1, 2] = np.diff(peak_info[:, 0])
    peak_info = peak_info[peak_info[:, 2] > period_min]
    peak_info = peak_info[peak_info[:, 2] < period_max]
    return peak_info

def calc_similarity(peak_info, sim_thres=-0.5):
    """
    # calculate similarity for all peaks
    :param peak_info: the step peak table, the similarity will be calculated based on column 2 and store the results in
    column 3. We calculate the difference between every two peaks and consider it as the similarity.
    :param sim_thres: the threshold used to cut off the difference(a.k.a similarity)
    :return: a 5D matrix contains filtered similarity data
    """

    num_peaks = len(peak_info[:, 1])
    peak_info[:(num_peaks-2), 3] = -np.abs(peak_info[:, 1][2:] - peak_info[:, 1][:-2])
    peak_info = peak_info[peak_info[:, 3] > sim_thres]
    peak_info = peak_info[~np.in1d(peak_info[:, 3], np.inf)]
    # num_peaks = len(peak_info[:,1])
    return peak_info

def filter_by_continue_threshold_variance_threshold(peak_info, acc, cont_win_size=3, cont_thres=4, var_thres=0.001):
    """
    Calculate the continuity by a given window length, then calculate the variance and filter the data by
    a given threshold
    :param peak_info: a 5D matrix
    :param cont_win_size: continue window len
    :param cont_thres: continue threshold
    :param var_thres: variance threshold
    :param fs: frequency of accelerometer data
    :return: all_steps: step count list
    """
    end_for = len(peak_info[:,2])-1
    for i in np.arange(cont_thres-1, end_for):
        v_count = 0
        for x in np.arange(1, cont_thres+1):
            if np.var(acc[int(peak_info[i-x+1, 0]):int(peak_info[i-x+2, 0]+1)], ddof=1) > var_thres:
                v_count = v_count + 1
        if v_count >= cont_win_size:
            peak_info[i, 4] = 1
        else:
            peak_info[i, 4] = 0
    peak_info = peak_info[peak_info[:, 4] == 1, 0]
    return peak_info

def counts_peaks(peak_info, acc, fs=15):
    """
    count the peaks from
    :param peak_info:
    :param fs:
    :return:
    """
    peak_info_count = np.ceil(peak_info/fs).astype(int).tolist()
    peak_info_count_dict = dict((x, peak_info_count.count(x)) for x in set(peak_info_count))
    all_steps = pd.Series(np.arange(np.floor(acc.shape[0]/fs).astype(int)))
    all_steps = all_steps.map(peak_info_count_dict).fillna(0)
    return all_steps

def step_counts_per_sec(raw_acc, peak_win_len=3, period_min=5, period_max=15, fs=15, mag_thres=1.2, cont_win_size=3, cont_thres = 4, var_thres = 0.001):
    """
    # peak_info[,0] - peak location
    # peak_info[,1] - acc magnitude
    # peak_info[,2] - periodicity (samples)
    # peak_info[,3] - similarity
    # peak_info[,4] - continuity
    :param raw_acc:  raw accelerometer data consists of x,y,z readings at 15 hz sampling rate shape: [num_sample, 3]
    :param peak_win_len: window length of peak detection algorithms
    :param period_min: minimum period number
    :param period_max: maximum period number
    :param fs: sampling frequency (algorithm defined at 15 Hz)
    :param mag_thres: magnitude threshold for vector magnitude sqrt(x^2+y^2+z^2)
    :param cont_win_size:  window length for calculating continuity
    :param cont_thres: continuity threshold
    :param var_thres: variance threshold
    :return: a pandas series with steps counted for every second
    """
    acc = np.sqrt(np.power(raw_acc[:,0],2) + np.power(raw_acc[:,1],2) + np.power(raw_acc[:,2],2))
    peak_data = find_peak(acc, peak_win_len)
    peak_data = filter_magnitude(peak_data, mag_thres)
    peak_data = calc_periodicity(peak_data, period_min, period_max)
    peak_data = calc_similarity(peak_data, sim_thres=-0.5)
    peak_data = filter_by_continue_threshold_variance_threshold(peak_data, acc, cont_win_size, cont_thres, var_thres)
    peak_data = counts_peaks(peak_data, acc, fs)
    return peak_data

def testEnsureSampleData(csvDataFile, rdsDataFile = None, rdsSourceUrl = None, sourceFs = 15):
    """
    Ensure the sample timestamped .csv data file exists,
    otherwise convert from the original .rds source (downloaded if required).
    """
    import os

    # If .csv file doesn't exist yet, but an .rds source file is given, convert it from the .rds source
    if not os.path.isfile(csvDataFile) and rdsDataFile is not None:
        print('NOTE: CSV file does not yet exist (but an .rds source data file is known): ' + csvDataFile)

        # If .rds file doesn't exist yet, but a URL is given, download it from the source URL
        if not os.path.isfile(rdsDataFile) and rdsSourceUrl is not None:
            print('NOTE: .rds source data file not found (but a URL is known): ' + rdsDataFile)

            # Download the .rds data
            print('DOWNLOADING: ' + rdsSourceUrl)
            import requests
            data = requests.get(rdsSourceUrl)

            # Store to an .rds file
            print('STORING: ' + rdsDataFile)
            with open(rdsDataFile, 'wb') as file:
                file.write(data.content)

        # Read the .rds file
        print('READING: ' + rdsDataFile)
        try:
            import pyreadr
            rawXYZ = pyreadr.read_r(rdsDataFile)[None].values
        except ImportError:
            print('ERROR: pyreadr not installed -- cannot read .rds file')
            exit(1)

        # Generate timestamps
        time = np.arange(rawXYZ.shape[0]) / sourceFs
        timedXYZ = np.insert(rawXYZ, 0, time, axis=1)

        # Write a .csv file
        print('WRITING: ' + csvDataFile)
        np.savetxt(csvDataFile, timedXYZ, delimiter=',', fmt='%f')

# TODO: From step count module?
requiredFs = 15

def testSteps(sourceFile, expectedSteps):
    import openmovement.load.multi_load as multi_load

    print('LOADING: ' + sourceFile)
    with multi_load.MultiData(sourceFile) as data:
        timedXYZ = data.get_sample_values()
        fs = data.get_sample_rate()
        print('SOURCE-RATE: ' + str(fs))

        ## Resample timestamped data to 15 Hz for step algorithm
        ## Implement and use openmovement.experimental.resample for better resampling
        if fs != requiredFs:
            if fs > 2 * requiredFs:
                filterFreq = requiredFs / 2
                print('FILTER: Low-pass filter, cut-off @%f Hz...' % filterFreq)
                from openmovement.process.filter import filter
                timedXYZ[:, 1:4] = filter(timedXYZ[:, 1:4], fs, high_freq=filterFreq)
                print(timedXYZ)

            sourceCount = timedXYZ.shape[0]
            destNum = math.floor((requiredFs * sourceCount) // fs)
            indexes = np.linspace(start=0, stop=sourceCount, num=destNum, endpoint=False, dtype=int)
            print('RESAMPLE: Nearest from %f samples @%fHz (%f s) to %f samples @%fHz (%f s)' % (sourceCount, fs, sourceCount / fs, destNum, requiredFs, destNum / requiredFs))
            timedXYZ = np.take(timedXYZ, indexes, axis=0)
            fs = requiredFs

        rawXYZ = timedXYZ[:,1:4]
        print(rawXYZ)

        # ? Clip to +/- 2 g as with the test data
        g_range = None
        #g_range = 2
        if g_range is not None:
            clippedXYZ = np.clip(rawXYZ, -g_range, g_range)
        else:
            clippedXYZ = rawXYZ

        print('CALCULATING (%f Hz)...' % (fs))
        totalSteps = sum(step_counts_per_sec(clippedXYZ, fs=fs))
        print('TOTAL: %f (expected %f)' % (totalSteps, expectedSteps))

        # TODO: Return step count aggregated into timestamped epochs
        return timedXYZ

# Test function
def main():
    import os
    import pathlib

    sourceDir = pathlib.Path(__file__).resolve().parent

    # Future?: Test against full sample data: http://cecas.clemson.edu/tracking/PedometerData/PedometerData.zip

    # Sample data file (relative path to source file)
    dataPath = os.path.join(sourceDir, '..', '..', '_local', 'data')
    csvDataFile = os.path.join(dataPath, 'acc_xyz_for_step_counts.csv')
    rdsDataFile = os.path.join(dataPath, 'acc_xyz_for_step_counts.rds')
    sourceFs = 15     # 15 Hz
    rdsSourceUrl = 'https://github.com/bzhai/AFAR/blob/main/acc_xyz_for_step_counts.rds?raw=true'
    expectedSteps = 5874
    testEnsureSampleData(csvDataFile, rdsDataFile, rdsSourceUrl, sourceFs)

    testSteps(csvDataFile, expectedSteps)

    testDataFile = os.path.join(sourceDir, '..', '..', '_local', 'data', '610steps.cwa')
    testExpectedSteps = 610
    result = testSteps(testDataFile, testExpectedSteps)

if __name__ == '__main__':
    main()


import numpy as np

# 1. 데이터
from sklearn.datasets import load_breast_cancer
datasets = load_breast_cancer()

x = datasets.data
y = datasets.target
print(x.shape)      # (569, 30)
print(y.shape)      # (569,)

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=45)

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)

# 2. 모델
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model = Sequential()
model.add(Dense(256, activation='relu', input_shape=(30,)))
model.add(Dense(64, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# 마지막 layer의 activation은 sigmoid

# 3. 컴파일, 훈련
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
from tensorflow.keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='loss', patience=20, mode='auto')
model.fit(x_train, y_train, epochs=2000, batch_size=4, validation_split=0.2, verbose=2, callbacks=[early_stopping])

loss, acc = model.evaluate(x_test, y_test)
print('loss :', loss)
print('acc :', acc)
print('========================')

# loss : 0.344977468252182
# acc : 0.9824561476707458

y_pred = np.round(model.predict(x_test))

for i in range(10,20):
    true = y_test[i]
    pred = y_pred[i]
    print('실제 :', true, '| 예측 :', pred)
print('========================')


import logging
import os.path

import pytest
from mock import Mock
from pip._vendor import html5lib, requests
from pip._vendor.packaging.specifiers import SpecifierSet

from pip._internal.download import PipSession
from pip._internal.index import (
    CandidateEvaluator,
    CandidatePreferences,
    FormatControl,
    HTMLPage,
    Link,
    LinkEvaluator,
    PackageFinder,
    _check_link_requires_python,
    _clean_link,
    _determine_base_url,
    _extract_version_from_fragment,
    _find_name_version_sep,
    _get_html_page,
    filter_unallowed_hashes,
    group_locations,
)
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.models.search_scope import SearchScope
from pip._internal.models.selection_prefs import SelectionPreferences
from pip._internal.models.target_python import TargetPython
from pip._internal.pep425tags import get_supported
from pip._internal.utils.hashes import Hashes
from tests.lib import CURRENT_PY_VERSION_INFO

def make_mock_candidate(version, yanked_reason=None, hex_digest=None):
    url = 'https://example.com/pkg-{}.tar.gz'.format(version)
    if hex_digest is not None:
        assert len(hex_digest) == 64
        url += '#sha256={}'.format(hex_digest)

    link = Link(url, yanked_reason=yanked_reason)
    candidate = InstallationCandidate('mypackage', version, link)

    return candidate

@pytest.mark.parametrize('requires_python, expected', [
    ('== 3.6.4', False),
    ('== 3.6.5', True),
    # Test an invalid Requires-Python value.
    ('invalid', True),
])
def test_check_link_requires_python(requires_python, expected):
    version_info = (3, 6, 5)
    link = Link('https://example.com', requires_python=requires_python)
    actual = _check_link_requires_python(link, version_info)
    assert actual == expected

def check_caplog(caplog, expected_level, expected_message):
    assert len(caplog.records) == 1
    record = caplog.records[0]
    assert record.levelname == expected_level
    assert record.message == expected_message

@pytest.mark.parametrize('ignore_requires_python, expected', [
    (None, (
        False, 'DEBUG',
        "Link requires a different Python (3.6.5 not in: '== 3.6.4'): "
        "https://example.com"
    )),
    (True, (
        True, 'DEBUG',
        "Ignoring failed Requires-Python check (3.6.5 not in: '== 3.6.4') "
        "for link: https://example.com"
    )),
])
def test_check_link_requires_python__incompatible_python(
    caplog, ignore_requires_python, expected,
):
    """
    Test an incompatible Python.
    """
    expected_return, expected_level, expected_message = expected
    link = Link('https://example.com', requires_python='== 3.6.4')
    caplog.set_level(logging.DEBUG)
    actual = _check_link_requires_python(
        link, version_info=(3, 6, 5),
        ignore_requires_python=ignore_requires_python,
    )
    assert actual == expected_return

    check_caplog(caplog, expected_level, expected_message)

def test_check_link_requires_python__invalid_requires(caplog):
    """
    Test the log message for an invalid Requires-Python.
    """
    link = Link('https://example.com', requires_python='invalid')
    caplog.set_level(logging.DEBUG)
    actual = _check_link_requires_python(link, version_info=(3, 6, 5))
    assert actual

    expected_message = (
        "Ignoring invalid Requires-Python ('invalid') for link: "
        "https://example.com"
    )
    check_caplog(caplog, 'DEBUG', expected_message)

class TestLinkEvaluator:

    @pytest.mark.parametrize(
        'py_version_info,ignore_requires_python,expected', [
            ((3, 6, 5), None, (True, '1.12')),
            # Test an incompatible Python.
            ((3, 6, 4), None, (False, None)),
            # Test an incompatible Python with ignore_requires_python=True.
            ((3, 6, 4), True, (True, '1.12')),
        ],
    )
    def test_evaluate_link(
        self, py_version_info, ignore_requires_python, expected,
    ):
        target_python = TargetPython(py_version_info=py_version_info)
        evaluator = LinkEvaluator(
            project_name='twine',
            canonical_name='twine',
            formats={'source'},
            target_python=target_python,
            allow_yanked=True,
            ignore_requires_python=ignore_requires_python,
        )
        link = Link(
            'https://example.com/#egg=twine-1.12',
            requires_python='== 3.6.5',
        )
        actual = evaluator.evaluate_link(link)
        assert actual == expected

    @pytest.mark.parametrize('yanked_reason, allow_yanked, expected', [
        (None, True, (True, '1.12')),
        (None, False, (True, '1.12')),
        ('', True, (True, '1.12')),
        ('', False, (False, 'yanked for reason: <none given>')),
        ('bad metadata', True, (True, '1.12')),
        ('bad metadata', False,
         (False, 'yanked for reason: bad metadata')),
        # Test a unicode string with a non-ascii character.
        (u'curly quote: \u2018', True, (True, '1.12')),
        (u'curly quote: \u2018', False,
         (False, u'yanked for reason: curly quote: \u2018')),
    ])
    def test_evaluate_link__allow_yanked(
        self, yanked_reason, allow_yanked, expected,
    ):
        target_python = TargetPython(py_version_info=(3, 6, 4))
        evaluator = LinkEvaluator(
            project_name='twine',
            canonical_name='twine',
            formats={'source'},
            target_python=target_python,
            allow_yanked=allow_yanked,
        )
        link = Link(
            'https://example.com/#egg=twine-1.12',
            yanked_reason=yanked_reason,
        )
        actual = evaluator.evaluate_link(link)
        assert actual == expected

    def test_evaluate_link__incompatible_wheel(self):
        """
        Test an incompatible wheel.
        """
        target_python = TargetPython(py_version_info=(3, 6, 4))
        # Set the valid tags to an empty list to make sure nothing matches.
        target_python._valid_tags = []
        evaluator = LinkEvaluator(
            project_name='sample',
            canonical_name='sample',
            formats={'binary'},
            target_python=target_python,
            allow_yanked=True,
        )
        link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl')
        actual = evaluator.evaluate_link(link)
        expected = (
            False, "none of the wheel's tags match: py2-none-any, py3-none-any"
        )
        assert actual == expected

@pytest.mark.parametrize('hex_digest, expected_versions', [
    (None, ['1.0', '1.1', '1.2']),
    (64 * 'a', ['1.0', '1.1']),
    (64 * 'b', ['1.0', '1.2']),
    (64 * 'c', ['1.0', '1.1', '1.2']),
])
def test_filter_unallowed_hashes(hex_digest, expected_versions):
    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1', hex_digest=(64 * 'a')),
        make_mock_candidate('1.2', hex_digest=(64 * 'b')),
    ]
    hashes_data = {
        'sha256': [hex_digest],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )

    actual_versions = [str(candidate.version) for candidate in actual]
    assert actual_versions == expected_versions
    # Check that the return value is always different from the given value.
    assert actual is not candidates

def test_filter_unallowed_hashes__no_hashes(caplog):
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1'),
    ]
    actual = filter_unallowed_hashes(
        candidates, hashes=Hashes(), project_name='my-project',
    )

    # Check that the return value is a copy.
    assert actual == candidates
    assert actual is not candidates

    expected_message = (
        "Given no hashes to check 2 links for project 'my-project': "
        "discarding no candidates"
    )
    check_caplog(caplog, 'DEBUG', expected_message)

def test_filter_unallowed_hashes__log_message_with_match(caplog):
    caplog.set_level(logging.DEBUG)

    # Test 1 match, 2 non-matches, 3 no hashes so all 3 values will be
    # different.
    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1',),
        make_mock_candidate('1.2',),
        make_mock_candidate('1.3', hex_digest=(64 * 'a')),
        make_mock_candidate('1.4', hex_digest=(64 * 'b')),
        make_mock_candidate('1.5', hex_digest=(64 * 'c')),
    ]
    hashes_data = {
        'sha256': [64 * 'a', 64 * 'd'],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )
    assert len(actual) == 4

    expected_message = (
        "Checked 6 links for project 'my-project' against 2 hashes "
        "(1 matches, 3 no digest): discarding 2 non-matches:\n"
        "  https://example.com/pkg-1.4.tar.gz#sha256="
        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
        "  https://example.com/pkg-1.5.tar.gz#sha256="
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
    )
    check_caplog(caplog, 'DEBUG', expected_message)

def test_filter_unallowed_hashes__log_message_with_no_match(caplog):
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1', hex_digest=(64 * 'b')),
        make_mock_candidate('1.2', hex_digest=(64 * 'c')),
    ]
    hashes_data = {
        'sha256': [64 * 'a', 64 * 'd'],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )
    assert len(actual) == 3

    expected_message = (
        "Checked 3 links for project 'my-project' against 2 hashes "
        "(0 matches, 1 no digest): discarding no candidates"
    )
    check_caplog(caplog, 'DEBUG', expected_message)

class TestCandidateEvaluator:

    @pytest.mark.parametrize('allow_all_prereleases, prefer_binary', [
        (False, False),
        (False, True),
        (True, False),
        (True, True),
    ])
    def test_create(self, allow_all_prereleases, prefer_binary):
        target_python = TargetPython()
        target_python._valid_tags = [('py36', 'none', 'any')]
        specifier = SpecifierSet()
        evaluator = CandidateEvaluator.create(
            project_name='my-project',
            target_python=target_python,
            allow_all_prereleases=allow_all_prereleases,
            prefer_binary=prefer_binary,
            specifier=specifier,
        )
        assert evaluator._allow_all_prereleases == allow_all_prereleases
        assert evaluator._prefer_binary == prefer_binary
        assert evaluator._specifier is specifier
        assert evaluator._supported_tags == [('py36', 'none', 'any')]

    def test_create__target_python_none(self):
        """
        Test passing target_python=None.
        """
        evaluator = CandidateEvaluator.create('my-project')
        expected_tags = get_supported()
        assert evaluator._supported_tags == expected_tags

    def test_create__specifier_none(self):
        """
        Test passing specifier=None.
        """
        evaluator = CandidateEvaluator.create('my-project')
        expected_specifier = SpecifierSet()
        assert evaluator._specifier == expected_specifier

    def test_get_applicable_candidates(self):
        specifier = SpecifierSet('<= 1.11')
        versions = ['1.10', '1.11', '1.12']
        candidates = [
            make_mock_candidate(version) for version in versions
        ]
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
        )
        actual = evaluator.get_applicable_candidates(candidates)
        expected_applicable = candidates[:2]
        assert [str(c.version) for c in expected_applicable] == [
            '1.10',
            '1.11',
        ]
        assert actual == expected_applicable

    @pytest.mark.parametrize('specifier, expected_versions', [
        # Test no version constraint.
        (SpecifierSet(), ['1.0', '1.2']),
        # Test a version constraint that excludes the candidate whose
        # hash matches.  Then the non-allowed hash is a candidate.
        (SpecifierSet('<= 1.1'), ['1.0', '1.1']),
    ])
    def test_get_applicable_candidates__hashes(
        self, specifier, expected_versions,
    ):
        """
        Test a non-None hashes value.
        """
        candidates = [
            make_mock_candidate('1.0'),
            make_mock_candidate('1.1', hex_digest=(64 * 'a')),
            make_mock_candidate('1.2', hex_digest=(64 * 'b')),
        ]
        hashes_data = {
            'sha256': [64 * 'b'],
        }
        hashes = Hashes(hashes_data)
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
            hashes=hashes,
        )
        actual = evaluator.get_applicable_candidates(candidates)
        actual_versions = [str(c.version) for c in actual]
        assert actual_versions == expected_versions

    def test_compute_best_candidate(self):
        specifier = SpecifierSet('<= 1.11')
        versions = ['1.10', '1.11', '1.12']
        candidates = [
            make_mock_candidate(version) for version in versions
        ]
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        expected_applicable = candidates[:2]
        assert [str(c.version) for c in expected_applicable] == [
            '1.10',
            '1.11',
        ]
        assert result._applicable_candidates == expected_applicable

        assert result.best_candidate is expected_applicable[1]

    def test_compute_best_candidate__none_best(self):
        """
        Test returning a None best candidate.
        """
        specifier = SpecifierSet('<= 1.10')
        versions = ['1.11', '1.12']
        candidates = [
            make_mock_candidate(version) for version in versions
        ]
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        assert result._applicable_candidates == []
        assert result.best_candidate is None

    @pytest.mark.parametrize('hex_digest, expected', [
        # Test a link with no hash.
        (None, 0),
        # Test a link with an allowed hash.
        (64 * 'a', 1),
        # Test a link with a hash that isn't allowed.
        (64 * 'b', 0),
    ])
    def test_sort_key__hash(self, hex_digest, expected):
        """
        Test the effect of the link's hash on _sort_key()'s return value.
        """
        candidate = make_mock_candidate('1.0', hex_digest=hex_digest)
        hashes_data = {
            'sha256': [64 * 'a'],
        }
        hashes = Hashes(hashes_data)
        evaluator = CandidateEvaluator.create('my-project', hashes=hashes)
        sort_value = evaluator._sort_key(candidate)
        # The hash is reflected in the first element of the tuple.
        actual = sort_value[0]
        assert actual == expected

    @pytest.mark.parametrize('yanked_reason, expected', [
        # Test a non-yanked file.
        (None, 0),
        # Test a yanked file (has a lower value than non-yanked).
        ('bad metadata', -1),
    ])
    def test_sort_key__is_yanked(self, yanked_reason, expected):
        """
        Test the effect of is_yanked on _sort_key()'s return value.
        """
        candidate = make_mock_candidate('1.0', yanked_reason=yanked_reason)
        evaluator = CandidateEvaluator.create('my-project')
        sort_value = evaluator._sort_key(candidate)
        # Yanked / non-yanked is reflected in the second element of the tuple.
        actual = sort_value[1]
        assert actual == expected

    def test_sort_best_candidate__no_candidates(self):
        """
        Test passing an empty list.
        """
        evaluator = CandidateEvaluator.create('my-project')
        actual = evaluator.sort_best_candidate([])
        assert actual is None

    def test_sort_best_candidate__all_yanked(self, caplog):
        """
        Test all candidates yanked.
        """
        candidates = [
            make_mock_candidate('1.0', yanked_reason='bad metadata #1'),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate('3.0', yanked_reason='bad metadata #3'),
            make_mock_candidate('2.0', yanked_reason='bad metadata #2'),
        ]
        expected_best = candidates[1]
        evaluator = CandidateEvaluator.create('my-project')
        actual = evaluator.sort_best_candidate(candidates)
        assert actual is expected_best
        assert str(actual.version) == '3.0'

        # Check the log messages.
        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        assert record.message == (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 3.0 at https://example.com/pkg-3.0.tar.gz)\n'
            'Reason for being yanked: bad metadata #3'
        )

    @pytest.mark.parametrize('yanked_reason, expected_reason', [
        # Test no reason given.
        ('', '<none given>'),
        # Test a unicode string with a non-ascii character.
        (u'curly quote: \u2018', u'curly quote: \u2018'),
    ])
    def test_sort_best_candidate__yanked_reason(
        self, caplog, yanked_reason, expected_reason,
    ):
        """
        Test the log message with various reason strings.
        """
        candidates = [
            make_mock_candidate('1.0', yanked_reason=yanked_reason),
        ]
        evaluator = CandidateEvaluator.create('my-project')
        actual = evaluator.sort_best_candidate(candidates)
        assert str(actual.version) == '1.0'

        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        expected_message = (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 1.0 at https://example.com/pkg-1.0.tar.gz)\n'
            'Reason for being yanked: '
        ) + expected_reason
        assert record.message == expected_message

    def test_sort_best_candidate__best_yanked_but_not_all(
        self, caplog,
    ):
        """
        Test the best candidates being yanked, but not all.
        """
        candidates = [
            make_mock_candidate('4.0', yanked_reason='bad metadata #4'),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate('2.0'),
            make_mock_candidate('3.0', yanked_reason='bad metadata #3'),
            make_mock_candidate('1.0'),
        ]
        expected_best = candidates[1]
        evaluator = CandidateEvaluator.create('my-project')
        actual = evaluator.sort_best_candidate(candidates)
        assert actual is expected_best
        assert str(actual.version) == '2.0'

        # Check the log messages.
        assert len(caplog.records) == 0

class TestPackageFinder:

    @pytest.mark.parametrize('allow_all_prereleases, prefer_binary', [
        (False, False),
        (False, True),
        (True, False),
        (True, True),
    ])
    def test_create__candidate_prefs(
        self, allow_all_prereleases, prefer_binary,
    ):
        """
        Test that the _candidate_prefs attribute is set correctly.
        """
        selection_prefs = SelectionPreferences(
            allow_yanked=True,
            allow_all_prereleases=allow_all_prereleases,
            prefer_binary=prefer_binary,
        )
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=selection_prefs,
            session=PipSession(),
        )
        candidate_prefs = finder._candidate_prefs
        assert candidate_prefs.allow_all_prereleases == allow_all_prereleases
        assert candidate_prefs.prefer_binary == prefer_binary

    def test_create__target_python(self):
        """
        Test that the _target_python attribute is set correctly.
        """
        target_python = TargetPython(py_version_info=(3, 7, 3))
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=SelectionPreferences(allow_yanked=True),
            session=PipSession(),
            target_python=target_python,
        )
        actual_target_python = finder._target_python
        # The target_python attribute should be set as is.
        assert actual_target_python is target_python
        # Check that the attributes weren't reset.
        assert actual_target_python.py_version_info == (3, 7, 3)

    def test_create__target_python_none(self):
        """
        Test passing target_python=None.
        """
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=SelectionPreferences(allow_yanked=True),
            session=PipSession(),
            target_python=None,
        )
        # Spot-check the default TargetPython object.
        actual_target_python = finder._target_python
        assert actual_target_python._given_py_version_info is None
        assert actual_target_python.py_version_info == CURRENT_PY_VERSION_INFO

    @pytest.mark.parametrize('allow_yanked', [False, True])
    def test_create__allow_yanked(self, allow_yanked):
        """
        Test that the _allow_yanked attribute is set correctly.
        """
        selection_prefs = SelectionPreferences(allow_yanked=allow_yanked)
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=selection_prefs,
            session=PipSession(),
        )
        assert finder._allow_yanked == allow_yanked

    @pytest.mark.parametrize('ignore_requires_python', [False, True])
    def test_create__ignore_requires_python(self, ignore_requires_python):
        """
        Test that the _ignore_requires_python attribute is set correctly.
        """
        selection_prefs = SelectionPreferences(
            allow_yanked=True,
            ignore_requires_python=ignore_requires_python,
        )
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=selection_prefs,
            session=PipSession(),
        )
        assert finder._ignore_requires_python == ignore_requires_python

    def test_create__format_control(self):
        """
        Test that the format_control attribute is set correctly.
        """
        format_control = FormatControl(set(), {':all:'})
        selection_prefs = SelectionPreferences(
            allow_yanked=True,
            format_control=format_control,
        )
        finder = PackageFinder.create(
            search_scope=SearchScope([], []),
            selection_prefs=selection_prefs,
            session=PipSession(),
        )
        actual_format_control = finder.format_control
        assert actual_format_control is format_control
        # Check that the attributes weren't reset.
        assert actual_format_control.only_binary == {':all:'}

    @pytest.mark.parametrize(
        'allow_yanked, ignore_requires_python, only_binary, expected_formats',
        [
            (False, False, {}, frozenset({'binary', 'source'})),
            # Test allow_yanked=True.
            (True, False, {}, frozenset({'binary', 'source'})),
            # Test ignore_requires_python=True.
            (False, True, {}, frozenset({'binary', 'source'})),
            # Test a non-trivial only_binary.
            (False, False, {'twine'}, frozenset({'binary'})),
        ]
    )
    def test_make_link_evaluator(
        self, allow_yanked, ignore_requires_python, only_binary,
        expected_formats,
    ):
        # Create a test TargetPython that we can check for.
        target_python = TargetPython(py_version_info=(3, 7))
        format_control = FormatControl(set(), only_binary)
        finder = PackageFinder(
            search_scope=SearchScope([], []),
            session=PipSession(),
            target_python=target_python,
            allow_yanked=allow_yanked,
            format_control=format_control,
            ignore_requires_python=ignore_requires_python,
        )

        # Pass a project_name that will be different from canonical_name.
        link_evaluator = finder.make_link_evaluator('Twine')

        assert link_evaluator.project_name == 'Twine'
        assert link_evaluator._canonical_name == 'twine'
        assert link_evaluator._allow_yanked == allow_yanked
        assert link_evaluator._ignore_requires_python == ignore_requires_python
        assert link_evaluator._formats == expected_formats

        # Test the _target_python attribute.
        actual_target_python = link_evaluator._target_python
        # The target_python attribute should be set as is.
        assert actual_target_python is target_python
        # For good measure, check that the attributes weren't reset.
        assert actual_target_python._given_py_version_info == (3, 7)
        assert actual_target_python.py_version_info == (3, 7, 0)

    @pytest.mark.parametrize('allow_all_prereleases, prefer_binary', [
        (False, False),
        (False, True),
        (True, False),
        (True, True),
    ])
    def test_make_candidate_evaluator(
        self, allow_all_prereleases, prefer_binary,
    ):
        target_python = TargetPython()
        target_python._valid_tags = [('py36', 'none', 'any')]
        candidate_prefs = CandidatePreferences(
            prefer_binary=prefer_binary,
            allow_all_prereleases=allow_all_prereleases,
        )
        finder = PackageFinder(
            search_scope=SearchScope([], []),
            session=PipSession(),
            target_python=target_python,
            allow_yanked=True,
            candidate_prefs=candidate_prefs,
        )

        specifier = SpecifierSet()
        # Pass hashes to check that _hashes is set.
        hashes = Hashes({'sha256': [64 * 'a']})
        evaluator = finder.make_candidate_evaluator(
            'my-project',
            specifier=specifier,
            hashes=hashes,
        )
        assert evaluator._allow_all_prereleases == allow_all_prereleases
        assert evaluator._hashes == hashes
        assert evaluator._prefer_binary == prefer_binary
        assert evaluator._project_name == 'my-project'
        assert evaluator._specifier is specifier
        assert evaluator._supported_tags == [('py36', 'none', 'any')]

def test_group_locations__file_expand_dir(data):
    """
    Test that a file:// dir gets listdir run with expand_dir
    """
    files, urls = group_locations([data.find_links], expand_dir=True)
    assert files and not urls, (
        "files and not urls should have been found at find-links url: %s" %
        data.find_links
    )

def test_group_locations__file_not_find_link(data):
    """
    Test that a file:// url dir that's not a find-link, doesn't get a listdir
    run
    """
    files, urls = group_locations([data.index_url("empty_with_pkg")])
    assert urls and not files, "urls, but not files should have been found"

def test_group_locations__non_existing_path():
    """
    Test that a non-existing path is ignored.
    """
    files, urls = group_locations(
        [os.path.join('this', 'doesnt', 'exist')])
    assert not urls and not files, "nothing should have been found"

@pytest.mark.parametrize(
    ("html", "url", "expected"),
    [
        (b"<html></html>", "https://example.com/", "https://example.com/"),
        (
            b"<html><head>"
            b"<base href=\"https://foo.example.com/\">"
            b"</head></html>",
            "https://example.com/",
            "https://foo.example.com/",
        ),
        (
            b"<html><head>"
            b"<base><base href=\"https://foo.example.com/\">"
            b"</head></html>",
            "https://example.com/",
            "https://foo.example.com/",
        ),
    ],
)
def test_determine_base_url(html, url, expected):
    document = html5lib.parse(
        html, transport_encoding=None, namespaceHTMLElements=False,
    )
    assert _determine_base_url(document, url) == expected

@pytest.mark.parametrize(
    ("fragment", "canonical_name", "expected"),
    [
        # Trivial.
        ("pip-18.0", "pip", 3),
        ("zope-interface-4.5.0", "zope-interface", 14),

        # Canonicalized name match non-canonicalized egg info. (pypa/pip#5870)
        ("Jinja2-2.10", "jinja2", 6),
        ("zope.interface-4.5.0", "zope-interface", 14),
        ("zope_interface-4.5.0", "zope-interface", 14),

        # Should be smart enough to parse ambiguous names from the provided
        # package name.
        ("foo-2-2", "foo", 3),
        ("foo-2-2", "foo-2", 5),

        # Should be able to detect collapsed characters in the egg info.
        ("foo--bar-1.0", "foo-bar", 8),
        ("foo-_bar-1.0", "foo-bar", 8),

        # The package name must not ends with a dash (PEP 508), so the first
        # dash would be the separator, not the second.
        ("zope.interface--4.5.0", "zope-interface", 14),
        ("zope.interface--", "zope-interface", 14),

        # The version part is missing, but the split function does not care.
        ("zope.interface-", "zope-interface", 14),
    ],
)
def test_find_name_version_sep(fragment, canonical_name, expected):
    index = _find_name_version_sep(fragment, canonical_name)
    assert index == expected

@pytest.mark.parametrize(
    ("fragment", "canonical_name"),
    [
        # A dash must follow the package name.
        ("zope.interface4.5.0", "zope-interface"),
        ("zope.interface.4.5.0", "zope-interface"),
        ("zope.interface.-4.5.0", "zope-interface"),
        ("zope.interface", "zope-interface"),
    ],
)
def test_find_name_version_sep_failure(fragment, canonical_name):
    with pytest.raises(ValueError) as ctx:
        _find_name_version_sep(fragment, canonical_name)
    message = "{} does not match {}".format(fragment, canonical_name)
    assert str(ctx.value) == message

@pytest.mark.parametrize(
    ("fragment", "canonical_name", "expected"),
    [
        # Trivial.
        ("pip-18.0", "pip", "18.0"),
        ("zope-interface-4.5.0", "zope-interface", "4.5.0"),

        # Canonicalized name match non-canonicalized egg info. (pypa/pip#5870)
        ("Jinja2-2.10", "jinja2", "2.10"),
        ("zope.interface-4.5.0", "zope-interface", "4.5.0"),
        ("zope_interface-4.5.0", "zope-interface", "4.5.0"),

        # Should be smart enough to parse ambiguous names from the provided
        # package name.
        ("foo-2-2", "foo", "2-2"),
        ("foo-2-2", "foo-2", "2"),
        ("zope.interface--4.5.0", "zope-interface", "-4.5.0"),
        ("zope.interface--", "zope-interface", "-"),

        # Should be able to detect collapsed characters in the egg info.
        ("foo--bar-1.0", "foo-bar", "1.0"),
        ("foo-_bar-1.0", "foo-bar", "1.0"),

        # Invalid.
        ("the-package-name-8.19", "does-not-match", None),
        ("zope.interface.-4.5.0", "zope.interface", None),
        ("zope.interface-", "zope-interface", None),
        ("zope.interface4.5.0", "zope-interface", None),
        ("zope.interface.4.5.0", "zope-interface", None),
        ("zope.interface.-4.5.0", "zope-interface", None),
        ("zope.interface", "zope-interface", None),
    ],
)
def test_extract_version_from_fragment(fragment, canonical_name, expected):
    version = _extract_version_from_fragment(fragment, canonical_name)
    assert version == expected

def test_request_http_error(caplog):
    caplog.set_level(logging.DEBUG)
    link = Link('http://localhost')
    session = Mock(PipSession)
    session.get.return_value = resp = Mock()
    resp.raise_for_status.side_effect = requests.HTTPError('Http error')
    assert _get_html_page(link, session=session) is None
    assert (
        'Could not fetch URL http://localhost: Http error - skipping'
        in caplog.text
    )

def test_request_retries(caplog):
    caplog.set_level(logging.DEBUG)
    link = Link('http://localhost')
    session = Mock(PipSession)
    session.get.side_effect = requests.exceptions.RetryError('Retry error')
    assert _get_html_page(link, session=session) is None
    assert (
        'Could not fetch URL http://localhost: Retry error - skipping'
        in caplog.text
    )

@pytest.mark.parametrize(
    ("url", "clean_url"),
    [
        # URL with hostname and port. Port separator should not be quoted.
        ("https://localhost.localdomain:8181/path/with space/",
         "https://localhost.localdomain:8181/path/with%20space/"),
        # URL that is already properly quoted. The quoting `%`
        # characters should not be quoted again.
        ("https://localhost.localdomain:8181/path/with%20quoted%20space/",
         "https://localhost.localdomain:8181/path/with%20quoted%20space/"),
        # URL with IPv4 address and port.
        ("https://127.0.0.1:8181/path/with space/",
         "https://127.0.0.1:8181/path/with%20space/"),
        # URL with IPv6 address and port. The `[]` brackets around the
        # IPv6 address should not be quoted.
        ("https://[fd00:0:0:236::100]:8181/path/with space/",
         "https://[fd00:0:0:236::100]:8181/path/with%20space/"),
        # URL with query. The leading `?` should not be quoted.
        ("https://localhost.localdomain:8181/path/with/query?request=test",
         "https://localhost.localdomain:8181/path/with/query?request=test"),
        # URL with colon in the path portion.
        ("https://localhost.localdomain:8181/path:/with:/colon",
         "https://localhost.localdomain:8181/path%3A/with%3A/colon"),
        # URL with something that looks like a drive letter, but is
        # not. The `:` should be quoted.
        ("https://localhost.localdomain/T:/path/",
         "https://localhost.localdomain/T%3A/path/"),
        # VCS URL containing revision string.
        ("git+ssh://example.com/path to/repo.git@1.0#egg=my-package-1.0",
         "git+ssh://example.com/path%20to/repo.git@1.0#egg=my-package-1.0"),
        # URL with Windows drive letter. The `:` after the drive
        # letter should not be quoted. The trailing `/` should be
        # removed.
        pytest.param(
            "file:///T:/path/with spaces/",
            "file:///T:/path/with%20spaces",
            marks=pytest.mark.skipif("sys.platform != 'win32'"),
        ),
        # URL with Windows drive letter, running on non-windows
        # platform. The `:` after the drive should be quoted.
        pytest.param(
            "file:///T:/path/with spaces/",
            "file:///T%3A/path/with%20spaces/",
            marks=pytest.mark.skipif("sys.platform == 'win32'"),
        ),
    ]
)
def test_clean_link(url, clean_url):
    assert(_clean_link(url) == clean_url)

class TestHTMLPage:

    @pytest.mark.parametrize(
        ('anchor_html, expected'),
        [
            # Test not present.
            ('<a href="/pkg1-1.0.tar.gz"></a>', None),
            # Test present with no value.
            ('<a href="/pkg2-1.0.tar.gz" data-yanked></a>', ''),
            # Test the empty string.
            ('<a href="/pkg3-1.0.tar.gz" data-yanked=""></a>', ''),
            # Test a non-empty string.
            ('<a href="/pkg4-1.0.tar.gz" data-yanked="error"></a>', 'error'),
            # Test a value with an escaped character.
            ('<a href="/pkg4-1.0.tar.gz" data-yanked="version &lt 1"></a>',
                'version < 1'),
            # Test a yanked reason with a non-ascii character.
            (u'<a href="/pkg-1.0.tar.gz" data-yanked="curlyquote \u2018"></a>',
                u'curlyquote \u2018'),
        ]
    )
    def test_iter_links__yanked_reason(self, anchor_html, expected):
        html = (
            # Mark this as a unicode string for Python 2 since anchor_html
            # can contain non-ascii.
            u'<html><head><meta charset="utf-8"><head>'
            '<body>{}</body></html>'
        ).format(anchor_html)
        html_bytes = html.encode('utf-8')
        page = HTMLPage(html_bytes, url='https://example.com/simple/')
        links = list(page.iter_links())
        link, = links
        actual = link.yanked_reason
        assert actual == expected


import sys
import time
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtWidgets
from functools import partial
from PyQt5.QtGui import QIcon, QPixmap

from JailSpyder import Ui_MainWindow
from BplusTree import Bptree, KeyValue

import re
import random
import datetime

movies = []     # 每一个movie被封装成了dict，存在movies这个list中
num = 250
tree = Bptree(4, 4)
cnt = 0

# log here
logname = "log.txt"
f = open(logname, "w", encoding="utf-8")

#  region 一个电影元素的内容：rank、title、 rating、cmnt、link、year
# 1
# 肖申克的救赎
# 9.7
# 希望让人自由。
# https://movie.douban.com/subject/1292052/
# 1994
# endregion

Jwelcome = "欢迎来到豆瓣电影Top250检索系统！\n系统的反馈会在这里出现哦o(*￣▽￣*)ブ"
luck_int = "不知道要看哪部电影？\n试试“手气不错”！"
tags = "犯罪 剧情 爱情 同性 动作 灾难 喜剧  战争 动画 奇幻 历史 科幻 悬疑 冒险  音乐 歌舞 古装 传记 家庭 惊悚 运动  西部 情色 儿童 纪录片 武侠 恐怖"

def lst_to_dct(lst):
    """
    把列表变成字典
    """
    movie = {}
    movie["rank"] = int(lst[0])
    movie["title"] = lst[1]
    movie["tag"] = lst[2]

    movie["dir"] = lst[3]
    movie["star"] = lst[4]
    movie["rgn"] = lst[5]

    movie["rating"] = float(lst[6])
    movie["year"] = int(lst[7])

    movie["cmnt"] = lst[8]
    movie["link"] = lst[9]

    movie["path"] = "Movies/movie-" + str(movie["rank"]) + ".txt"
    return movie

def movie_to_str(movie, fuzzy_lst=None, value=None):
    out = ''
    if fuzzy_lst != None:
        out += "关键词："
        out += " ".join(fuzzy_lst)
        out += "\n\n"
    out += '排名：' + str(movie['rank']) + '\n'
    out += '名称：' + movie['title'] + '\n'
    out += '类别：' + movie['tag'] + '\n\n'

    out += '导演：' + movie['dir'] + '\n'
    out += '主演：' + movie['star'] + '\n'
    out += '国家或地区：' + movie['rgn'] + '\n\n'

    out += '评分：' + str(movie['rating']) + '\n'
    out += '上映年份：' + str(movie['year']) + '\n'

    out += '精选评论：\n' + movie['cmnt'] + '\n\n'
    out += '链接：\n' + movie['link'] + '\n'
    out += '本地路径：\n' + 'Movies/movie-' + str(movie['rank']) + '.txt\n'
    out += '----------\n\n\n'

    return out

def fuzzy_value(movie, keywords):
    value = 0
    fuzzy_lst = []
    for kw in keywords:
        flag = 0
        if kw in movie["title"]:
            value += 1
            flag = 1
        else:
            pass
        if kw in movie['cmnt']:
            value += 1
            flag = 1
        else:
            pass
        if kw in movie["tag"]:
            value += 1
            flag = 1
        else:
            pass
        if flag == 1:
            fuzzy_lst.append(kw)
    return (value, fuzzy_lst)

def tag_value(movie, tag_lst):
    value = 0
    for tag in tag_lst:
        if tag in movie["tag"]:
            value += 1
        else:
            pass
    return value

def star_value(movie, star_lst):
    value = 0
    for star in star_lst:
        if star in movie["star"]:
            value += 1
        else:
            pass
    return value

def savelog(word_in, search_mode):
    global f
    log = ""
    log += "time: " + str(datetime.datetime.now()) + "\n"
    log += "search_mode: " + search_mode + "\n"
    if search_mode == "lucky search":
        log += "movie number:\n" + word_in + "\n"
    else:
        log += "search word:\n" + word_in + "\n"
    log += "----------"
    print(log, file=f)

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)

        self.setWindowIcon(QIcon('img/douban.ico'))

        # search
        self.pushButton_search.clicked.connect(self.search)

        # feeling lucky, give a random to user
        self.pushButton_luck.clicked.connect(self.luck)

        # init UI
        self.textBrowser_GuideJ.setText(Jwelcome)
        self.textBrowser_luck.setText(luck_int)

    def search(self):
        global movies
        res = ''
        Jstr = ''
        word_in = self.lineEdit_input.text()
        search_mode = self.comboBox.currentText()
        savelog(word_in, search_mode)

        if len(word_in.strip()) == 0:
            Jstr = "请输入些什么吧，ball ball您了/(ㄒoㄒ)/~~"
        elif self.comboBox.currentText() == "全名搜索":
            Jstr = "很抱歉，没有找到！"
            for movie in movies:
                if movie["title"] == word_in:
                    res = movie_to_str(movie)
                    Jstr = "找到了！"
                    break
                else:
                    pass
        elif self.comboBox.currentText() == "模糊搜索":
            search_res = []
            res = ''
            Jstr = ''
            keywords = word_in.split(' ')
            search_res = [(movie, fuzzy_value(movie, keywords))
                          for movie in movies if (fuzzy_value(movie, keywords)[0] > 0)]
            # search_res: [(movie, (value, fuzzy_lst)), ]
            if len(search_res) == 0:
                Jstr = "很抱歉，没有找到。\n"
                Jstr += "要不换个关键词试试？ : )"
            else:
                search_res.sort(key=lambda tp: (
                    len(tp[1][1]), tp[1][0]), reverse=True)
                Jstr = "共找到了" + str(len(search_res)) + "条结果！"
                for tp in search_res:
                    res += movie_to_str(tp[0], fuzzy_lst=tp[1]
                                        [1], value=tp[1][0])

        elif self.comboBox.currentText() == "类别搜索":
            Jstr = ''
            res = ''
            tag_lst = word_in.split()
            search_res = [(movie, tag_value(movie, tag_lst))
                          for movie in movies if (tag_value(movie, tag_lst)) > 0]
            if len(search_res) == 0:
                Jstr = "很抱歉，没有找到。\n"
                Jstr += "支持的类的关键字有：\n"
                Jstr += tags + "\n"
                Jstr += "要不换个类别试试？ : )"
            else:
                search_res.sort(key=lambda tp: tp[1], reverse=True)
                Jstr = "共有" + str(len(search_res)) + "部电影的类别和您的输入相关 (*^_^*)"
                for tp in search_res:
                    res += movie_to_str(tp[0])

        elif self.comboBox.currentText() == "导演搜索":
            Jstr = ''
            res = ''
            cnt = 0
            for movie in movies:
                if word_in in movie["dir"]:
                    res += movie_to_str(movie)
                    cnt += 1
                else:
                    pass
            if cnt == 0:
                Jstr += "抱歉，好像没有导演的名字能匹配上您的输入呢/(ㄒoㄒ)/~~\n"
                Jstr += "要不，换个关键字（词）试试"
            else:
                Jstr += "共有" + str(cnt) + "部电影的导演名字匹配上了您的输入！O(∩_∩)O"

        elif self.comboBox.currentText() == "主演搜索":
            Jstr = ''
            res = ''
            star_lst = word_in.split()
            search_res = [(movie, star_value(movie, star_lst))
                          for movie in movies if (star_value(movie, star_lst)) > 0]
            if len(search_res) == 0:
                Jstr = "很抱歉，什么也没有找到。,,ԾㅂԾ,,\n"
                Jstr += "要不换个主演的名字试试？"
            else:
                search_res.sort(key=lambda tp: tp[1], reverse=True)
                Jstr = "共有" + str(len(search_res)) + "部电影和您的输入的主演信息相关 (*^_^*)"
                for tp in search_res:
                    res += movie_to_str(tp[0])

        elif self.comboBox.currentText() == "排名搜索":
            Jstr = r"请输入一个1到250之间的整数\(￣︶￣*\))"
            res = ""
            try:
                rank = int(word_in)
            except:
                pass
            else:
                if rank in range(1, 251):
                    movie = tree.search(rank).value
                    res = movie_to_str(movie)
                    Jstr = "找到啦😄"
                else:
                    Jstr = "请输入一个1到250之间的整数！"
                    res = ""
        elif self.comboBox.currentText() == "排名范围":
            Jstr = "请输入两个1到250之间的数，空格隔开。\n谢谢 :)"
            try:
                rank_range = [int(i) for i in word_in.split()]
            except:
                pass
            else:
                if len(rank_range) != 2:
                    Jstr = Jstr = "请输入两个1到250之间的数，空格隔开。\n谢谢 :)"
                elif rank_range[0] in range(1, 251) and rank_range[1] in range(1, 251):
                    rank_range.sort()
                    for i in range(rank_range[0], rank_range[1]+1):
                        movie = tree.search(i).value
                        res += movie_to_str(movie)
                    Jstr = ""
                else:
                    Jstr = "请输入两个1到250之间的数，空格隔开。\n谢谢 : )"
        elif self.comboBox.currentText() == "评分搜索":
            try:
                rating = float(word_in)
                search_num = 0
                for movie in movies:
                    if movie['rating'] == rating:
                        res += movie_to_str(movie)
                        search_num += 1
                    else:
                        pass
                if res == '':
                    Jstr = "抱歉，看来没有电影是这个评分 😓"
                else:
                    Jstr = "一共有" + str(search_num) + \
                        "部电影评分为" + str(rating) + "!"
            except:
                Jstr = "请输入一个1到10之间的数 :)"
        elif self.comboBox.currentText() == "评分范围":
            Jstr = "请输入两个0到10之间的实数，空格隔开。\n谢谢 :)"
            try:
                rating_range = [float(i) for i in word_in.split()]
            except:
                pass
            else:
                if len(rating_range) != 2:
                    Jstr = Jstr = "请输入两个0到10之间的实数，空格隔开。\n谢谢 :)"
                elif (0 <= rating_range[0] <= 10) and (0 <= rating_range[1] <= 10):
                    search_num = 0
                    rating_range.sort()
                    for movie in movies:
                        if rating_range[0] <= movie["rating"] <= rating_range[1]:
                            search_num += 1
                            res += movie_to_str(movie)
                        else:
                            pass
                    Jstr = "有" + str(search_num) + "部电影的评分落在" + "[" + str(
                        rating_range[0])+", " + str(rating_range[1]) + "]" + "内！"
                else:
                    Jstr = "请输入两个0到10之间的实数，空格隔开。\n谢谢 : )"
        elif self.comboBox.currentText() == "年份搜索":
            try:
                year = int(word_in)
            except:
                Jstr = "请输入一个年份 : )"
            else:
                search_num = 0
                for movie in movies:
                    if movie['year'] == year:
                        search_num += 1
                        res += movie_to_str(movie)
                    else:
                        pass
                Jstr = "共有" + str(search_num) + "部电影在" + str(year) + "年上映。"
        elif self.comboBox.currentText() == "年份范围":
            Jstr = "现在是2020年，\n世界上第一部电影上映年份是1895年哦\n请输入两个合法的年份，空格隔开。\n谢谢 :)"
            try:
                year_range = [int(i) for i in word_in.split()]
            except:
                pass
            else:
                if len(year_range) != 2:
                    pass
                elif (1895 <= year_range[0] <= 2020) and (1895 <= year_range[1] <= 2020):
                    search_num = 0
                    year_range.sort()
                    for movie in movies:
                        if year_range[0] <= movie["year"] <= year_range[1]:
                            search_num += 1
                            res += movie_to_str(movie)
                        else:
                            pass
                    Jstr = "有" + str(search_num) + "部电影在" + \
                        str(year_range[0])+"年到" + str(year_range[1]) + "年内上映！"
                else:
                    Jstr = "世界上第一部电影上映年份是1895年哦\n请输入两个合法的年份，空格隔开。\n谢谢 :)"
        else:
            self.textBrowser_GuideJ.setText("comboBox Error")

        self.textBrowser_res.setText(res)
        self.textBrowser_GuideJ.setText(Jstr)
        res = ''
        Jstr = ''

    def luck(self):
        ran = random.randint(1, num)
        # print(ran)
        res = ''
        Jstr = ''
        try:
            movie = tree.search(ran).value
            res = movie_to_str(movie)
            Jstr = "哦，你找到了《" + movie['title'] + "》\n"
            Jstr += "不知道你看过没有，真的很不错哦！"
            path = "Covers/" + str(ran) + "-" + movies[ran-1]['title'] + ".jpg"
            self.cover.setPixmap(QPixmap(path))
            savelog(str(ran), "lucky search")
            self.cover.resize(54, 77)
            self.textBrowser_GuideJ.setText(Jstr)
            self.textBrowser_luck.setText(res)

        except:
            Jstr = "第" + str(ran) + "部电影出了点问题 ,,ԾㅂԾ,,"

    # region 写入B+树
    f = open("data.txt", "r", encoding="utf-8")
    data = [str(line.strip()) for line in f]
    for i in range(250):

        movie_lst = data[i*11: i*11+10]

        movies.append(lst_to_dct(movie_lst))
        i += 1
    # region test movies
    # x = random.randint(0, 250)
    # print(x+1)
    # print(movies[x])
    # endregion

    for i in range(250):
        tree.insert(KeyValue(movies[i]["rank"], movies[i]))
    # endregion

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = mywindow()
    ui.show()
    sys.exit(app.exec_())


try:
    from quandl_set import *
except:
    import quandl
import numpy as np
import pandas as pd

class SDP:
    def __init__(self,**args):
        assert 'scode' in args
        self.scode = args['scode']
        self.rawdata = None
        self.rawdata_c = None
    def get_raw_data(self):
        """
        download raw data with quandl and store it into rawdata and rawdata_c
        """
        data = quandl.get("EOD/"+self.scode)[['Adj_Open','Adj_High','Adj_Low','Adj_Close','Adj_Volume']]
        data.columns = ['O','H','L','C','V']
        cl = data['C']
        c1 = cl.shift(1)
        lv = (data['V']+1).apply(np.log)
        self.rawdata = data
        self.rawdata_c = pd.DataFrame()
        self.rawdata_c['O'] = (self.rawdata['O']-c1)/c1
        self.rawdata_c['H'] = (self.rawdata['H']-c1)/c1
        self.rawdata_c['L'] = (self.rawdata['L']-c1)/c1
        self.rawdata_c['C'] = (cl-c1)/c1
        self.rawdata_c['V'] = lv - lv.shift(1)

    def __call__(self,on = None,shuffle = False,split_ratio = 1):
        """
        process raw data and return traning/test data

        ptype(str): what kind of Y data to be returned, regression:float, classification: one hot matrix, unsupervised: no Y data
        on(str): which attribute to be predicted
        shuffle(bool): shuffle the training data or not
        split_ratio(float): precentage of data to be used as training data
        """

        assert on in ['H','L','C','all',None]
        assert split_ratio <= 1
        assert split_ratio >= 0
        return None

    def save(self,path):
        """
        save processed data from local
        """
        raise NotImplementedError

    def load(self,path):
        """
        load processed data from local
        """
        raise NotImplementedError

    def update(self,n):
        """
        update raw data and process
        n(int): add records of the least n days from quandl
        """
        raise NotImplementedError

    def last_updated(self):
        return self.rawdata.index[-1]


from django.urls import path,include
from rest_framework import routers
from.import views

router=routers.DefaultRouter()
router.register(r'data',views.PlanViewSet),
router.register(r'features',views.FeaturesViewSet),
router.register(r'retailer-plan',views.RetailerPlanViewSet),

urlpatterns=[
    path('',include(router.urls)),
]


# -*- coding: utf-8 -*-
"""
Class definition of YOLO_v3 style detection model on image and video
"""

import colorsys
import os
from timeit import default_timer as timer

import numpy as np
from keras import backend as K
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageFont, ImageDraw

from yolo3.model import yolo_eval, yolo_body, tiny_yolo_body
from yolo3.utils import letterbox_image
import os
from keras.utils import multi_gpu_model

import _thread
import winsound

danger_level = 0
a = (0, 180)
b = (480, 180)
c = (800, 180)
d = (1280, 180)
e = (0, 720)
f = (1280, 720)

class YOLO(object):
    _defaults = {
        "model_path": 'logs/000/trained_weights.h5',
        "anchors_path": 'model_data/yolo_anchors.txt',
        "classes_path": 'model_data/voc_classes.txt',
        "score": 0.3,
        "iou": 0.45,
        "model_image_size": (416, 416),
        "gpu_num": 1,
    }

    @classmethod
    def get_defaults(cls, n):
        if n in cls._defaults:
            return cls._defaults[n]
        else:
            return "Unrecognized attribute name '" + n + "'"

    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults) # set up default values
        self.__dict__.update(kwargs) # and update with user overrides
        self.class_names = self._get_class()
        self.anchors = self._get_anchors()
        self.sess = K.get_session()
        self.boxes, self.scores, self.classes = self.generate()

    def _get_class(self):
        classes_path = os.path.expanduser(self.classes_path)
        with open(classes_path) as f:
            class_names = f.readlines()
        class_names = [c.strip() for c in class_names]
        return class_names

    def _get_anchors(self):
        anchors_path = os.path.expanduser(self.anchors_path)
        with open(anchors_path) as f:
            anchors = f.readline()
        anchors = [float(x) for x in anchors.split(',')]
        return np.array(anchors).reshape(-1, 2)

    def generate(self):
        model_path = os.path.expanduser(self.model_path)
        assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'

        # Load model, or construct model and load weights.
        num_anchors = len(self.anchors)
        num_classes = len(self.class_names)
        is_tiny_version = num_anchors==6 # default setting
        try:
            self.yolo_model = load_model(model_path, compile=False)
        except:
            self.yolo_model = tiny_yolo_body(Input(shape=(None,None,3)), num_anchors//2, num_classes) \
                if is_tiny_version else yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes)
            self.yolo_model.load_weights(self.model_path) # make sure model, anchors and classes match
        else:
            assert self.yolo_model.layers[-1].output_shape[-1] == \
                num_anchors/len(self.yolo_model.output) * (num_classes + 5), \
                'Mismatch between model and given anchor and class sizes'

        print('{} model, anchors, and classes loaded.'.format(model_path))

        # Generate colors for drawing bounding boxes.
        hsv_tuples = [(x / len(self.class_names), 1., 1.)
                      for x in range(len(self.class_names))]
        self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
        self.colors = list(
            map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
                self.colors))
        np.random.seed(10101)  # Fixed seed for consistent colors across runs.
        np.random.shuffle(self.colors)  # Shuffle colors to decorrelate adjacent classes.
        np.random.seed(None)  # Reset seed to default.

        # Generate output tensor targets for filtered bounding boxes.
        self.input_image_shape = K.placeholder(shape=(2, ))
        if self.gpu_num>=2:
            self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
        boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
                len(self.class_names), self.input_image_shape,
                score_threshold=self.score, iou_threshold=self.iou)
        return boxes, scores, classes

    def detect_image(self, image, save_result_img_name=""):
        start = timer()

        if self.model_image_size != (None, None):
            assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
            assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (image.width - (image.width % 32),
                              image.height - (image.height % 32))
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype='float32')

        print(image_data.shape)
        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0
            })

        print('Found {} boxes for {}'.format(len(out_boxes), 'img'))

        font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
                    size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
        thickness = (image.size[0] + image.size[1]) // 300

        global danger_level, a, b, c, d
        danger_level = 0
        for i, j in reversed(list(enumerate(out_classes))):
            predicted_class = self.class_names[j]
            box = out_boxes[i]
            score = out_scores[i]

            label = '{} {:.2f}'.format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)

            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype('int32'))
            left = max(0, np.floor(left + 0.5).astype('int32'))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
            right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
            print(label, (left, top), (right, bottom))

            #################保存结果#####################
            if save_result_img_name != "":
                result_file = open('C:/AIoT/Projects/keras-yolo3-master/VOCtest/results/VOC2007/Main/comp3_det_test_person.txt', 'a')
                line = save_result_img_name + " " + '{:.2f}'.format(score) + " " + str(left) + " " + str(top) + " " + str(right) + " " + str(bottom) + "\n"
                result_file.write(line)
                result_file.close()
            #############################################
            if len(a) == 1:
                a = a + ((top + bottom) // 2,)
                b = b + ((top + bottom) // 2,)
                c = c + ((top + bottom) // 2,)
                d = d + ((top + bottom) // 2,)
            #################危险等级判断##################
            p = ((right + left) / 2, bottom)
            A = (c[0] - b[0]) * (p[1] - b[1]) - (c[1] - b[1]) * (p[0] - b[0])
            B = (f[0] - c[0]) * (p[1] - c[1]) - (f[1] - c[1]) * (p[0] - c[0])
            C = (e[0] - f[0]) * (p[1] - f[1]) - (e[1] - f[1]) * (p[0] - f[0])
            D = (b[0] - e[0]) * (p[1] - e[1]) - (b[1] - e[1]) * (p[0] - e[0])
            box_size = (right - left) * (bottom - top)
            if (A > 0 and B > 0 and C > 0 and D > 0) or (A < 0 and B < 0 and C < 0 and D < 0):
                if box_size > 1500:
                    danger_level = 2
                else:
                    danger_level = max(1, danger_level)
            else:
                if box_size > 1500:
                    danger_level = max(1, danger_level)
                else:
                    danger_level = max(0, danger_level)
            #############################################

            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, top + 1])

            # My kingdom for a good redistributable image drawing library.
            for i in range(thickness):
                draw.rectangle(
                    [left + i, top + i, right - i, bottom - i],
                    outline=self.colors[j])
            draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=self.colors[j])
            draw.text(text_origin, label, fill=(0, 0, 0), font=font)
            del draw

        end = timer()
        print(end - start)
        return image

    def close_session(self):
        self.sess.close()

def alarm():
    winsound.Beep(2000, 100)

def detect_video(yolo, video_path, output_path=""):
    import cv2
    vid = cv2.VideoCapture("test1.mp4")
    if not vid.isOpened():
        raise IOError("Couldn't open webcam or video")
    video_FourCC    = int(vid.get(cv2.CAP_PROP_FOURCC))
    video_fps       = vid.get(cv2.CAP_PROP_FPS)
    width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
    video_size      = (width, height)
    global a, b, c, d, e, f
    a = (0,)  # (0, height // 4)
    b = (3 * (width // 8),)  # (3 * (width // 8), height // 4)
    c = (5 * (width // 8),)  # (5 * (width // 8), height // 4)
    d = (width,)  # (width, height // 4)
    e = (0, height)
    f = (width, height)

    isOutput = True if output_path != "" else False
    if isOutput:
        print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size))
        out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size)
    accum_time = 0
    curr_fps = 0
    fps = "FPS: ??"
    prev_time = timer()
    while True:
        return_value, frame = vid.read()
        image = Image.fromarray(frame)
        image = yolo.detect_image(image)
        result = np.asarray(image)

        ###############预警设计################
        green = (0, 255, 0)
        red = (0, 0, 255)
        yellow = (0, 255, 255)
        if len(a) == 2:
            cv2.line(result, b, c, red, 3)
            cv2.line(result, b, e, red, 3)
            cv2.line(result, c, f, red, 3)
            cv2.line(result, a, b, green, 3)
            cv2.line(result, c, d, green, 3)
        danger = "Dangerous: " + str(danger_level)
        if danger_level == 2:
            danger_color = red
            #  winsound.Beep(2000, 100)
            _thread.start_new_thread(alarm, ())
        elif danger_level == 1:
            danger_color = yellow
        else:
            danger_color = green
        cv2.putText(result, text=danger, org=(600, 30), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=1, color=danger_color, thickness=2)
        #########################################

        curr_time = timer()
        exec_time = curr_time - prev_time
        prev_time = curr_time
        accum_time = accum_time + exec_time
        curr_fps = curr_fps + 1
        if accum_time > 1:
            accum_time = accum_time - 1
            fps = "FPS: " + str(curr_fps)
            curr_fps = 0
        cv2.putText(result, text=fps, org=(3, 15), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=0.50, color=(255, 0, 0), thickness=2)
        cv2.namedWindow("result", cv2.WINDOW_NORMAL)
        cv2.imshow("result", result)
        if isOutput:
            out.write(result)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    yolo.close_session()


import pygame
from comet import Comet

# créer une classe pour la gestion de evenemet
class CommetFallEvent:

    # au chargement on créer un compteur
    def __init__(self, game):
        self.percent = 0
        self.percent_speed = 33
        self.game = game
        self.fall_mode = False

        # definir un groupe de sprite pour stocker les cometes
        self.all_comets = pygame.sprite.Group()

    def add_percent(self):
        self.percent += self.percent_speed / 100

    def is_full_loaded(self):
        return self.percent >= 100

    def rest_percent(self):
        self.percent = 0

    def meteor_fall(self):
        # boucle pour les valeurs entre 1 et 10
        for i in range(1, 10):
            # appraitre un premier donut
            self.all_comets.add(Comet(self))

    def attempt_fall(self):
        # la jauge d'event est totalement chargé
        if self.is_full_loaded() and len(self.game.all_monsters) == 0:
            print("pluie de cometes !!")
            self.meteor_fall()
            self.fall_mode = True # active l'evenement

    def update_bar(self, surface):

        # ajouter du % a la bar
        self.add_percent()

        # la barre noir en arriere plan
        pygame.draw.rect(surface, (0 ,0 ,0), [
            0, # axe des x
            surface.get_height() - 20, # axe des y
            surface.get_width(),# longueur de la fenetre
            10 # epaisseur de la barre
        ])
        # barre rouge (jauge d'event)
        pygame.draw.rect(surface, (187, 11, 11), [
            0,  # axe des x
            surface.get_height()- 20,  # axe des y
            (surface.get_width() / 100) * self.percent ,  # longueur de la fenetre
            10  # epaisseur de la barre
        ])


import os
import numpy as np
from sklearn.datasets import make_blobs
from dnadapt.utils.data import random_split
from dnadapt.utils.utils import folder_if_not_exist, pcts_to_sizes
from dnadapt.globals import datadir

def blob_data(size=1000, pcts=None, centers=None, std=1.0):
    if pcts is not None:
        size = pcts_to_sizes(size, pcts)
    return make_blobs(n_samples=size, centers=centers, cluster_std=std)

def create_data(src_centers=None, trg_centers=None, src_pcts=None, trg_pcts=None, src_size=1000,
                trg_size=1000, ratio=0.2):
    # create data
    src_data = blob_data(size=src_size, pcts=src_pcts, centers=src_centers, std=1)
    trg_data = blob_data(size=trg_size, pcts=trg_pcts, centers=trg_centers, std=1)
    # split src data
    train_idx, valid_idx = random_split(src_data[1], ratio=ratio)
    src_train = [d[train_idx] for d in src_data]
    src_valid = [d[valid_idx] for d in src_data]
    # split target data
    train_idx, valid_idx = random_split(trg_data[1], ratio=ratio)
    trg_train = [d[train_idx] for d in trg_data]
    trg_valid = [d[valid_idx] for d in trg_data]
    return [src_train, trg_train], [src_valid, trg_valid]

def create_data_file(path, src_centers=None, trg_centers=None, src_pcts=None, trg_pcts=None, src_size=1000,
                     trg_size=1000, ratio=0.2):
    # create data
    [src_train, src_test], [trg_train, trg_test] = create_data(
        src_centers=src_centers, trg_centers=trg_centers, src_pcts=src_pcts, trg_pcts=trg_pcts,
        src_size=src_size, trg_size=trg_size, ratio=ratio)

    src_folder = folder_if_not_exist(os.path.join(path, 'src'))
    np.savez_compressed(os.path.join(src_folder, 'train'), x=src_train[0], y=src_train[1])
    np.savez_compressed(os.path.join(src_folder, 'test'), x=src_test[0], y=src_test[1])

    trg_folder = folder_if_not_exist(os.path.join(path, 'trg'))
    np.savez_compressed(os.path.join(trg_folder, 'train'), x=trg_train[0], y=trg_train[1])
    np.savez_compressed(os.path.join(trg_folder, 'test'), x=trg_test[0], y=trg_test[1])

if __name__ == '__main__':
    data_config = {
        'src_size': 5000,
        'trg_size': 1000,
        'src_pcts': [0.37, 0.63],
        'trg_pcts': [0.37, 0.63],
        'src_centers': [[0, 0], [0, 10]],
        'trg_centers': [[50, -20], [50, -10]]
    }

    create_data_file(os.path.join(datadir, 'toy'), **data_config)


from lingpy import *

wl = Wordlist('O_shijing.tsv', col='shijing', row='stanza')

# first make a link between a character in a section and its occurrence as
# rhyme word
chars = []
for k in wl:

    char = wl[k,'character']
    poem = wl[k,'number']
    stanza = wl[k,'stanza']
    section = wl[k,'section_number']
    ocbs = wl[k,'ocbs']
    pwy = wl[k,'pwy']
    mch = wl[k,'mchascii']
    pin = wl[k,'pinyin']
    gls = wl[k,'och_gloss']
    gsr = wl[k,'gsr']

    chars += [[k, char, pin, gls, mch, ocbs, pwy, gsr, poem, stanza, section]]

# now assemble poems under their id
poems = {}
for k in wl:

    poem = int(wl[k,'number'])
    name = wl[k,'title']
    block = wl[k,'block'] + '·'+wl[k,'chapter']
    rhyme = wl[k,'rhyme']
    arhyme = wl[k,'alternative_rhyme']
    section = wl[k,'raw_section']
    stanza = wl[k,'stanza']
    ocbs = wl[k,'ocbs']
    pwy = wl[k,'pwy']
    mch = wl[k,'mch']
    yun = wl[k,'ocbsyun']
    char = wl[k,'character']

    try:
        poems[poem]['sections'] += [[stanza, section, rhyme, arhyme, ocbs, pwy,
            mch, yun, char]]
    except KeyError:
        poems[poem] = { "name" : name, "block" : block }
        poems[poem]['sections'] = [[stanza, section, rhyme, arhyme, ocbs, pwy,
            mch, yun, char]]

import json
import os
import shutil

if not os.path.isdir('browser'):
    os.mkdir('browser')
shutil.copyfile('T_main.js', 'browser/main.js')
shutil.copyfile('T_index.html', 'browser/index.html')
shutil.copyfile('T_style.css', 'browser/style.css')
with open('browser/shijing.js', 'w') as f:

    f.write('var POEMS = '+json.dumps(poems,indent=2)+';\n')
    f.write('var CHARS = '+json.dumps(chars,indent=2)+';\n')


import torch
from fastff import FastFeedForward

# Example Usage
input_dim = 768  # Example input dimension
output_dim = 768  # Output dimension
depth = 11  # Depth of the FFF tree

# Create the Fast Feedforward module
fast_ff = FastFeedForward(input_dim=input_dim, output_dim=output_dim, depth=depth)

# Example input tensor (batch_size, seq_len, input_dim)
example_input = torch.randn(32, 128, input_dim)

# Forward pass
output = fast_ff(example_input)
print(output)


# -*- coding: utf-8 -*-
import xbmc
import xbmcgui
from twitch.constants import Keys
from constants import Images
from utils import theArt, TitleBuilder, getMediaType

class PlaylistConverter(object):
    @staticmethod
    def convertToXBMCPlaylist(InputPlaylist, title='', image=''):
        # Create playlist in Kodi, return tuple (playlist, {listitem dict}) or ()
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        playlist.clear()
        initialItem = None
        for (url, details) in InputPlaylist:
            if url:
                if details != ():
                    (title, image) = details
                playbackItem = xbmcgui.ListItem(label=title, path=url)
                playbackItem.setArt(theArt({'poster': image, 'thumb': image}))
                playbackItem.setProperty('IsPlayable', 'true')
                playlist.add(url, playbackItem)
                if not initialItem and url:
                    initialItem = {'label': title, 'thumbnail': image, 'path': url, 'is_playable': True}

        if playlist and initialItem:
            return playlist, initialItem
        else:
            return ()

class JsonListItemConverter(object):
    def __init__(self, plugin, title_length):
        self.plugin = plugin
        self.titleBuilder = TitleBuilder(plugin, title_length)

    def convertGameToListItem(self, game):
        name = game[Keys.NAME].encode('utf-8')
        if not name:
            name = self.plugin.get_string(30064)
        image = Images.BOXART
        if game.get(Keys.BOX):
            image = game[Keys.BOX].get(Keys.LARGE) if game[Keys.BOX].get(Keys.LARGE) else image
        return {'label': name,
                'path': self.plugin.url_for('createListForGame', gameName=name, index='0'),
                'icon': image,
                'thumbnail': image,
                'art': theArt({'poster': image, 'thumb': image})}

    def convertTeamToListItem(self, team):
        name = team[Keys.NAME]
        background = team.get(Keys.BACKGROUND) if team.get(Keys.BACKGROUND) else Images.FANART
        image = team.get(Keys.LOGO) if team.get(Keys.LOGO) else Images.ICON
        return {'label': name,
                'path': self.plugin.url_for(endpoint='createListOfTeamStreams', team=name),
                'icon': image,
                'thumbnail': image,
                'art': theArt({'fanart': background, 'poster': image, 'thumb': image})}

    def convertTeamChannelToListItem(self, teamChannel):
        images = teamChannel.get(Keys.IMAGE)
        image = Images.ICON
        if images:
            image = images.get(Keys.SIZE600) if images.get(Keys.SIZE600) else Images.ICON
        channelname = teamChannel[Keys.NAME]
        titleValues = self.extractChannelTitleValues(teamChannel)
        title = self.titleBuilder.formatTitle(titleValues)
        return {'label': title,
                'path': self.plugin.url_for(endpoint='playLive', name=channelname, quality='-2'),
                'context_menu': [(self.plugin.get_string(30077), 'RunPlugin(%s)' %
                                  self.plugin.url_for(endpoint='playLive', name=channelname, quality='-1'))],
                'is_playable': True,
                'icon': image,
                'thumbnail': image,
                'art': theArt({'poster': image, 'thumb': image}),
                'stream_info': {'video': {'duration': 0}}}

    def convertFollowersToListItem(self, follower):
        image = follower.get(Keys.LOGO) if follower.get(Keys.LOGO) else Images.ICON
        videobanner = follower.get(Keys.VIDEO_BANNER)
        if not videobanner:
            videobanner = follower.get(Keys.PROFILE_BANNER) if follower.get(Keys.PROFILE_BANNER) else Images.FANART
        return {'label': follower[Keys.DISPLAY_NAME],
                'path': self.plugin.url_for(endpoint='channelVideos', name=follower[Keys.NAME]),
                'icon': image,
                'thumbnail': image,
                'art': theArt({'fanart': videobanner, 'poster': image, 'thumb': image})}

    def convertVideoListToListItem(self, video):
        duration = video.get(Keys.LENGTH)
        plot = video.get(Keys.DESCRIPTION)
        date = video.get(Keys.CREATED_AT)[:10] if video.get(Keys.CREATED_AT) else ''
        year = video.get(Keys.CREATED_AT)[:4] if video.get(Keys.CREATED_AT) else ''
        image = video.get(Keys.PREVIEW) if video.get(Keys.PREVIEW) else Images.VIDEOTHUMB
        return {'label': video[Keys.TITLE],
                'path': self.plugin.url_for(endpoint='playVideo', _id=video['_id'], quality='-2'),
                'context_menu': [(self.plugin.get_string(30077), 'RunPlugin(%s)' %
                                  self.plugin.url_for(endpoint='playVideo', _id=video['_id'], quality='-1'))],
                'is_playable': True,
                'icon': image,
                'thumbnail': image,
                'info': {'duration': str(duration), 'plot': plot, 'plotoutline': plot, 'tagline': plot,
                         'year': year, 'date': date, 'premiered': date, 'mediatype': getMediaType()},
                'art': theArt({'poster': image, 'thumb': image}),
                'stream_info': {'video': {'duration': duration}}}

    def convertStreamToListItem(self, stream):
        channel = stream[Keys.CHANNEL]
        videobanner = channel.get(Keys.PROFILE_BANNER)
        if not videobanner:
            videobanner = channel.get(Keys.VIDEO_BANNER) if channel.get(Keys.VIDEO_BANNER) else Images.FANART
        preview = stream.get(Keys.PREVIEW)
        if preview:
            preview = preview.get(Keys.MEDIUM)
        logo = channel.get(Keys.LOGO) if channel.get(Keys.LOGO) else Images.VIDEOTHUMB
        image = preview if preview else logo
        title = self.getTitleForStream(stream)
        info = self.getPlotForStream(stream)
        info['mediatype'] = getMediaType()
        return {'label': title,
                'path': self.plugin.url_for(endpoint='playLive', name=channel[Keys.NAME], quality='-2'),
                'context_menu': [(self.plugin.get_string(30077), 'RunPlugin(%s)' %
                                  self.plugin.url_for(endpoint='playLive', name=channel[Keys.NAME], quality='-1'))],
                'is_playable': True,
                'icon': image,
                'thumbnail': image,
                'info': info,
                'art': theArt({'fanart': videobanner, 'poster': image, 'thumb': image}),
                'stream_info': {'video': {'height': stream.get(Keys.VIDEO_HEIGHT), 'duration': 0}}}

    def convertStreamToPlayItem(self, stream):
        # path is returned '' and must be set after
        channel = stream[Keys.CHANNEL]
        preview = stream.get(Keys.PREVIEW)
        if preview:
            preview = preview.get(Keys.MEDIUM)
        logo = channel.get(Keys.LOGO) if channel.get(Keys.LOGO) else Images.VIDEOTHUMB
        image = preview if preview else logo
        title = self.getTitleForStream(stream)
        return {'label': title,
                'path': '',
                'icon': image,
                'thumbnail': image,
                'is_playable': True}

    def getVideoInfo(self, video):
        channel = video.get(Keys.CHANNEL)
        streamer = channel.get(Keys.DISPLAY_NAME) if channel.get(Keys.DISPLAY_NAME) else self.plugin.get_string(30060)
        game = video.get(Keys.GAME) if video.get(Keys.GAME) else video.get(Keys.META_GAME)
        game = game if game else self.plugin.get_string(30064)
        views = video.get(Keys.VIEWS) if video.get(Keys.VIEWS) else '0'
        title = video.get(Keys.TITLE) if video.get(Keys.TITLE) else self.plugin.get_string(30061)
        image = video.get(Keys.PREVIEW) if video.get(Keys.PREVIEW) else Images.VIDEOTHUMB
        return {'streamer': streamer,
                'title': title,
                'game': game,
                'views': views,
                'thumbnail': image}

    def getTitleForStream(self, stream):
        titleValues = self.extractStreamTitleValues(stream)
        return self.titleBuilder.formatTitle(titleValues)

    def extractStreamTitleValues(self, stream):
        channel = stream[Keys.CHANNEL]

        if Keys.VIEWERS in channel:
            viewers = channel.get(Keys.VIEWERS)
        else:
            viewers = stream.get(Keys.VIEWERS)
        viewers = viewers if viewers else self.plugin.get_string(30062)

        streamer = channel.get(Keys.DISPLAY_NAME) if channel.get(Keys.DISPLAY_NAME) else self.plugin.get_string(30060)
        title = channel.get(Keys.STATUS) if channel.get(Keys.STATUS) else self.plugin.get_string(30061)
        game = channel.get(Keys.GAME) if channel.get(Keys.GAME) else self.plugin.get_string(30064)

        return {'streamer': streamer,
                'title': title,
                'game': game,
                'viewers': viewers}

    def extractChannelTitleValues(self, channel):
        streamer = channel.get(Keys.DISPLAY_NAME) if channel.get(Keys.DISPLAY_NAME) else self.plugin.get_string(30060)
        title = channel.get(Keys.TITLE) if channel.get(Keys.TITLE) else self.plugin.get_string(30061)
        game = channel.get(Keys.GAME) if channel.get(Keys.GAME) else channel.get(Keys.META_GAME)
        game = game if game else self.plugin.get_string(30064)
        viewers = channel.get(Keys.CURRENT_VIEWERS) \
            if channel.get(Keys.CURRENT_VIEWERS) else self.plugin.get_string(30062)

        return {'streamer': streamer,
                'title': title,
                'viewers': viewers,
                'game': game}

    def getPlotForStream(self, stream):
        channel = stream[Keys.CHANNEL]

        headings = {Keys.GAME: self.plugin.get_string(30088).encode('utf-8'),
                    Keys.VIEWERS: self.plugin.get_string(30089).encode('utf-8'),
                    Keys.BROADCASTER_LANGUAGE: self.plugin.get_string(30090).encode('utf-8'),
                    Keys.MATURE: self.plugin.get_string(30091).encode('utf-8'),
                    Keys.PARTNER: self.plugin.get_string(30092).encode('utf-8'),
                    Keys.DELAY: self.plugin.get_string(30093).encode('utf-8')}
        info = {
            Keys.GAME: stream.get(Keys.GAME).encode('utf-8') if stream.get(Keys.GAME) else self.plugin.get_string(30064),
            Keys.VIEWERS: str(stream.get(Keys.VIEWERS)) if stream.get(Keys.VIEWERS) else '0',
            Keys.BROADCASTER_LANGUAGE: channel.get(Keys.BROADCASTER_LANGUAGE).encode('utf-8')
            if channel.get(Keys.BROADCASTER_LANGUAGE) else None,
            Keys.MATURE: str(channel.get(Keys.MATURE)) if channel.get(Keys.MATURE) else 'False',
            Keys.PARTNER: str(channel.get(Keys.PARTNER)) if channel.get(Keys.PARTNER) else 'False',
            Keys.DELAY: str(stream.get(Keys.DELAY)) if stream.get(Keys.DELAY) else '0'
        }
        title = channel.get(Keys.STATUS).encode('utf-8') + '\r\n' if channel.get(Keys.STATUS) else ''

        item_template = '{head}:{info}  '  # no whitespace around {head} and {info} for word wrapping in Kodi
        plot_template = '{title}{game}{viewers}{broadcaster_language}{mature}{partner}{delay}'

        def formatKey(thisKey):
            value = ''
            if info.get(thisKey) is not None:
                try:
                    val_heading = headings.get(thisKey).encode('utf-8', 'ignore')
                except:
                    val_heading = headings.get(thisKey)
                try:
                    val_info = info.get(thisKey).encode('utf-8', 'ignore')
                except:
                    val_info = info.get(thisKey)
                value = item_template.format(head=val_heading, info=val_info)
            return value

        plot = plot_template.format(title=title, game=formatKey(Keys.GAME),
                                    viewers=formatKey(Keys.VIEWERS), delay=formatKey(Keys.DELAY),
                                    broadcaster_language=formatKey(Keys.BROADCASTER_LANGUAGE),
                                    mature=formatKey(Keys.MATURE), partner=formatKey(Keys.PARTNER))

        return {'plot': plot, 'plotoutline': plot, 'tagline': title.rstrip('\r\n')}


import copy
import os
import numpy as np
from PIL import Image
from RootSeg.RootSeg import RootSeg

if __name__ == "__main__":
    class_colors = [[0, 0, 0], [0, 255, 0]]
    # input image size
    HEIGHT = 512
    WIDTH = 512
    # background + root = 2
    NCLASSES = 2
    # example: logs/ep059-loss0.005-val_loss0.029.h5
    weight_path = ""
    test_img_path = ""
    predict_out_path = ""

    model = RootSeg(n_classes=NCLASSES, input_height=HEIGHT, input_width=WIDTH)
    model.load_weights(weight_path)

    imgs = os.listdir(test_img_path)
    for jpg in imgs:
        img = Image.open(test_img_path + jpg)

        old_img = copy.deepcopy(img)
        orininal_h = np.array(img).shape[0]
        orininal_w = np.array(img).shape[1]

        img = img.resize((WIDTH, HEIGHT), Image.BICUBIC)
        img = np.array(img) / 255
        img = img.reshape(-1, HEIGHT, WIDTH, 3)

        pr = model.predict(img)[0]
        pr = pr.reshape((int(HEIGHT), int(WIDTH), NCLASSES)).argmax(axis=-1)

        seg_img = np.zeros((int(HEIGHT), int(WIDTH), 3))
        for c in range(NCLASSES):
            seg_img[:, :, 0] += ((pr[:, :] == c) *
                                 class_colors[c][0]).astype('uint8')
            seg_img[:, :, 1] += ((pr[:, :] == c) *
                                 class_colors[c][1]).astype('uint8')
            seg_img[:, :, 2] += ((pr[:, :] == c) *
                                 class_colors[c][2]).astype('uint8')

        seg_img = Image.fromarray(np.uint8(seg_img)).resize(
            (orininal_w, orininal_h))
        image = Image.blend(old_img, seg_img, 0.3)

        image.save(predict_out_path + jpg)