# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals

import sys
from numbers import Number

import six
import tldextract

from osxcollector.output_filters.summary_filters.summary import SummaryFilter

class HtmlSummaryFilter(SummaryFilter):
    """Prints the analysis summary (AKA "Very Readable Output") in HTML format."""

    def __init__(self, html_output_file=None, **kwargs):
        super(HtmlSummaryFilter, self).__init__(summary_output_file=html_output_file, **kwargs)

    def filter_line(self, blob):
        """Each Line of OSXCollector output will be passed to filter_line.

        The OutputFilter should return the line, either modified or unmodified.
        The OutputFilter can also choose to return nothing, effectively swallowing the line.

        Args:
            blob: A dict

        Returns:
            A dict or None
        """
        isIOC = False

        if 'osxcollector_vthash' in blob:
            self._vthash.append(blob)
            isIOC = True

        if 'osxcollector_vtdomain' in blob:
            self._vtdomain.append(blob)
            isIOC = True

        if 'osxcollector_alexa_rank' in blob:
            self._alexarank.append(blob)

        if 'osxcollector_opendns' in blob:
            self._opendns.append(blob)
            isIOC = True

        if 'osxcollector_blacklist' in blob:
            self._blacklist.append(blob)
            isIOC = True

        if 'osxcollector_related' in blob:
            self._related.append(blob)
            isIOC = True

        if self._show_signature_chain:
            if 'signature_chain' in blob and blob['osxcollector_section'] in ['startup', 'kext']:
                signature_chain = blob['signature_chain']
                if not len(signature_chain) or 'Apple Root CA' != signature_chain[-1]:
                    self._signature_chain.append(blob)
                    isIOC = True

        if self._show_browser_ext:
            if blob['osxcollector_section'] in ['firefox', 'chrome'] and blob.get('osxcollector_subsection') == 'extensions':
                self._extensions.append(blob)
                isIOC = True

        if isIOC:
            if self._group_key in blob:
                key = blob[self._group_key]
                if self._group_key == 'osxcollector_domains':
                    key = tldextract.extract(key[0]).domain + '.' + tldextract.extract(key[0]).suffix
                self._iocs_by_key[key].append(blob)
            else:
                self._iocs.append(blob)

        return blob

    def _write(self, text):
        try:
            self._output_stream.write(text.encode('utf-8', errors='replace'))
        except UnicodeDecodeError as err:
            self._output_stream.write(text)
            sys.stderr.write(
                'Unicode decode error when encoding text:\n{0}\nError:\n{1}\n'
                .format(text, err),
            )

    def end_of_lines(self):
        """Called after all lines have been fed to filter_output_line.

        The OutputFilter can do any batch processing on that requires the complete input.

        Returns:
            An array of dicts (empty array if no lines remain)
        """
        self._write('''''')
        self._print_header('Very Readable Output Bot')
        self._print_para('Let\'s see what\'s up with this machine.')

        if self._group_by_iocs:
            self.summarize_by_ioc()
        else:
            self.summarize_by_threat_indicator()

        self._print_para('Very Readable Output Bot')
        self._print_para('#kaythanksbye')

        self._write('')

        return []

    def summarize_by_ioc(self):

        if self._group_key:
            self._print_header('Table of contents (sorted by {0})'.format(self._group_key), level=2)
            self._write('
')
            for ioc_key, ioc_value in six.iteritems(self._iocs_by_key):
                self._print_section_link(
                    ioc_key, ioc_key, len(ioc_value),
                )
            self._print_section_link('iocs', 'Remaining IOCs not tagged by key', len(self._iocs))
            self._write('
')

            for ioc_key, ioc_value in six.iteritems(self._iocs_by_key):
                self._write('
'.format(ioc_key))
                self._print_header('{0}'.format(ioc_key), level=2)
                self._print_para('Here is the analysis for the IOC {0}.'.format(ioc_key))
                self._summarize_blobs(ioc_value)
                self._print_para('Hopefully that was helpful.')
                self._write('
')

        self._write('
')
        if (self._group_key):
            self._print_header('Remaining IOCs ({0})'.format(self._iocs), level=2)
        else:
            self._print_header('All IOCs ({0})'.format(len(self._iocs)), level=2)
        if (self._group_key):
            self._print_para('Here is a list of remaining IOCs that were not tagged by your key, just in case!')
        else:
            self._print_para('Get ready to analyze a bunch of IOCs!')
        self._summarize_blobs(self._iocs)
        self._print_para('Hopefully that was helpful.')
        self._write('
')

    def summarize_by_threat_indicator(self):

        self._print_header('Table of contents', level=2)
        self._write('
')

        if len(self._vthash):
            self._print_section_link(
                'vthash', 'VirusTotal bad hash hits', len(self._vthash),
            )

        if len(self._vtdomain):
            self._print_section_link(
                'vtdomain', 'VirusTotal bad domain hits', len(self._vtdomain),
            )

        if len(self._opendns):
            self._print_section_link(
                'opendns', 'OpenDNS Investigate hits', len(self._opendns),
            )

        if len(self._blacklist):
            self._print_section_link(
                'blacklist', 'Blacklist hits', len(self._blacklist),
            )

        if len(self._related):
            self._print_section_link(
                'related', 'Related hits', len(self._related),
            )

        if len(self._signature_chain):
            self._print_section_link(
                'signature_chain', 'Signature chain',
                len(self._signature_chain),
            )

        if len(self._extensions):
            self._print_section_link(
                'extensions', 'Extensions', len(self._extensions),
            )

        if len(self._add_to_blacklist):
            self._print_section_link(
                'add_to_blacklist', 'Blacklist update suggestions',
                len(self._add_to_blacklist),
            )

        self._write('
')

        if len(self._vthash):
            self._write('
')
            self._print_header('VirusTotal bad hash hits', level=2)
            self._print_para('Dang! You\'ve got known malware on this machine. Hope it\'s commodity stuff')
            self._summarize_blobs(self._vthash)
            self._print_para('Sheesh! This is why we can\'t have nice things!')
            self._write('
')

        if len(self._vtdomain):
            self._write('
')
            self._print_header('VirusTotal bad domain hits', level=2)
            self._print_para('I see you\'ve been visiting some \'questionable\' sites. If you trust VirusTotal that is.')
            self._summarize_blobs(self._vtdomain)
            self._print_para('I hope it was worth it!')
            self._write('
')

        if len(self._opendns):
            self._write('
')
            self._print_header('OpenDNS Investigate hits', level=2)
            self._print_para('Well, here\'s some domains OpenDNS wouldn\'t recommend.')
            self._summarize_blobs(self._opendns)
            self._print_para('You know you shouldn\'t just click every link you see? #truth')
            self._write('
')

        if len(self._blacklist):
            self._write('
')
            self._print_header('Blacklist hits', level=2)
            self._print_para('We put stuff on a blacklist for a reason. Mostly so you don\'t do this.')
            self._summarize_blobs(self._blacklist)
            self._print_para('SMH')
            self._write('
')

        if len(self._related):
            self._write('
')
            self._print_header('Related hits', level=2)
            self._print_para('This whole things started with just a few clues. Now look what I found.')
            self._summarize_blobs(self._related)
            self._print_para('Nothing hides from Very Readable Output Bot')
            self._write('
')

        if len(self._signature_chain):
            self._write('
')
            self._print_header('Signature chain', level=2)
            self._print_para('If these binaries were signed by \'Apple Root CA\' I\'d trust them more.')
            self._summarize_blobs(self._signature_chain)
            self._print_para('Let\'s just try and stick with some safe software')
            self._write('
')

        if len(self._extensions):
            self._write('
')
            self._print_header('Extensions', level=2)
            self._print_para('Let\'s see what\'s hiding in the browser, shall we.')
            self._summarize_blobs(self._extensions)
            self._print_para('You know these things have privileges galore.')
            self._write('
')

        if len(self._add_to_blacklist):
            self._write('
')
            self._add_to_blacklist = list(set(self._add_to_blacklist))
            self._print_header('Blacklist update suggestions', level=2)
            self._print_para('If I were you, I\'d probably update my blacklists to include:')
            for key, val in self._add_to_blacklist:
                self._summarize_val(key, val)
            self._print_para('That might just help things, Skippy!')
            self._write('
')

    def _print_section_link(self, section, title, size):
        self._write(
            '
{1} ({2})
'.format(
                section, title, size,
            ),
        )

    def _summarize_blobs(self, blobs):
        self._write('
')
        for blob in blobs:
            self._write('
')
            section = blob.get('osxcollector_section')
            subsection = blob.get('osxcollector_subsection', '')
            self._print_header(u'{0} {1}'.format(section, subsection), level=3)
            self._write('
')
            self._summarize_general(blob)

            add_to_blacklist = False

            if 'osxcollector_vthash' in blob:
                self._summarize_vthash(blob)
                add_to_blacklist = True

            if 'osxcollector_vtdomain' in blob:
                self._summarize_vtdomain(blob)

            if 'osxcollector_alexa_rank' in blob:
                self._summarize_alexa_rank(blob)

            if 'osxcollector_opendns' in blob:
                self._summarize_opendns(blob)

            if 'osxcollector_blacklist' in blob:
                self._summarize_blacklist(blob)

            if 'osxcollector_related' in blob:
                self._summarize_related(blob)

            if 'md5' in blob and '' == blob['md5']:
                add_to_blacklist = True

            if add_to_blacklist:
                blacklists = blob.get('osxcollector_blacklist', {})
                values_on_blacklist = blacklists.get('hashes', [])
                for key in ['md5', 'sha1', 'sha2']:
                    val = blob.get(key, '')
                    if len(val) and val not in values_on_blacklist:
                        self._add_to_blacklist.append((key, val))

                values_on_blacklist = blacklists.get('domains', [])
                for domain in blob.get('osxcollector_domains', []):
                    if domain not in values_on_blacklist:
                        self._add_to_blacklist.append(('domain', domain))
            self._write('
')  # this is the end of the list started by "_summarize_line"
            self._write('
')
        self._write('
')

    def _summarize_general(self, blob):
        self._write(u'
General
')
        for key in sorted(blob):
            if not key.startswith('osxcollector') and blob.get(key):
                val = blob.get(key)
                self._summarize_val(key, val, etype='dd')

    def _summarize_vthash(self, blob):
        self._write(u'
Virustotal Hash
')
        for blob in blob['osxcollector_vthash']:
            for key in ['positives', 'total', 'scan_date']:
                val = blob.get(key)
                self._summarize_val(key, val, 'vthash', etype='dd')
            permalink = blob.get('permalink')
            self._write(u'
{0}
'.format(permalink))

    def _summarize_vtdomain(self, blob):
        self._write(u'
Virustotal Domain
')
        for blob in blob['osxcollector_vtdomain']:
            for key in ['domain', 'detections']:
                val = blob.get(key)
                self._summarize_val(key, val, 'vtdomain', etype='dd')

    def _summarize_alexa_rank(self, blob):
        for blob in blob['osxcollector_alexa_rank']:
            for key in ['attributes']:
                val = blob.get(key)
                self._summarize_val(key, val, 'alexarank')

    def _summarize_opendns(self, blob):
        self._write(u'
OpenDNS
')
        for blob in blob['osxcollector_opendns']:
            for key in ['domain', 'categorization', 'security']:
                val = blob.get(key)
                self._summarize_val(key, val, 'opendns', etype='dd')
            link = blob.get('link')
            self._write(u'
{0}
'.format(link))

    def _summarize_blacklist(self, blob):
        self._write(u'
Blacklist
')
        for key in blob['osxcollector_blacklist']:
            self._summarize_val(u'blacklist-{0}'.format(key), blob['osxcollector_blacklist'][key])

    def _summarize_related(self, blob):
        self._write(u'
Related
')
        for key in blob['osxcollector_related']:
            self._summarize_val(u'related-{0}'.format(key), blob['osxcollector_related'][key])

    def _summarize_val(self, key, val, prefix=None, etype='li'):
        self._write('<{0}>'.format(etype))
        self._print_key(key, prefix)
        self._print_val(val)
        self._write('</{0}>'.format(etype))

    def _print_header(self, text, level=1):
        self._write(u'<h{0}>{1}</h{0}>'.format(level, text))

    def _print_para(self, text):
        self._write(u'
{0}
'.format(text))

    def _print_list_item(self, item):
        self._write('
')
        self._print_val(item)
        self._write('
')

    def _print_key(self, key, prefix=None):
        if not prefix:
            prefix = ''
        else:
            prefix += '-'
        self._write(u'{0}{1}: '.format(prefix, key))

    def _print_val(self, val):
        if isinstance(val, list):
            self._write('
')
            for v in val:
                self._print_list_item(v)
            self._write('
')
        elif isinstance(val, dict):
            self._write('
')
            for key in val:
                self._summarize_val(key, val[key])
            self._write('
')
        elif isinstance(val, Number):
            val = str(val)
            self._encode_val(val)
        elif isinstance(val, six.string_types):
            self._encode_val(val)

    def _encode_val(self, val):
        if not isinstance(val, six.text_type):
            val = six.text_type(val, errors='replace')
        self._write(u'{0}'.format(val))


import asyncio
from copy import deepcopy
import time
import heapq

async def gather_transaction_batches(queue: dict, expected_batches: int, timeout=5):
    # Wait until the queue is filled before starting timeout
    while len(set(queue.keys())) == 0:
        await asyncio.sleep(0)

    # Now wait until the rest come in or the timeout is triggered
    start = time.time()
    while len(set(queue.keys())) < expected_batches and time.time() - start < timeout:
        await asyncio.sleep(0)

    work = deepcopy(list(queue.values()))
    queue.clear()

    return work

def pad_work(work: list, expected_masters: list):
    for task in work:
        if task['sender'] in expected_masters:
            expected_masters.remove(task['sender'])

    for missing_master in expected_masters:
        shim = {
            'transactions': [],
            'timestamp': int(time.time()),
            'signature': '0' * 128,
            'input_hash': missing_master,
            'sender': missing_master
        }
        work.append(shim)

def filter_work(work):
    actual_work = [w for w in work if w is not None]
    return sorted(actual_work, key=lambda x: x['timestamp'])
    # filtered_work = []
    # print(work)
    # for tx_batch in work:
    #     # Filter out None responses
    #     if tx_batch is None:
    #         continue
    #
    #     # Add the rest to a priority queue based on their timestamp
    #     print(filtered_work)
    #     print(tx_batch)
    #     heapq.heappush(filtered_work, (tx_batch['timestamp'], tx_batch))
    #
    # # Actually sorts the heap. This can be rewritten to use heap push pop.
    # w = []
    # for i in range(len(filtered_work)):
    #     w.append(heapq.heappop(filtered_work))
    #
    # return w


import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="chartree",
    version="0.1.0",
    author="bsmrvl",
    author_email="ben.j.somerville@icloud.com",
    description="Grow trees",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/bsmrvl/a-trees-character",
    packages=setuptools.find_packages(),
    install_requires=['numpy','IPython'],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
)


'''
Created on 13.08.2018

@author: larissa.hoefling@uni-tuebingen.de
-*- coding: utf-8 -*-
'''
import numpy as np
import matplotlib.pyplot as plt
from analysis.utils import smooth
from scipy.signal import periodogram
import pickle as pkl
import matplotlib as mpl

class Stimulus():
    '''
    #########################################################################
    When an object of the class stimulus is instantiated, a stimulus file (.txt)
    is opened and the timeline and voltage commands are read, and the expected
    current is computed. For now, a general capacitance value is assumed for all
    chips of the same type (typically no oxide), however in a future version, a
    chip name should be passed and the corresponding exact capacitance should be
    retrieved from a .csv file and saved as an instance variable
    '''
    temp_res = 10000
    conversion_factor = 10**(-3) #times 10**-6 to convert from uF to F,
                                 #times 10**-6 to convert from uV to V,
                                 #times 10**4 to convert from 1/0.0001 s to 1/s
                                 #times 10**3 to convert from A to mA
                                 #times 10**2 to convert from 1/mm**2 to 1/cm**2

    def __init__(self, path = None, len_snippets = 200, stepwidth_snippets=20, \
                 rcond=10**-5, smoothing_window_len = 20):
        '''
        set the path to the stimulus file, set the capacitance that should be
        used to convert from voltage command to expected current density;

        load the stimulus time_line and the voltage_command from the .txt file
        found under path

        compute the expected current density

        Inputs:
        -----------------------------------------------------------------------
        path    path to stimulus file
        len_snippets    int
        stepwidth_snippets    int
        rcond                 float
        smoothing_window_len    int
                parameters to reconstruct_stimulus

        Outputs:
        -----------------------------------------------------------------------
        None;
        sets
        self.path to path
        self.capacitance to fixed value
        self.time_line to the time line read from file
        self.voltage_command to the voltage command read from file
        self.current_density to the output of self.expected_current()
        self.white_current_density to the output of self.reconstruct_stimulus()
        '''
        if path == None:
            #fill this later with a gui
            raise ValueError("no path for the stimulus file was passed")
        else:
            self.path = path

        self.capacitance = 0.04227
        temp = np.genfromtxt(path)

        self.time_line = temp[:-1,0]
        self.voltage_command = temp[:,1]
        self.current_density = self.expected_current()
        self.white_current_density = \
            self.reconstruct_stimulus(len_snippets, stepwidth_snippets, rcond, smoothing_window_len)
#         self.white_current_density = \
#         np.concatenate(np.transpose(self.whiten_stimulus(len_snippets, stepwidth_snippets, rcond)))

    def expected_current(self):
        '''
        using I = C*dV/dt and i = I/A, compute the expected current density
        '''
        current_density = \
        np.diff(self.voltage_command)*self.capacitance*self.conversion_factor
        return current_density

    def create_stimulus_ensemble(self, len_sta, stepwidth = 1, white = False):
        '''
        from the continuous stimulus loaded from the file, create a stimulus
        ensemble, where each element is a len_sta long snippet, and snippets are
        taken stepwidth ms apart

        input:
        len_sta     int
                    length of the snippets in samples
        stepwidth    int
                    stepwidth between the snippets in ms
        white        boolean
            if white is true, then the stimulus ensemble is created from the
            reconstructed whitened stimulus

        output:
        stim_ensemble    array
                        the created stimulus ensemble, dimensions
                        len_sta x # of snippets (i.e. 1 column is 1 snippet)

        '''
        stim_ensemble = []
        sample_stepwidth = int((self.temp_res/1000)*stepwidth)
        if white:

            len_stim = len(self.white_current_density)
            dim = len_stim-len_sta
            [stim_ensemble.append(self.white_current_density[i:i+len_sta]) \
                                    for i in range(0, dim+sample_stepwidth, sample_stepwidth)]
        else:

            len_stim = len(self.current_density)
            dim = len_stim-len_sta
            [stim_ensemble.append(self.current_density[i:i+len_sta]) \
                                    for i in range(0, dim+sample_stepwidth, sample_stepwidth)]

        # if len(stim_ensemble[-1]) != len(stim_ensemble[-2]):
        #     stim_ensemble.pop(-1)
        #     print("Last element of stimulus ensemble had to be removed because it was of a different dimension ")
        if stepwidth==1:
            stim_ensemble.pop(-1)
        stim_ensemble = np.asarray(stim_ensemble)
        stim_ensemble = np.transpose(stim_ensemble)
        return stim_ensemble

    def compute_stimulus_cov(self, len_sta, mode = 'original'):
        '''
        computes the surrogate stimulus covariance, based on the stimulus
        ensemble with snippets of length len_sta (for more details, see
        description of create_stimulus_ensemble)

        '''
        if mode == 'original':
            stim_ensemble = self.create_stimulus_ensemble(len_sta)
        elif mode == 'white_smooth':
            stim_ensemble = self.create_stimulus_ensemble(len_sta, white=True)
        elif mode == 'white_raw':
            stim_ensemble = self.whiten_stimulus(len_sta, stepwidth_stim_snippets=1)

        stim_cov = np.cov(stim_ensemble)

        return stim_cov

    def compute_stim_cov_inverse_sqrt(self, len_sta, rcond=10**-5):
        '''
        computes sqrt pseudoinverse of the stimulus covariance matrix. For
        details, see Aljadeff et al. (2016), Neuron
        '''
        stim_cov = self.compute_stimulus_cov(len_sta)
        u,s,v = np.linalg.svd(stim_cov)
        singular_values = s
        rcond = rcond * np.max(singular_values)
        ind = np.where(singular_values<=rcond)
        singular_values = 1/np.sqrt(singular_values)
        singular_values[ind] = 0
        sqrt_inv = np.dot(np.dot(u, np.diag(singular_values)), v)
        return sqrt_inv

    def compute_stim_cov_inverse(self, len_sta, rcond=10**-5):
        '''
        computes pseudoinverse of the stimulus covariance matrix. For
        details, see Aljadeff et al. (2016), Neuron
        '''
        stim_cov = self.compute_stimulus_cov(len_sta)
        u,s,v = np.linalg.svd(stim_cov)
        singular_values = s
        rcond = rcond * np.max(singular_values)
        ind = np.where(singular_values<=rcond)
        singular_values = 1/singular_values
        singular_values[ind] = 0
        inv = np.dot(np.dot(u, np.diag(singular_values)), v)
        return inv

    def whiten_stimulus(self, len_sta, stepwidth_stim_snippets, rcond = 10**-5):
        '''
        creates a stimulus ensemble, and whitens it, i.e. removes autocorrelations
        from this ensemble by multiplying with the sqrt of the pseudo inverse
        of the stimulus covariance matrix
        '''

        stim_cov_sqrt_inv = self.compute_stim_cov_inverse_sqrt(len_sta, rcond)
        stimulus_ensemble = self.create_stimulus_ensemble(len_sta, stepwidth_stim_snippets)
        whitened_stimulus_ensemble = \
        np.matmul(stim_cov_sqrt_inv, stimulus_ensemble)

        return whitened_stimulus_ensemble

    def reconstruct_stimulus(self, len_snippets, stepwidth_snippets, rcond, \
                             smoothing_window_len):
        '''
        This function expects a stimulus ensemble of shape snippet_length x
        snippet_number, where the snippets just have to be appended to yield
        the full stimulus (i.e. snippet_length * snippet_number = stimulus
        length), but the transitions need to be smoothed. The smoothing is
        performed here.

        Inputs:
        -----------------------------------------------------------------------
            len_snippets    int
                            length of the stimulus snippets in samples
        stepwidth_snippets    int
                                stepwidth between the snippets in ms;
        rcond            float
                         rounding condition to compute_stim_cov_inverse_sqrt
        smoothing_window_len    int
                                length of the smoothing window to smooth, in samples

        Outputs:
        -----------------------------------------------------------------------
        the whitened stimulus, reconstructed by appending and smoothing the
        snippets from the whitened ensemble
        '''

#         stim_ensemble = []
#         sample_stepwidth = int((self.temp_res/1000)*stepwidth_snippets)
#
#
#         dim = len(self.current_density)
#
#         [stim_ensemble.append(self.current_density[i:i+len_snippets]) \
#                                         for i in range(0, dim, sample_stepwidth)]
#
#
#
#         stim_ensemble = np.asarray(stim_ensemble)
#         stim_ensemble = np.transpose(stim_ensemble)

        stim_ensemble = self.create_stimulus_ensemble(len_snippets, stepwidth_snippets)
        stim_cov_inv_sqrt = self.compute_stim_cov_inverse_sqrt(len_snippets, rcond)
        white_ensemble = np.matmul(stim_cov_inv_sqrt, stim_ensemble)
        shift = int(smoothing_window_len/2)
        recon = np.concatenate(np.transpose(white_ensemble))

        smooth_recon = smooth(recon, window_len=smoothing_window_len)
        return smooth_recon

    def check_and_plot(self, len_snippets = 200, stepwidth_snippets = 20,\
                        rcond = 10**-5, path = None, load_pickled_version = False):

        '''
        creates a 4x3 plot of
                    (1) an excerpt from x
                    (2) the periodogram of x
                    (3) the covariance of x
                    (4) the autocorrelation of x
        where x
                    (1) the original stimulus
                    (2) the whitened and smoothed version of the stimulus
                    (3) the whitened raw version of the stimulus
        '''

        def format_func(value, tick_number):
            return value/self.temp_res

        fname = 'stimulus'
        if load_pickled_version:
            f = open(r'D:/Lara Analysis/paper pickles/stim_versions.pkl', 'rb')
            stim_versions = pkl.load(f)
            f = open(r'D:/Lara Analysis/paper pickles/cov_versions.pkl', 'rb')
            cov_versions = pkl.load(f)

        else:
            original = self.current_density
            original_cov = self.compute_stimulus_cov(len_snippets, mode = 'original')
            whitened_smoothed = self.white_current_density
            whitened_smoothed_cov = self.compute_stimulus_cov(len_snippets, mode='white_smooth')
            whitened_raw = np.concatenate(np.transpose(self.whiten_stimulus(len_snippets, stepwidth_snippets, rcond)))
            whitened_raw_cov = self.compute_stimulus_cov(len_snippets, mode='white_raw')
    #         stim_versions = dict(zip(['original', 'whitened and smoothed', 'whitened raw'], \
    #                                  [original, whitened_smoothed, whitened_raw]))
    #
    #         cov_versions = dict(zip(['original', 'whitened and smoothed', 'whitened raw'], \
    #                                  [original_cov, whitened_smoothed_cov, whitened_raw_cov]))

            stim_versions = dict(zip(['original', 'whitened and smoothed'], \
                                     [original, whitened_smoothed]))

            cov_versions = dict(zip(['original', 'whitened and smoothed'], \
                                     [original_cov, whitened_smoothed_cov]))

            f = open(r'D:/Lara Analysis/paper pickles/stim_versions.pkl', 'wb')
            pkl.dump(stim_versions, f)
            f = open(r'D:/Lara Analysis/paper pickles/cov_versions.pkl', 'wb')
            pkl.dump(cov_versions, f)

        fs = self.temp_res
        n_cols = 1
        n_rows = 3
        counter = 0

        sample_start = 1000
        sample_stop = 2500
        t_start = sample_start/fs
        t_stop = sample_stop/fs

        time_line = np.linspace(t_start, t_stop, sample_stop-sample_start)

        '''
        plot original stimulus
        '''

#         plt.figure(figsize=[6,8])
#         plt.figure(figsize=[6.4,8])
        plt.figure(figsize=[8,6])
        plt.style.use('seaborn-paper')
        s=13
        mpl.rcParams.update({'font.size':s, 'axes.labelsize':s,\
                          'xtick.labelsize':s, 'ytick.labelsize':s})
        axes_orig = []

#         axes_orig.append(plt.subplot2grid([n_rows, 3], [1, 0]))
#         ax = plt.imshow(cov_versions['original'], cmap = 'Greys')
#         plt.gca().set_axis_off()
# #         plt.colorbar(ticks = [-0.1, 0, 0.3])
#
#
#
#         axes_orig.append(plt.subplot2grid([n_rows, 3], [1, 1]))
#         plt.imshow(self.compute_stim_cov_inverse_sqrt(len_sta=len_snippets, \
#                                                  rcond = rcond), cmap = 'Greys')
#         plt.gca().set_axis_off()
# #         plt.colorbar(ticks = [-2, 0, 5])
#
#         axes_orig.append(plt.subplot2grid([n_rows, 3], [1, 2]))
#         plt.imshow(cov_versions['whitened and smoothed'], cmap = 'Greys')
#         plt.gca().set_axis_off()
#         plt.colorbar(ticks = [0, 0.02, 0.05])

        axes_orig.append(plt.subplot2grid([n_rows, n_cols], [0, counter]))
        plt.plot(time_line, stim_versions['original'][sample_start:sample_stop],\
                 color = '0.5')

        plt.plot(time_line, stim_versions['whitened and smoothed'][sample_start:sample_stop],\
                 color = 'k')
        plt.xlabel('Time [s]')
        plt.ylabel('Current \n'  r'density [$\frac{mA}{cm^2}$]')
        plt.gca().xaxis.set_major_locator(plt.MaxNLocator(4))
        plt.gca().yaxis.tick_right()

        ax = plt.subplot2grid([n_rows, n_cols], [1, counter])

        start = 20

        axes_orig.append(ax)
        '''
        compute the absolute current in Amperes
        '''
        area = 3*((5*0.003)**2)                #active stimulation area, assuming 3 x 5x5 active electrodes, one
                                              #electrode has 0.003 cm length

        orig_stim = stim_versions['original'] * area * 10**-3   #last factor to convert from mA to A
        whitened_smoothed_stim = stim_versions['whitened and smoothed'] * area * 10**-3

        frequencies, psd = periodogram(orig_stim, fs, return_onesided = True)
#         bax = brokenaxes(ylims = ((psd[0], psd[22]),(psd[23], psd[2000])), subplot_spec=psd_ax)
        plt.semilogy(frequencies[start:2000], psd[start:2000], color = '0.5')
#         plt.yscale(value='log')
        frequencies, psd = periodogram(whitened_smoothed_stim, fs, return_onesided = True)
#         bax = brokenaxes(ylims = ((psd[0], psd[20]),(psd[21], psd[2000])), subplot_spec=psd_ax)
        plt.semilogy(frequencies[start:2000], psd[start:2000], color = 'k')
#         plt.yscale(value='log')
#         plt.gca().xaxis.set_major_locator(plt.MaxNLocator(5))
        ax.set_xlim((frequencies[start], frequencies[2000]))
        current_ticks = list(plt.xticks()[0])
        current_ticks.append(4)
        current_ticks.pop(0)
        plt.xticks(current_ticks)
        plt.gca().yaxis.tick_right()
        print(frequencies[20])
#         plt.gca().yaxis.tick_right()
#         plt.gca().xaxis.set_major_locator(plt.MaxNLocator(6))
        plt.xlabel('Frequency [Hz]')
#         plt.gca().yaxis.set_label_position('right')
        plt.ylabel('Power spectral' +'\n' +r'density [$\frac{A}{\sqrt{Hz}}$]', labelpad = 14)

        axes_orig[1].spines["top"].set_visible(False)
#         axes_orig[1].spines["bottom"].set_visible(False)
        axes_orig[1].spines["left"].set_visible(False)
        axes_orig[1].spines["right"].set_visible(False)
#         plt.semilogy(frequencies[20:2000], psd[20:2000])
#         axes_orig.append(plt.subplot2grid([n_rows, n_cols+1], [2, counter]))
#
#         plt.imshow(cov_versions['original'],cmap = 'hot')
#
#         axes_orig.append(plt.subplot2grid([n_rows, n_cols+1], [2, 1]))
#
#         plt.imshow(cov_versions['whitened and smoothed'], cmap='hot')
#
#         axes_orig[2].spines["top"].set_visible(False)
#         axes_orig[2].spines["bottom"].set_visible(False)
#         axes_orig[2].spines["left"].set_visible(False)
#         axes_orig[2].spines["right"].set_visible(False)
#         axes_orig[2].xaxis.set_major_locator(plt.NullLocator())
#         axes_orig[2].yaxis.set_major_locator(plt.NullLocator())
#
#         axes_orig[3].spines["top"].set_visible(False)
#         axes_orig[3].spines["bottom"].set_visible(False)
#         axes_orig[3].spines["left"].set_visible(False)
#         axes_orig[3].spines["right"].set_visible(False)
#         axes_orig[3].xaxis.set_major_locator(plt.NullLocator())
#         axes_orig[3].yaxis.set_major_locator(plt.NullLocator())

        axes_orig.append(plt.subplot2grid([n_rows, n_cols], [2, counter]))
        plt.acorr(stim_versions['original'], maxlags = 200, color = '0.5', \
                  usevlines= False, linewidth = 1, linestyle = '-')

        plt.acorr(stim_versions['whitened and smoothed'], maxlags = 200, \
                  color = 'k', usevlines = False, linestyle = '-')

        plt.xlabel('Time [s]')
        plt.ylabel('Auto-\n correlation')
        axes_orig[-1].xaxis.set_major_formatter(plt.FuncFormatter(format_func))
        plt.gca().xaxis.set_major_locator(plt.MaxNLocator(4))
        plt.gca().yaxis.tick_right()
        for ax in axes_orig:
            ax.spines["top"].set_visible(False)
            ax.spines["left"].set_visible(False)
            ax.spines["right"].set_visible(False)

        '''
        plot whitened and smoothed stimulus
        '''
#         counter = 1
#         axes_ws = []
#         axes_ws.append(plt.subplot2grid([n_rows, n_cols], [0, counter], sharey= axes_orig[0]))
#         plt.plot(time_line, stim_versions['whitened and smoothed'][sample_start:sample_stop])
#
#         axes_ws.append(plt.subplot2grid([n_rows, n_cols], [1, counter]))
#         frequencies, psd = periodogram(stim_versions['whitened and smoothed'], fs, return_onesided = True)
#         plt.plot(frequencies[:2000], psd[:2000])
#         axes_ws[1].spines["top"].set_visible(False)
#         axes_ws[1].spines["bottom"].set_visible(False)
#         axes_ws[1].spines["left"].set_visible(False)
#         axes_ws[1].spines["right"].set_visible(False)
# #         plt.semilogy(frequencies[20:2000], psd[20:2000])
#         axes_ws.append(plt.subplot2grid([n_rows, n_cols], [2, counter]))
#
#         plt.imshow(cov_versions['whitened and smoothed'])
#         axes_ws[2].spines["top"].set_visible(False)
#         axes_ws[2].spines["bottom"].set_visible(False)
#         axes_ws[2].spines["left"].set_visible(False)
#         axes_ws[2].spines["right"].set_visible(False)
#         axes_ws[2].xaxis.set_major_locator(plt.NullLocator())
#         axes_ws[2].yaxis.set_major_locator(plt.NullLocator())
#
#         axes_ws.append(plt.subplot2grid([n_rows, n_cols], [3, counter]))
#         plt.acorr(stim_versions['whitened and smoothed'], maxlags = 200)
#         axes_ws[-1].xaxis.set_major_formatter(plt.FuncFormatter(format_func))

#         plt.tight_layout()

        plt.subplots_adjust(bottom = 0.2,wspace = 0.3, hspace = 1)
        if path is not None:
            plt.savefig(path+fname+'.png', dpi = 300, fmt='png')
            plt.savefig(path+fname+'.pdf', dpi = 300, fmt='pdf')
            plt.savefig(path + fname + '.svg', dpi=300, fmt='svg')
        else:
            plt.show()


import TimNghichDao as _1
p = 43
q = 47
e = 67

n = p*q
print("n = p*q = " + str(p) + "*" +str(q)+" = ", n)

Phi_n = (p-1)*(q-1)
print(Phi_n)

d = _1.TimNghichDao(e, Phi_n)

def PU():
	print("PU = {e, n} = {"+ str(e) + "," + str(n) + "}")
def PR():
	print("PR = {d, n} = {"+ str(d) + "," + str(n) + "}")
def MaHoaM(M, i = 0, BaoMat = True):
	if BaoMat:
		C = pow(M, e) % n
	else:
		C = pow(M, d) % n
	if i != 0:
		if BaoMat:
		 	print("
C = Me mod n = " + str(M) + "" + str(e) + " mod " + str(n) + " = " + str(C), end = "
\n")
		else:
		 	print("
C = Md mod n = " + str(M) + "" + str(d) + " mod " + str(n) + " = " + str(C), end = "
\n")
	return C
def GiaiMaC(C, i = 0, BaoMat = True):
	if BaoMat:
		M = pow(C, d) % n
	else:
		M = pow(C, e) % n
	if i != 0:
		if BaoMat:
			print("
M = Cd mod n = " + str(C) + "" + str(d) + " mod " + str(n) + " = " + str(M), end = "
\n")
		else:
			print("
M = Ce mod n = " + str(C) + "" + str(e) + " mod " + str(n) + " = " + str(M), end = "
\n")
	return M
PU()
PR()
M = 59
BaoMat = True
MaHoaM(M, 1, BaoMat)
GiaiMaC(MaHoaM(M, 0, BaoMat), 1, BaoMat)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Démultiplication(/2) ☺
# Version 3

""" Cette version-3 pour les petits nombres à 7 chiffres,
    sans les afficher les listes."""

def quantum(cas):
    """Selon la quantité de nombres dans la liste terminale."""
    # ('\nQuantum cas: ', cas, ' cap: ', cap)
    for m in cap:  # Initialise en_len.keys() en valeur de liste vide
        en_len[m] = []
        en_fin[m] = []
    for k in cas.keys():  # Range les listes par longueur
        que = len(cas[k])
        en_len[que].append(cas[k][0])
        # ('Q_en_len[que].', en_len[que], que)
    nbr1, nbr2 = 0, 0
    for k in en_len.keys():
        nbr1 += (len(en_len[k]) * k)
        nbr2 = len(en_len[k]) * k
        en_fin[k] = nbr1, nbr2
        # ('Q_en_len : ', k, ' en_len[k] : ', en_len[k], 'nbr1 : ', nbr1, ' nbr2 : ', nbr2)
    ('Q_Pairs.', en_len.keys())

iota = int(input("Nombre à évaluer : "))
glob_part = int(input("0=sans partiels, 1=avec partiels. Votre choix = "))
roma = int(input("0=sans listes, 1=listes, 2=listes>1. Votre choix = "))
# Choisir de voir toutes les listes supérieures à deux nombres.
choix = roma  # Choix 0=nul. 1=Toutes listes. 2=Listes supérieures à un élément.

secteur = 0
origine = iota
while iota > 1:
    iota /= 2
    secteur += 1
section = 2 ** secteur
print('origine :', origine, '. Appartient à la section : ', 2 ** secteur)
if choix:
    if choix == 1:
        print(". Toutes les listes.")
    elif choix == 2:
        print(". Les listes supérieures à une unité.")
en_cas, en_dic, en_len, cap, en_fin = [], {}, {}, [], {}  # Construire listes i%2
pot = eau = True
# Construction du secteur demandé.
for x in range(section, section // 2, -2):
    secte = x
    while not x % 2:
        en_cas.append(x)
        x //= 2
    if en_cas:  # Liste les nombres pairs
        en_dic[secte] = en_cas.copy()
    if choix == 0 and eau:
        eau = False
        print(". Le choix zéro n'est pas affichable.")
    elif choix == 1:
        if pot:
            pot = False
            print('Dico = ', en_dic[section], '  \t\t Terminale = ', len(en_dic[section]))
        else:
            print('Dico = ', en_dic[secte], '    \t\t\t Longueur = ', len(en_dic[secte]))
    elif choix == 2:
        if len(en_dic[secte]) > 1:
            print('Dico = ', en_dic[secte], '    \t\t\t Longueur = ', len(en_dic[secte]))
    x_cap = len(en_dic[secte])
    if x_cap not in cap:
        cap.append(x_cap)
    en_cas.clear()
cap.sort()
quantum(en_dic)

print('\n Résultats Globaux')
print('Origine = ', origine, '. Appartient à la section : ', 2 ** secteur)
long_max = len(en_dic[max(en_dic.keys())])  # Où l'exposant de la mantisse 2
print('Longueur terminale = ', long_max, " = L'exposant de 2")
nbr_list = max(en_dic.keys()) // 4  # Nombre total des listes
print('Nombre    listes = ', nbr_list, ' = Le nombre total des listes')
par_list = (nbr_list - 1) // 3  # Nombre de parties trilog
print('Partie    listes = ', par_list,
      ' = Le nombre de parties trilog. Il reste = ', (nbr_list - 1) - (par_list * 3))
sec_list = long_max - 2  # Longueur de la plus grande sous-liste
print('Section   listes = ', sec_list, ' = La longueur de la plus grande sous-liste')
print('Cap = ', cap, ' = Liste les longueurs des listes ')
# ☺
if glob_part:
    print('\n Résultats Partiels')  # en_le et en_fin = Précisions quantitatives
    debut, grade, viel = ' _ ', '♦', '☺'
    for c in cap:  # c = Une quantité dans la liste cap
        c_cap = en_len[c][:8]  # Liste les listes de même longueur
        soluce = c * len(c_cap)  #
        nbr_liste = int(en_fin[c][1]) // c  # Même quantité d'éléments des listes
        print('c=', c, "c_cap=", c_cap, '\n\tQuantités (cumulées, partielles)', en_fin[c], '\tNbr_liste//c= ',
              nbr_liste)

# Définition de la mesure de la section terminale
""" Une section terminale = Une des organisations régulières des nombres pairs.   _[Voir # Visite des terminales]_***
La section  terminale = De max(liste) à max(liste)/2+2
    = [2=min(liste), max(liste)=2**n], séquence les listes fondamentales précédentes.***
En faisant ; maxi = max(liste fondamentale) = 64 || Alors ; max(liste fondamentale)/2+2 = 34...........
= Longueur de la liste terminale 64 = 64/4 = La section 64 a 16 nombres pairs index.    _[Voir # Liste mesurable]_
    Les 16 index sont des listes desquelles ou non-divisibles par 2 aux quotients pairs.
    Liste = Un nombre calculé à n%4 (le reste du quotient du diviseur 4 sur n) = 0.
        [Débat n%4=2] = (n/4=impair) = Liste avec un seul élément.
        [Débat n%4=0] L'index est divisé par deux tant que [n%2!=0], puis il est ajouté à la liste."""

# Visite des sections terminales
"""
*** Terminal  4 [4, 2] 	 ____ ____ Terminal = 4 		len(vec): 2
*** Terminal  8 [8, 4, 2] 	 ____ ____ Terminal = 8 		len(vec): 3
*** Terminal  16 [16, 8, 4, 2] 	 ____ ____ Terminal = 16 		len(vec): 4
*** Terminal  32 [32, 16, 8, 4] 	 ____ ____ Terminal = 32 		len(vec): 5
*** Terminal  64 [64, 32, 16, 8] 	 ____ ____ Terminal = 64 		len(vec): 6
*** Terminal  128 [128, 64, 32, 16] 	 ____ ____ Terminal = 128 		len(vec): 7
*** Terminal  256 [256, 128, 64, 32] 	 ____ ____ Terminal = 256 		len(vec): 8
*** Terminal  512 [512, 256, 128, 64] 	 ____ ____ Terminal = 512 		len(vec): 9
*** Terminal  1024 [1024, 512, 256, 128] 	 ____ ____ Terminal = 1024 		len(vec): 10
*** Terminal  2048 [2048, 1024, 512, 256] 	 ____ ____ Terminal = 2048 		len(vec): 11
*** Terminal  4096 [4096, 2048, 1024, 512] 	 ____ ____ Terminal = 4096 		len(vec): 12
*** Terminal  8192 [8192, 4096, 2048, 1024] 	 ____ ____ Terminal = 8192 		len(vec): 13
*** Terminal  16384 [16384, 8192, 4096, 2048] 	 ____ ____ Terminal = 16384 		len(vec): 14
*** Terminal  32768 [32768, 16384, 8192, 4096] 	 ____ ____ Terminal = 32768 		len(vec): 15
*** Terminal  65536 [65536, 32768, 16384, 8192] 	 ____ ____ Terminal = 65536 		len(vec): 16
*** Terminal  131072 [131072, 65536, 32768, 16384] 	 ____ ____ Terminal = 131072 		len(vec): 17
*** Terminal  262144 [262144, 131072, 65536, 32768] 	 ____ ____ Terminal = 262144 		len(vec): 18
"""

# Comment mesurer la section terminale
""" À une section terminale correspond une suite régulière de nombres pairs indexés.
***          La section  terminale = De max(liste fondamentale) à max(liste fondamentale)/2+2                  .***
***          La liste à  indexions = De max(liste[0]) à min(liste[-1] divisible par deux)                      .***
Premier temps non terminé ici mais dans la version 4 ☺
"""

# Liste minimale 2(1*2)
"""
Nombre à évaluer : 2
0=sans partiels, 1=avec partiels. Votre choix = 1
0=sans listes, 1=avec listes, 2=listes>1µ. Votre choix = 1
origine : 2 . Appartient à la section :  2
Dico =  [2]   			 Longueur Terminale =  1

 Résultats Globaux
Origine =  2 . Appartient à la section :  2
Longueur terminale =  1  = L'exposant de 2
Nombre    listes =  0  = Le nombre total des listes
Partie    listes =  -1  = Le nombre de parties trilog. Il reste =  2
Section   listes =  -1  = La longueur de la plus grande sous-liste
Cap =  [1]  = Liste les longueurs des listes

 Résultats Partiels
Ci:  1 [2] Quantités (cumulées, partielles) (1, 1)
*	Nbr liste//c=  1
"""

# Liste trilog 3(2*2)
"""
Nombre à évaluer : 3
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=avec listes, 2=listes>1µ. Votre choix = 1
origine : 3 . Appartient à la section :  4
. Toutes les listes.
Dico =  [4, 2]   		 Terminale =  2

 Résultats Globaux
Origine =  3 . Appartient à la section :  4
Longueur terminale =  2  = L'exposant de 2
Nombre    listes =  1  = Le nombre total des listes
Partie    listes =  0  = Le nombre de parties trilog. Il reste =  0
Section   listes =  0  = La longueur de la plus grande sous-liste
Cap =  [2]  = Liste les longueurs des listes
"""
# Liste 16(8*2)
"""
Nombre à évaluer : 16
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=listes, 2=listes>1. Votre choix = 1
origine : 16 . Appartient à la section :  16
. Toutes les listes.
Dico =  [16, 8, 4, 2]   		 Terminale =  4
Dico =  [14]     			 Longueur =  1
Dico =  [12, 6]     			 Longueur =  2
Dico =  [10]     			 Longueur =  1

 Résultats Globaux
Origine =  16 . Appartient à la section :  16
Longueur terminale =  4  = L'exposant de 2
Nombre    listes =  4  = Le nombre total des listes
Partie    listes =  1  = Le nombre de parties trilog. Il reste =  0
Section   listes =  2  = La longueur de la plus grande sous-liste
Cap =  [1, 2, 4]  = Liste les longueurs des listes
"""
# Liste 32(16*2)
"""
Nombre à évaluer : 31
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=avec listes, 2=listes>1µ. Votre choix = 1
origine : 31 . Appartient à la section :  32
. Toutes les listes.
Dico =  [32, 16, 8, 4, 2]   		 Terminale =  5
Dico =  [30]     			 Longueur =  1
Dico =  [28, 14]     			 Longueur =  2
Dico =  [26]     			 Longueur =  1
Dico =  [24, 12, 6]     			 Longueur =  3
Dico =  [22]     			 Longueur =  1
Dico =  [20, 10]     			 Longueur =  2
Dico =  [18]     			 Longueur =  1

 Résultats Globaux
Origine =  31 . Appartient à la section :  32
Longueur terminale =  5  = L'exposant de 2
Nombre    listes =  8  = Le nombre total des listes
Partie    listes =  2  = Le nombre de parties trilog. Il reste =  1
Section   listes =  3  = La longueur de la plus grande sous-liste
Cap =  [1, 2, 3, 5]  = Liste les longueurs des listes
"""

# Liste 64(32*2)
"""
Nombre à évaluer : 64
0=sans listes, 1=avec listes, 2=listes>1. Votre choix = 1
origine : 64 . Appartient à la section :  64
Dico =  [64, 32, 16, 8, 4, 2]   			 Longueur Terminale =  6
Dico =  [62]     			 Longueur =  1
Dico =  [60, 30]     			 Longueur =  2
Dico =  [58]     			 Longueur =  1
Dico =  [56, 28, 14]     			 Longueur =  3
Dico =  [54]     			 Longueur =  1
Dico =  [52, 26]     			 Longueur =  2
Dico =  [50]     			 Longueur =  1
Dico =  [48, 24, 12, 6]     			 Longueur =  4
Dico =  [46]     			 Longueur =  1
Dico =  [44, 22]     			 Longueur =  2
Dico =  [42]     			 Longueur =  1
Dico =  [40, 20, 10]     			 Longueur =  3
Dico =  [38]     			 Longueur =  1
Dico =  [36, 18]     			 Longueur =  2
Dico =  [34]     			 Longueur =  1

 Résultats Globaux
Origine =  64 . Appartient à la section :  64
Longueur terminale =  6  = La l'exposant de 2
Nombre    listes =  16  = Le nombre total des listes
Partie    listes =  5  = Le nombre de parties trilog. Il reste =  0
Section   listes =  4  = La longueur de la plus grande sous-liste

 Résultats Partiels
Ci:  1 [62, 58, 54, 50, 46, 42, 38, 34] Quantités (cumul, partiel) (8, 8)
*	Nbr liste//c=  8
Ci:  2 [60, 52, 44, 36] Quantités (cumul, partiel) (16, 8)
*	Nbr liste//c=  4
Ci:  3 [56, 40] Quantités (cumul, partiel) (22, 6)
*	Nbr liste//c=  2
Ci:  4 [48] Quantités (cumul, partiel) (26, 4)
*	Nbr liste//c=  1
Ci:  6 [64] Quantités (cumul, partiel) (32, 6)
*	Nbr liste//c=  1
"""
# Liste 128(64*2)
"""_______________________________________________________________________________
Nombre à évaluer : 99
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=avec listes, 2=listes>1µ. Votre choix = 1
origine : 99 . Appartient à la section :  128
. Toutes les listes.
Dico =  [128, 64, 32, 16, 8, 4, 2]   		 Terminale =  7
Dico =  [126]     			 Longueur =  1
Dico =  [124, 62]     			 Longueur =  2
Dico =  [122]     			 Longueur =  1
Dico =  [120, 60, 30]     			 Longueur =  3
Dico =  [118]     			 Longueur =  1
Dico =  [116, 58]     			 Longueur =  2
Dico =  [114]     			 Longueur =  1
Dico =  [112, 56, 28, 14]     			 Longueur =  4
Dico =  [110]     			 Longueur =  1
Dico =  [108, 54]     			 Longueur =  2
Dico =  [106]     			 Longueur =  1
Dico =  [104, 52, 26]     			 Longueur =  3
Dico =  [102]     			 Longueur =  1
Dico =  [100, 50]     			 Longueur =  2
Dico =  [98]     			 Longueur =  1
Dico =  [96, 48, 24, 12, 6]     			 Longueur =  5
Dico =  [94]     			 Longueur =  1
Dico =  [92, 46]     			 Longueur =  2
Dico =  [90]     			 Longueur =  1
Dico =  [88, 44, 22]     			 Longueur =  3
Dico =  [86]     			 Longueur =  1
Dico =  [84, 42]     			 Longueur =  2
Dico =  [82]     			 Longueur =  1
Dico =  [80, 40, 20, 10]     			 Longueur =  4
Dico =  [78]     			 Longueur =  1
Dico =  [76, 38]     			 Longueur =  2
Dico =  [74]     			 Longueur =  1
Dico =  [72, 36, 18]     			 Longueur =  3
Dico =  [70]     			 Longueur =  1
Dico =  [68, 34]     			 Longueur =  2
Dico =  [66]     			 Longueur =  1

 Résultats Globaux
Origine =  99 . Appartient à la section :  128
Longueur terminale =  7  = L'exposant de 2
Nombre    listes =  32  = Le nombre total des listes
Partie    listes =  10  = Le nombre de parties trilog. Il reste =  1
Section   listes =  5  = La longueur de la plus grande sous-liste
Cap =  [1, 2, 3, 4, 5, 7]  = Liste les longueurs des listes
"""
# Liste section terminale 256 (128*2)
"""Nombre à évaluer : 180
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=avec listes, 2=listes>1µ. Votre choix = 2
origine : 180 . Appartient à la section :  256
. Les listes supérieures à une unité.
Dico =  [256, 128, 64, 32, 16, 8, 4, 2]     			 Longueur =  8
Dico =  [252, 126]     			 Longueur =  2
Dico =  [248, 124, 62]     			 Longueur =  3
Dico =  [244, 122]     			 Longueur =  2
Dico =  [240, 120, 60, 30]     			 Longueur =  4
Dico =  [236, 118]     			 Longueur =  2
Dico =  [232, 116, 58]     			 Longueur =  3
Dico =  [228, 114]     			 Longueur =  2
Dico =  [224, 112, 56, 28, 14]     			 Longueur =  5
Dico =  [220, 110]     			 Longueur =  2
Dico =  [216, 108, 54]     			 Longueur =  3
Dico =  [212, 106]     			 Longueur =  2
Dico =  [208, 104, 52, 26]     			 Longueur =  4
Dico =  [204, 102]     			 Longueur =  2
Dico =  [200, 100, 50]     			 Longueur =  3
Dico =  [196, 98]     			 Longueur =  2
Dico =  [192, 96, 48, 24, 12, 6]     			 Longueur =  6
Dico =  [188, 94]     			 Longueur =  2
Dico =  [184, 92, 46]     			 Longueur =  3
Dico =  [180, 90]     			 Longueur =  2
Dico =  [176, 88, 44, 22]     			 Longueur =  4
Dico =  [172, 86]     			 Longueur =  2
Dico =  [168, 84, 42]     			 Longueur =  3
Dico =  [164, 82]     			 Longueur =  2
Dico =  [160, 80, 40, 20, 10]     			 Longueur =  5
Dico =  [156, 78]     			 Longueur =  2
Dico =  [152, 76, 38]     			 Longueur =  3
Dico =  [148, 74]     			 Longueur =  2
Dico =  [144, 72, 36, 18]     			 Longueur =  4
Dico =  [140, 70]     			 Longueur =  2
Dico =  [136, 68, 34]     			 Longueur =  3
Dico =  [132, 66]     			 Longueur =  2

 Résultats Globaux
Origine =  180 . Appartient à la section :  256
Longueur terminale =  8  = L'exposant de 2
Nombre    listes =  64  = Le nombre total des listes
Partie    listes =  21  = Le nombre de parties trilog. Il reste =  0
Section   listes =  6  = La longueur de la plus grande sous-liste
Cap =  [1, 2, 3, 4, 5, 6, 8]  = Liste les longueurs des listes """

# Liste section terminale 512 (256*2)
"""Nombre à évaluer : 500
0=sans partiels, 1=avec partiels. Votre choix = 0
0=sans listes, 1=listes, 2=listes>1. Votre choix = 2
origine : 500 . Appartient à la section :  512
. Les listes supérieures à une unité.
Dico =  [512, 256, 128, 64, 32, 16, 8, 4, 2]   		 Terminale =  9
Dico =  [510]     			 Longueur =  1
Dico =  [508, 254]     			 Longueur =  2
Dico =  [506]     			 Longueur =  1
Dico =  [504, 252, 126]     			 Longueur =  3
Dico =  [502]     			 Longueur =  1
Dico =  [500, 250]     			 Longueur =  2
Dico =  [498]     			 Longueur =  1
Dico =  [496, 248, 124, 62]     			 Longueur =  4
Dico =  [494]     			 Longueur =  1
Dico =  [492, 246]     			 Longueur =  2
Dico =  [490]     			 Longueur =  1
Dico =  [488, 244, 122]     			 Longueur =  3
Dico =  [486]     			 Longueur =  1
Dico =  [484, 242]     			 Longueur =  2
Dico =  [482]     			 Longueur =  1
Dico =  [480, 240, 120, 60, 30]     			 Longueur =  5
Dico =  [478]     			 Longueur =  1
Dico =  [476, 238]     			 Longueur =  2
Dico =  [474]     			 Longueur =  1
Dico =  [472, 236, 118]     			 Longueur =  3
Dico =  [470]     			 Longueur =  1
Dico =  [468, 234]     			 Longueur =  2
Dico =  [466]     			 Longueur =  1
Dico =  [464, 232, 116, 58]     			 Longueur =  4
Dico =  [462]     			 Longueur =  1
Dico =  [460, 230]     			 Longueur =  2
Dico =  [458]     			 Longueur =  1
Dico =  [456, 228, 114]     			 Longueur =  3
Dico =  [454]     			 Longueur =  1
Dico =  [452, 226]     			 Longueur =  2
Dico =  [450]     			 Longueur =  1
Dico =  [448, 224, 112, 56, 28, 14]     			 Longueur =  6
Dico =  [446]     			 Longueur =  1
Dico =  [444, 222]     			 Longueur =  2
Dico =  [442]     			 Longueur =  1
Dico =  [440, 220, 110]     			 Longueur =  3
Dico =  [438]     			 Longueur =  1
Dico =  [436, 218]     			 Longueur =  2
Dico =  [434]     			 Longueur =  1
Dico =  [432, 216, 108, 54]     			 Longueur =  4
Dico =  [430]     			 Longueur =  1
Dico =  [428, 214]     			 Longueur =  2
Dico =  [426]     			 Longueur =  1
Dico =  [424, 212, 106]     			 Longueur =  3
Dico =  [422]     			 Longueur =  1
Dico =  [420, 210]     			 Longueur =  2
Dico =  [418]     			 Longueur =  1
Dico =  [416, 208, 104, 52, 26]     			 Longueur =  5
Dico =  [414]     			 Longueur =  1
Dico =  [412, 206]     			 Longueur =  2
Dico =  [410]     			 Longueur =  1
Dico =  [408, 204, 102]     			 Longueur =  3
Dico =  [406]     			 Longueur =  1
Dico =  [404, 202]     			 Longueur =  2
Dico =  [402]     			 Longueur =  1
Dico =  [400, 200, 100, 50]     			 Longueur =  4
Dico =  [398]     			 Longueur =  1
Dico =  [396, 198]     			 Longueur =  2
Dico =  [394]     			 Longueur =  1
Dico =  [392, 196, 98]     			 Longueur =  3
Dico =  [390]     			 Longueur =  1
Dico =  [388, 194]     			 Longueur =  2
Dico =  [386]     			 Longueur =  1
Dico =  [384, 192, 96, 48, 24, 12, 6]     			 Longueur =  7
Dico =  [382]     			 Longueur =  1
Dico =  [380, 190]     			 Longueur =  2
Dico =  [378]     			 Longueur =  1
Dico =  [376, 188, 94]     			 Longueur =  3
Dico =  [374]     			 Longueur =  1
Dico =  [372, 186]     			 Longueur =  2
Dico =  [370]     			 Longueur =  1
Dico =  [368, 184, 92, 46]     			 Longueur =  4
Dico =  [366]     			 Longueur =  1
Dico =  [364, 182]     			 Longueur =  2
Dico =  [362]     			 Longueur =  1
Dico =  [360, 180, 90]     			 Longueur =  3
Dico =  [358]     			 Longueur =  1
Dico =  [356, 178]     			 Longueur =  2
Dico =  [354]     			 Longueur =  1
Dico =  [352, 176, 88, 44, 22]     			 Longueur =  5
Dico =  [350]     			 Longueur =  1
Dico =  [348, 174]     			 Longueur =  2
Dico =  [346]     			 Longueur =  1
Dico =  [344, 172, 86]     			 Longueur =  3
Dico =  [342]     			 Longueur =  1
Dico =  [340, 170]     			 Longueur =  2
Dico =  [338]     			 Longueur =  1
Dico =  [336, 168, 84, 42]     			 Longueur =  4
Dico =  [334]     			 Longueur =  1
Dico =  [332, 166]     			 Longueur =  2
Dico =  [330]     			 Longueur =  1
Dico =  [328, 164, 82]     			 Longueur =  3
Dico =  [326]     			 Longueur =  1
Dico =  [324, 162]     			 Longueur =  2
Dico =  [322]     			 Longueur =  1
Dico =  [320, 160, 80, 40, 20, 10]     			 Longueur =  6
Dico =  [318]     			 Longueur =  1
Dico =  [316, 158]     			 Longueur =  2
Dico =  [314]     			 Longueur =  1
Dico =  [312, 156, 78]     			 Longueur =  3
Dico =  [310]     			 Longueur =  1
Dico =  [308, 154]     			 Longueur =  2
Dico =  [306]     			 Longueur =  1
Dico =  [304, 152, 76, 38]     			 Longueur =  4
Dico =  [302]     			 Longueur =  1
Dico =  [300, 150]     			 Longueur =  2
Dico =  [298]     			 Longueur =  1
Dico =  [296, 148, 74]     			 Longueur =  3
Dico =  [294]     			 Longueur =  1
Dico =  [292, 146]     			 Longueur =  2
Dico =  [290]     			 Longueur =  1
Dico =  [288, 144, 72, 36, 18]     			 Longueur =  5
Dico =  [286]     			 Longueur =  1
Dico =  [284, 142]     			 Longueur =  2
Dico =  [282]     			 Longueur =  1
Dico =  [280, 140, 70]     			 Longueur =  3
Dico =  [278]     			 Longueur =  1
Dico =  [276, 138]     			 Longueur =  2
Dico =  [274]     			 Longueur =  1
Dico =  [272, 136, 68, 34]     			 Longueur =  4
Dico =  [270]     			 Longueur =  1
Dico =  [268, 134]     			 Longueur =  2
Dico =  [266]     			 Longueur =  1
Dico =  [264, 132, 66]     			 Longueur =  3
Dico =  [262]     			 Longueur =  1
Dico =  [260, 130]     			 Longueur =  2
Dico =  [258]     			 Longueur =  1

 Résultats Globaux
Origine =  500 . Appartient à la section :  512
Longueur terminale =  9  = L'exposant de 2
Nombre    listes =  128  = Le nombre total des listes
Partie    listes =  42  = Le nombre de parties trilog. Il reste =  1
Section   listes =  7  = La longueur de la plus grande sous-liste
Cap =  [1, 2, 3, 4, 5, 6, 7, 9]  = Liste les longueurs des listes
"""

# Pied


# from Post.decorators import unauthenticated_user
from copy import error

from django import db, http
from django.contrib.auth import login
from django.core.checks.messages import ERROR
from django.db.models import query
from django.db.models.query import QuerySet
from django.dispatch.dispatcher import NONE_ID
from django.http import Http404, HttpResponse, JsonResponse
from django.http.response import HttpResponseGone
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.csrf import requires_csrf_token
from django.views.generic.base import View

# allows us to authenticate tokens from knox auth
from knox.auth import TokenAuthentication
from knox.models import User  # ****
from knox.models import AuthToken
from knox.views import LoginView as KnoxLoginView
from Post.models import Article
from Post.serializers import ArticleSerializer
from Post.views import ArticleViewSet
from rest_framework import (
    generics,
    mixins,
    permissions,
    relations,
    response,
    serializers,
    status,
    views,
    viewsets,
)
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import (
    APIView,
    api_view,
    authentication_classes,
    permission_classes,
)
from rest_framework.fields import to_choices_dict
from rest_framework.parsers import JSONParser
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.response import Response
from rest_framework.serializers import Serializer

# from .decorators import promoter_only
from .models import FollowerRelation, User, UserProfile
from .serializers import (
    ChangePasswordSerializer,
    ProfileEditSerializer,
    RegisterSerializer,
    UserProfileSerializer,
    UserSerializer,
    ViewUserProfileSerializer,
    followSerializer,
)

@api_view(["POST"])
@permission_classes([IsAuthenticated])
@authentication_classes([TokenAuthentication])
def followUser(request, *args, **kwargs):
    # a class to follow a another user
    is_following = False
    prof = request.data.get("profile")

    profile_ = UserProfile.objects.get(user_id=prof)
    profile_username = profile_.user

    user_ = User.objects.get(username=request.user)

    # check follower count of focused profile
    follower_count = profile_.followers.count()
    # check if user is in the list of followers of the profile.followers
    follower_list = profile_.followers.all()

    if user_ in follower_list:
        is_following = True

    if is_following == False:
        relation = FollowerRelation.objects.create(user=user_, profile=profile_)
        profile_.followers.add(user_)

        return Response(
            {
                "isFollowing": True,
                "followCount": follower_count,
                "response": f"{user_.username} followed {profile_username}",
            }
        )

    elif is_following == True:
        relation = FollowerRelation.objects.filter(
            user=user_, profile=profile_
        ).delete()
        profile_.followers.remove(user_)

        return Response(
            {
                "isFollowing": False,
                "followCount": follower_count,
                "response": f"{user_.username} unfollowed {profile_username}",
            }
        )

class ProfileAPI(viewsets.ViewSet):
    permission_classes = (IsAuthenticated,)
    authentication_classes = (TokenAuthentication,)

    def retrieve(self, request, pk=None):
        # print(pk)
        try:
            profile = UserProfile.objects.get(user=pk)
            user = request.user

            user_username = user.username
            str(user_username)
            if profile.user.username == user_username:

                UserSerializers = UserProfileSerializer(profile)
            else:
                UserSerializers = ViewUserProfileSerializer(
                    profile, context={"request": request, "pk": pk}
                )
            return Response(UserSerializers.data)
        except error:
            print(error)

    def update(self, request, pk=None):
        """
        update() is function of the Profile API, that allows users to edit their profile
        """
        try:
            user = request.user
            profile = UserProfile.objects.get(user=pk)
            # check if request is by by profile's user
            if user != profile.user:
                return HttpResponse("invalid credentials")
            else:
                serializers = ProfileEditSerializer(
                    profile, data=request.data, context={"request": request}
                )
                if serializers.is_valid():
                    serializers.save()
                # return Response(serializers.data, status=status.HTTP_201_CREATED)
            return Response(serializers.data)
        except (error):
            return HttpResponse(error)

class ProfilePostsAPI(viewsets.ViewSet):
    permission_classes = (IsAuthenticated,)
    authentication_classes = (TokenAuthentication,)

    def retrieve(self, request, pk=None):
        try:
            userProfile = UserProfile.objects.get(user=pk)
            userArticles = Article.objects.filter(author=userProfile)
            # userArticles = Article.objects.filter(author=user_)
            articleSerializer = ArticleSerializer(
                userArticles, many=True, context={"request": request}
            )

            return Response(articleSerializer.data)
        except error:
            print(error)

# Register API
#
###
class RegisterAPI(generics.GenericAPIView):

    serializer_class = RegisterSerializer

    def post(self, request, *args, **kwargs):
        user = None
        data = request.data

        serializer = self.get_serializer(data=data)

        if serializer.is_valid(raise_exception=True):

            user = serializer.create(data)
        else:
            print("invalid data")
        return Response(
            {
                # returns the given fields of UserSerializer
                "user": UserSerializer(
                    user, context=self.get_serializer_context()
                ).data,
                "token": AuthToken.objects.create(user)[1],
            }
        )

#
# LoginAPI
#
# #
class LoginAPI(KnoxLoginView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        serializer = AuthTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data["user"]
        login(request, user)

        return super(LoginAPI, self).post(request, format=None)

#
# ChangePasswordView
#
# #
class ChangePasswordView(generics.UpdateAPIView):
    """
    An endpoint for changing password.
    """

    serializer_class = ChangePasswordSerializer
    model = User
    permission_classes = (IsAuthenticated,)
    authentication_classes = (TokenAuthentication,)

    def get_object(self, queryset=None):
        obj = self.request.user
        return obj

    def update(self, request, *args, **kwargs):
        self.object = self.get_object()
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            # Check old password
            if not self.object.check_password(serializer.data.get("old_password")):
                return Response(
                    {"old_password": ["Wrong password."]},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            # set_password also hashes the password that the user will get
            self.object.set_password(serializer.data.get("new_password"))
            self.object.save()
            response = {
                "status": "success",
                "code": status.HTTP_200_OK,
                "message": "Password updated successfully",
                "data": [],
            }

            return Response(response)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


#!/usr/bin/python
# -*- coding:utf-8 -*-
# 评分/评论页面
import json
import math

from django.http.response import HttpResponse, HttpResponseRedirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
from GameModel.models import MagzineScores, Shelf, Magazines
from .util import *

active = "comment"
theme = "weui"

# 首页
def home(request):
    # 每个杂志一块，每块显示评分Top4的游戏
    magazines = Magazines.objects.filter(enable=True)
    data = {}
    review_ids = []
    for m in magazines:
        top4 = MagzineScores.objects.filter(magazine=m.title, gameId__gt=0).order_by("-score")[:4]
        data[m.title] = top4
        review_ids += map(lambda x: x.gameId, top4)

    # 获取评测的游戏标题、封图等
    games = Shelf.objects.filter(gameId__in=review_ids).only("gameId", "cover", "titleCh")

    # 游戏信息和杂志块发生关联
    game_cover = {}
    for game in games:
        game_cover[game.gameId] = json.loads(game.cover.replace('\'', '\"'), encoding="utf-8")[0]
    print(logo)
    # 评测信息和游戏信息不必捏合到一起，通过gameId可以访问game_data里的数据
    render_data = {
        "active": active, "magazines": data, "game_cover": game_cover,
        "logo": logo
    }
    return render(request, "weui/review/home.html", render_data)
    # return HttpResponse("test")

# 媒体评分
def magazine(request, magazine=""):
    # request数据
    get_data = request.GET.copy()
    page = get_data.setdefault("page", 1)

    # 根据游戏名查找评分 @TODO
    game_name = get_data.setdefault("g", "")
    # 根据得分范围查找评分 @TODO
    score_low = get_data.setdefault("low", 1)
    score_high = get_data.setdefault("high", 10)

    # 获取数据
    size = 10
    filters = {"gameId__gt": 0}
    if len(magazine):
        filters["magazine"] = magazine
    if len(game_name):
        #@TODO 根据游戏名查找ID
        pass
    if score_low > 0:
        # filter["score"]
        pass

    mag_obj = MagzineScores()
    # magzines = MagzineScores.objects.filter(**filters)[offset:size]
    data_list = MagzineScores.objects.filter(**filters).order_by("-score")
    # 分页
    paginator = Paginator(data_list, size)
    try:
        current_page_data = paginator.page(page)
    except PageNotAnInteger:
        current_page_data = paginator.page(1)
    except EmptyPage:
        current_page_data = paginator.page(paginator.num_pages)

    template = "weui/review/magazine.html"
    if theme == "bootstrap":
        template = "bootstrap/comment/magazine.html"

    # 获取评测所属游戏
    for item in current_page_data.object_list:
        shelf = Shelf.objects.filter(gameId=item.gameId).first()
        if shelf is not None:
            shelf.cover = shelf.cover.replace("\'", "\"")
            cover = json.loads(shelf.cover, encoding="utf-8")[0]
            item.__setattr__("shelf_cover", cover)
        else:
            item.__setattr__("shelf_cover", "/static/image/ns.png")

    page_range = range(1, paginator.num_pages+1)
    if paginator.num_pages > 6:
        page_range = range(1, 6+1)
    if current_page_data.number > 3:
        page_range = range(current_page_data.number - 3, current_page_data.number + 3)

    render_data = {
        "active": active,
        "list": current_page_data.object_list,
        "page_count": paginator.num_pages,
        "page_range": page_range,
        "current_page": current_page_data,
        "magzines": mag_obj.getMagzineNames(),
        "logo": logo,
        "magazine_title": magazine
    }

    return render(request, template, render_data)

# 根据游戏id获取评测
def review(request, pk):
    current_action = "review"

    if pk != 0:
        review = MagzineScores.objects.filter(id=pk).first()
        game = None
        if review.gameId != 0:
            game = Shelf.objects.filter(gameId=review.gameId).first()
            # 如果数据库里没有关联或gameId查不到，跳转到原url吧。。。
            if game is None:
                return HttpResponseRedirect(review.url)

            game.cover = json.loads(game.cover.replace("\'", "\""))[0]

        render_data = {
            "active": active,
            "review": review,
            "game": game,
            "breadcrumb": breadcrumb(current_action, gameId=review.gameId),
            "logo": logo,
        }

        if theme == "weui":
            template = "weui/review/game.html"
        else:
            template = "comment/review.html"

        return render(request, template, render_data)
    else:
        return HttpResponse("请求的游戏ID不存在！")

# 用户评分（@TODO）
def member(request):
    pass


import hashlib
import time
import urllib.request as urlrequest
import json

class RiskCheckDemo(object):
    """本接口的功能是智能风控明细数据查询，主要用于数据同步：从易盾拉取数据场景，以固定时间窗口拉取数据。
       例如，每次查询1分钟前的数据，时间跨度也是1分钟，则可以按1分钟时间窗口，周期性滑动拉取数据。"""

    API_URL = "http://ir-open.dun.163.com/v5/risk/detail"

    def __init__(self, secret_id, secret_key, business_id, version):
        """
        Args:
            secret_id (str) 产品id，每个应用接入时，会分配secretId和私钥secretKey。
            secret_key (str) 产品密钥，每个应用接入时，会分配secretId和私钥secretKey。
            business_id (str) 每个业务接入时，均会分配业务 ID
            version (str) 版本号，如500
        """
        self.secret_id = secret_id
        self.secret_key = secret_key
        self.business_id = business_id
        self.version = version

    def gen_signature(self, params):
        buff = ""
        for k in sorted(params.keys()):
            buff += str(k) + str(params[k])
        buff += self.secret_key
        return hashlib.md5(buff.encode("utf8")).hexdigest()

    def check(self, params):
        """请求易盾接口
        Args:
            params (object) 请求参数
        Returns:
            请求结果，json格式
        """
        params["secretId"] = self.secret_id
        params["businessId"] = self.business_id
        params["version"] = self.version
        params["timestamp"] = int(time.time() * 1000)
        # 随机码，32位
        params["nonce"] = "mmm888f73yyy59440583zzz9bfcc79de"
        params["signature"] = self.gen_signature(params)

        try:
            headers = {"Content-Type": 'application/json'}
            params = json.dumps(params)
            params = bytes(params, 'utf8')
            request = urlrequest.Request(url=self.API_URL, data=params, headers=headers)
            content = urlrequest.urlopen(request, timeout=1).read()
            return json.loads(content)
        except Exception as ex:
            print("调用API接口失败:", str(ex))

if __name__ == "__main__":
    """示例代码入口"""
    SECRET_ID = "your_secret_id"
    SECRET_KEY = "your_secret_key"
    BUSINESS_ID = "your_business_id"
    VERSION = "500"
    api = RiskCheckDemo(SECRET_ID, SECRET_KEY, BUSINESS_ID, VERSION)

    params = {
        "beginTimestamp": 1667959831798,
        "endTimestamp": 1667959915103,
        # 用于分页查询的关联标记。
        "startFlag": "",
        # 用户/玩家的账号
        "account": "zzzzzzz",
        # 用户/玩家的角色ID
        "roleId": "yyyyyyy",
        # 风险等级, 1-低风险, 2-中风险, 3-高风险
        "riskLevel": 1,
        # 包名(仅限Android/iOS平台)
        "packageName": "com.aaa.bbb",
        # app版本(仅限Android/iOS平台)
        "appVersion": "1.0.2",
        # 用户/ 玩家的IP，或当前客户端业务事件发生时的公网IP地址（ipv4）
        "ip": "192.168.1.1"
    }

    ret = api.check(params)

    code: int = ret["code"]
    msg: str = ret["msg"]
    if code == 200:
        print("msg=%s, data=%s" % (msg, ret["data"]))
    else:
        print("ERROR: code=%s, msg=%s" % (ret["code"], ret["msg"]))


from cgi import test
import os
import json

class Data:
    def __init__(self, trainPath, testPath, valPath):
        self.train = self.readFile(trainPath)
        self.val = self.readFile(valPath)
        self.test = self.readFile(testPath)

    def readFile(self, path):
        with open(os.path.join(os.getcwd(), path), 'r') as f:
            return json.loads(f.read())


people_count = int(input('Введите количество человек: '))
genealogical_tree = dict()
height = dict()

for i_couple in range(people_count - 1):
    couple = input(f'{i_couple + 1} пара: ').split()
    if i_couple == 0:
        height[couple[1]] = 0
        height[couple[0]] = 1
    else:
        height[couple[0]] = height[couple[1]] + 1

print('\n«Высота» каждого члена семьи:')
for i_height in sorted(height):
    print(i_height, height[i_height])


print("Import Sequence Initiated...")
import os
import librosa   #for audio processing
#import IPython.display as ipd
import matplotlib.pyplot as plt
import numpy as np
from scipy.io import wavfile #for audio processing
#print('A')
#print ('Hi')
#print ('Audio 1: Harshitha "a"')
#print ('Audio 2: Anant "a"')
f1=input("FILE 1:")
f2=input("FILE 2:")

#from os import listdir
#from os.path import isfile, join
#mypath='C://Users//Anant//Downloads//F//F01//Session1'
#onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
#print(onlyfiles)

print("Import Sequence Completed...")
path = 'D://mpstme//SEM 7//PROJECT//Datasets//Control//Male//MC01'

files1 = [f1]
files2 = [f2]
# r=root, d=directories, f = files
# for r, d, f in os.walk(path):
#     for file in f:
#         if '.wav' in file:
#             files1.append(os.path.join(r, file))
# print("DIR 1 Imported")
# path = 'D://mpstme//SEM 7//PROJECT//Datasets//Control//Male//MC02'
# for r, d, f in os.walk(path):
#     for file in f:
#         if '.wav' in file:
#             files2.append(os.path.join(r, file))
# print("DIR 2 Imported")
m=-1
for f1 in files1:
    for i in range (1):
        m=m+1
        f2=files2[m]

        samples, sample_rate = librosa.load(f1, sr = 16000)
        #print(samples)
        #print(sample_rate)
        samples = librosa.resample(samples, sample_rate, 8000)
        #print(samples)
        #print("No of samples (audio 1):",len(samples))
        l1=len(samples)
        #for i in range(10):
        #    print (samples[i])
        #fig = plt.figure(figsize=(14, 8))
        #ax1 = fig.add_subplot(211)
        #a=np.linspace(0, sample_rate/len(samples), 8000)
        #print(a)
        #ax1.plot(np.linspace(0, sample_rate/len(samples), sample_rate), samples)
        #ax1.plot(np.linspace(0, sample_rate,num=len(samples)), samples)
        #print(np.linspace(0, sample_rate, num=len(samples)).shape)
        #print(samples.shape)
        #plt.show()
        #print("zfdv")

        samples2, sample_rate2 = librosa.load(f2, sr = 16000)
        samples2 = librosa.resample(samples2, sample_rate2, 8000)
        #print("No of samples (audio 2):",len(samples2))
        l2=len(samples2)
        #print(type(samples2))
        m1=samples.max()
        m2=samples2.max()
        s3=[]
        s4=[]
        s5=[]
        #l1=100
        #l2=100
        for i in range(l1):
            s3.append(samples[i]/m1)
        for j in range(l2):

            s4.append(samples2[j]/m2)
        #print(s3)
        #print(s4)
        g=0
        h=0
        while(s4[g]<0):
            s4.pop(g)
        while(s3[h]<0):
            s3.pop(h)
        #print(s3)
        #print(s4)

        if(len(s3)<len(s4)):
            a=len(s3)
        else:
            a=len(s4)

        for k in range(a):
            if(abs(s3[k]-s4[k])<0.1):
                s5.append(1)
            else:
                s5.append(0)

        sums=sum(s5)
        c=100*(sums/l1)
        print("File 1"+str(f1))
        print("File 2"+str(f2))
        print("Percentage similarity:",c)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import cv2
import numpy as np
import tensorflow as tf
import tensorflow.python.platform
import pickle

NCLASS = 10
NSIZE = 32
NDATA = NSIZE * NSIZE * 3
NUNITS = [NDATA, 500, 300, 200, 150, 100, 60, 40, 30, NCLASS]
EPOCH = 100
MBATCH = 100
LEARNING_RATE = 0.05
DATASET = 'CIFAR-10'
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('train', 'train.txt', 'File name of train data')
flags.DEFINE_string('test', 'test.txt', 'File name of train data')
flags.DEFINE_string('train_dir', '/tmp/data', 'Directory to put the training data.')
flags.DEFINE_integer('max_steps', 200, 'Number of steps to run trainer.')
flags.DEFINE_integer('batch_size', 10, 'Batch size'
                     'Must divide evenly into the dataset sizes.')
flags.DEFINE_float('learning_rate', 1e-4, 'Initial learning rate.')

def unpickle(file):
    fp = open(file, 'rb')
    if sys.version_info.major == 2:
        data = pickle.load(fp)
    elif sys.version_info.major == 3:
        data = pickle.load(fp, encoding='latin-1')
    fp.close()

    return data

# ラベル名をロード
label_names = unpickle("../datasets/data/cifar10/cifar-10-batches-py/batches.meta")["label_names"]
d = unpickle("../datasets/data/cifar10/cifar-10-batches-py/data_batch_1")
data = d["data"]
labels = np.array(d["labels"])
nsamples = len(data)

print(label_names)


import pandas as pd
from sklearn import metrics
import numpy as np
import matplotlib.pyplot as plt

label_result = pd.read_csv('HW_AI/HW_Final/label.csv')
label_result = label_result.iloc[:,1]
label_result = label_result.to_numpy()
cpu_result = pd.read_csv('HW_AI/HW_Final/cpu.csv')
cpu_result = cpu_result.iloc[:,1]
cpu_result = cpu_result.to_numpy()
cpu_result = cpu_result.astype(np.int32)
gpu_result = pd.read_csv('HW_AI/HW_Final/gpu.csv')
gpu_result = gpu_result['label'].to_numpy()

label_cpu_mutual = metrics.adjusted_mutual_info_score(label_result, cpu_result)
label_gpu_mutual = metrics.adjusted_mutual_info_score(label_result, gpu_result)
cpu_gpu_mutual = metrics.adjusted_mutual_info_score(cpu_result, gpu_result)
print(cpu_result)
print(gpu_result)
print(label_cpu_mutual)
print(label_gpu_mutual)
print(cpu_gpu_mutual)

cpu_time = [1.4,14.5,1170.2]
gpu_time = [0.97, 0.16, 0.32]

x = [1,2]
read = [1.4, 0.97]
build_graph = [15.9, 1.13]
louvain = [1186.1, 1.45]

plt.barh(x, read, label = 'Read_Files')
plt.barh(x, build_graph, label = 'Build Graph')
plt.barh(x, louvain, label = 'Louvain_Modularity')
plt.yticks([1,2],['Cpu', 'Gpu'])
plt.title('Time compare')
plt.xlabel('Time')
plt.ylabel('Device')
plt.legend(loc = 'best')
plt.show()


EPOCH_MAX = 5000
GRAPH_DIR = "../data/graph"
TRAIN_BATCH_RATIO = 0.05
TRAIN_RATIO = 0.5
BC_TH = 0.5
# Used for visualization
EPS = 1e-6

GTYPES = None

OPT = "ADAM" # "SGD"


import requests
from haversine import haversine

from config import api_key, home

LOC_HOME = [float(x) for x in home.split(",")]

def get_loc_weather(loc):
    degree_sign = "\N{DEGREE SIGN}"
    condition_url = f"https://api.aerisapi.com/observations/{loc}?&format=json&filter=allstations&limit=1&{api_key}"
    resp = requests.get(condition_url).json()
    observation = resp["response"]["ob"]
    condition = observation["weatherShort"]
    temp_cel = str(observation["tempC"]) + degree_sign + "C"
    humidity = str(observation["humidity"]) + " %"
    wind_spe = str(observation["windKPH"]) + " kmph"
    wind_dir = str(observation["windDirDEG"]) + degree_sign
    full_location = str(resp["response"]["place"]["name"]).capitalize()
    print(
        f"The current conditions in {full_location} are:",
        f"Temeprature : {temp_cel}",
        f"Condition   : {condition}",
        f"Humidity    : {humidity}",
        f"Wind Speed  : {wind_spe}",
        f"Wind Dir.   : {wind_dir}",
        sep="\n"
    )

def get_weather(loc):
    co_ors = []
    index = 1
    lookup_url = f"https://api.aerisapi.com/places/search?query=name:{loc}&limit=10&{api_key}"
    geolookup = requests.get(lookup_url)
    places = geolookup.json()["response"]
    if not places:
        print("Location lookup failed")
        return
    for place in places:
        coor = [place["loc"]["lat"], place["loc"]["long"]]
        co_ors.append(coor)
        how_far = round(haversine(coor, LOC_HOME), ndigits=2)
        city = place["place"]["name"]
        country = place["place"]["countryFull"]
        print(index, city, "({})".format(country), how_far, "km")
        index += 1
    choice = int(input("Enter location: "))
    get_loc_weather(co_ors[choice - 1])

def conditions():
    selection = input("Enter City Name:")
    if selection.lower() == "h":
        get_loc_weather(home)
    else:
        get_weather(selection)

if __name__ == "__main__":
    conditions()


from ....General.Auxiliary_General.linearize_values import linearize_values

def aggregate_technologies_info(object_id, technologies, power_fraction, max_power_available, max_power_convertible,
                                object_type, teo_equipment_name, stream_id):

    """ Aggregate conversion technologies and compute data for TEO

    Parameters
    ----------
    object_id : str
        Source/sink ID or 'grid_specfic'

    technologies : list with dicts
        Technologies data

    power_fraction : float
        Design equipment for max and fraction power; value between 0 and 1 []

    max_power_available : float
        Stream max power available before conversion (source-wise) [kW]
        This is the power before any conversion

    max_power_convertible : float
        Stream power given to the the DHN after conversion (source-wise) [kW]
        This is the power after all conversion

    object_type : str
        'sink' or 'source'

    teo_equipment_name : str
        Specific TEO nomenclature for the technology name

    stream_id : int, str
        Stream ID

    Returns
    -------
    data_teo : dict
        technologies data for the TEO module, with the following keys:

        - teo_equipment_name : str
            Specific nomenclature for the TEO

        - output : str
            Specific nomenclature for the TEO

        - input_fuel : str
            Specific nomenclature for the TEO

        - output_fuel : str
            Specific nomenclature for the TEO

        - equipment : list
            All conversion equipments; list with technologies names; e.g. ['hx_plate', 'heat_pump','hx_plate']

        - max_capacity : float
            Stream power (sources- excess heat; sinks - grid heat)  [kW]

        - turnkey_a : float
            Aggregated turnkey [€/kW]

        - turnkey_b : float
            Aggregated om_var [€]

        - conversion_efficiency :
            Aggregated conversion_efficiency []

        - electrical_conversion_efficiency : float
            ONLY FOR ORC - electrical conversion efficiency []

        - om_fix : float
            Aggregated om_fix [€/year.kW]

        - om_var : float
            Aggregated om_var [€/kWh]

        - emissions : float
            Aggregated emissions [kg.CO2/kWh]

        - technologies : list with dicts
            Each equipment info in detail (check General/Convert_Equipments/Convert_Options)

    """

    turnkey_max_power = 0
    turnkey_power_fraction = 0
    om_fix = 0
    om_var = 0
    emissions = 0
    max_supply_capacity = 0
    all_equipment = []
    technologies_dict = []

    if object_type == 'sink':
        if object_id == 'grid_specific':
            input_fuel = None
        else:
            if teo_equipment_name.find('hp') == 0 or teo_equipment_name.find('absorption_chiller') == 0:
                input_fuel = 'dhnwaterdemand'  # + electricity
            else:
                input_fuel = 'dhnwaterdemand'

        if object_id == 'grid_specific':
            output_fuel = 'dhnwatersupply'
        else:
            output_fuel = 'sink' + str(object_id) + 'str' + str(stream_id) + 'dem'

    else:
        if teo_equipment_name.find('hp') == 0:
            input_fuel = "eh" + 'str' + str(stream_id) + 'sou' + str(object_id)  # + electricity
        else:
            input_fuel = "eh" + 'str' + str(stream_id) + 'sou' + str(object_id)

        if teo_equipment_name.find('orc') == 0 or teo_equipment_name.find('chp') == 0:
            output_fuel = 'dhnwatersupply'  # + electricity
        else:
            output_fuel = 'dhnwatersupply'

    for technology in technologies:
        technologies_dict.append(technology.__dict__)
        all_equipment.append(technology.data_teo['equipment'])

        max_supply_capacity_val = (
            technology.data_teo['max_average_supply_capacity']
            if technology.data_teo['equipment'] in ('fresnel', 'evacuated_tube', 'flat_plate')
            else technology.data_teo['max_input_capacity']
        )

        turnkey_max_power += max_supply_capacity_val * technology.data_teo['turnkey_a'] + technology.data_teo['turnkey_b']
        turnkey_power_fraction += max_supply_capacity_val * power_fraction * technology.data_teo['turnkey_a'] + technology.data_teo['turnkey_b']

        om_fix += technology.data_teo['om_fix'] * max_supply_capacity_val
        om_var += technology.data_teo['om_var'] * max_supply_capacity_val
        emissions += technology.data_teo['emissions'] * max_supply_capacity_val

    power_fraction_supply_capacity = max_power_available * power_fraction
    conversion_efficiency = max_power_convertible/max_power_available
    turnkey_a, turnkey_b = linearize_values(turnkey_max_power, turnkey_power_fraction, max_power_available, power_fraction_supply_capacity)

    # TEO CHANGES FOR THE NAMES
    teo_equipment_name = (
        f'grid_specific_{teo_equipment_name}'
        if object_type == 'sink' and object_id == 'grid_specific'
        else f'{object_type}_{object_id}_str{stream_id}_{teo_equipment_name}'
    )
    teo_equipment_name = teo_equipment_name.replace('_', '')

    if object_id == 'grid_specific':
        gs_cost = 10 ** 6
        data_teo = {
            'teo_equipment_name': teo_equipment_name,
            'output': 1,
            'input_fuel': input_fuel,
            'output_fuel': output_fuel,
            'equipment': all_equipment,
            'max_capacity': max_power_convertible,  # [kW]
            'turnkey_a': round(turnkey_a, 3),  # [€/kW]
            'turnkey_b': round(turnkey_b, 3),  # [€]
            'conversion_efficiency': round(conversion_efficiency, 3),  # []
            'om_fix': round(om_fix / max_power_convertible, 3) * gs_cost,  # [€/year.kW]
            'om_var': (om_var / max_power_convertible) * gs_cost,  # [€/kWh]
            'emissions': round(emissions / max_power_convertible, 3),  # [kg.CO2/kWh]
            'technologies': technologies_dict,
        }
        return data_teo

    data_teo = {
        'teo_equipment_name': teo_equipment_name,
        'output': 1,
        'input_fuel': input_fuel,
        'output_fuel': output_fuel,
        'equipment': all_equipment,
        'max_capacity': max_power_convertible,  # [kW]
        'turnkey_a': round(turnkey_a, 3),  # [€/kW]
        'turnkey_b': round(turnkey_b, 3),  # [€]
        'conversion_efficiency': round(conversion_efficiency, 3),  # []
        'om_fix': round(om_fix / max_power_convertible, 3),  # [€/year.kW]
        'om_var': om_var / max_power_convertible,  # [€/kWh]
        'emissions': round(emissions / max_power_convertible, 3),  # [kg.CO2/kWh]
        'technologies': technologies_dict,
    }

    if 'orc' in teo_equipment_name:
        for technology in technologies:
            if technology.data_teo['equipment'] == 'orc':
                electrical_conversion_efficiency = technology.data_teo.get('electrical_conversion_efficiency', 0)
                data_teo['electrical_conversion_efficiency'] = round(electrical_conversion_efficiency, 3)

    return data_teo


from crashtec.db.schema.types import DBSchemaTypes

TASKS_TABLE ='tasks'
TASKS_DUMP_FILE_FIELD = 'dump_file_name'
TASKS_PROBLEM_ID = 'problem_id'
TASKS_PLATFORM_FIELD = 'platform'
TASKS_PROBLEM_CLASS = 'problem_class'
TASKS_SYMBOL_NAME = 'symbol_name'
TASKS_FAIL_IMAGE = 'failure_image_name'
TASKS_FAILURE_BUCKET_ID = 'failure_bucket_id'
TASKS_SYMBOLS_PATH = 'symbols_path'

_task = {
            TASKS_DUMP_FILE_FIELD : DBSchemaTypes.long_string(),
            TASKS_PROBLEM_ID : DBSchemaTypes.short_string(),
            TASKS_PLATFORM_FIELD : DBSchemaTypes.short_string(),
            TASKS_PROBLEM_CLASS: DBSchemaTypes.short_string(),
            TASKS_SYMBOL_NAME : DBSchemaTypes.long_string(),
            TASKS_FAIL_IMAGE : DBSchemaTypes.short_string(),
            TASKS_FAILURE_BUCKET_ID : DBSchemaTypes.long_string(),
            TASKS_SYMBOLS_PATH : DBSchemaTypes.long_string()
        }

RAWRESULTS_TABLE = 'raw_results'
RAWRESULTS_TASK_ID = 'task_id'
RAWRESULTS_DBG_OUTPUT = 'debugger_output'

_raw_results = {
                RAWRESULTS_TASK_ID : DBSchemaTypes.int(),
                RAWRESULTS_DBG_OUTPUT : DBSchemaTypes.text_file()
               }

model = {TASKS_TABLE:_task, RAWRESULTS_TABLE:_raw_results}


import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QApplication, QMainWindow, QShortcut

class Ui_Output_Ui(QMainWindow):
	resized = QtCore.pyqtSignal()

	def __init__(self, icon_path=''):
		super(Ui_Output_Ui, self).__init__()

		if icon_path != '':
			self.setWindowIcon(QtGui.QIcon(icon_path))

		self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)  # Делаю окно поверх всех окон
		self.setObjectName("Output_Ui")

		self.textBrowser = QtWidgets.QTextBrowser(self)
		self.textBrowser.setGeometry(QtCore.QRect(0, 0, 0, 0))
		self.textBrowser.setObjectName("textBrowser")

		self.close_shortcut = QShortcut(QKeySequence("Esc"), self) # Выход при 'esc'
		self.close_shortcut.activated.connect(self.close)

		self.resized.connect(self.resize_textBrowser) # Делаю ивент на изменение размера окна

	def	setText(self, text: str, point_size: int, font_family:str):
		font = self.font()
		font.setPointSize(point_size) # Делаю шрифт нужного размера
		font.setFamily(font_family)
		self.setWindowTitle("TS2_Output")
		self.textBrowser.setText(text)
		self.textBrowser.setFont(font)

	def resizeEvent(self, event):
		self.resized.emit()
		return super(Ui_Output_Ui, self).resizeEvent(event)

	def resize_textBrowser(self):
		self.textBrowser.setGeometry(QtCore.QRect(0, 0, self.size().width(), self.size().height())) #Устанавливаю размер textBrowser как у окна

if __name__ == '__main__':
	app = QApplication(sys.argv)

	Output_Ui = Ui_Output_Ui()

	Output_Ui.setText('тестовый текст', 10)
	Output_Ui.resize(100, 200)
	Output_Ui.move(0, 0)

	Output_Ui.show()

	sys.exit(app.exec_())


import tkinter
import PIL.Image
import PIL.ImageTk
from tkinter import *
from tkinter.font import Font
from tkinter.ttk import *

def UkIndividual(window, canvas):
    soleil = Font(family="Soleil", size=26)
    lato = Font(family="Lato", size=18)

    style = Style()
    style.configure("Next.TButton", background='#6558F5', foreground='#020202', font=lato)
    style.configure("Exit.TButton", background='#D3455B', foreground='#020202', font=lato)
    style.configure("Main.TCheckbutton", font=lato, foreground='#020202', background='#EDEDF3')

    def UkIndExitButton():
        window.destroy()

    def UkIndNextButton():
        canvas.delete("all")
        chk1.place(x=-1000, y=-1000)
        chk2.place(x=-1000, y=-1000)
        chk3.place(x=-1000, y=-1000)
        nextBtn.place(x=-1000, y=-1000)
        x = varTrue()
        if x == 1:
            canvas.create_text(640, 100, text="You are eligible for 80% of your salary\nup to a maximum of £625 per week.\n(Paid as a lump sum payment every 3 months).", justify=CENTER, fill='#020202', font=soleil)
        elif x == 2:
            canvas.create_text(640, 100, text="You are eligible for 80% of your average\nmonthly profits for the last three years up to a maximum of £625 per week.\n(Paid as a lump sum payment every 3 months).", justify=CENTER, fill='#020202', font=soleil)
        elif x == 3:
            canvas.create_text(640, 100, text="You are ineligible for any COVID-19 financial aid.", justify=CENTER, fill='#020202', font=soleil)
        canvas.create_text(388, 660, text="Progress: 100%", justify=LEFT, fill='#020202', font=lato)
        canvas.create_rectangle(320, 680, 960, 695, fill='#90929C', outline='#90929C')
        canvas.create_rectangle(320, 680, 960, 695, fill='#6558F5', outline='#6558F5')
        exitBtn.place(x=560, y=575)

    def varTrue():
        if var1.get() == 1 and var2.get() == 0 and var3.get() == 1:
            return 1
        elif var1.get() == 0 and var2.get() == 1 and var3.get() == 1:
            return 2
        elif var1.get() == 1 and var2.get() == 1 and var3.get() == 1:
            return 2
        else:
            return 3

    canvas.create_text(640, 100, text="A British individual? Awesome.\nPlease check any boxes that are relevant to you.", justify=CENTER, fill='#020202', font=soleil)

    var1 = IntVar()
    chk1 = Checkbutton(canvas, text='Work in the private sector full-time or part-time.', variable=var1, style='Main.TCheckbutton')
    chk1.place(x=350, y=200)

    var2 = IntVar()
    chk2 = Checkbutton(canvas, text='Self-employed and had a loss of income.', variable=var2, style='Main.TCheckbutton')
    chk2.place(x=350, y=250)

    var3 = IntVar()
    chk3 = Checkbutton(canvas, text='Pay tax through the Pay-As-You-Earn (PAYE) system.', variable=var3, style='Main.TCheckbutton')
    chk3.place(x=350, y=300)

    nextBtn = Button(canvas, text='FINISH', style='Next.TButton', command=UkIndNextButton)
    nextBtn.place(x=715, y=575);

    exitBtn = Button(canvas, text='EXIT', style='Exit.TButton', command=UkIndExitButton)
    exitBtn.place(x=400, y=575);

    canvas.create_text(388, 660, text="Progress: 40%", justify=LEFT, fill='#020202', font=lato)
    canvas.create_rectangle(320, 680, 960, 695, fill='#90929C', outline='#90929C')
    canvas.create_rectangle(320, 680, 576, 695, fill='#6558F5', outline='#6558F5')