import pytest

from rnalysis.utils.parsing import *
from rnalysis.utils.parsing import _parse_r_arg

class DummyClass:
    def __init__(self):
        pass

    def __eq__(self, other):
        return type(self) == type(other)

@pytest.mark.parametrize('is_input_path', [True, False])
@pytest.mark.parametrize('path,expected_path', [
    ('file.csv', 'file'),
    ('path/to/file.exe', 'path/to/file'),
    ('name.fastq.gz', 'name'),
    ('path/to/a/filename.sam.tar.gz', 'path/to/a/filename'),
])
def test_remove_suffixes(path, expected_path, is_input_path):
    if is_input_path:
        assert remove_suffixes(Path(path)) == Path(expected_path)
    else:
        assert remove_suffixes(path) == expected_path

@pytest.mark.parametrize('input_val,sort,truth',
                         [([1, 2, 'hi'], False, [1, 2, 'hi']),
                          ((1, 2, 'hi'), False, [1, 2, 'hi']),
                          ('fifty seven brave men', False, ['fifty seven brave men']),
                          ('fifty seven brave men', True, ['fifty seven brave men']),
                          ({'three', 'different', 'elements'}, True, ['different', 'elements', 'three']),
                          (np.array([6, 9, 2]), False, [6, 9, 2]),
                          (np.array([6, 9, 2]), True, [2, 6, 9]),
                          (DummyClass(), False, [DummyClass()]),
                          (None, False, [None])])
def test_data_to_list(input_val, sort, truth):
    assert data_to_list(input_val, sort=sort) == truth

@pytest.mark.parametrize('input_val,sort,truth',
                         [([1, 2, 'hi'], False, (1, 2, 'hi')),
                          ((1, 2, 'hi'), False, (1, 2, 'hi')),
                          ('fifty seven brave men', False, ('fifty seven brave men',)),
                          ('fifty seven brave men', True, ('fifty seven brave men',)),
                          ({'three', 'different', 'elements'}, True, ('different', 'elements', 'three')),
                          (np.array([6, 9, 2]), False, (6, 9, 2)),
                          (np.array([6, 9, 2]), True, (2, 6, 9)),
                          (67.2, False, (67.2,)),
                          ((67.2,), False, (67.2,)),
                          ((67.5,), True, (67.5,)),
                          (DummyClass(), False, (DummyClass(),)),
                          (None, False, (None,))])
def test_data_to_tuple(input_val, sort, truth):
    assert data_to_tuple(input_val, sort=sort) == truth

@pytest.mark.parametrize('val,expected', [
    ([1, 2, 'hi'], {1, 2, 'hi'}),
    ((1, 2, 'hi'), {1, 2, 'hi'}),
    ('fifty seven brave men', {'fifty seven brave men'}),
    ({'three', 'different', 'elements'}, {'three', 'different', 'elements'}),
    (np.array([6, 9, 2]), {6, 9, 2}),
    (67.2, {67.2}),
    (None, {None}),
])
def test_data_to_set(val, expected):
    assert data_to_set(val) == expected

def test_from_string(monkeypatch):
    monkeypatch.setattr('builtins.input', lambda x: 'one\t\ntwo \nthree; and four\n')
    assert from_string() == ['one\t', 'two ', 'three; and four']
    assert from_string(del_spaces=True) == ['one\t', 'two', 'three;andfour']

def test_uniprot_tab_to_dict():
    tab = 'From\tTo\nWBGene00019883\tP34544\nWBGene00023497\tQ27395\nWBGene00003515\tP12844\nWBGene00000004\t' \
          'A0A0K3AVL7\nWBGene00000004\tO17395\n'
    tab_rev = 'From\tTo\nP34544\tWBGene00019883\nQ27395\tWBGene00023497\nP12844\tWBGene00003515\nA0A0K3AVL7\t' \
              'WBGene00000004\nO17395\tWBGene00000004\n'

    truth = ({'WBGene00019883': 'P34544', 'WBGene00023497': 'Q27395', 'WBGene00003515': 'P12844'},
             ['A0A0K3AVL7', 'O17395'])
    truth_rev = ({'P34544': 'WBGene00019883', 'Q27395': 'WBGene00023497', 'P12844': 'WBGene00003515',
                  'A0A0K3AVL7': 'WBGene00000004', 'O17395': 'WBGene00000004'}, [])
    assert truth == uniprot_tab_to_dict(tab)

    assert truth_rev == uniprot_tab_to_dict(tab_rev)

def test_uniprot_tab_to_dict_empty():
    tab = 'From\tTo\n'
    assert uniprot_tab_to_dict(tab) == ({}, [])

def test_uniprot_tab_with_score_to_dict_empty():
    tab = 'Entry\tAnnotation\tyourlist:M20200816216DA2B77BFBD2E6699CA9B6D1C41EB2A5FE6AF\n'
    assert uniprot_tab_with_score_to_dict(tab) == {}
    assert uniprot_tab_with_score_to_dict(tab, True) == {}

def test_uniprot_tab_with_score_to_dict():
    tab = 'Entry\tAnnotation\tyourlist:M20200816216DA2B77BFBD2E6699CA9B6D1C41EB2A5FE6AF\nP34544\t5 out of 5\t' \
          'WBGene00019883\nQ27395\t4 out of 5\tWBGene00023497\nP12844\t5 out of 5\tWBGene00003515\nA0A0K3AVL7\t' \
          '1 out of 5\tWBGene00000004\nO17395\t2 out of 5\tWBGene00000004\n'

    truth = {'WBGene00019883': 'P34544', 'WBGene00023497': 'Q27395', 'WBGene00003515': 'P12844',
             'WBGene00000004': 'O17395'}
    truth_rev = {'P34544': 'WBGene00019883', 'Q27395': 'WBGene00023497', 'P12844': 'WBGene00003515',
                 'A0A0K3AVL7': 'WBGene00000004', 'O17395': 'WBGene00000004'}
    assert truth == uniprot_tab_with_score_to_dict(tab)

    assert truth_rev == uniprot_tab_with_score_to_dict(tab, True)

def test_sparse_dict_to_bool_df():
    truth = pd.read_csv('tests/test_files/sparse_dict_to_df_truth.csv', index_col=0).sort_index(axis=1)
    sparse_dict = {'gene1': {'a', 'c'}, 'gene2': {'b'}, 'gene3': {'b', 'g', 'h'}, 'gene4': {'e', 'd', 'a', 'c', 'f'},
                   'gene5': set()}
    res = sparse_dict_to_bool_df(sparse_dict).sort_index(axis=1)
    assert res.equals(truth)

@pytest.mark.parametrize("lst,chunk_size,truth", [([1, 2, 3, 4, 5], 1, [[1], [2], [3], [4], [5]]),
                                                  ([1, 2, 3, 4], 2, [[1, 2], [3, 4]]),
                                                  ([1, 2, 3, 4, 5], 2, [[1, 2], [3, 4], [5]]),
                                                  ([], 3, [[]]),
                                                  ((1, 2, 3, 4), 3, [(1, 2, 3), (4,)]),
                                                  ((1, 2, 3, 4, 5), 5, [(1, 2, 3, 4, 5)]),
                                                  ((1, 2, 3, 4), 5, [(1, 2, 3, 4)]),
                                                  (tuple(), 1, [tuple()])])
def test_partition_list(lst, chunk_size, truth):
    res = partition_list(lst, chunk_size)
    assert res == truth

@pytest.mark.parametrize("lst,chunk_size", [([1, 2, 3, 4], 0),
                                            ([1, 2], -1),
                                            ({1, 2}, 2),
                                            ([1, 2, 3], 1.0),
                                            ((i for i in range(3)), 2)])
def test_partition_list_invalid_input(lst, chunk_size):
    with pytest.raises(AssertionError):
        _ = partition_list(lst, chunk_size)

@pytest.mark.parametrize("lst,truth", [([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]),
                                       ([], []),
                                       ([1, 2, [3, 4], [5]], [1, 2, 3, 4, 5]),
                                       ([1, 2, [3, [], 4], 5, [], 6], [1, 2, 3, 4, 5, 6]),
                                       ([[1, 2], [3, 4, [5, 6], 7, [], [8, [9]]]], [1, 2, 3, 4, 5, 6, 7, 8, 9])])
def test_flatten(lst, truth):
    assert flatten(lst) == truth

def test_generate_upset_series():
    names = ('a', 'b', 'c')
    tuples = [(True, True, True), (True, False, True), (True, True, False), (True, False, False),
              (False, True, True), (False, True, False), (False, False, True)]
    multi_index_truth = pd.MultiIndex.from_tuples(tuples, names=names).sort_values()
    srs_truth = pd.Series(index=multi_index_truth, dtype='uint32').sort_index()
    srs_truth.loc[True, True, True] = 1
    srs_truth.loc[True, True, False] = 2
    srs_truth.loc[True, False, True] = 1
    srs_truth.loc[True, False, False] = 0
    srs_truth.loc[False, True, True] = 1
    srs_truth.loc[False, True, False] = 1
    srs_truth.loc[False, False, True] = 0
    srs = generate_upset_series(
        {'a': {'1', '2', '3', '6'}, 'b': {'2', '3', '4', '5', '6'}, 'c': {'1', '5', '6'}}).sort_index()
    assert srs.index.sort_values().equals(multi_index_truth)
    assert srs.sort_index().equals(srs_truth.sort_index())

@pytest.mark.parametrize('version,expected', [('3.0.0', [3, 0, 0]), ('0.1.3', [0, 1, 3]), ('2.0.5', [2, 0, 5])])
def test_parse_version(version, expected):
    assert parse_version(version) == expected

@pytest.mark.parametrize('attribute_str,expected', [
    ('attr1 "Val1"; attr_2 "val_2"; ', {'attr1': 'Val1', 'attr_2': 'val_2'}),
    ('gene_id "ENSG00000186092"; transcript_id "ENST00000335137"; '
     'gene_name "OR4F5"; gene_source "ensembl_havana"; gene_biotype "protein_coding"; transcript_name "OR4F5-001"; '
     'transcript_source "ensembl_havana"; tag "CCDS"; ccds_id "CCDS30547";',
     {'gene_id': 'ENSG00000186092', 'transcript_id': 'ENST00000335137', 'gene_name': 'OR4F5',
      'gene_source': 'ensembl_havana', 'gene_biotype': 'protein_coding', 'transcript_name': 'OR4F5-001',
      'transcript_source': 'ensembl_havana', 'tag': 'CCDS', 'ccds_id': 'CCDS30547'})
])
def test_parse_gtf_attributes(attribute_str, expected):
    assert parse_gtf_attributes(attribute_str) == expected

@pytest.mark.parametrize('arg,expected', [
    (None, 'NULL'),
    (35, '35'),
    (7.22, '7.22'),
    (-3.52, '-3.52'),
    ('my str', '"my str"'),
    (True, 'TRUE'),
    (False, 'FALSE'),
    (['a', 'ab', 'cde'], 'c("a", "ab", "cde")'),
    ({}, 'c()')
])
def test_parse_r_arg(arg, expected):
    res = _parse_r_arg(arg)
    assert res == expected

@pytest.mark.parametrize('kwargs,expected', [
    ({'arg1': False}, 'arg1 = FALSE'),
    ({'arg1': 'val1', 'arg2': -0.25, 'arg3': True}, 'arg1 = "val1",\narg2 = -0.25,\narg3 = TRUE'),
    ({'arg1': None, 'arg2': ['b', 'dc', 'ad f']}, 'arg1 = NULL,\narg2 = c("b", "dc", "ad f")')
])
def test_python_to_r_kwargs(kwargs, expected):
    res = python_to_r_kwargs(kwargs)
    assert res == expected

@pytest.mark.parametrize('attrs,expected', [
    ('ID=mrna0001;Name=sonichedgehog', {'ID': 'mrna0001', 'Name': 'sonichedgehog'}),
    ('ID=exon00003;Parent=mrna0001', {'ID': 'exon00003', 'Parent': 'mrna0001'}),
    ('ID=B0348.6a.1;Parent=WBGene00002061', {'ID': 'B0348.6a.1', 'Parent': 'WBGene00002061'}),
    ('ID=exon00004;Parent=mRNA00001,mRNA00002,mRNA00003', {'ID': 'exon00004', 'Parent':
        ['mRNA00001', 'mRNA00002', 'mRNA00003']}),
    ('ID=exon00005;Parent=mRNA00001,mRNA00003', {'ID': 'exon00005', 'Parent': ['mRNA00001', 'mRNA00003']}),
    ('ID=mRNA00003;Parent=gene00001;Name=EDEN.3', {'ID': 'mRNA00003', 'Parent': 'gene00001', 'Name': 'EDEN.3'}),
])
def test_parse_gff3_attributes(attrs, expected):
    res = parse_gff3_attributes(attrs)
    assert res == expected

@pytest.mark.parametrize('allow_unicode,string,expected', [
    (False, 'text', 'text'),
    (False, 'text with spaces', 'text-with-spaces'),
    (True, 'text_without_spaces', 'text_without_spaces'),
    (False, 'text---without--spaces', 'text-without-spaces'),
    (False, 'dash_', 'dash'),
    (True, 'dash-', 'dash'),
    (False, 'more!characters?:&%a', 'morecharactersa')
])
def test_slugify(allow_unicode, string, expected):
    res = slugify(string, allow_unicode)
    assert res == expected

@pytest.mark.parametrize('regex,repl,item,expected', [
    ('cat', 'dog', 'The cat sat on the cat', 'The cat sat on the dog'),
    ('1', 'one', '1234 1 5678 1', '1234 1 5678 one'),
    ('([A-Za-z]+)', r'\1\1', 'hello world', 'hello worldworld'),
    ('abc', 'xyz', 'abcdefabc', 'abcdefxyz'),
    ('[0-9]+', '', 'abcd1234', 'abcd'),
    ('(abc)+', 'def', 'abcabcabc', 'def'),
    ('', 'xyz', 'Hello, world!', 'Hello, world!xyz'),
    ('[A-Z][a-z]+', 'Mr.', 'Hello John Smith', 'Hello John Mr.'),
    ('[0-9]{2,3}', 'one', '12345', '123one'),
    ('e', 'replaced', 'escaped', 'escapreplacedd')
])
def test_replace_last_occurrence(regex, repl, item, expected):
    res = replace_last_occurrence(regex, repl, item)
    assert res == expected

@pytest.fixture
def sample_df():
    return pd.DataFrame({
        "A": [1.0, 2, 3, 4, 5],
        "B": [6.00111, 7, 8, 9, 10],
        "C": [11, 12, 13, 14, 15],
        "D": [16, 17, 18, 19, 20],
        "E": [21, 22, 23, 24, 25]
    })

def test_df_to_html_returns_string(sample_df):
    html = df_to_html(sample_df)
    assert isinstance(html, str)

@pytest.mark.parametrize('n_rows', [2, 3, 4])
def test_df_to_html_limits_number_of_rows(sample_df, n_rows):
    html = df_to_html(sample_df, max_rows=n_rows)
    assert html.count("
") == n_rows + 2  # includes header row and '...'

def test_df_to_html_formats_floats_with_two_decimals(sample_df):
    html = df_to_html(sample_df)
    assert "1.00" in html
    assert "6.00" in html

def test_df_to_html_does_not_truncate_values(sample_df):
    long_string = "a" * 100
    df = pd.DataFrame({
        "A": [1, 2, 3],
        "B": [long_string, long_string, long_string],
    })
    html = df_to_html(df)
    assert long_string in html

def test_df_to_html_removes_redundant_dots(sample_df):
    df = pd.DataFrame({
        "A": ["A", "B", "C"],
        "B": ["...", "...", "..."],
    })
    html = df_to_html(df, max_rows=2, max_cols=2)
    assert "...
" not in html

@pytest.mark.parametrize("items, expected_output", [
    ([], '
\n
'),
    (['item'],
     '
\n
item
\n
'),
    (['item1', 'item2', 'item3'],
     '
\n
item1
\n
item2
\n
item3
\n
'),
])
def test_items_to_html_table(items, expected_output):
    assert items_to_html_table(items) == expected_output

@pytest.mark.parametrize("d, expected", [
    ({}, ''),
    ({'a': 1}, "a = 1"),
    ({'a': 1, 'b': 'hello'}, "a = 1, \nb = 'hello'"),
    ({'a': [1, 2, 3], 'b': {'x': 1}}, "a = [1, 2, 3], \nb = {'x': 1}")
])
def test_format_dict_for_display(d, expected):
    assert format_dict_for_display(d) == expected


import cv2
import numpy as np

# 画像を読み込み、モノクロに変換する
def img2gray(path):
    img = cv2.imread(path)
    gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    return gray_img

# モノクロにした画像を、2値化する（閾値を決めない場合、大津の方法を使う）
def thresh(path, thresh=-1):
    gray = img2gray(path)
    if thresh == -1:
        retval_otsu, dst_otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
        return dst_otsu, retval_otsu

    elif 0 < thresh < 255:
        retval, dst = cv2.threshold(gray, thresh, 255, cv2.THRESH_BINARY)
        return dst, retval

    else:
        print("thresh error")

# 高速フーリエ変換後、2次元パワースペクトルを出力する
def fft(img):
    f_uv = np.fft.fft2(img)
    shifted_f_uv = np.fft.fftshift(f_uv)
    magnitude_spectrum2d = 20 * np.log(np.absolute(shifted_f_uv)) #type numpy.ndarray
    return magnitude_spectrum2d


from PySide2.QtWidgets import QWidget

from .ui.comparison_multiple_ships import Ui_ComparisonMultipleShips
from data import Data
from comparison_multiple_shipfus_table_model import (
    ComparisonMultipleShipfusTableModel,
    ProxyComparisonMultipleShipfusTableModel)

class ComparisonMultipleShips(QWidget, Ui_ComparisonMultipleShips):
    def __init__(self, shipfus, rarities):
        super().__init__()
        self.setupUi(self)

        self.shipfuStats = dict()
        for shipfu in shipfus:
            self.shipfuStats[shipfu] = Data.getStatsForShipfu(
                shipfu.Shipfu.shipfu_id)

        nb_levels = len(max(self.shipfuStats.values(), key=lambda x: len(x)))

        # Rearrange the selection of levels accordingly
        if self.levelComboBox.count() == 3 and nb_levels == 2:
            self.levelComboBox.removeItem(0)
        elif nb_levels == 3:
            if self.levelComboBox.count() == 2:
                self.levelComboBox.insert(0, "1")
            for stats in self.shipfuStats.values():
                if len(stats) != 3:
                    stats.insert(0, None)

        self.model = ComparisonMultipleShipfusTableModel(shipfus,
                                                         self.shipfuStats)
        self.proxyModel = ProxyComparisonMultipleShipfusTableModel(rarities)
        self.proxyModel.setSourceModel(self.model)
        self.shipTableView.setModel(self.proxyModel)

        self.levelComboBox.currentIndexChanged.connect(self.setLevelIndex)

    def setLevelIndex(self, idx):
        self.model.setLevelIndex(idx)
        # We have no focus on the table, so we need to manually repaint it
        self.shipTableView.viewport().repaint()


# -*- coding: utf-8 -*-
"""
Created on Mon Nov 11 19:16:07 2019
drive end fault at 1750rpm, 0.021in, 12ksps and 48ksps
@author: caiom
"""
#%%
# Importing modules
import numpy as np
from keras.utils import np_utils
import scipy.io
import scipy.signal
import math
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, accuracy_score

#%% Defining some constants to be used throughout
# number os data points per set
data_points = 120000
# image width
img_w = 14
# image length
img_h = 14
# matrix used to hold final images
A = np.zeros((0, img_w, img_h))
# image length when unidimensional
img_length = img_w*img_h
# number of data points used to build image
N = img_length*2
# images in each class
samples_per_class = (2*data_points)//N

#%% normal baseline at 48ksps
# import matlab file using scipy
normal_48 = scipy.io.loadmat('./data/normal_1750.mat')
# get only the acc data points
normal_48 = normal_48['X099_DE_time']
# undersample by 4 to get 12ksps (resampled)
normal_48_rs = normal_48[::4]

#%% rolling element (ball) at 12ksps
# import matlab file using scipy
ball_12 = scipy.io.loadmat('./data/b021')
# get only the acc data points
ball_12 = ball_12['X224_DE_time']
# resample to 48ksps
ball_12_rs = scipy.signal.resample(ball_12, data_points)

#%% rolling element (ball) at 48ksps
# import matlab file using scipy
ball_48 = scipy.io.loadmat('./data/b021_48')
# get only the acc data points
ball_48 = ball_48['X228_DE_time']
# undersample to 12ksps
ball_48_rs = ball_48[::4]

#%% inner race at 12ksps
# import matlab file using scipy
inner_race_12 = scipy.io.loadmat('./data/ir021')
# get only the acc data points
inner_race_12 = inner_race_12['X211_DE_time']
# resample to 48ksps
inner_race_12_rs = scipy.signal.resample(inner_race_12, data_points)

#%% inner race at 48ksps
# import matlab file using scipy
inner_race_48 = scipy.io.loadmat('./data/ir021_48')
# get only the acc data points
inner_race_48 = inner_race_48['X215_DE_time']
# undersample to 12ksps
inner_race_48_rs = inner_race_48[::4]

#%% outer race at different angles at 12ksps
# import matlab file using scipy
outer_race_at3_12 = scipy.io.loadmat('./data/or021at3')
# get only the acc data points
outer_race_at3_12 = outer_race_at3_12['X248_DE_time']
# resample to 48ksps
outer_race_at3_12_rs = scipy.signal.resample(outer_race_at3_12, data_points)

# import matlab file using scipy
outer_race_at6_12 = scipy.io.loadmat('./data/or021at6')
# get only the acc data points
outer_race_at6_12 = outer_race_at6_12['X236_DE_time']
# resample to 48ksps
outer_race_at6_12_rs = scipy.signal.resample(outer_race_at6_12, data_points)

# import matlab file using scipy
outer_race_at12_12 = scipy.io.loadmat('./data/or021at12')
# get only the acc data points
outer_race_at12_12 = outer_race_at12_12['X260_DE_time']
# resample to 48ksps
outer_race_at12_12_rs = scipy.signal.resample(outer_race_at12_12, data_points)

#%% outer race at different angles at 48ksps
# import matlab file using scipy
outer_race_at3_48 = scipy.io.loadmat('./data/or021at3_48')
# get only the acc data points
outer_race_at3_48 = outer_race_at3_48['X252_DE_time']
# undersample to 12ksps
outer_race_at3_48_rs = outer_race_at3_48[::4]

# import matlab file using scipy
outer_race_at6_48 = scipy.io.loadmat('./data/or021at6_48')
# get only the acc data points
outer_race_at6_48 = outer_race_at6_48['X240_DE_time']
# undersample to 12ksps
outer_race_at6_48_rs = outer_race_at6_48[::4]

# import matlab file using scipy
outer_race_at12_48 = scipy.io.loadmat('./data/or021at12_48')
# get only the acc data points
outer_race_at12_48 = outer_race_at12_48['X264_DE_time']
# undersample to 12ksps
outer_race_at12_48_rs = outer_race_at12_48[::4]

#%% build final data set for each class using both 48ksps and 12ksps (resampled accordingly)
normal = np.append(normal_48_rs, normal_48_rs)
inner_race = np.append(inner_race_48_rs, inner_race_12)
ball = np.append(ball_48_rs, ball_12)
outer_race_at3 = np.append(outer_race_at3_48_rs, outer_race_at3_12)
outer_race_at6 = np.append(outer_race_at6_48_rs, outer_race_at6_12)
outer_race_at12 = np.append(outer_race_at12_48_rs, outer_race_at12_12)

#%% some statistics
#df_48 = pd.DataFrame(inner_race_48)
#df_12 = pd.DataFrame(inner_race_12)
#avg_48 = sum(inner_race_48)/len(inner_race_48)
#avg_12 = sum(inner_race_12)/len(inner_race_12)
#avg_b48 = sum(ball_48)/len(ball_48)
#avg_b12 = sum(ball_12)/len(ball_12)
#ds1[0].plot(figsize = (600,6))
#plt.show()
#ds2[0].plot(figsize = (600,6))
#plt.show()
#rms_48 = np.sqrt(np.mean(df_48**2))
#rms_12 = np.sqrt(np.mean(df_12**2))

#%% build images for normal baseline
# (same for each other class)

# for each sample
for i in range(0, samples_per_class):
    # fft
    y = normal[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    # B2LS and append to S
    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))

    # make S a numpy array
    S = np.asarray(S)

    # normalize into I
    m = max(S)
    I = S/m

    # make vector into 2d image and append to A
    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    # plot each image
#    It = I
#    It.shape = (It.size//img_h, img_h)
#    plt.imshow(It, cmap="gray")
#    plt.show()

# plot last image
It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% build images for fault outer race at 3 oclock

for i in range(0, samples_per_class):
    y = outer_race_at3[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))
    S = np.asarray(S)

    m = max(S)
    I = S/m

    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    It = I
    It.shape = (It.size//img_h, img_h)
    plt.imshow(It, cmap="gray")
    plt.show()

It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% build images for fault outer race at 6 oclock

for i in range(0, samples_per_class):
    y = outer_race_at6[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))
    S = np.asarray(S)

    m = max(S)
    I = S/m

    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    It = I
    It.shape = (It.size//img_h, img_h)
    #plt.imshow(It, cmap="gray")
    #plt.show()

It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% build images for fault outer race at 12 oclock

for i in range(0, samples_per_class):
    y = outer_race_at12[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))
    S = np.asarray(S)

    m = max(S)
    I = S/m

    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    It = I
    It.shape = (It.size//img_h, img_h)
#    plt.imshow(It, cmap="gray")
#    plt.show()

It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% build images for fault at rolling element (ball)

for i in range(0, samples_per_class):
    y = ball[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))
    S = np.asarray(S)

    m = max(S)
    I = S/m

    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    It = I
    It.shape = (It.size//img_h, img_h)
#    plt.imshow(It, cmap="gray")
#    plt.show()

It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% build images for fault at inner race

for i in range(0, samples_per_class):
    y = inner_race[(i*N):((i+1)*N)]
    yf = fft(y)
    ffty = 2.0/N * np.abs(yf[0:N//2])
    ffty[ffty == 0] = 8.82619e-05

    S = []
    for x in range(0, len(ffty)):
        S.append(abs(math.log2(ffty[x]/img_length)))
    S = np.asarray(S)

    m = max(S)
    I = S/m

    I.shape = (1, I.size//img_h, img_h)
    A = np.insert(A, 0, I, axis = 0)

    It = I
    It.shape = (It.size//img_h, img_h)
#    plt.imshow(It, cmap="gray")
#    plt.show()

It = I
It.shape = (It.size//img_h, img_h)
plt.imshow(It, cmap="gray")
plt.show()

#%% Reshape A
A = A.reshape(A.shape[0], img_w, img_h, 1)

#%% Appy labels to samples
# Label1 identifies only normal baseline and fault, two classes
label1 = np.zeros(samples_per_class*6)
label1[0:(samples_per_class*4)] = 1

# label2 identifies normal baseline and each specific fault, six classes
label2 = np.zeros(samples_per_class*6)
label2[0:samples_per_class] = 5
label2[samples_per_class:samples_per_class*2] = 4
label2[samples_per_class*2:samples_per_class*3] = 3
label2[samples_per_class*3:samples_per_class*4] = 2
label2[samples_per_class*4:samples_per_class*5] = 1
label2 = np_utils.to_categorical(label2, 6)

#%% Separate classes, labels, train and test
#X_train, X_test, y_train, y_test = train_test_split(A, label1, test_size=0.25)
X_train, X_test, y_train, y_test = train_test_split(A, label2, test_size=0.25)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

#%% Build first CNN
# import modules
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from keras import models
from keras.optimizers import Adam

# define as sequential
model1 = models.Sequential()
# add first convolutional layer
model1.add(Conv2D(16, (3, 3), activation='relu', input_shape=(img_w,img_h,1)))
# add first max pooling layer
model1.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
# add second convolutional layer
model1.add(Conv2D(32, (3, 3), activation='relu'))
# add second max pooling layer
model1.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
# flatten before mlp
model1.add(Flatten())
# add fully connected wih 128 neurons and relu activation
model1.add(Dense(128, activation='relu'))
# output six classes with softmax activtion
model1.add(Dense(6, activation='softmax'))

# print CNN info
model1.summary()
# compile CNN and define its functions
model1.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])

#%% Train CNN model1
model1.fit(X_train, y_train, batch_size=10, nb_epoch=100, validation_data=(X_test, y_test))

#%% Results
# Make inference
# Predict and normalize predictions into 0s and 1s
predictions = model1.predict(X_test)
predictions = (predictions > 0.5)
# Find accuracy of inference
accuracy = accuracy_score(y_test, predictions)
print(accuracy)
# calculate confusion matrix and print it
matrix = confusion_matrix(y_test.argmax(axis=1), predictions.argmax(axis=1))
print(matrix)

# Use evaluate to test, just another way to do the same thing
result = model1.evaluate(X_test, y_test)
print(result)
confusion_matrix(y_test.argmax(axis=1), predictions.argmax(axis=1))
###############################################################################

#%% Same as above for another, simpler CNN model
# define as sequential
model2 = models.Sequential()
# add first convolutional layer
model2.add(Conv2D(2, (2, 2), activation='relu', input_shape=(img_w,img_h,1)))
# add first max pooling layer
model2.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
# flatten befor MLP
model2.add(Flatten())
# add fully connected wih 8 neurons and relu activation
model2.add(Dense(8, activation='relu'))
# output six classes with softmax activtion
model2.add(Dense(6, activation='softmax'))

# print CNN info
model2.summary()
# compile CNN and define its functions
model2.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])

#%% Train CNN model2
model2.fit(X_train, y_train, batch_size=10, nb_epoch=100, validation_data=(X_test, y_test))

#%% Results
# Make inference
# Predict and normalize predictions into 0s and 1s
predictions = model2.predict(X_test)
predictions = (predictions > 0.5)
# Find accuracy of inference
accuracy = accuracy_score(y_test, predictions)
print(accuracy)
# calculate confusion matrix and print it
matrix = confusion_matrix(y_test.argmax(axis=1), predictions.argmax(axis=1))
print(matrix)

# Use evaluate to test, just another way to do the same thing
result = model2.evaluate(X_test, y_test)
print(result)
confusion_matrix(y_test.argmax(axis=1), predictions.argmax(axis=1))


# HTMLParser

from html.parser import HTMLParser
from html.entities import name2codepoint
import urllib.request

class MyHTMLParser(HTMLParser):

    def handle_startendtag(self, tag, attrs):
        print('<%s>' % tag)

    def handle_endtag(self, tag):
        print('<%s>' % tag)

    def handle_data(self, data):
        print(data)

    def handle_comment(self, data):
        print('')

    def handle_entityref(self, name):
        print('&%s;' % name)

    def handle_charref(self, name):
        print('&#%s;' % name)

parser = MyHTMLParser()
parser.feed('''

Some html HTML tutorial...
END

''')

# practice

response = urllib.request.urlopen('https://www.python.org/events/python-events/')
class PythonEvent(HTMLParser):
    def __init__(self):
        super(PythonEvent,self).__init__()
        self.key = 0
        self.location_key = 0
        self.event_list = []
        self.event_tmp = []

    def handle_starttag(self, tag, attrs):
        if attrs:
            if attrs[0][1] == 'event-title' or tag == 'time':
                self.key = 1 # self.key=1 表示data需要保存
            if attrs[0][1] == 'event-location':
                self.key = 1
                self.location_key = 1 # self.location_key = 1表示单个data信息结尾

    def handle_data(self, data):
        if self.key:
            self.event_tmp.append(data)

        if self.location_key:
            self.event_list.append(self.event_tmp) # event_tmp保存进list并重置
            self.event_tmp = []

    def handle_endtag(self, tag):
        self.key = 0
        self.location_key = 0

event = PythonEvent()
event.feed(response.read().decode('utf-8'))
for i in event.event_list:
    print(i)


import csv
from operator import itemgetter
fields = ['EMPID','Name','DOB','Department','Designation','Experience',	'No of leaves','Salary']
rows = [['1',   'Mounika',  '02-05-2001',   'E-104',    'HR',       '1',    '20',   '30000'],
        ['2',   'Vishal',   '11-06-1984',	'E-105',    'Admin',    '5',    '15',   '25000'],
        ['3',   'Amitabh',  '20-02-2000',   'E-106',    'HR',       '10',   '30',   '15000'],
        ['4',	'Vivek',	'18-05-1986',	'E-107',	'Account',	'3',	'20',	'25000'],
        ['5',	'Niharika',	'05-12-1996',	'E-108',	'Account',	'18',	'20',	'15000'],
        ['6',	'Vipul'	,   '16-12-1992',	'E-109',	'Account',	'14',	'15',	'15000'],
        ['7',	'Satish',	'21-07-1990',	'E-110',	'Admin',	'2',	'17',	'40000'],
        ['8',	'Harsha',	'07-02-1999',	'E-111',	'Admin',	'6',	'18',	'20000'],
        ['9',	'Akash',	'21-04-1993',	'E-112',	'HR',	    '12',	'6',	'50000'],
        ['10',	'Pavan',	'07-03-1997',	'E-113',	'Admin',	'5',	'9',	'47000'],
        ['11',	'Gowtham',	'19-09-2000',	'E-114',	'Account',	'10',	'15',	'83000'],
        ['12',	'Sushmitha',	'04-11-1989',	'E-115',	'HR',	'4',	'5',	'60000'],
        ['13',	'Keshanand',	'03-06-1999',	'E-116',	'HR',	'3',	'6',	'55000'],
        ['14',	'Charan',	    '15-12-1998',	'E-117',	'Admin',	'0',	'9',	'48000'],
        ['15',	'Tejaswini',	'25-05-2000',	'E-118',	'Account',	'1',	'21',	'10000']]
print('*-*-* Working with CSV files in python *-*-*')
print('1. Insert into CSV File')
print('2. Read from CSV File')
print('3. Salary Less than 20000')
print('4. No of Leaves more than 2 days')
print('5. Experience greater than 10 years')
print('6. Access specific Employee using EMPID and Name')
choice=int(input('Enter Your choice : '))
if choice==1:
    filename = "Employees.csv"
    with open(filename, 'w') as csvfile:
        try:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(fields)
            csvwriter.writerows(rows)
            print('Inserted into the CSV file')
        except Exception as e:
            print(e)
elif choice==2:
    with open("Employees.csv", mode='r') as file:
        csvFile = csv.reader(file)
        for lines in csvFile:
            print(lines)
elif choice==3:
    with open("Employees.csv", "r") as csv_file:
        csv_reader = csv.DictReader(csv_file, delimiter=',')
        # csv_reader = csv.reader(csv_file)
        for lines in csv_reader:
            if(int(lines['Salary'])<int(20000)):
                print(lines)
elif choice==4:
    with open("Employees.csv", "r") as csv_file:
        csv_reader = csv.DictReader(csv_file, delimiter=',')
        # csv_reader = csv.reader(csv_file)
        for lines in csv_reader:
            if(int(lines['No of leaves'])>int(2)):
                print(lines)
elif choice==5:
    with open("Employees.csv", "r") as csv_file:
        csv_reader = csv.DictReader(csv_file, delimiter=',')
        for lines in csv_reader:
            if(int(lines['Experience'])>int(10)):
                print(lines)
elif choice==6:
    with open("Employees.csv", "r") as csv_file:
        csv_reader = csv.DictReader(csv_file, delimiter=',')
        for lines in csv_reader:
            print("Name : ",lines["Name"])
            print("EMPID : ",lines["EMPID"])
else:
    print('*-*-*   **   *-*-*')
    print('Improper Selection')
    print('*-*-*   **   *-*-*')
    exit()


"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: A Tree
    @return: Level order a list of lists of integer
    """
    def levelOrder(self, root):
        # write your code here
        res = []
        if not root:
            return res
        stack = [root]
        while stack:
            new_stack = []
            levelValue = []
            for node in stack:
                levelValue.append(node.val)
                if node.left:
                    new_stack.append(node.left)
                if node.right:
                    new_stack.append(node.right)
            res.append(levelValue)
            stack = new_stack
        return res


import json
from dagster import DagsterType

def is_json(_, value):
    try:
        json.loads(value)
        return True
    except ValueError:
        return False

real_estate_dataframe = DagsterType(
    name = "RealEstateDataFrame",
    type_check_fn = lambda _, value: isinstance(value, list),
    description = "This is the list of data scrapped from the WG website"
)

JsonType = DagsterType(
    name = "JsonType",
    description = "a valid json representation",
    type_check_fn = is_json,
)


import hashlib
import os

def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

def create_list_of_files(dir_name):
    # create a list of file and sub directories
    # names in the given directory
    list_of_file = os.listdir(dir_name)
    all_files = list()
    # Iterate over all the entries
    for entry in list_of_file:
        # Create full path
        full_path = os.path.join(dir_name, entry)
        # If entry is a directory then get the list of files in this directory
        if os.path.isdir(full_path):
            all_files = all_files + create_list_of_files(full_path)
        else:
            all_files.append(full_path)

    return all_files

def create_hashes_of_file_list(items):
    return [md5(item) for item in items]

def create_dict_with_names_and_hashes(items, hashes):
    return {
        items[i]: hashes[i]
        for i in range(len(items))
     }

def create_list_of_duplicates(path):
    items = create_list_of_files(path)

    hashes = create_hashes_of_file_list(items)

    names_with_hash = create_dict_with_names_and_hashes(items, hashes)

    set_of_duplicates = set()
    identical_files_list = []

    for key1, value1 in names_with_hash.items():
        for key2, value2 in names_with_hash.items():
            if value1 == value2 and key1 != key2:
                set_of_duplicates.add(value1)

    flag = False
    for file_hash in set_of_duplicates:
        if flag:
            flag = False
        for key, value in names_with_hash.items():
            if not flag:
                flag = True
                identical_files_list.append([])
            if file_hash == value:
                identical_files_list[-1].append(key)
    return identical_files_list


# -*- coding: utf-8 -*-
""" Jolly Jumper challenge, posted at
https://www.reddit.com/r/dailyprogrammer/comments/65vgkh/20170417_challenge_311_easy_jolly_jumper/. """

# authorship information
__author__ = 'Scott Crowe'
__email__ = 'sb.crowe@gmail.com'
__license__ = 'MIT'

# define challenge input
_input = ['4 1 4 2 3',
          '5 1 4 2 -1 6',
          '4 19 22 24 21',
          '4 19 22 24 25',
          '4 2 -1 0 2']

def jolly_jumper(sequence):
    """ Determine if sequence of n > 0 integers is a 'jolly jumper' (with absolute values of differences between
    successive elements taking on all possible values 1 through n-1).

    Args:
        sequence: The sequence of numbers, preceded by a count (e.g. '4 1 4 2 3').
    """
    numbers = [int(x) for x in sequence.split()][1:]
    exp_diff = list(range(1, len(numbers), 1))
    diff = []
    for index in range(len(numbers) - 1):
        diff.append(abs(numbers[index + 1] - numbers[index]))
    if sorted(diff) == exp_diff:
        print(sequence + ' JOLLY')
    else:
        print(sequence + ' NOT JOLLY')

# run the code
for case in _input:
    jolly_jumper(case)


# Joshua Hui - 8/25/2019

class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        if len(nums) < 1:
            return []
        for _ in range(k):
            k = nums.pop()
            nums.insert(0,k)

        return nums

# Runtime: 172 ms, faster than 7.48% of Python online submissions for Rotate Array.
# Memory Usage: 12.1 MB, less than 60.42% of Python online submissions for Rotate Array.

# If not in-place:
# But this is wrong if [1,2] ,0
        # lenNums = len(nums)
        # stepsToMove = k % lenNums
        # firstHalf = nums[stepsToMove+1:]
        # secondHalf = nums[:stepsToMove+1]
        # newArray = firstHalf + secondHalf
        # print(newArray)
        # return newArray

# So the correct answer will be
        # lenNums = len(nums)
        # stepsToMove = k % lenNums
        # firstHalf = nums[-stepsToMove:]
        # secondHalf = nums[:-stepsToMove]
        # nums[:] = firstHalf + secondHalf

# Runtime: 44 ms, faster than 86.29% of Python online submissions for Rotate Array.
# Memory Usage: 12.5 MB, less than 10.42% of Python online submissions for Rotate Array.


from sqlalchemy import MetaData, create_engine
from sqlalchemy.engine.reflection import Inspector
from sqlalchemy.exc import OperationalError
import logging
import json
import os
from time import time as t_time
from multiprocessing import Pool

from lib.util import json_comment_filter
from targets.csv import csv
from lib.config import get_dburi, get_remote_csv_dir, get_csv_dir, get_latest_version
from .db import table_from_fields, drop_create_table, full_view_refresh
from views.views import create_views

def postgresql(file_prefixes=None):
    """
    Move CSV files into corresponding postgresql tables
    using bulk postgresql COPY command.
    Table names and columns are lowercased
    for ease of working in SQL.
    Types conversion:
        Date: Applicable columns ending in '_DATE'
        Time: Applicable columns ending in '_TIME'
    The CSV files must be on the same server as the postgres
    db and readable by the postgres process.
    Composite primary keys have blanks (rather than null) in columns.
    """
    log = logging.getLogger('targets_postgresql')
    stime = t_time()
    dburi = get_dburi()
    engine = create_engine(dburi)
    connection = engine.connect()  # trigger conn. related exceptions, e.g. if db doesn't exist
    metadata = MetaData()

    file_fields = json_comment_filter(json.load(open('file-fields.json', 'r')))
    field_pks = json_comment_filter(json.load(open('field-pks.json', 'r')))
    if not file_prefixes:
        file_prefixes = file_fields.keys()
    todo = []
    for fprefix in sorted(file_prefixes):
        csv_dir = get_remote_csv_dir()
        if not os.path.exists(csv_dir) and csv_dir != get_csv_dir():
            # We don't have access to the directory we'll be COPYing from
            # versions are included in CSV filenames so db server will fail
            # to COPY from an old file
            pass
        else:
            if not os.path.exists(csv_dir):
                csv([fprefix])
            else:
                with open(os.path.join(csv_dir, '.version.' + fprefix), 'r') as f:
                    csv_version = f.read().strip()
                if csv_version != get_latest_version(fprefix).lstrip('F'):
                    log.warning('%s: Newer version available, converting to CSV again' % (fprefix))
                    csv([fprefix])

        for filename in file_fields[fprefix]:
            for record_type, fields in file_fields[fprefix][filename].items():
                pks = field_pks.get(fprefix, {}).get(filename, {}).get(record_type, [])
                if not fields:
                    log.warning('%s: Missing spec for %s %s' % (fprefix, filename, record_type))
                    continue
                if False:
                    table_name, creating = csv_to_table(engine, metadata, fprefix,
                                                        filename, record_type, fields, pks)
                    if table_name and creating:
                        log.info('Finished recreating %s' % (table_name))
                    elif table_name:
                        log.info('Finished creating %s' % (table_name))
                else:
                    todo.append((fprefix, filename, record_type, fields, pks))
    if todo:
        n = 1
        with Pool() as pool:
            for table_name, creating in pool.imap_unordered(csv_to_table_tup, todo):
                if table_name and creating:
                    log.info('Finished recreating %s (%d of %d)' % (table_name, n, len(todo)))
                elif table_name:
                    log.info('Finished creating %s (%d of %d)' % (table_name, n, len(todo)))
                n += 1

    if full_view_refresh:
        create_views(connection)

    log.debug('csv to postgresql: %ds total time' % (t_time()-stime))

def csv_to_table_tup(tup):
    # required as we don't have pool.starmap_unordered
    dburi = get_dburi()
    engine = create_engine(dburi)  # each process needs it's own engine
    metadata = MetaData()
    tup_with_cx = (engine, metadata) + tup
    return csv_to_table(*tup_with_cx)

def csv_to_table(
        engine, metadata,
        fprefix, filename, record_type, fields, pks=[],
        csv_path=None):
    """
    WARNING: this drops and recreates tables
    table schema is as specified in file-fields.json and field-pks.json
    """
    log = logging.getLogger('targets_postgresql_csv_to_table')

    version = get_latest_version(fprefix).lstrip('F')
    if csv_path is None:
        if record_type:
            csv_name = '%s-%s-%s.%s.csv' % (fprefix, filename, record_type, version)
        else:
            csv_name = '%s-%s.%s.csv' % (fprefix, filename, version)
        csv_path = os.path.join(get_remote_csv_dir(), csv_name)

    table = table_from_fields(engine, metadata, fprefix, filename,
                              record_type, fields, pks)

    inspector = Inspector.from_engine(engine)
    creating = table.name in inspector.get_table_names()

    connection = engine.connect()
    trans = connection.begin()
    try:

        drop_create_table(connection, table)

        # data insert using COPY method
        force_not_null = ''
        if pks and pks != ['invalid']:
            force_not_null = ', FORCE_NOT_NULL ("%s")' % ('", "'.join([p.lower() for p in pks]))
        connection.execute("""COPY "%s"
FROM '%s'
WITH (FORMAT CSV, HEADER%s);
        """ % (table.name, csv_path, force_not_null))

        trans.commit()
    except OperationalError as oe:
        trans.rollback()
        if 'No such file or directory' in str(oe):
            if creating:
                log.warning('%s not found, no table created' % (csv_path))
            else:
                log.warning('%s not found, table kept as-is' % (csv_path))
            table.name = None
        else:
            raise

    return table.name, creating


from typing import *

class Solution:
    def largestWordCount(self, messages: List[str], senders: List[str]) -> str:
        d = dict()
        for i, j in zip(messages, senders):
            if j in d:
                d[j] += len(i.split())
            else:
                d[j] = len(i.split())
        return max(d, key=lambda x: (d[x], x))

if __name__ == "__main__":
    sln = Solution()
    print(sln.largestWordCount(messages=["Hello userTwooo", "Hi userThree", "Wonderful day Alice",
                                         "Nice day userThree"], senders=["Alice", "userTwo", "userThree", "Alice"]))
    print(sln.largestWordCount(messages=[
          "How is leetcode for everyone", "Leetcode is useful for practice"], senders=["Bob", "Charlie"]))


from flask import Flask, Response, url_for

app = Flask(__name__)
freeze_config = {
    'status_handlers': {'3xx': 'follow'},
}

@app.route('/')
def index():
    """Redirect to the second page.
    """
    return Response(
        "Redirecting to second page...",
        status='301 Moved Permanently',
        headers=[('Location', url_for('second_page'))],
    )

@app.route('/second_page.html')
def second_page():
    """Redirect to the third page.
    """
    return Response(
        "Redirecting to third page...",
        status='301 Moved Permanently',
        headers=[('Location', url_for('third_page'))],
    )

@app.route('/third_page.html')
def third_page():
    """Show the third page of the web app."""
    return """
    <html>
        <head>
            <title>Hello world third page</title>
        </head>
        <body>
            Page 3 !!!
        </body>
    </html>
    """

expected_dict = {
    'index.html':
            b"\n    <html>\n        <head>\n"
            + b"            <title>Hello world third page</title>\n"
            + b"        </head>\n        <body>\n            Page 3 !!!\n"
            + b"        </body>\n    </html>\n    ",

    'second_page.html':
            b"\n    <html>\n        <head>\n"
            + b"            <title>Hello world third page</title>\n"
            + b"        </head>\n        <body>\n            Page 3 !!!\n"
            + b"        </body>\n    </html>\n    ",

    'third_page.html':
            b"\n    <html>\n        <head>\n"
            + b"            <title>Hello world third page</title>\n"
            + b"        </head>\n        <body>\n            Page 3 !!!\n"
            + b"        </body>\n    </html>\n    "
}


# https://www.algoexpert.io/questions/longest-substring-without-duplication

# O(n) time | O(min(a, n)) space
# a = is the length of character alphabet in input string, i.e length of `mapper`
def longestSubstringWithoutDuplication(string):
    mapper = {}
    l = 0
    res_l = res_r = 0
    for r, char in enumerate(string):
        if char in mapper:
            l = max(l, mapper[char] + 1)
        mapper[char] = r
        if r - l > res_r - res_l:
            res_l, res_r = l, r
    return string[res_l:res_r + 1]

if __name__ == '__main__':
    assert longestSubstringWithoutDuplication("clementisacap") == 'mentisac'
    assert longestSubstringWithoutDuplication("abc") == 'abc'
    assert longestSubstringWithoutDuplication("abcbde") == 'cbde'


import TreeNode

class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root: return []
        queue = [(root, 1)]
        nodesOnTheRight = []

        while queue:
            currentNode, currentLayer = queue.pop()
            if len(nodesOnTheRight) < currentLayer: nodesOnTheRight.append(currentNode.val)
            if currentNode.right: queue.insert(0, (currentNode.right, currentLayer + 1))
            if currentNode.left: queue.insert(0, (currentNode.left, currentLayer + 1))

        return nodesOnTheRight


from django.conf.urls import patterns, url
from .views import *

urlpatterns = patterns('Digital_con.apps.company.views',
	url(r'^list/$', 'company_listing', name='companies_list'),
    url(r'^detail/(?P<pk>\d+)/$', 'company_detail', name='company_detail'),
    url(r'^update/(?P<pk>\d+)/$', CompanyUpdate.as_view(), name='company_update'),
    url(r'^delete/(?P<pk>\d+)/$', CompanyDelete.as_view(), name='company_delete'),
    url(r'^companyform/$', CompanyForm.as_view(), name='company_form'),
)


from keras.models import load_model
from PIL import Image, ImageOps
import numpy as np

import os
from datetime import datetime
import shutil

def imgload(pathdir, Filename, model):
    imgFilename = pathdir + '\\' + Filename
    ngFilename = _ngDirname + '\\' + Filename
    okFilename = _okDirname + '\\' + Filename
    data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)
    image = Image.open(imgFilename)
    size = (224, 224)
    image = ImageOps.fit(image, size, Image.ANTIALIAS)
    image_array = np.asarray(image)
    normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1
    data[0] = normalized_image_array
    prediction = model.predict(data)
    ok = prediction.T[0]
    ng = prediction.T[1]

    # print(prediction)
    if  (ok < ng) and (ng > 0.5)  :
        print(imgFilename + ' : ng', ng)
        shutil.copyfile(imgFilename, ngFilename)
        with open(_savefilename, mode='a', encoding='utf-8') as file:
            file.write('{0} {1} \n'.format(imgFilename , ng))
    elif (ok > ng) and (ok < 0.6):
        print(imgFilename + ' : ok', ok)
        shutil.copyfile(imgFilename, okFilename)

def loadImg(path):
    # path = r'C:\Users\jslee\Desktop\새 폴더\세방이미지\현대신형-L70\Right'
    list = os.listdir(path)

    for i in range(len(list)):
        if list[i].find('0.jpg') > 0 :
            imgload(path, list[i], model_L)
        # elif list[i].find('1.jpg') > 0 :
        #     imgload(path, list[i], model_R)

########### Main ############
loadDir = r'C:\Users\jslee\Desktop\세방전지\세방이미지'
_ngDirname = r'C:\Users\jslee\Desktop\세방전지\NG'
_okDirname = r'C:\Users\jslee\Desktop\세방전지\OK'
_savefilename = 'test_' + str(datetime.now())[0:10] + '.txt'
if not os.path.exists(_ngDirname): os.mkdir(_ngDirname)
if not os.path.exists(_okDirname): os.mkdir(_okDirname)

model_L = load_model('keras_model_L.h5')
model_R = load_model('keras_model_R.h5')
for (path, dir, files) in os.walk(loadDir):
    for dirname in dir:
        loadImg(path + '\\' + dirname)


# Python implementation of insertion in BST

# class node
class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

# check the value to be inserted with root
# if value is greater than root move to right
# if value is less than root move to left
# once reached to the leaf node
# depending upon smaller/greather inset value in left/right

# recurssion insertion approach
def insertIntoBSTRecurssion(root, val):
    if root == None:
        return Node(val)

    if root.val == val:
        return root

    elif root.val < val:
        root.right = insertIntoBSTRecurssion(root.right, val)

    else:
        root.left = insertIntoBSTRecurssion(root.left, val)

    return root

# iterative insertion approach:
def insertIntoBST(root, val):
    node = Node(val)

    if root == None:
        root = node
        return root

    temp = root
    while temp:
        prev = temp
        if temp.val >= val:
            temp = temp.left

        else:
            temp = temp.right

    if prev.val >= val:
        prev.left = node

    else:
        prev.right = node

    return root

# inorder traversal of tree
def inorderTraversal(root):
    stack = []

    current = root

    while True:
        if current:
            stack.append(current)
            current = current.left

        elif stack:
            current = stack.pop()
            print(current.val, end=" ")
            current = current.right

        else:
            break

# drive the code
if __name__ == "__main__":
    r = Node(50)
    r = insertIntoBSTRecurssion(r, 30)
    r = insertIntoBSTRecurssion(r, 20)
    r = insertIntoBSTRecurssion(r, 40)
    r = insertIntoBSTRecurssion(r, 70)
    r = insertIntoBSTRecurssion(r, 60)
    r = insertIntoBSTRecurssion(r, 80)

    root = Node(50)
    root = insertIntoBST(root, 30)
    root = insertIntoBST(root, 20)
    root = insertIntoBST(root, 40)
    root = insertIntoBST(root, 70)
    root = insertIntoBST(root, 60)
    root = insertIntoBST(root, 80)

    print("Recurssive approach insertion:")
    inorderTraversal(r)
    print("\nIterative approach insertion:")
    inorderTraversal(root)

# Output:
# Recurssive approach insertion:
# 20 30 40 50 60 70 80
# Iterative approach insertion:
# 20 30 40 50 60 70 80


from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import PermissionDenied
from django.db.models import Count
from django.db.models.functions import Lower
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.views import View, generic
from django.views.generic.detail import SingleObjectMixin

from . import forms, models

### Authentication checkers ###
class StaffRequiredMixin(UserPassesTestMixin):
    """
    Mixin to check if user is staff.
    """

    def test_func(self):
        return self.request.user.is_staff

### LANDING VIEWS ###
class LandingPage(generic.TemplateView):
    """
    Landing page displaying 4 most recent posts and 4 most posted topics.
    """
    template_name = 'blog/landing.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Add tags context with 4 most posted topics
        context['tags'] = models.Tag.objects.annotate(
            num_posts=Count('posts')).order_by('-num_posts')[:4]

        # Add posts context with 4 most recent posts
        context['posts'] = models.Post.objects.filter(
            publish_date__isnull=False).order_by('-publish_date')[:4]

        return context

### POST VIEWS ###
class PostCreateView(StaffRequiredMixin, SuccessMessageMixin,
                     generic.CreateView):
    """
    Post create view accessible by any user with staff privileges.
    """
    form_class = forms.PostForm
    model = models.Post

    # On success, display message on base template.
    success_message = "%(title)s was created successfully"

    def form_valid(self, form_class):
        """
        Additional to base, sets user as post author.
        """
        form_class.instance.author = self.request.user
        return super().form_valid(form_class)

class PostDetailView(View):
    """
    Post detail selects CBV depending on the request HTTP method (POST/GET).
    """

    def get(self, *args, **kwargs):
        """
        For GET method select PostDisplay as view.
        """
        view = PostDisplay.as_view()
        return view(self.request, *args, **kwargs)

    def post(self, *args, **kwargs):
        """
        For POST method select Comment as view.
        """
        view = Comment.as_view()
        return view(self.request, *args, **kwargs)

class PostDisplay(generic.DetailView):
    """
    GET method for PostDetailView. Displays post, comments and comment form.
    """
    model = models.Post

    def get_object(self):
        """
        Checks if post not published and user not author. Returns post object.
        """
        obj = super().get_object()
        if obj.publish_date is None and self.request.user != obj.author:
            raise PermissionDenied()
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Add comments and comment form as additional context.
        context['form'] = forms.CommentForm
        context['comments'] = self.object.comments.order_by('-created_date')

        return context

class SearchView(generic.ListView):
    """
    List view of all posts with search, filter and sort functionality.
    """
    template_name = 'blog/search.html'
    context_object_name = "posts"
    paginate_by = 12
    search_form = forms.SearchPostForm

    def get_queryset(self):
        """
        Modifies queryset based on user input to form and returns.
        """
        form = self.search_form(self.request.GET)

        # If valid form data submitted (HTTP GET).
        if form.is_valid():

            # Obtain form data.
            tag_filter = form.cleaned_data['tag_input']
            post_filter = form.cleaned_data['post_input']
            order_by = form.cleaned_data['order_input']

            # Base queryset, filtered to show posts that have been published.
            queryset = models.Post.objects.filter(publish_date__isnull=False)

            # Chain queryset dependent on user search form input.
            if tag_filter is not None:
                queryset = queryset.filter(tags__name__iexact=str(tag_filter))
            if post_filter is not None:
                queryset = queryset.filter(title__icontains=post_filter)
            if order_by == '0':
                queryset = queryset.order_by('-publish_date')
            elif order_by == '1':
                queryset = queryset.order_by('publish_date')

            # Set search_form values so they are displayed on post-search render.
            self.search_form = form

        # If form data not submitted.
        else:
            # If URL contains a tag slug, filter queryset by the slug. This is
            # done if  the pre-search URL is used to access this view. This is
            # used if the user selects all posts from a tag detail page.
            # Set the search form tag value to show the tag on the page render.
            try:
                queryset = models.Post.objects.filter(publish_date__isnull=False).filter(
                    tags__slug__iexact=self.kwargs['slug']).order_by('-publish_date')

                self.search_form = self.search_form({
                    'tag_input': models.Tag.objects.get(slug=self.kwargs['slug']),
                    'order_input': 0
                })

            # If accessing the URL slug kwarg throws an exception (i.e. the
            # pre-search URL has not been used to access the view) set queryset
            # to return all publish posts with newest first.
            except:
                queryset = models.Post.objects.filter(
                    publish_date__isnull=False).order_by('-publish_date')

        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Add search form to context.
        context['search_form'] = self.search_form

        return context

class UserDraftListView(StaffRequiredMixin, generic.ListView):
    """
    List view of user's drafts with search, filter and sort functionality.
    """
    template_name = 'blog/user_draft_list.html'
    context_object_name = "posts"
    search_form = forms.SearchDraftForm
    paginate_by = 12

    def get_queryset(self):
        """
        Modifies queryset based on user input to form and returns.
        """
        username = self.kwargs['username']
        if not User.objects.filter(username=username).exists():
            raise Http404("User does not exist")
        else:
            if username != self.request.user.username:
                raise PermissionDenied()
            else:
                form = self.search_form(self.request.GET)

                # If valid form data submitted (GET).
                if form.is_valid():
                    # Obtain form data.
                    tag_filter = form.cleaned_data['tag_input']
                    post_filter = form.cleaned_data['post_input']
                    order_by = form.cleaned_data['order_input']

                    # Base queryset, filtered to show user posts that are not published.
                    queryset = models.Post.objects.filter(
                        publish_date__isnull=True).filter(author=self.request.user)

                    # Chain queryset dependent on user search form input.
                    if tag_filter is not None:
                        queryset = queryset.filter(tags__name__iexact=str(tag_filter))
                    if post_filter is not None:
                        queryset = queryset.filter(title__icontains=post_filter)
                    if order_by == '0':
                        queryset = queryset.order_by('-created_date')
                    elif order_by == '1':
                        queryset = queryset.order_by('created_date')

                    # Set search_form values so they are displayed on post-search render.
                    self.search_form = form

                # If form data not submitted, set queryset to return all user posts
                # that are not published with newest first.
                else:
                    queryset = models.Post.objects.filter(publish_date__isnull=True).filter(
                        author=self.request.user).order_by('-created_date')

                return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Add search form to context data.
        context['search_form'] = self.search_form

        return context

class PostUpdateView(StaffRequiredMixin, SuccessMessageMixin,
                     generic.UpdateView):
    """
    Post update accessible by user with staff privileges and is post author.
    """
    form_class = forms.PostForm
    model = models.Post

    # On success, display message on base template.
    success_message = "%(title)s was edited successfully"

    def get_object(self):
        """
        Returns post object if post exists and user is post author.
        """
        obj = get_object_or_404(self.model, pk=self.kwargs.get('pk'))
        if obj.author == self.request.user:
            return obj
        else:
            raise PermissionDenied()

    def form_valid(self, form_class):
        """
        Additional to base, sets post edited date to current date.
        """
        self.object.edited_date = timezone.now()
        return super().form_valid(form_class)

class PostDeleteView(StaffRequiredMixin, generic.DeleteView):
    """
    Post delete accessible by any user with staff privileges.
    """
    model = models.Post
    context_object_name = "post"
    success_url = reverse_lazy('blog:landing')

    def delete(self, *args, **kwargs):
        """
        Additional to base, on success, displays message on base template.
        """
        messages.success(self.request, "Post deleted")
        return super().delete(*args, **kwargs)

### TAG VIEWS ###
class TagCreateView(StaffRequiredMixin, SuccessMessageMixin,
                    generic.CreateView):
    """
    Tag create view accessible by any user with staff privileges.
    """
    form_class = forms.TagForm
    model = models.Tag

    # On success, display message on base template.
    success_message = "%(name)s tag was created successfully"

class TagOverviewView(generic.DetailView):
    """
    Displays tag detail and 4 most recent published posts under that topic.
    """
    model = models.Tag

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Adds post_list context with the 4 most recent posts under the topic.
        context['post_list'] = self.object.posts.filter(
            publish_date__isnull=False)[:4]

        return context

class TagListView(generic.ListView):
    """
    List view of all tags with search and sort functionality.
    """
    template_name = 'blog/tag_list.html'
    context_object_name = "tags"
    paginate_by = 12
    search_form = forms.SearchTagForm

    def get_queryset(self):
        """
        Modifies queryset based on user input to form and returns.
        """
        form = self.search_form(self.request.GET)

        # If valid form data submitted (GET).
        if form.is_valid():

            # Obtain form data.
            name_filter = form.cleaned_data['name_input']
            order_by = form.cleaned_data['order_input']

            # Base queryset, annotated with number of related posts.
            queryset = models.Tag.objects.all().annotate(num_posts=Count('posts'))

            # Chain queryset dependent on user search form input.
            if name_filter is not None:
                queryset = queryset.filter(name__icontains=name_filter)
            if order_by == '0':
                queryset = queryset.annotate(
                    num_posts=Count('posts')).order_by('-num_posts')
            if order_by == '1':
                queryset = queryset.annotate(
                    num_posts=Count('posts')).order_by('num_posts')
            if order_by == '2':
                queryset = queryset.annotate(
                    num_posts=Count('posts')).order_by(Lower('name'))
            if order_by == '3':
                queryset = queryset.annotate(num_posts=Count(
                    'posts')).order_by(Lower('name').desc())

            # Set search_form values so they are displayed on post-search render.
            self.search_form = form

        # If data not submitted, set queryset to return all tags annoted with
        # number of related posts and sorted by highest number of related posts.
        else:
            queryset = models.Tag.objects.annotate(
                num_posts=Count('posts')).order_by('-num_posts')

        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Add search form to context data.
        context['search_form'] = self.search_form

        return context

class TagUpdateView(StaffRequiredMixin, SuccessMessageMixin,
                    generic.UpdateView):
    """
    Tag update view accessible by any user with staff privileges.
    """
    form_class = forms.TagForm
    model = models.Tag

    # On success, display message on base template.
    success_message = "%(name)s tag was edited successfully"

class TagDeleteView(StaffRequiredMixin, generic.DeleteView):
    """
    Tag delete view accessible by any user with staff privileges.
    """
    model = models.Tag
    context_object_name = "tag"
    success_url = reverse_lazy('blog:tag-list')

    def delete(self, *args, **kwargs):
        """
        Additional to base, on success, displays message on base template.
        """
        messages.success(self.request, "Topic deleted")
        return super().delete(*args, **kwargs)

### COMMENT VIEWS ###
class Comment(LoginRequiredMixin, SingleObjectMixin, generic.FormView):
    """
    POST method CBV for PostDetailView. Requires user to be logged in.
    """
    template_name = 'blog/post_detail.html'
    form_class = forms.CommentForm
    model = models.Post

    def form_valid(self, form_class):
        """
        Additional to base, sets author to user and saves post to comment.
        """
        form_class.instance.author = self.request.user
        form_class.instance.post = self.object
        form_class.instance.save()

        # On success, display message on base template.
        messages.success(self.request, "Comment posted successfully!")

        return super().form_valid(self.form_class)

    def post(self, *args, **kwargs):
        """
        Additional to base, sets post object to comment class object attribute.
        """
        self.object = self.get_object()

        # Raises HTTP 403 if post not published.
        if self.object.publish_date is None:
            raise PermissionDenied()

        return super().post(self.request, *args, **kwargs)

    def get_success_url(self):
        """
        Sets success URL as the current post detail page.
        """
        return reverse('blog:post-detail', kwargs={'pk': self.object.pk})

class CommentListView(generic.ListView):
    """
    Additonal comment list view if >10 comments under post.
    """
    template_name = 'blog/comment_list.html'
    context_object_name = "comments"
    paginate_by = 10

    def get_queryset(self):
        """
        Returns queryset with post comments and order with newest first.
        """
        return (models.Comment.objects
                .filter(post=self.kwargs.get('pk'))
                .order_by("-created_date"))

class CommentUpdateView(LoginRequiredMixin, generic.UpdateView):
    """
    Comment update accessible user who is logged in and is comment author.
    """
    form_class = forms.CommentForm
    model = models.Comment

    def get_object(self):
        """
        Returns object if exists and user has permission.
        """
        obj = get_object_or_404(self.model, pk=self.kwargs.get('pk'))
        if obj.author == self.request.user:
            return obj
        else:
            raise PermissionDenied()

    def form_valid(self, form_class):
        """
        Additional to base, sets edited date to current and displays message.
        """
        self.object.edited_date = timezone.now()
        messages.success(self.request, "Comment was edited successfully!")
        return super().form_valid(form_class)

class CommentDeleteView(LoginRequiredMixin, generic.DeleteView):
    """
    Comment delete accessible by user who is comment author or staff.
    """
    model = models.Comment

    def get_object(self):
        """
        Get comment object if user is comment author.
        """
        obj = get_object_or_404(self.model, pk=self.kwargs.get('pk'))
        if obj.author == self.request.user or self.request.user.is_staff:
            return obj
        else:
            raise PermissionDenied()

    def get_success_url(self):
        """
        Sets success URL as the current post detail page.
        """
        return reverse('blog:post-detail', kwargs={'pk': self.object.post.pk})

    def delete(self, *args, **kwargs):
        """
        Additional to base, on success, displays message on base template.
        """
        messages.success(self.request, "Comment deleted")
        return super().delete(*args, **kwargs)

### More funtionality ###
def is_staff(user):
    """
    Callable returning if user is staff for user_passes_test decorator.
    """
    return user.is_staff

@user_passes_test(is_staff, login_url='/', redirect_field_name=None)
def post_publish(request, pk):
    """
    Sets publish date to current date.
    """
    post = get_object_or_404(models.Post, pk=pk)
    post.publish()
    messages.success(request, "Published!")
    return redirect('blog:post-detail', pk=post.pk)


import tensorflow as tf
print(" we are currently using Tensorflow version {}".format(tf.__version__))
import numpy as np
import random
#from IPython.display import clear_output
from collections import deque
import MyFrozenLakeEnv as MyEnv
#import progressbar

#import gym

#from tensorflow.keras import Model, Sequential
#from tensorflow.keras.layers import Dense, Reshape
#from tensorflow.keras.optimizers import Adam, SGD
#from tensorflow import keras

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
#from tensorflow import keras

#env = gym.make("FrozenLake8x8-v0")
#env = gym.make("FrozenLake-v0")
env = MyEnv.FrozenLakeEnv()
env.render()
print('Number of states: {}'.format(env.observation_space.n))
print("number of actions: {}".format(env.action_space.n))

# make some changes for git
class Q_learn:
  def __init__(self, env, optimizer, episodes, explore):
    self._state_size = env.observation_space.n
    self._action_size = env.action_space.n
    self._optimizer = optimizer
    self.gamma = 0.9
    self.episodes = episodes
    self.epsilon = explore
    #We save the experience for success and failures induvidually.
    #Usually there are two many faliure and we get rewards only when we readch the goal. There are no intermediate rewards.
    # Consequently, distribution over success /failures are imbalanced.
    #So training the algo on failures is useful, only if we have some date where we succeeded.
    self.experience_replay_s = deque(maxlen = 2000)
    self.experience_replay_f = deque(maxlen = 2000)

    self.q_network = self.network_model()
    self.target_network = self.network_model()
    self.copy_weights()

  def copy_weights(self):
    """
    copies weigths from current Q network to a target Q network
    """
    self.target_network.set_weights(self.q_network.get_weights())

  def store(self, state, action, reward, next_state, terminated):
    """
    We save the experience for success and failures induvidually.
    """
    if reward>0.0:
      self.experience_replay_s.append((state, action, reward, next_state, terminated))
    else:
      self.experience_replay_f.append((state, action, reward, next_state, terminated))

  def eps_policy(self, state):
    """
    Episilon greedy policy
    """
    if np.random.rand() <= self.epsilon:
      return env.action_space.sample()
    else:
      q_values = self.q_network.predict(np.array([state]))
      return np.argmax(q_values[0])

  def network_model(self):
    """
    NN model for Q value function
    """
    model = Sequential()
    model.add(Dense(50, activation='relu', input_shape=[1]))
    model.add(Dense(50, activation='relu'))
    model.add(Dense(self._action_size, activation='relu'))
    model.compile(loss = 'mse', optimizer = self._optimizer)
    return model

  def test_fun(self, state, action, reward, next_state, terminated):
    """
    using s, a, r, s' we compute the target
    """
    target = self.q_network.predict(np.array([state]))
    if terminated:
      target[0][int(action)] = reward
    else:
      #A = np.ones(self._action_size, dtype=float)*self.epsilon/self._action_size # [eps/n ....n.... eps/n]
      #q_values = self.target_network.predict(np.array([state]))
      #best_action = np.argmax(q_values[0])
      #A[best_action] += (1.0 - self.epsilon)
      #A captures the prop distribution of actions for a given state
      q_val_next_state = self.target_network.predict(np.array([next_state]))
      # Now take the Expectation of Next Q value over all possible actions of the given policy A
      #Expected_next_q_value = np.sum(np.array(q_val_next_state)*A)
      target[0][int(action)] = reward + self.gamma*np.amax(q_val_next_state)
    return list(target[0])

  def train(self, batch_size):
    """
    we randomly sample a batch with replacement from both successful and and failure buffers
    We fit the Q network with this batch
    """
    minibatch_s = np.array(random.choices(self.experience_replay_s, k = batch_size))
    minibatch_f = np.array(random.choices(self.experience_replay_f, k = batch_size))
    minibatch = np.concatenate((minibatch_s,minibatch_f), axis =0)
    batch_state = minibatch[:,0]
    batch_target = np.array([self.test_fun(state, action, reward, next_state, terminated) for state, action, reward, next_state, terminated in minibatch])

    self.q_network.fit(batch_state, batch_target, epochs = 1, verbose = 1)

optimizer = Adam(learning_rate=0.01)
test_agent = Q_learn(env, optimizer, episodes= 100, explore =0.9)

print("Testing the model:")
test_agent.q_network.build()
print(test_agent.q_network.summary())
test_predicted = test_agent.q_network.predict(np.array([env.observation_space.sample()]))
print("predict the q_values for a random sample is {}".format(test_predicted))
test_history = test_agent.q_network.fit(np.array([env.observation_space.sample()]), test_predicted, epochs=1)

optimizer = Adam(learning_rate=0.01)
#optimizer = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)

agent = Q_learn(env, optimizer,episodes=1000000, explore = 0.9)

batch_size = 2000
num_of_episodes = 1000000
timesteps_per_episode = 128
Fail = 0
S = 0
for epi in range(0,num_of_episodes):
  state = env.reset()

  reward = 0
  if S>=1000:
    agent.epsilon = 0.1
  else:
    #until we get 50 success we explore a lot
    agent.epsilon = 0.99

  terminated  = False

  for steps in range(timesteps_per_episode):
    action = agent.eps_policy(state)
    next_state, reward, terminated, _  = env.step(action)
    agent.store(state, action, reward, next_state, terminated)
    state = next_state

    #bar.finish()
    if S>=1000:
        print("**********************************")
        env.render()
        print("**********************************")
    if terminated:
      if reward > 0.0:
        S=S+1
      else:
        Fail = Fail +1
      break
  if S>=1000:
    """
    we train only after getting enough experience
    """
    agent.train(batch_size)
    agent.copy_weights()
    print("Episode: {}, Success = {}, Failures = {}, exploration ={}".format(epi + 1, S, Fail, agent.epsilon))
  if epi%100 ==0:
    print("Episode: {}, Success = {}, Failures = {}, exploration ={}".format(epi + 1, S, Fail, agent.epsilon))


from tkinter import *
import random
from tkinter import messagebox

gewinner_zahlen = []
geclickt = 0

def play():
    gewinner_zahlen = []
    x = 0
    y = 0
    main = Tk()
    main.title("Glücksklicker")
    main.geometry("600x600")
    for _ in range(10):
        for _ in range(10):
            Teil = Button(main, text="Drücken", command=click)
            Teil.place(x=x, y=y, width=60, height=60)
            x += 60
        y += 60
        x = 0
    main.mainloop()

def nochmal():
    question = messagebox.askquestion("Nochmal?", "Willst es nochmal versuchen?")
    if question == "yes":
        main.destroy()
        play()
    else:
        exit()

def click():
    gewinner_zahlen = []
    janein = random.randint(1, 36)
    for _ in range(6):
        gewinne = random.randint(1,36)
        while gewinne in gewinner_zahlen:
            gewinne = random.randint(1, 36)

        gewinner_zahlen.append(gewinne)
    if janein in gewinner_zahlen:
        messagebox.showinfo("Win", "Du hast gewonnen")
        nochmal()
    else:
        messagebox.showerror("Verloren", "Du hast leider verloren")
        nochmal()

play()


class ObjcProperty(object):
    __NUMBER__ = ('NSUnderlineStyle', 'BOOL', 'NSLigatureType', 'float', 'NSInteger', 'NSVerticalGlyphForm')
    __ASSIGN__ = __NUMBER__ + ('NSWritingDirectionAttributes',)
    __IMPL__ = ('writingDirection', 'writingDirectionArray')

    def __init__(self, type, name, available=None):
        self.type = type
        self.name = name
        self.available = available
        self.proptype = 'assign' if self.type in self.__ASSIGN__ else 'retain'

    @property
    def Name(self):
        return self.name[0].upper() + self.name[1:]
    @property
    def is_pointer(self):
        return self.type[-1] == '*'

    @property
    def has_number(self):
        return self.type in self.__NUMBER__

    @property
    def has_impl(self):
        return self.name in self.__IMPL__

    @property
    def available_ios(self):
        return 'NS_AVAILABLE_IOS(%s)' % self.available

    @property
    def number(self):
        if self.type == 'float':
            return 'float'
        if self.type == 'NSInteger':
            return 'integer'
        if self.type == 'BOOL':
            return 'bool'
        return 'unsignedInteger'

    @property
    def Number(self):
        n = self.number
        return n[0].upper() + n[1:]

O = ObjcProperty

props = [
    O('UIFont *', 'font'),
    O('NSParagraphStyle *', 'paragraphStyle'),
    O('UIColor *', 'foregroundColor'),
    O('UIColor *', 'backgroundColor'),
    O('NSLigatureType', 'ligature'),
    O('float', 'kern'),
    O('NSUnderlineStyle', 'strikethroughStyle'),
    O('NSUnderlineStyle', 'underlineStyle'),
    O('UIColor *', 'strokeColor'),
    O('float', 'strokeWidth'),
    O('NSShadow *', 'shadow'),
    O('NSVerticalGlyphForm', 'verticalGlyphForm', '6_0'),
]


#Romania Problem with dictionary
distance_problem=Dict(
    Arad=Dict(Zerind=75, Sibiu=140, Timisoara=118),
    Bucharest=Dict(Urziceni=85, Pitesti=101, Giurgiu=90, Fagaras=211),
    Craiova=Dict(Drobeta=120, Rimnicu=146, Pitesti=138),
    Drobeta=Dict(Mehadia=75),
    Etorie=Dict(Hirsova=86),
    Fagaras=Dict(Sibiu=99),
    Hirsova=Dict(Urziceni=98),
    Iasi=Dict(Vaslui=92, Neamt=87),
    Lugoj=Dict(Timisoara=111, Mehadia=70),
    Oradea=Dict(Zerind=71, Sibiu=151),
    Pitesti=Dict(Rimnica=97),
    Rimnicu=Dict(Sibiu=80),
    Uraziceni=Dict(Vaslui=142))


from __future__ import absolute_import, division, print_function

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch_geometric.nn as geom_nn

class MLP(nn.Module):
    """
    This class implements a Multi-layer Perceptron in PyTorch.
    It handles the different layers and parameters of the model.
    Once initialized an MLP object can perform forward.
    """

    def __init__(self, n_inputs, n_hidden, n_outputs):
        """
        Initializes MLP object for (multivariate) regression

        Parameters
        ----------
        n_inputs : int
            number of inputs.
        n_hidden : list of int
            specifies the number of units in each linear layer.
            If the list is empty, the MLP will not have any
            linear layers, and the model will simply
            perform a multinomial logistic regression.
        n_outputs : int
            This number is required in order to specify the
            output dimensions of the MLP
        """

        #######################
        # PUT YOUR CODE HERE  #
        #######################
        super(MLP, self).__init__()
        # getting all dims
        dims = [n_inputs] + n_hidden + [n_outputs]
        # first layer outside loop so that loop ends with linear
        self.layers = nn.ModuleList([nn.Linear(dims[0], dims[1])])
        for i in range(1, len(dims) - 1):
            self.layers.append(nn.ReLU())
            self.layers.append(nn.Linear(dims[i], dims[i + 1]))
        #######################
        # END OF YOUR CODE    #
        #######################

    def forward(self, x):
        """
        Performs forward pass of the input. Here an input tensor x is transformed through
        several layer transformations.

        Args:
            x: input to the network
        Returns:
            out: outputs of the network
        """

        #######################
        # PUT YOUR CODE HERE  #
        #######################
        x = x.view(x.shape[0], -1)
        for layer in self.layers:
            x = layer(x)
        out = x
        #######################
        # END OF YOUR CODE    #
        #######################
        return out

    @property
    def device(self):
        """
        Returns the device on which the model is. Can be useful in some situations.
        """
        return next(self.parameters()).device

class GNN(nn.Module):
    """
    implements a graph neural network in pytorch.
    In particular, we will use pytorch geometric's
    nn_conv module so we can apply a neural network to the edges.
    """

    def __init__(
        self,
        n_node_features: int,
        n_edge_features: int,
        n_hidden: int,
        n_output: int,
        num_convolution_blocks: int,
    ) -> None:
        """
        Initializes a GNN with the following structure:
        node embedding -> [ReLU -> RGCNConv -> ReLU -> MFConv] x num_convs -> Add-Pool -> Linear -> ReLU -> Linear

        Parameters
        ----------
        n_node_features : int
            number of input features on each node
        n_edge_features : int
            number of input features on each edge
        n_hidden : int
            number of hidden features within the neural networks
            (embeddings, nodes after graph convolutions, etc.)
        n_output : int
            how many output features
        num_convolution_blocks : int
            how many blocks convolutions should be performed.
            A block may include multiple convolutions
        """

        #######################
        # PUT YOUR CODE HERE  #
        #######################
        super(GNN, self).__init__()
        self.embedding = nn.Linear(n_node_features, n_hidden)
        self.GNN = nn.ModuleList([])
        for i in range(num_convolution_blocks):
            conv_block = nn.ModuleList(
                [
                    nn.ReLU(),
                    geom_nn.RGCNConv(n_hidden, n_hidden, n_edge_features),
                    nn.ReLU(),
                    geom_nn.MFConv(n_hidden, n_hidden),
                ]
            )
            self.GNN.append(conv_block)
        self.head = nn.Sequential(
            nn.Linear(n_hidden, n_hidden), nn.ReLU(), nn.Linear(n_hidden, n_output)
        )
        #######################
        # END OF YOUR CODE    #
        #######################

    def forward(
        self,
        x: torch.Tensor,
        edge_index: torch.Tensor,
        edge_attr: torch.Tensor,
        batch_idx: torch.Tensor,
    ) -> torch.Tensor:
        """
        Parameters
        ----------
        x : torch.Tensor
            Input features per node
        edge_index : torch.Tensor
            List of vertex index pairs representing the edges in the graph
            (PyTorch geometric notation)
        edge_attr : torch.Tensor
            edge attributes (pytorch geometric notation)
        batch_idx : torch.Tensor
            Index of batch element for each node

        Returns
        -------
        prediction : torch.Tensor
        """

        #######################
        # PUT YOUR CODE HERE  #
        #######################
        x = self.embedding(x)
        for block in self.GNN:
            for layer in block:
                if isinstance(layer, geom_nn.RGCNConv):
                    x = layer(x, edge_index, edge_attr)
                elif isinstance(layer, geom_nn.MFConv):
                    x = layer(x, edge_index)
                else:
                    x = layer(x)
        x = geom_nn.global_add_pool(x, batch_idx)
        out = self.head(x)
        #######################
        # END OF YOUR CODE    #
        #######################
        return out

    @property
    def device(self):
        """
        Returns the device on which the model is. Can be useful in some situations.
        """
        return next(self.parameters()).device


""" @author: Adam, @date: 8-6-2019

Convert to numeric values, then back to minimal Roman numerals. """

import time

#%% Solution.

roman_dict = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}

def roman_to_n(roman):
    """Convert a Roman numeral to its numeric value."""
    s = 0
    str_len = len(roman)
    i = 0
    while i < str_len:
        if i == (str_len - 1):  # Don't check for subtractive pairs
            s += roman_dict[roman[i]]
            break

        # Add value, accounting for subtracive pairs.
        val = roman_dict[roman[i]]
        next_val = roman_dict[roman[i+1]]
        if val < next_val:
            s += next_val - val
            i += 2
        else:
            s += val
            i += 1
    return s

# Possible values and Roman numeral combinations to add.
roman_options = [(900, 'CM'), (500, 'D'), (400, 'CD'),
                 (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
                 (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

def n_to_roman(n, options):
    """Convert a number to its minimal Roman numeral representation."""

    # Pad with largest denomination M
    roman = '' + 'M' * (n // 1000)
    n = n % 1000

    # Iteratively append to Roman numeral, depending on option.
    for option in roman_options:
        val = option[0]
        letters = option[1]
        while n >= val:
            n -= val
            roman += letters

    return roman

# Extract list of valid Roman numerals.
file = open("p89_roman.txt")
text = file.read()
file.close()
romans = text.split("\n")

# Sum difference between original and minimal representation.
start_time = time.time()

count = 0
for roman in romans:
    n_original = len(roman)
    n_minimal = len(n_to_roman(roman_to_n(roman), roman_options))
    count += (n_original - n_minimal)
print(count)

print(time.time() - start_time)

#%% Comments.
""" Potential improvements:

    Extensions/Remarks:
"""


path_1 = input('Please enter file path 1: ')
path_2 = input('Please enter file path 2: ')
fg1 = open(path_1)
fg2 = open(path_2)
list1 = fg1.readlines()
list2 = fg2.readlines()
length1 = len(list1)
length2 = len(list2)
min1 = min(length1, length2)
max1 = max(length1, length2)
list_linenum = []
for i in range(0,min1):
	if list1[i].strip('\n') != list2[i].strip('\n'):
		list_linenum.append(str(i))
for j in range(min1,max1):
	list_linenum.append(str(j))
print(', '.join(list_linenum))
fg1.close()
fg2.close()


from pathlib import Path
import tempfile
from kttool.actions.gen import Gen
import unittest
import shutil
import pytest

@pytest.mark.parametrize(
    "test_id", ['oddmanout', 'https://open.kattis.com/problems/oddmanout']
)
def test_gen_action(test_id):
    temp_dir = Path(tempfile.gettempdir()) / 'kttool' / 'gen_test'

    action = Gen(test_id, cwd=temp_dir)
    action.act()
    assert (temp_dir / 'oddmanout/ans1.txt').is_file()
    assert (temp_dir / 'oddmanout/in1.txt').is_file()

    with open(temp_dir / 'oddmanout/in1.txt', 'r') as f:
        assert f.read(
        ) == """3\n3\n1 2147483647 2147483647\n5\n3 4 7 4 3\n5\n2 10 2 10 5\n"""
    with open(temp_dir / 'oddmanout/ans1.txt', 'r') as f:
        assert f.read() == """Case #1: 1\nCase #2: 7\nCase #3: 5\n"""

    shutil.rmtree(temp_dir)


from django.urls import include, re_path
from django.contrib.auth import views as auth_views

from punkweb_boards.conf.settings import BOARD_THEME
from punkweb_boards import views
from punkweb_boards.forms import LoginForm

app_name = "board"

urlpatterns = [
    re_path(r"^$", views.index_view, name="index"),
    re_path(r"^page/", include("punkweb_boards.page_urls")),
    re_path(r"^unpermitted/$", views.unpermitted_view, name="unpermitted"),
    re_path(r"^register/$", views.registration_view, name="register"),
    re_path(
        r"^login/$",
        auth_views.LoginView.as_view(
            template_name="punkweb_boards/themes/{}/login.html".format(BOARD_THEME),
            authentication_form=LoginForm,
        ),
        name="login",
    ),
    re_path(
        r"^logout/$",
        auth_views.LogoutView.as_view(),
        name="logout",
    ),
    re_path(r"^me/$", views.my_profile, name="me"),
    re_path(r"^settings/$", views.settings_view, name="settings"),
    re_path(r"^profile/(?P<username>[^/]+)/$", views.profile_view, name="profile"),
    re_path(r"^search/$", views.keyword_search_view, name="search"),
    re_path(
        r"^category/(?P<pk>[^/]+)/$",
        views.category_detail,
        name="category-detail",
    ),
    re_path(
        r"^subcategory/(?P<pk>[^/]+)/$",
        views.subcategory_detail,
        name="subcategory-detail",
    ),
    re_path(r"^thread/(?P<pk>[^/]+)/?$", views.thread_view, name="thread"),
    re_path(
        r"^create_thread/(?P<category_id>[^/]+)/$",
        views.thread_create,
        name="thread-create",
    ),
    re_path(
        r"^update_thread/(?P<pk>[^/]+)/$",
        views.thread_update,
        name="thread-update",
    ),
    re_path(
        r"^delete_thread/(?P<pk>[^/]+)/$",
        views.thread_delete,
        name="thread-delete",
    ),
    re_path(r"^update_post/(?P<pk>[^/]+)/$", views.post_update, name="post-update"),
    re_path(r"^delete_post/(?P<pk>[^/]+)/$", views.post_delete, name="post-delete"),
    re_path(r"^reports/$", views.reports_list, name="reports-list"),
    re_path(r"^report/(?P<pk>[^/]+)/", views.report_view, name="report"),
    re_path(
        r"^report_thread/(?P<thread>[^/]+)/$",
        views.report_create,
        name="report-thread",
    ),
    re_path(
        r"^report_post/(?P<post>[^/]+)/$",
        views.report_create,
        name="report-post",
    ),
    re_path(r"^members/$", views.members_list, name="members-list"),
    re_path(
        r"^notification_redirect/(?P<pk>[^/]+)/$",
        views.notification_redirect,
        name="notification-redirect",
    ),
]