#################################################################
# FILE : image_editor.py
# WRITER : your_name , your_login , your_id
# EXERCISE : intro2cs ex5 2022-2023
# DESCRIPTION: A simple program that...
# STUDENTS I DISCUSSED THE EXERCISE WITH: Bugs Bunny, b_bunny.
#								 	      Daffy Duck, duck_daffy.
# WEB PAGES I USED: www.looneytunes.com/lola_bunny
# NOTES: ...
#################################################################

##############################################################################
#                                   Imports                                  #
##############################################################################
import math
import sys
from math import floor

from ex5_helper import *
from typing import Optional

##############################################################################
#                                  Functions                                 #
##############################################################################
GRAY_SCALE = 'G'

def separate_channels(image: ColoredImage) -> List[SingleChannelImage]:
    res = []
    num_channels = len(image[0][0])
    for i in range(num_channels):
        channel_lines = []
        for line in image:
            channel_line = []
            for channels in line:
                channel_line.append(channels[i])
            channel_lines.append(channel_line)
        res.append(channel_lines)
    return res

def combine_channels(channels: List[SingleChannelImage]) -> ColoredImage:
    num_channels = len(channels)
    num_lines = len(channels[0])
    num_cols = len(channels[0][0])

    image = []
    for i in range(num_lines):
        image.append([])
        for _ in range(num_cols):
            image[i].append([])

    for c in range(num_channels):
        for i in range(num_lines):
            for j in range(num_cols):
                image[i][j].append(channels[c][i][j])

    return image

def RGB2grayscale(colored_image: ColoredImage) -> SingleChannelImage:
    def channel2grayscale(channel):
        return round(channel[0] * 0.299 + channel[1] * 0.587 + channel[2] * 0.114)

    gray_image = []
    for line in colored_image:
        gray_line = []
        for channel in line:
            gray_line.append(channel2grayscale(channel))
        gray_image.append(gray_line)
    return gray_image

def blur_kernel(size: int) -> Kernel:
    return [[1 / (size ** 2) for _ in range(size)] for _ in range(size)]

'''def apply_kernel(image: SingleChannelImage, kernel: Kernel) -> SingleChannelImage:
    side = len(kernel) // 2
    nrows = len(image)
    ncolumns = len(image[0])
    rows = []
    for _ in range(ncolumns):
        rows.append(0)
    new_image = [[rows] * nrows]
    for i_image in range(len(image)):
        for j_image in range(len(image)):
            for i_kernel in range(len(kernel)):
                for j_kernel in range(len(kernel)):
                    i_transposed = i_kernel - side
                    j_transposed = j_kernel - side
                    if i_image + i_transposed < 0:
                        if i_image + i_transposed >= len(image):
                            if j_image + j_transposed < 0:
                                if j_image + j_transposed >= len(image[0]):
                                    new_image[i_image][j_image] += image[i_image][j_image] * kernel[i_kernel][j_kernel]
                    else:
                        new_image[i_image][j_image] += image[i_image + i_kernel][j_image + j_kernel] * kernel[i_kernel][
                            j_kernel]

'''

def apply_kernel(image: SingleChannelImage, kernel: Kernel) -> SingleChannelImage:
    num_lines = len(image)
    num_cols = len(image[0])
    k_size = len(kernel)
    half_k_size = k_size // 2

    def conv_op(im, k, i, j):
        sum = 0.0
        for i_im, i_k in zip(range(i - half_k_size, i + half_k_size + 1), range(0, k_size)):

            for j_im, j_k in zip(range(j - half_k_size, j + half_k_size + 1), range(0, k_size)):
                if 0 <= j_im < num_cols and 0 <= i_im < num_lines:
                    sum += im[i_im][j_im] * k[i_k][j_k]
                else:
                    sum += im[i][j] * k[i_k][j_k]
        sum = round(sum)

        if sum > 255:
            return 255
        if sum < 0:
            return 0
        return sum

    res = []

    for i in range(num_lines):
        line = []
        for j in range(num_cols):
            line.append(conv_op(image, kernel, i, j))
        res.append(line)
    return res

def bilinear_interpolation(image: SingleChannelImage, y: float, x: float) -> int:
    h = len(image)
    w = len(image[0])

    x_floor = math.floor(x)
    x_ceil = min(w - 1, math.ceil(x))
    y_floor = math.floor(y)
    y_ceil = min(h - 1, math.ceil(y))
    #print(f'h: {h}, w:{w}, x_ceil = {x_ceil}, x_floor: {x_floor}, y_ceil: {y_ceil}, y_floor: {y_floor}, new_x: {x}, new_y: {y}')

    if (x_ceil == x_floor) and (y_ceil == y_floor):
        q = image[int(x_ceil)][int(x_ceil)]

    elif x_ceil == x_floor:
        q1 = image[ int(y_floor)][int(x_ceil)]
        q2 = image[ int(y_ceil)][int(x_ceil)]

        #print(f'q1: {q1}, q2: {q2}')

        q = q1 * (y_ceil - y) + q2 * (y - y_floor)
    elif y_ceil == y_floor:
        q1 = image[int(y_ceil)][int(x_floor)]
        q2 = image[int(y_ceil)][int(x_ceil)]
        #print(f'q1: {q1}, q2: {q2}')
        q = q1 * (x_ceil - x) + q2 * (x - x_floor)
    else:
        a = image[y_floor][x_floor]
        b = image[y_ceil][x_floor]
        c = image[y_floor][x_ceil]
        d = image[y_ceil][x_ceil]
        #print(f'a: {a}, b: {b}, c: {c}, d: {d} ')
        q1 = a * (x_ceil - x) + b * (x - x_floor)
        q2 = c * (x_ceil - x) + d * (x - x_floor)
        q = q1 * (y_ceil - y) + q2 * (y - y_floor)

    return math.ceil(q)

def resize(image: SingleChannelImage, new_height: int, new_width: int) -> SingleChannelImage:
    old_h = len(image)
    old_w = len(image[0])

    w_scale_factor = old_w / new_width
    h_scale_factor = old_h / new_height

    new_im = []
    mat_coord = []
    for i in range(0,new_height):
        line = []
        c_line = []
        for j in range(0, new_width):
            y =i  * h_scale_factor
            x =j  * w_scale_factor
            c_line.append([round(y,2),round(x,2)])
            line.append(bilinear_interpolation(image, y,x))
        new_im.append(line)
        mat_coord.append(c_line)

    new_im[0][0] = image[0][0]
    new_im[0][-1] = image[0][-1]
    new_im[-1][0] = image[-1][0]
    new_im[-1][-1] = image[-1][-1]
    #print(mat_coord)
    #print(new_im)
    return new_im
def rotate_90(image: Image, direction: str) -> Image:
    num_lines = len(image)
    num_cols = len(image[0])
    if direction == 'R':
        new_image = list(reversed(image))

    if direction == 'L':
        new_image = []
        for line in image:
            new_image.append(list(reversed(line)))
    res = []
    for i in range(num_cols):
        res.append([])

    for i in range(num_lines):
        for j in range(num_cols):
            res[j].append(new_image[i][j])

    return res

def get_edges(image: SingleChannelImage, blur_size: int, block_size: int, c: float) -> SingleChannelImage:
    blurred_image = apply_kernel(image, blur_kernel(blur_size))
    half_k_size = block_size // 2
    num_lines = len(image)
    num_cols = len(image[0])
    k_size = block_size

    def avg_op(im, i, j):
        vals = []
        for i_im, i_k in zip(range(i - half_k_size, i + half_k_size + 1), range(0, k_size)):

            for j_im, j_k in zip(range(j - half_k_size, j + half_k_size + 1), range(0, k_size)):
                if 0 <= j_im < num_cols and 0 <= i_im < num_lines:
                    vals.append(im[i_im][j_im])
                else:
                    vals.append(im[i][j])
        return sum(vals)/len(vals)
    new_img = []

    for i in range(len(blurred_image)):
        new_line = []
        for j in range(len(blurred_image[i])):
            t = avg_op(blurred_image, i,j) - c
            if blurred_image[i][j] < t:
                new_line.append(0)
            else:
                new_line.append(255)
        new_img.append(new_line)
    return new_img

def quantize(image: SingleChannelImage, N: int) -> SingleChannelImage:
    return [[round(math.floor(image[i][j] * (N / 256)) * (255 / (N - 1))) for j in range(len(image[0]))] for i in
            range(len(image))]

def quantize_colored_image(image: ColoredImage, N: int) -> ColoredImage:
    channels = separate_channels(image)
    quantized_channels = [quantize(c, N) for c in channels]
    return combine_channels(quantized_channels)

def type_image(img):
    if type(img[0][0]) == type(2):
        return GRAYSCALE_CODE
    else:
        return RGB_CODE

if __name__== "__main__":
    img_path = sys.argv[1]
    img = load_image(img_path)
    keep_running = True
    while keep_running:

        x = input('Choose operation: ')
        while x not in [str(i) for i in range(1,9)]:
            print('Invalid op')
            x = input('Choose operation: ')

        # Convert to Grayscale
        if x == '1':
            if type_image(img) == RGB_CODE:
                img = RGB2grayscale(img)
                print('Successfully converted to grayscale')
            else:
                print('Image already in grayscale')

        # Blur the image
        elif x == '2':
            blur_size = input('Choose blur size: ')
            if not blur_size.isnumeric() and int(blur_size) % 2 == 0:
                print('Invalid Blur Size')
            else:
                blur_size = int(blur_size)
                k = blur_kernel(blur_size)
                if type_image(img) == GRAYSCALE_CODE:
                    img = apply_kernel(img, k)
                else:
                    img = combine_channels([apply_kernel(channel, k) for channel in separate_channels(img)])
                print('Successfully blurred')

        # Resize
        elif x == '3':
            params = input('Chose new height and width (format H,W): ')
            h,w = params.split(',')
            if h.isnumeric() and int(h) > 0 and w.isnumeric() and int(w) > 0:
                h = int(h)
                w = int(w)
                if type_image(img) == GRAYSCALE_CODE:
                    img = resize(img, h,w)
                else:
                    img = combine_channels([resize(channel,h,w) for channel in separate_channels(img)])
                print(f'Successfully reshaped to {h}x{w}')
            else:
                print('Invalid input')

        # Rotate the image:
        elif x == '4':
            rotation = input('Chose rotation (R for right or L for left): ')
            if rotation == 'R':
                img = rotate_90(img,rotation)
                print('Successfully rotated the image 90° right')
            elif rotation == 'L':
                img = rotate_90(img, rotation)
                print('Successfully rotated the image 90° left')
            else:
                print(f'Invalid rotation {rotation} is not R or L')

        # Edge detection
        elif x == '5':
            params = input('Chose the params (format: blur_size, block_size,block_size,c): ')
            blur_size, block_size, c = params.split(',')

            block_ok = block_size.isnumeric and int(block_size) % 2 == 1 and  int(block_size) > 0
            blur_ok = blur_size.isnumeric and int(blur_size) % 2 == 1 and int(blur_size) > 0
            c_ok = c.replace('.','').isnumeric() and float(c) >= 0

            if block_ok and blur_ok and c_ok:

                block = int(block_size)
                blur = int(blur_size)
                c = float(c)

                if type_image(img) == GRAYSCALE_CODE:
                    img = get_edges(img,blur, block,c)
                else:
                    img = get_edges(RGB2grayscale(img),blur, block,c)

                print('Edges Successfully detected')
            else:
                print('Invalid input')

        # Quantization
        elif x == '6':
            N = input('Chose the number of tints: ')

            if N.isnumeric() and 2 <= int(N) <= 255:
                N = int(N)
                if type_image(img) == RGB_CODE:
                    img = quantize_colored_image(img, N)
                else:
                    img = quantize(img, N)

                print(f'Successfully quantized the image to {N} colors')
            else:
                print('Invalid input')

        elif x == '7':
            show_image(img)
        elif x == '8':
            save_image(img,'my_'+img_path)
            print('Successfully saved the image')
            break


import asyncio
import json
from datetime import datetime

from .exception import (
    AioAlipayTimeoutError,
    AioAlipayAuthError,
)
from .util import sign_data

class AioAlipayAuth:

    async def get_oauth_token(self, code):
        timestamp = datetime.now()
        params = {
            'app_id': self.app_id,
            'method': 'alipay.system.oauth.token',
            'charset': 'utf-8',
            'sign_type': 'RSA2',
            'version': '1.0',
            'timestamp': timestamp.strftime("%Y-%m-%d %H:%M:%S"),
            'grant_type': 'authorization_code',
            'code': code,
        }

        sign = sign_data(self.app_private_key, params)
        params['sign'] = sign

        url = 'https://openapi.alipay.com/gateway.do'

        try:
            async with self._session.get(url, params=params,
                                         timeout=self.timeout) as resp:
                resp_text = await resp.text()
                # print(resp_text)
                result = json.loads(resp_text)
                if 'error_response' in result:
                    raise AioAlipayAuthError(result)
                data = result.get('alipay_system_oauth_token_response')
                access_token = data.get('access_token')
                user_id = data.get('user_id')
                return access_token, user_id

        except asyncio.TimeoutError:
            raise AioAlipayTimeoutError()


#!/usr/bin/python3

#this file contains a gold standard of case markers for Latin, Modern Greek, German, Russian, Turkish and Finnish
#for each language, a nested dictionary in three-levels is created
#the first level keys are the inflected parts of speech, the second level keys the differentiated numbers and the third level keys the respective cases whose final value is a set of their markers
#word boundaries are indicated by $ to differentiate suffixes ('a$') from prefixes ('$a'), infixes ('a') and complete word forms ('$a$')

#gold standard of Latin case markers
latin = {}

#POS
latin['noun'] = {}
latin['adjective'] = {}
latin['numeral'] = {}
latin['pronoun'] = {}

#NUM
latin['noun']['singular'] = {}
latin['adjective']['singular'] = {}
latin['numeral']['singular'] = {}
latin['pronoun']['singular'] = {}

latin['noun']['plural'] = {}
latin['adjective']['plural'] = {}
latin['numeral']['plural'] = {}
latin['pronoun']['plural'] = {}

#CAS
#nouns
latin['noun']['singular']['nominative'] = {'a$', 'us$', 'um$', 'is$', 's$', 'e$', 'o$', 'u$', 'es$'}
latin['noun']['singular']['vocative'] = {'a$', 'e$', 'um$', 'is$', 's$', 'us$', 'u$', 'es$'}
latin['noun']['singular']['genitive'] = {'ae$', 'i$', 'is$', 'us$', 'ei$'}
latin['noun']['singular']['dative'] = {'ae$', 'o$', 'i$', 'ui$', 'u$', 'ei$'}
latin['noun']['singular']['accusative'] = {'am$', 'um$', 'em$', 'e$', 'im$', 'u$'}
latin['noun']['singular']['ablative'] = {'a$', 'o$', 'e$', 'i$', 'u$'}

latin['noun']['plural']['nominative'] = {'ae$', 'i$', 'a$', 'es$', 'ia$', 'us$', 'ua$'}
latin['noun']['plural']['vocative'] = {'ae$', 'i$', 'a$', 'es$', 'ia$', 'us$', 'ua$'}
latin['noun']['plural']['genitive'] = {'arum$', 'orum$', 'um$', 'ium$', 'm$', 'uum$', 'erum$'}
latin['noun']['plural']['dative'] = {'is$', 'ibus$', 'bus$', 'ebus$'}
latin['noun']['plural']['accusative'] = {'as$', 'os$', 'a$', 'es$', 'is$', 'ia$', 'us$', 'ua$'}
latin['noun']['plural']['ablative'] = {'is$', 'ibus$', 'bus$', 'ebus$'}

#adjectives
latin['adjective']['singular']['nominative'] = {'us$', 'a$', 'um$', 'is$', 'e$', 's$'}
latin['adjective']['singular']['vocative'] = {'us$', 'a$', 'um$', 'is$', 'e$', 's$'}
latin['adjective']['singular']['genitive'] = {'i$', 'ae$', 'is$'}
latin['adjective']['singular']['dative'] = {'i$', 'ae$', 'o$'}
latin['adjective']['singular']['accusative'] = {'am$', 'um$', 'em$', 'e$', 's$'}
latin['adjective']['singular']['ablative'] = {'a$', 'o$', 'i$', 'e$'}

latin['adjective']['plural']['nominative'] = {'i$', 'ae$', 'a$', 'es$', 'ia$'}
latin['adjective']['plural']['vocative'] = {'i$', 'ae$', 'a$', 'es$', 'ia$'}
latin['adjective']['plural']['genitive'] = {'orum$', 'arum$', 'ium$', 'um$'}
latin['adjective']['plural']['dative'] = {'is$', 'ibus$'}
latin['adjective']['plural']['accusative'] = {'os$', 'as$', 'a$', 'es$', 'is$', 'ia$'}
latin['adjective']['plural']['ablative'] = {'is$', 'ibus$'}

#numerals
latin['numeral']['singular']['nominative'] = {'us$', 'a$', 'um$'}
latin['numeral']['singular']['vocative'] = {'e$', 'a$', 'um$'}
latin['numeral']['singular']['genitive'] = {'i$', 'ae$', 'ius$'}
latin['numeral']['singular']['dative'] = {'o$', 'ae$', 'i$'}
latin['numeral']['singular']['accusative'] = {'um$', 'am$'}
latin['numeral']['singular']['ablative'] = {'o$', 'a$'}

latin['numeral']['plural']['nominative'] = {'i$', 'ae$', 'a$', 'o$', 'es$', 'ia$'}
latin['numeral']['plural']['vocative'] = {'i$', 'ae$', 'a$', 'o$', 'es$', 'ia$'}
latin['numeral']['plural']['genitive'] = {'orum$', 'arum$', 'ium$'}
latin['numeral']['plural']['dative'] = {'is$', 'obus$', 'abus$', 'ibus$'}
latin['numeral']['plural']['accusative'] = {'os$', 'as$', 'a$', 'o$', 'es$', 'ia$'}
latin['numeral']['plural']['ablative'] = {'is$', 'obus$', 'abus$', 'ibus$'}

#pronouns
latin['pronoun']['singular']['nominative'] = {'$ego$', '$tu$', 'us$', 'a$', 'um$', '$qui$', '$quae$', '$quod$', '$quis$', '$quid$', '$qua$', 'quis$', 'quid$', 'qui$', 'qua$', 'quod$', '$quis', '$quid', '$qui', '$quae', '$quod', '$quic', 'e$', 'ud$', '$hic$', '$haec$', '$hoc$', '$is$', '$ea$', '$id$', '$i', '$ea', '$uter', '$utra', '$utrum', '$nihil$', '$nemo$'}
latin['pronoun']['singular']['genitive'] = {'$mei$', '$tui$', '$sui$', 'i$', 'ae$', '$cuius$', 'cuius$', '$cuius', 'ius$', '$huius$', '$eius$', '$eius', '$utrius', '$neminis$'}
latin['pronoun']['singular']['dative'] = {'$mihi$', '$tibi$', '$sibi$', 'o$', 'ae$', '$cui$', 'cui$', '$cui', 'i$', '$huic$', '$ei$', '$ei', '$utri', '$nemini$'}
latin['pronoun']['singular']['accusative'] = {'$me$', '$te$', '$se$', 'um$', 'am$', '$quem$', '$quam$', '$quod$', 'quem$', 'quid$', 'quam$', 'quod$', '$quem', '$quid', '$quam', '$quod', '$quic', '$quen', '$quan', 'um$', 'ud$', '$hunc$', '$hanc$', '$hoc$', '$eum$', '$eam$', '$id$', '$eun', '$ean', '$i', '$utrum', '$utram', '$nihil$', '$neminem$'}
latin['pronoun']['singular']['ablative'] = {'$me$', '$te$', '$se$', '$mecum$', '$tecum$', '$secum$', 'o$', 'a$', '$quo$', '$qua$', 'quo$', 'qua$', '$quo', '$qua', '$hoc$', '$hac$', '$eo$', '$ea$', '$eo', '$ea', '$utro', '$utra'}

latin['pronoun']['plural']['nominative'] = {'$nos$', '$vos$', '$uos$', 'i$', 'ae$', 'a$', '$qui$', '$quae$', '$qua$', 'qui$', 'quae$', 'quod$', '$qui', '$quae', '$hi$', '$hae$', '$haec$', '$ei$', '$ii$', '$i$', '$eae$', '$ea$', '$i', '$ii', '$eae', '$ea', '$utri', '$utrae', '$utra'}
latin['pronoun']['plural']['genitive'] = {'$nostri$', '$nostrum$', '$vestri$', '$vestrum$', '$uestri$', '$uestrum$', 'orum$', 'arum$', '$quorum$', '$quarum$', 'quorum$', 'quarum$', '$quorum', '$quarum', '$quorun', '$quarun', '$horum$', '$horunc$', '$harum$', '$harunc$', '$eorum$', '$earum$', '$eorun', '$earun', '$utrorum', '$utrarum'}
latin['pronoun']['plural']['dative'] = {'$nobis$', '$vobis$', '$uobis$', 'is$', '$quibus$', 'quibus$', '$quibus', '$his$', '$eis$', '$iis$', '$is$', '$eis', '$iis', '$is', '$utris'}
latin['pronoun']['plural']['accusative'] = {'$nos$', '$vos$', '$uos$', 'os$', 'as$', 'a$', '$quos$', '$quas$', '$quae$', '$qua$', 'quos$', 'quas$', 'qua$', '$quos', '$quas', '$quae', 'ud$', '$hos$', '$has$', '$haec$', '$eos$', '$eas$', '$ea$', '$eos' , '$eas', '$ea', '$utros', '$utras', '$utra'}
latin['pronoun']['plural']['ablative'] = {'$nobis$', '$vobis$', '$uobis$', '$nobiscum$', '$vobiscum$', '$uobiscum$', 'is$', '$quibus$', 'quibus$', '$quibus', '$his$', '$eis$', '$iis$', '$is$', '$eis', '$iis', '$is', '$utris'}

#gold standard of Modern Greek case markers

modern_greek = {}

#POS
modern_greek['noun'] = {}
modern_greek['adjective'] = {}
modern_greek['numeral'] = {}
modern_greek['article'] = {}
modern_greek['pronoun'] = {}

#NUM
modern_greek['noun']['singular'] = {}
modern_greek['adjective']['singular'] = {}
modern_greek['numeral']['singular'] = {}
modern_greek['article']['singular'] = {}
modern_greek['pronoun']['singular'] = {}

modern_greek['noun']['plural'] = {}
modern_greek['adjective']['plural'] = {}
modern_greek['numeral']['plural'] = {}
modern_greek['article']['plural'] = {}
modern_greek['pronoun']['plural'] = {}

#CAS
#nouns
modern_greek['noun']['singular']['nominative'] = {'ος$', 'ης$', 'ας$', 'ες$', 'ους$', 'εας$', 'ου$', 'η$', 'α$', 'ω$', 'ι$', 'ο$', 'μα$', 'ιμο$'}
modern_greek['noun']['singular']['accusative'] = {'ου$', 'ο$', 'η$', 'α$', 'ε$', 'εα$', 'ω$', 'ι$', 'ο$', 'μα$', 'ιμο$'}
modern_greek['noun']['singular']['genitive'] = {'ου$', 'ο$', 'η$', 'α$', 'ε$', 'εα$', 'ας$', 'ης$', 'εως$', 'ους$', 'ως$', 'ιου$', 'ματος$', 'ιματος$'}
modern_greek['noun']['singular']['vocative'] = {'ου$', 'ο$', 'η$', 'α$', 'ε$', 'εα$', 'ω$', 'ι$', 'μα$', 'ιμο$'}

modern_greek['noun']['plural']['nominative'] = {'οι$', 'ες$', 'εις$', 'ηδες$',  'αδες$', 'εδες$', 'ουδες$', 'α$', 'ια$', 'η$', 'ματα$', 'ιματα$'}
modern_greek['noun']['plural']['accusative'] = {'ους$', 'ες$', 'εις$', 'ηδες$', 'αδες$',  'εδες$', 'ουδες$', 'α$', 'ια$', 'η$', 'ματα$', 'ιματα$'}
modern_greek['noun']['plural']['genitive'] = {'ων$', 'εων$', 'ηδων$', 'αδων$', 'εδων$', 'ουδων$', 'ιων$', 'ματων$', 'ιματων$'}
modern_greek['noun']['plural']['vocative'] = {'οι$', 'ες$', 'εις$', 'ηδες$',  'αδες$', 'εδες$', 'ουδες$', 'α$', 'ια$', 'η$', 'ματα$', 'ιματα$'}

#adjectives
modern_greek['adjective']['singular']['nominative'] = {'ος$', 'η$', 'ο$', 'α$', 'ια$', 'υς$', 'υ$', 'ης$', 'ι$', 'ες$', 'ας$', 'ου$', 'ικο$', 'αδικο$', 'ων$', 'ουσα$', 'ον$'}
modern_greek['adjective']['singular']['accusative'] = {'ο$', 'η$', 'α$', 'ια$', 'υ$', 'η$', 'ι$', 'ες$', 'ου$', 'ικο$', 'αδικο$', 'οντα$', 'ουσα$', 'ον$'}
modern_greek['adjective']['singular']['genitive'] = {'ον$', 'ης$', 'ας$', 'ιας$', 'ιου$', 'υ$', 'η$', 'ι$', 'ονς$', 'ικον$', 'αδικου$', 'οντος$', 'ουσας$'}
modern_greek['adjective']['singular']['vocative'] = {'ε$', 'η$', 'ο$', 'α$', 'ια$', 'υ$', 'η$', 'ι$', 'ικο$', 'αδικο$', 'ων$', 'ουσα$', 'ον$'}

modern_greek['adjective']['plural']['nominative'] = {'οι$', 'ες$', 'α$', 'ιοι$', 'ιες$', 'ια$', 'εις$', 'η$', 'ηδες$', 'ικα$', 'αδες$', 'ουδες$', 'αδικα$', 'οντες$', 'ουσες$', 'οντα$'}
modern_greek['adjective']['plural']['accusative'] = {'ους$', 'ες$', 'α$', 'ιους$', 'ιες$', 'ια$', 'εις$', 'η$', 'ηδες$', 'ικα$', 'αδες$', 'ουδες$', 'αδικα$', 'οντες$', 'ουσες$', 'οντα$'}
modern_greek['adjective']['plural']['genitive'] = {'ωυν$', 'ιων$', 'ηδων$', 'ικων$', 'αδων$', 'ουδων$', 'αδικων$',  'οντων$', 'ουσων$'}
modern_greek['adjective']['plural']['vocative'] = {'οι$', 'ες$', 'α$', 'ιοι$', 'ιες$', 'ια$', 'ηδες$', 'ικα$', 'αδες$', 'ουδες$', 'αδικα$', 'ουτες$', 'ουσες$', 'ουτα$'}

#numerals
modern_greek['numeral']['singular']['nominative'] = {'ας$', 'α$'}
modern_greek['numeral']['singular']['accusative'] = {'α$', 'αν$'}
modern_greek['numeral']['singular']['genitive'] = {'ος$', 'ας$'}

modern_greek['numeral']['plural']['nominative'] = {'εις$', 'ις$', 'ια$', 'α$', 'οι$', 'ες$'}
modern_greek['numeral']['plural']['accusative'] = {'εις$', 'ις$', 'ια$', 'α$', 'ους$', 'ες$'}
modern_greek['numeral']['plural']['genitive'] = {'ων$'}

#articles
modern_greek['article']['singular']['nominative'] = {'$ο$', '$η$', '$το$', '$ενας$', '$μια$', '$ενα$'}
modern_greek['article']['singular']['accusative'] = {'$το$', '$τον$', '$τη$', '$την$', '$ενα$', '$εναν$', '$μια$', '$μιαν$'}
modern_greek['article']['singular']['genitive'] = {'$τον$', '$της$', '$ενος$', '$μιας$'}
modern_greek['article']['singular']['dative'] = {'$οτο$', '$οτον$', '$οτη$', '$οτην$', '$ενα$', '$εναν$', '$μια$'}

modern_greek['article']['plural']['nominative'] = {'$οι$', '$τα$'}
modern_greek['article']['plural']['accusative'] = {'$τους$', '$τις$', '$τα$'}
modern_greek['article']['plural']['genitive'] = {'$των$'}
modern_greek['article']['plural']['dative'] = {'$οτους$', '$οτις$', '$οτα$'}

#pronouns
modern_greek['pronoun']['singular']['nominative'] = {'$τος$', '$τη$', '$το$', '$εγω$', '$εσυ$', '$αυτος$', '$αυτη$', '$αυτο$', 'ος$', 'η$', 'ο$', 'ια$', 'α$', 'ις$', 'ας$', 'να$'}
modern_greek['pronoun']['singular']['accusative'] = {'$με$', '$σε$', '$τον$', '$τη$', '$την$', '$το$', '$εμενα$', '$εσενα$', '$αυτον$', '$αυτη$', '$αυτην$', '$αυτο$', 'ο$', 'η$', 'ια$', 'ν$', 'ον$', 'α$', 'αν$', 'να$', 'ναν$'}
modern_greek['pronoun']['singular']['genitive'] = {'$μου$', '$σου$', '$του$', '$της$', '$εμενα$', '$εσενα$', '$αυτου$', '$αυτης$', '$αυτουν$', '$αυτην$', 'ου$', 'ης$', 'ιας$', 'ανου$',  'ας$', 'ανης$', 'νος$'}

modern_greek['pronoun']['plural']['nominative'] = {'$τοι$', '$τες$', '$τα$', '$εμεις$', '$εσεις$', '$αυτοι$', '$αυτες$', '$αυτα$', 'οι$', 'ες$', 'α$'}
modern_greek['pronoun']['plural']['accusative'] = {'$μας$', '$σας$', '$τους$', '$τις$', '$τες$', '$τα$', '$εμας$', '$εσας$', '$αυτους$', '$αυες$', '$αυτα$', 'ους$', 'ες$', 'α$'}
modern_greek['pronoun']['plural']['genitive'] = {'$μας$', '$σας$', '$τους$', '$εμας$', '$εσας$', '$αυτων$', 'ων$', 'ανων$'}

#gold standard of German case markers

german = {}

#POS
german['noun'] = {}
german['adjective'] = {}
german['article'] = {}
german['pronoun'] = {}

#NUM
german['noun']['singular'] = {}
german['adjective']['singular'] = {}
german['article']['singular'] = {}
german['pronoun']['singular'] = {}

german['noun']['plural'] = {}
german['adjective']['plural'] = {}
german['article']['plural'] = {}
german['pronoun']['plural'] = {}

#CAS
#nouns
german['noun']['singular']['nominative'] = {}
german['noun']['singular']['genitive'] = {'s$','n$','es$','en$','ns$'}
german['noun']['singular']['accusative'] = {'n$', 'en$'}
german['noun']['singular']['dative'] = {'e$', 'en$', 'n$'}

german['noun']['plural']['nominative'] = {'e$','er$','en$','n$','s$'}
german['noun']['plural']['genitive'] = {'e$','er$','en$','n$','s$'}
german['noun']['plural']['accusative'] = {'e$','er$','en$','n$','s$'}
german['noun']['plural']['dative'] = {'en$','n$','s$','ern$'}

#adjectives
german['adjective']['singular']['nominative'] = {'e$','er$','es$'}
german['adjective']['singular']['genitive'] = {'en$','er$'}
german['adjective']['singular']['accusative'] = {'e$','es$','en$'}
german['adjective']['singular']['dative'] = {'en$','er$','em$'}

german['adjective']['plural']['nominative'] = {'e$','en$'}
german['adjective']['plural']['genitive'] = {'en$','er$'}
german['adjective']['plural']['accusative'] = {'e$','en$'}
german['adjective']['plural']['dative'] = {'en$'}

#articles
german['article']['singular']['nominative'] = {'$der$','$die$','$das$','$ein$','$eine$'}
german['article']['singular']['genitive'] = {'$des$','$der$','$einer$','$eines$'}
german['article']['singular']['accusative'] = {'$den$','$das$','$die$','$einen$','$ein$','$eine$'}
german['article']['singular']['dative'] = {'$dem$','$der$','$einem$','$einer$'}

german['article']['plural']['nominative'] = {'$die$'}
german['article']['plural']['genitive'] = {'$der$'}
german['article']['plural']['accusative'] = {'$die$'}
german['article']['plural']['dative'] = {'$den$'}

#pronouns
german['pronoun']['singular']['nominative'] = {'er$', 'es$', 'e$', '$der', '$das', '$die','$der$', '$das$', '$die$', '$ich$', '$du$', '$er$', '$sie$', '$es$'}
german['pronoun']['singular']['genitive'] = {'es$', 'er$', 'en$', 's$', '$des', '$der', '$des$', '$der$', '$dessen$', '$derer$', '$deren$', '$meiner$', '$deiner$', '$seiner$', '$ihrer$'}
german['pronoun']['singular']['accusative'] = {'en$', 'es$', 'e$', '$den', '$das', '$die', '$den$', '$das$', '$die$', '$mich$', '$dich$', '$ihn$', '$es$', '$sie$'}
german['pronoun']['singular']['dative'] = {'em$', 'er$', 'en$', '$dem', '$der', '$dem$', '$der$', '$mir$', '$dir$', '$ihm$', '$ihr$'}

german['pronoun']['plural']['nominative'] = {'e$', 'en$', '$die', '$die$', '$wir$', '$ihr$', '$sie$'}
german['pronoun']['plural']['genitive'] = {'er$', 'en$', '$der', '$der$', '$derer$', '$deren$', '$unser$', '$euer$', '$ihrer$'}
german['pronoun']['plural']['accusative'] = {'e$', 'en$', '$die', '$die$', '$uns$', '$euch$', '$sie$'}
german['pronoun']['plural']['dative'] = {'en$', '$den$', '$denen$', '$uns$', '$euch$', '$ihnen$'}

#gold standard of Russian case markers

russian = {}

#POS
russian['noun'] = {}
russian['adjective'] = {}
russian['numeral'] = {}
russian['pronoun'] = {}

#NUM
russian['noun']['singular'] = {}
russian['adjective']['singular'] = {}
russian['numeral']['singular'] = {}
russian['pronoun']['singular'] = {}

russian['noun']['plural'] = {}
russian['adjective']['plural'] = {}
russian['numeral']['plural'] = {}
russian['pronoun']['plural'] = {}

#CAS
#nouns
russian['noun']['singular']['nominative'] = {'й$', 'ъ$', 'о$', 'е$', 'ё$', 'а$', 'я$', 'мя$'}
russian['noun']['singular']['accusative'] = {'й$', 'ъ$', 'о$', 'е$', 'ё$', 'а$', 'я$', 'мя$', 'ы$', 'и$', 'у$', 'ю$', 'ени$'}
russian['noun']['singular']['genitive'] = {'а$', 'я$', 'ы$', 'и$', 'у$', 'ю$', 'ени$'}
russian['noun']['singular']['dative'] = {'у$', 'ю$', 'е$', 'и$', 'ени$'}
russian['noun']['singular']['instrumental'] = {'ем$', 'ом$', 'ём$', 'ей$', 'ой$', 'ёй$', 'ъю$', 'ою$', 'енем$'}
russian['noun']['singular']['prepositional'] = {'е$', 'и$', 'у$', 'ю$', 'ени$'}

russian['noun']['plural']['nominative'] = {'ы$', 'и$', 'а$', 'я$', 'ъя$', 'е$', 'ата$', 'ята$', 'ен$'}
russian['noun']['plural']['accusative'] = {'ы$', 'и$', 'а$', 'я$', 'ов$', 'ев$', 'ей$', 'ъя$', 'е$', 'ата$', 'ята$', 'ена$', 'й$', 'ёв$', 'ён$'}
russian['noun']['plural']['genitive'] = {'ов$', 'ев$', 'ей$', 'й$', 'ёв$', 'ён$'}
russian['noun']['plural']['dative'] = {'ам$', 'ям$', 'енам$'}
russian['noun']['plural']['instrumental'] = {'ами$', 'ями$', 'енами$'}
russian['noun']['plural']['prepositional'] = {'ах$', 'ях$', 'енах$'}

#adjectives
russian['adjective']['singular']['nominative'] = {'ый$', 'ая$', 'ое$', 'ий$', 'ее$', 'ой$', 'яя$', 'я$', 'е$', 'а$', 'о$'}
russian['adjective']['singular']['accusative'] = {'ый$', 'ого$', 'его$', 'ую$', 'ое$', 'ая$', 'ий$', 'ее$', 'ой$', 'юю$', 'ю$', 'е$', 'у$', 'о$'}
russian['adjective']['singular']['genitive'] = {'ого$', 'ой$', 'ей$', 'его$'}
russian['adjective']['singular']['dative'] = {'ому$', 'ой$', 'ему$', 'ей$', 'у$'}
russian['adjective']['singular']['instrumental'] = {'ым$', 'ой$', 'ою$', 'им$', 'ей$', 'ею$'}
russian['adjective']['singular']['prepositional'] = {'ом$', 'ой$', 'ем$', 'ей$'}

russian['adjective']['plural']['nominative'] = {'ые$', 'ие$', 'и$', 'ы$'}
russian['adjective']['plural']['accusative'] = {'ые$', 'ых$', 'ие$', 'их$', 'и$', 'ы$'}
russian['adjective']['plural']['genitive'] = {'ых$', 'их$'}
russian['adjective']['plural']['dative'] = {'ым$', 'им$'}
russian['adjective']['plural']['instrumental'] = {'ыми$', 'ими$'}
russian['adjective']['plural']['prepositional'] = {'ых$', 'их$'}

#numerals
russian['numeral']['singular']['nominative'] = {'а$', 'о$', 'ый$', 'ая$', 'ое$'}
russian['numeral']['singular']['accusative'] = {'ого$', 'у$', 'о$', 'ый$', 'ую$', 'ое$'}
russian['numeral']['singular']['genitive'] = {'ого$', 'ой$', 'и$', 'а$'}
russian['numeral']['singular']['dative'] = {'ому$', 'ой$', 'е$', 'у$'}
russian['numeral']['singular']['instrumental'] = {'им$', 'ой$', 'ою$', 'ей$', 'ом$', 'ым$'}
russian['numeral']['singular']['prepositional'] = {'ом$', 'ой$', 'е$'}

russian['numeral']['plural']['nominative'] = {'и$', 'е$', 'а$', 'о$', 'ы$', 'ые$'}
russian['numeral']['plural']['accusative'] = {'и$', 'их$', 'а$', 'е$', 'ух$', 'ёх$', 'ых$', 'ы$', 'ые$'}
russian['numeral']['plural']['genitive'] = {'их$', 'ух$', 'ёх$', 'и$', 'а$', 'ых$', 'ов$'}
russian['numeral']['plural']['dative'] = {'им$', 'ум$', 'ём$', 'и$', 'а$', 'ам$', 'ым$'}
russian['numeral']['plural']['instrumental'] = {'ими$', 'умя$', 'емя$', 'мя$', 'ю$', 'ью$', 'а$', 'ами$', 'ыми$', 'ьмя$'}
russian['numeral']['plural']['prepositional'] = {'их$', 'ух$', 'ёх$', 'и$', 'а$', 'ах$', 'ых$'}

#pronouns
russian['pronoun']['singular']['nominative'] = {'$я$', '$ты$', '$он$', '$она$', '$оно$', 'и$', 'я$', 'ё$', 'а$', 'е$', 'й$', '$его$', '$её$', '$кто$', '$что$', '$чей$', '$чья$', '$чьё$', 'ой$', 'ое$', 'ая$', 'ый$', '$зтот$', '$зта$', '$зто$', '$тот$', '$та$', '$то$', '$сей$', '$сия$', '$сие$', '$зкий$', '$зкая$', '$зкое$', 'о$', 'ий$', '$никто$', '$ничто$', '$ничей$', '$ничья$', '$ничьё$'}
russian['pronoun']['singular']['accusative'] = {'$меня$', '$тебя$', '$его$', '$её$', '$оно$', '$себя$', 'и$', 'его$', 'ю$', 'ё$', 'у$', 'е$', 'й$', '$кого$', '$что$', '$чей$', '$чьего$', '$чью$', '$чьё$', 'ой$', 'ое$', 'ая$', 'ый$', 'ую$', 'ого$', '$зтот$', '$зтого$', '$зту$', '$зто$', '$тот$', '$того$', '$ту$', '$то$', '$сей$', '$сего$', '$сию$', '$сие$', '$зкий$', '$зкоего$', '$зкую$', 'оё$', 'о$', 'ий$', '$никого$', '$ничто$', '$ничей$', '$ничьего$', '$ничью$', '$ничьё$', 'оего$'}
russian['pronoun']['singular']['genitive'] = {'$меня$', '$тебя$', '$его$', '$её$', '$оно$', '$себя$', 'его$', 'ей$', '$кого$', '$чего$', '$чьего$', '$чьей$', 'ого$', 'ой$', '$зтого$', '$зтой$', '$того$', '$той$', '$сего$', '$сей$', '$зкоего$', '$зкой$', 'ого$', 'ой$', '$никого$', '$ничего$', '$ничьего$', '$ничьей$', 'оего$', 'оей$'}
russian['pronoun']['singular']['dative'] = {'$мне$', '$тебе$', '$ему$', '$ей$', '$себе$', 'ему$', 'ей$', '$его$', '$её$', '$кому$', '$чему$', '$чьему$', '$чьей$', 'ому$', 'ой$', '$зтому$', '$зтой$', '$тому$', '$той$', '$сему$', '$сей$', '$зкоему$', '$зкой$', 'ому$', 'ой$', '$никому$', '$ничему$', '$ничьему$', '$ничьей$', 'оему$', 'оей$'}
russian['pronoun']['singular']['instrumental'] = {'$мной$', '$тебой$', '$им$', '$ей$', '$ею$', '$мною$', '$тебою$', '$собой$', '$собою$', 'им$', 'ей$', 'ею$', '$его$', '$её$', '$кем$',  '$чем$', '$чьим$', '$чьей$', '$чью$', 'ым$', 'ой$', 'им$', '$зтим$', '$зтой$', '$зтою$', '$тем$', '$той$', '$тою$', '$сим$', '$сей$', '$сею$', '$зким$', '$зкой$', '$зкою$', 'ой$', 'ою$', 'ем$', '$никем$',  '$ничем$', '$ничьим$', '$ничьей$', '$ничью$', 'оим$', 'оей$'}
russian['pronoun']['singular']['prepositional'] = {'$мне$', '$тебе$', '$нём$', '$ней$', '$себе$', 'ём$', 'ей$', 'ем$', '$его$', '$её$', '$ком$', '$чём$', '$чьём$', '$чьей$', 'ом$', 'ой$', '$зтом$', '$зтой$', '$том$', '$той$', '$сём$', '$сей$', '$зком$', '$зкой$', 'ом$', 'ой$', '$ником$', '$ничём$', '$ничьём$', '$ничьей$', 'оем$', 'оей$'}

russian['pronoun']['plural']['nominative'] = {'$нас$', '$вас$', '$их$', 'и$', '$чьи$', 'ые$', 'ие$', '$зти$', '$те$', '$сии$', '$зкие$', 'е$', '$ничьи$'}
russian['pronoun']['plural']['accusative'] = {'$мы$', '$вы$', '$оны$', '$себя$', 'и$', 'их$', '$их$', '$чьи$', '$чьих$', 'ые$', 'йе$', 'ых$', 'их$', '$зти$', '$зтих$', '$те$', '$тех$', '$сии$', '$сих$', '$зкие$', '$зких$', 'е$', 'ех$', 'ие$', '$ничьи$', '$ничьих$', 'оих$'}
russian['pronoun']['plural']['genitive'] = {'$нас$', '$вас$', '$их$', '$себя$', 'их$', '$чьих$', 'ых$', 'их$', '$зтих$', '$тех$', '$сих$', '$зких$', 'ех$', '$ничьих$', 'оих$'}
russian['pronoun']['plural']['dative'] = {'$нам$', '$вам$', '$им$', '$себе$', 'им$', '$их$', '$чьим$', 'ым$', 'им$', '$зтим$', '$тем$', '$сим$', '$зким$', 'ем$', '$ничьим$', 'оим$'}
russian['pronoun']['plural']['instrumental'] = {'$нами$', '$вами$', '$ими$', '$собой$', '$собою$', 'ими$', '$их$', '$чьими$', 'ыми$', 'ими$', '$зтими$', '$теми$', '$сими$', '$зкими$', 'еми$', '$ничьими$', 'оими$'}
russian['pronoun']['plural']['prepositional'] = {'$нас$', '$вас$', '$них$', '$себе$', 'их$', '$их$', '$чьих$', 'ых$', 'их$', '$зтих$', '$тех$', '$сих$', '$зких$', 'ех$', '$ничьих$', 'оих$'}

#gold standard of Turkish case markers

turkish = {}

#POS
turkish['noun'] = {}
turkish['pronoun'] = {}

#NUM
turkish['noun']['singular'] = {}
turkish['pronoun']['singular'] = {}

turkish['noun']['plural'] = {}
turkish['pronoun']['plural'] = {}

#CAS
#nouns
turkish['noun']['singular']['nominative'] = {}
turkish['noun']['singular']['accusative'] = {'ı$', 'i$', 'yi$', 'yü$', 'yı$', 'yu$', 'ü$', 'u$'}
turkish['noun']['singular']['genitive'] = {'ın$', 'nin$', 'nün$', 'nın$', 'nun$', 'in$', 'ün$', 'un$'}
turkish['noun']['singular']['dative'] = {'a$', 'ye$', 'ya$', 'e$'}
turkish['noun']['singular']['locative'] = {'da$', 'de$', 'te$', 'ta$', 'da', 'de', 'te', 'ta'}
turkish['noun']['singular']['ablative'] = {'dan$', 'den$', 'ten$', 'tan$'}

turkish['noun']['plural']['nominative'] = {}
turkish['noun']['plural']['accusative'] = {'ı$', 'i$', 'yi$', 'yü$', 'yı$', 'yu$', 'ü$', 'u$'}
turkish['noun']['plural']['genitive'] = {'ın$', 'nin$', 'nün$', 'nın$', 'nun$', 'in$', 'ün$', 'un$'}
turkish['noun']['plural']['dative'] = {'a$', 'ye$', 'ya$', 'e$'}
turkish['noun']['plural']['locative'] = {'da$', 'de$', 'te$', 'ta$', 'da', 'de', 'te', 'ta'}
turkish['noun']['plural']['ablative'] = {'dan$', 'den$', 'ten$', 'tan$'}

#pronouns
turkish['pronoun']['singular']['nominative'] = {'si$', 'sı$'}
turkish['pronoun']['singular']['accusative'] = {'i$', 'nu$', 'ni$', 'u$', 'yı$', 'yi$'}
turkish['pronoun']['singular']['genitive'] = {'im$', 'in$', 'nun$', 'nin$', 'nın$', 'yin$'}
turkish['pronoun']['singular']['dative'] = {'a$', 'na$', 'n$', 'e$', 'ya$', 'ne$', 'ye$'}
turkish['pronoun']['singular']['locative'] = {'de$', 'nda$', 'nde$'}
turkish['pronoun']['singular']['ablative'] = {'den$', 'dan$', 'nden$', 'ndan$', 'yden$'}

turkish['pronoun']['plural']['nominative'] = {'i$', 'ı$'}
turkish['pronoun']['plural']['accusative'] = {'i$', 'ı$', 'ini$'}
turkish['pronoun']['plural']['genitive'] = {'im$', 'in$', 'ın$', 'inin$'}
turkish['pronoun']['plural']['dative'] = {'i$', 'ı$', 'e$', 'a$', 'ine$'}
turkish['pronoun']['plural']['locative'] = {'de$', 'da$', 'inde$'}
turkish['pronoun']['plural']['ablative'] = {'den$', 'dan$', 'inden$'}

#gold standard of Finnish case markers

finnish = {}

#POS
finnish['noun'] = {}
finnish['adjective'] = {}
finnish['numeral'] = {}
finnish['pronoun'] = {}

#NUM
finnish['noun']['singular'] = {}
finnish['adjective']['singular'] = {}
finnish['numeral']['singular'] = {}
finnish['pronoun']['singular'] = {}

finnish['noun']['plural'] = {}
finnish['adjective']['plural'] = {}
finnish['numeral']['plural'] = {}
finnish['pronoun']['plural'] = {}

#CAS
#nouns
finnish['noun']['singular']['nominative'] = {}
finnish['noun']['singular']['genitive'] = {'n$'}
finnish['noun']['singular']['accusative'] = {'n$'}
finnish['noun']['singular']['partitive'] = {'a$', 'ä$', 'ta$', 'tta$', 'tä$', 'ttä$', 'a', 'ä', 't', 'tta', 'tä', 'ttä'}
finnish['noun']['singular']['inessive'] = {'ssa$', 'ssä$', 'ssa', 'ssä'}
finnish['noun']['singular']['elative'] = {'sta$', 'stä$', 'sta', 'stä'}
finnish['noun']['singular']['illative'] = {'on$', 'ön$', 'an$', 'än$', 'en$', 'in$', 'un$', 'yn$', 'han$', 'hän$', 'hin$', 'hen$', 'hun$', 'hon$', 'hön$', 'seen$', 'o', 'ö', 'a', 'ä', 'e', 'i', 'u', 'y', 'ha', 'hä', 'hi', 'he', 'hu', 'ho', 'hö', 'see'}
finnish['noun']['singular']['adessive'] = {'lla$', 'llä$', 'lla', 'llä'}
finnish['noun']['singular']['ablative'] = {'lta$', 'ltä$', 'lta', 'ltä'}
finnish['noun']['singular']['allative'] = {'lle$', 'lle'}
finnish['noun']['singular']['essive'] = {'na$', 'nä$', 'na', 'nä'}
finnish['noun']['singular']['translative'] = {'ksi$', 'kse'}
finnish['noun']['singular']['comitative'] = {}
finnish['noun']['singular']['abessive'] = {'tta$', 'ttä$', 'tta', 'ttä'}
finnish['noun']['singular']['instructive'] = {'n$'}

finnish['noun']['plural']['nominative'] = {}
finnish['noun']['plural']['genitive'] = {'en$', 'den$', 'ten$', 'tten$', 'e', 'de', 'te', 'tte'}
finnish['noun']['plural']['accusative'] = {'t$'}
finnish['noun']['plural']['partitive'] = {'a$', 'ä$', 'ta$', 'tä$', 'a', 'ä', 'ta', 'tä'}
finnish['noun']['plural']['inessive'] = {'ssa$', 'ssä$', 'ssa', 'ssä'}
finnish['noun']['plural']['elative'] = {'sta$', 'stä$', 'sta', 'stä'}
finnish['noun']['plural']['illative'] = {'in$', 'hin$', 'siin$', 'i', 'hi', 'sii'}
finnish['noun']['plural']['adessive'] = {'lla$', 'llä$', 'lla', 'llä'}
finnish['noun']['plural']['ablative'] = {'lta$', 'ltä$', 'lta', 'ltä'}
finnish['noun']['plural']['allative'] = {'lle$', 'lle'}
finnish['noun']['plural']['essive'] = {'na$', 'nä$', 'na', 'nä'}
finnish['noun']['plural']['translative'] = {'ksi$', 'kse'}
finnish['noun']['plural']['comitative'] = {'ne$', 'ne'}
finnish['noun']['plural']['abessive'] = {'tta$', 'ttä$', 'tta', 'ttä'}
finnish['noun']['plural']['instructive'] = {'n$'}

#adjectives
finnish['adjective']['singular']['nominative'] = {}
finnish['adjective']['singular']['genitive'] = {'n$'}
finnish['adjective']['singular']['accusative'] = {'n$'}
finnish['adjective']['singular']['partitive'] = {'a$', 'ä$', 'ta$', 'tta$', 'tä$', 'ttä$'}
finnish['adjective']['singular']['inessive'] = {'ssa$', 'ssä$'}
finnish['adjective']['singular']['elative'] = {'sta$', 'stä$'}
finnish['adjective']['singular']['illative'] = {'on$', 'ön$', 'an$', 'än$', 'en$', 'in$', 'un$', 'yn$', 'han$', 'hän$', 'hin$', 'hen$', 'hun$', 'hon$', 'hön$', 'seen$'}
finnish['adjective']['singular']['adessive'] = {'lla$', 'llä$'}
finnish['adjective']['singular']['ablative'] = {'lta$', 'ltä$'}
finnish['adjective']['singular']['allative'] = {'lle$'}
finnish['adjective']['singular']['essive'] = {'na$', 'nä$'}
finnish['adjective']['singular']['translative'] = {'ksi$'}
finnish['adjective']['singular']['comitative'] = {}
finnish['adjective']['singular']['abessive'] = {'tta$', 'ttä$'}
finnish['adjective']['singular']['instructive'] = {'n$'}

finnish['adjective']['plural']['nominative'] = {}
finnish['adjective']['plural']['genitive'] = {'en$', 'den$', 'ten$', 'tten$'}
finnish['adjective']['plural']['accusative'] = {'t$'}
finnish['adjective']['plural']['partitive'] = {'a$', 'ä$', 'ta$', 'tä$'}
finnish['adjective']['plural']['inessive'] = {'ssa$', 'ssä$'}
finnish['adjective']['plural']['elative'] = {'sta$', 'stä$'}
finnish['adjective']['plural']['illative'] = {'in$', 'hin$', 'siin$'}
finnish['adjective']['plural']['adessive'] = {'lla$', 'llä$'}
finnish['adjective']['plural']['ablative'] = {'lta$', 'ltä$'}
finnish['adjective']['plural']['allative'] = {'lle$'}
finnish['adjective']['plural']['essive'] = {'na$', 'nä$'}
finnish['adjective']['plural']['translative'] = {'ksi$'}
finnish['adjective']['plural']['comitative'] = {'ne$'}
finnish['adjective']['plural']['abessive'] = {'tta$', 'ttä$'}
finnish['adjective']['plural']['instructive'] = {'n$'}

#numerals
finnish['numeral']['singular']['nominative'] = {'s$'}
finnish['numeral']['singular']['genitive'] = {'n$'}
finnish['numeral']['singular']['accusative'] = {'n$'}
finnish['numeral']['singular']['partitive'] = {'a$', 'ä$', 'ta$', 'tta$', 'tä$', 'ttä$'}
finnish['numeral']['singular']['inessive'] = {'ssa$', 'ssä$'}
finnish['numeral']['singular']['elative'] = {'sta$', 'stä$'}
finnish['numeral']['singular']['illative'] = {'on$', 'ön$', 'an$', 'än$', 'en$', 'in$', 'un$', 'yn$', 'han$', 'hän$', 'hin$', 'hen$', 'hun$', 'hon$', 'hön$', 'seen$'}
finnish['numeral']['singular']['adessive'] = {'lla$', 'llä$'}
finnish['numeral']['singular']['ablative'] = {'lta$', 'ltä$'}
finnish['numeral']['singular']['allative'] = {'lle$'}
finnish['numeral']['singular']['essive'] = {'na$', 'nä$'}
finnish['numeral']['singular']['translative'] = {'ksi$'}
finnish['numeral']['singular']['comitative'] = {}
finnish['numeral']['singular']['abessive'] = {'tta$', 'ttä$'}
finnish['numeral']['singular']['instructive'] = {'n$'}

finnish['numeral']['plural']['nominative'] = {}
finnish['numeral']['plural']['genitive'] = {'en$', 'den$', 'ten$', 'tten$'}
finnish['numeral']['plural']['accusative'] = {'t$'}
finnish['numeral']['plural']['partitive'] = {'a$', 'ä$', 'ta$', 'tä$'}
finnish['numeral']['plural']['inessive'] = {'ssa$', 'ssä$'}
finnish['numeral']['plural']['elative'] = {'sta$', 'stä$'}
finnish['numeral']['plural']['illative'] = {'in$', 'hin$', 'siin$'}
finnish['numeral']['plural']['adessive'] = {'lla$', 'llä$'}
finnish['numeral']['plural']['ablative'] = {'lta$', 'ltä$'}
finnish['numeral']['plural']['allative'] = {'lle$'}
finnish['numeral']['plural']['essive'] = {'na$', 'nä$'}
finnish['numeral']['plural']['translative'] = {'ksi$'}
finnish['numeral']['plural']['comitative'] = {'ne$'}
finnish['numeral']['plural']['abessive'] = {'tta$', 'ttä$'}
finnish['numeral']['plural']['instructive'] = {'n$'}

#pronouns
finnish['pronoun']['singular']['nominative'] = {}
finnish['pronoun']['singular']['genitive'] = {'n$', 'män$', 'kä$', 'nkä$', 'n', 'ka$', 'nka$'}
finnish['pronoun']['singular']['accusative'] = {'t$', 'kä$'}
finnish['pronoun']['singular']['partitive'] = {'a$', 'ta$', 'tä$', 'ta', 'tä', 'a'}
finnish['pronoun']['singular']['inessive'] = {'ssa$', 'ssä$', 'nä$', 'ssa', 'ssä'}
finnish['pronoun']['singular']['elative'] = {'sta$', 'stä$', 'tä$', 'sta', 'stä'}
finnish['pronoun']['singular']['illative'] = {'un$', 'en$', 'hän$', 'hon$', 'hen$', 'hin$', 'an$', 'hun$', 'hon', 'en', 'hin', 'an', 'hun'}
finnish['pronoun']['singular']['adessive'] = {'lla$', 'llä$', 'lla', 'llä'}
finnish['pronoun']['singular']['ablative'] = {'lta$', 'ltä$', 'lta', 'ltä'}
finnish['pronoun']['singular']['allative'] = {'lle$', 'lle'}
finnish['pronoun']['singular']['essive'] = {'nä$', 'na$', 'na'}
finnish['pronoun']['singular']['translative'] = {'ksi$', 'ksi'}

finnish['pronoun']['plural']['nominative'] = {'kä$'}
finnish['pronoun']['plural']['genitive'] = {'dän$', 'den$', 'kä$', 'den', 'en'}
finnish['pronoun']['plural']['accusative'] = {'dät$', 'kä$'}
finnish['pronoun']['plural']['partitive'] = {'tä$', 'ta$', 'a$', 'ta', 'tä'}
finnish['pronoun']['plural']['inessive'] = {'ssä$', 'ssa$', 'ssa', 'ssä'}
finnish['pronoun']['plural']['elative'] = {'stä$', 'sta$', 'sta', 'stä'}
finnish['pronoun']['plural']['illative'] = {'hin$', 'in$', 'hin', 'in'}
finnish['pronoun']['plural']['adessive'] = {'lla$', 'llä$', 'lla', 'llä'}
finnish['pronoun']['plural']['ablative'] = {'lta$', 'ltä$', 'lta', 'ltä'}
finnish['pronoun']['plural']['allative'] = {'lle$', 'lle'}
finnish['pronoun']['plural']['essive'] = {'nä$', 'na$', 'na'}
finnish['pronoun']['plural']['translative'] = {'ksi$', 'ksi'}

print(latin)
print('\n','------------------------------------------','\n')
print(modern_greek)
print('\n','------------------------------------------','\n')
print(german)
print('\n','------------------------------------------','\n')
print(russian)
print('\n','------------------------------------------','\n')
print(turkish)
print('\n','------------------------------------------','\n')
print(finnish)
print('\n','------------------------------------------','\n')


from email import header
from typing import List, Tuple
import enum
import pandas as pd
import sys

from graph import Graph, printGraph
from path import Path

def main():
    arguments: List[str] = sys.argv[1:]
    if len(arguments) <= 0:
        print("Please provide a file path")
        sys.exit(0)

    if len(arguments) != 3:
        print("Please provide exactly 3 arguments")
        sys.exit(0)

    data: pd.DataFrame = pd.read_csv(arguments[0], sep=',')

    # Converting cities to lower case
    data['from_country'] = data['from_country'].apply(str.lower)
    data['to_country'] = data['to_country'].apply(str.lower)

    unique_countries: List[str] = list(data.from_country.unique())

    # Finding unique countries
    new_countries = [country for country in data.to_country.unique() if country not in unique_countries]

    unique_countries.extend(new_countries)
    unique_countries.sort()

    start = str.lower(arguments[1])
    end = str.lower(arguments[2])
    if start not in unique_countries or end not in unique_countries:
        print("Please provide valid countries")
        sys.exit(0)

    countries_enum: enum.Enum = enum.Enum('Countries', unique_countries, start=0)

    # Convering from_country, to_country to enum and adding to dataframe
    data['from_country_enum'] = data['from_country'].apply(lambda x: countries_enum[x].value)
    data['to_country_enum'] = data['to_country'].apply(lambda x: countries_enum[x].value)

    # Re-ordering columns
    order = ['from_country', 'from_country_enum', 'to_country', 'to_country_enum', 'cost', 'shipment_company']
    data = data.filter(order)

    # Creating tuple for graph
    data_to_list: List[Tuple[int]] = list(data.drop(
        columns=['from_country', 'to_country']).copy().itertuples(index=False, name=None),
        )

    graph = Graph(data_to_list, len(unique_countries))
    # printGraph(graph)

    # Dijkstra's algorithm
    path: Path = graph.dijkstra(countries_enum[start].value, countries_enum[end].value)
    path.result(countries_enum)

if __name__ == '__main__':
    main()


from datetime import datetime
from rest_framework import mixins, viewsets, status, views
from rest_framework.response import Response
from utils.alipay import AliPay
from .models import ShopCart, OrderGoods, OrderInfo
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
from utils.permission import IsOwnerOrReadOnly
from .serializers import ShopCartSerializer, ShopCartListSerializer, OrderInfoSerializer, OrderInfoListSerializer
import random, time
from gulishop.settings import APPID, APP_NOTIFY_URL, APP_PRIVATE_KEY_PATH, ALIPAY_PUBLIC_KEY_PATH, RETURN_URL

class ShopCartViewSet(viewsets.ModelViewSet):
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    lookup_field = 'goods_id'

    def get_queryset(self):
        return ShopCart.objects.filter(user=self.request.user)

    def get_serializer_class(self):
        if self.action == 'list':
            return ShopCartListSerializer
        else:
            return ShopCartSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        goods = serializer.validated_data['goods']
        nums = serializer.validated_data['nums']

        shopcart_list = ShopCart.objects.filter(user=self.request.user, goods=goods)
        if shopcart_list:
            shopcart = shopcart_list[0]
            shopcart.goods = goods
            shopcart.nums += nums
            shopcart.save()
        else:
            shopcart = ShopCart()
            shopcart.user = self.request.user
            shopcart.goods = goods
            shopcart.nums = nums
            shopcart.save()

        headers = self.get_success_headers(serializer.data)
        serializer = self.get_serializer(shopcart)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

class OrderInfoViewSet(mixins.CreateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin,
                       mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)

    def get_queryset(self):
        return OrderInfo.objects.filter(user=self.request.user)

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return OrderInfoListSerializer
        else:
            return OrderInfoSerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        alipay = AliPay(
            appid=APPID,
            app_notify_url=APP_NOTIFY_URL,
            app_private_key_path=APP_PRIVATE_KEY_PATH,
            alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            return_url=RETURN_URL
        )
        url = alipay.direct_pay(
            subject=instance.order_sn,
            # 订单号
            out_trade_no=instance.order_sn,
            # 订单总价
            total_amount=instance.order_mount
        )
        # 沙箱环境
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)
        ret = serializer.data
        ret['alipay_url'] = re_url
        return Response(ret)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 创建订单
        order = OrderInfo.objects.create(**serializer.validated_data)
        order.order_sn = self.get_order_sn()
        order.save()
        # 创建订单商品
        goods_list = ShopCart.objects.filter(user=self.request.user)
        for goods in goods_list:
            ordergoods = OrderGoods()
            ordergoods.order = order
            ordergoods.goods = goods.goods
            ordergoods.goods_num = goods.nums
            ordergoods.save()
        # 清空购物车
        goods_list.delete()
        # 支付
        alipay = AliPay(
            appid=APPID,
            app_notify_url=APP_NOTIFY_URL,
            app_private_key_path=APP_PRIVATE_KEY_PATH,
            alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            return_url=RETURN_URL
        )
        url = alipay.direct_pay(
            subject=order.order_sn,
            # 订单号
            out_trade_no=order.order_sn,
            # 订单总价
            total_amount=order.order_mount
        )
        # 沙箱环境
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)
        headers = self.get_success_headers(serializer.data)
        serializer = self.get_serializer(order)
        ret = serializer.data
        ret['alipay_url'] = re_url
        return Response(ret, status=status.HTTP_201_CREATED, headers=headers)

    def get_order_sn(self):
        sn = f'{time.strftime("%Y%m%d%H%M%S")}{self.request.user.id}{random.randint(10, 99)}'
        return sn

class AlipayView(views.APIView):
    # 如果用网页登陆支付，走这里
    def get(self, request):
        """
        处理支付宝返回的return_url
        :param request:
        :return:
        """

        processed_dict = {}
        for key, value in request.GET.items():
            processed_dict[key] = value
        # 得到签名
        sign = processed_dict.pop("sign", None)
        # 下面代码拷贝过来

        alipay = AliPay(
            appid=APPID,
            # 异步的通知接口，当在浏览器扫描创建订单后，这个时候关闭页面，此时可以在客户端或者支护宝账号里面看到这个为支付完成的信息
            app_notify_url=RETURN_URL,
            app_private_key_path=APP_PRIVATE_KEY_PATH,
            alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            # 同步接口，支付成功后会跳转的接口
            return_url=RETURN_URL
        )
        # 验证通过返回True
        verify_result = alipay.verify(processed_dict, sign)
        print("verify_result================", verify_result)
        if verify_result is True:
            # 该交易在支付宝系统中的交易流水号
            trade_no = processed_dict.get("trade_no", None)
            # 商户网站唯一订单号
            order_sn = processed_dict.get("out_trade_no", None)
            pay_status = processed_dict.get("trade_status", 'TRADE_SUCCESS')

            # 根据订单号查找已经存在的订单列表
            exited_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for exited_order in exited_orders:
                exited_order.trade_no = trade_no
                # 修改状态
                exited_order.pay_status = pay_status
                exited_order.pay_time = datetime.now()
                # 保存数据
                exited_order.save()
            # 发一个成功信息给支付宝，否则支付宝会不停的发消息给我们
            return Response("success")

    # 如果用沙箱客户端扫描支付走这里
    def post(self, request):
        """
        处理支付宝的notify_url
        :param request:
        :return:
        """
        # 从post取出数据，把对应
        processed_dict = {}
        for key, value in request.POST.items():
            processed_dict[key] = value
        # 得到签名
        sign = processed_dict.pop("sign", None)
        # 下面代码拷贝过来

        alipay = AliPay(
            appid=APPID,
            # 异步的通知接口，当在浏览器扫描创建订单后，这个时候关闭页面，此时可以在客户端或者支护宝账号里面看到这个为支付完成的信息
            app_notify_url=RETURN_URL,
            app_private_key_path=APP_PRIVATE_KEY_PATH,
            alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            # 同步接口，支付成功后会跳转的接口
            return_url=RETURN_URL
        )

        verify_result = alipay.verify(processed_dict, sign)
        if verify_result is True:
            # 该交易在支付宝系统中的交易流水号
            trade_no = processed_dict.get("trade_no", None)
            # 商户网站唯一订单号
            order_sn = processed_dict.get("out_trade_no", None)
            pay_status = processed_dict.get("pay_status", 'TRADE_SUCCESS')

            # 根据订单号查找已经存在的订单列表
            exited_orders = OrderInfo.objects.filter(order_sn=order_sn)
            for exited_order in exited_orders:
                exited_order.trade_no = trade_no
                # 修改状态
                exited_order.pay_status = pay_status
                exited_order.pay_time = datetime.now()
                # 保存数据
                exited_order.save()
            # 发一个成功信息给支付宝，否则支付宝会不停的发消息给我们
            return Response("success")


#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Train-Users: AWS CLI IAM/User Managment"""

import argparse
import sys

import boto

from vpc.config import *
import vpc.users as users

conn = boto.connect_iam(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)

# configure parser
parser = argparse.ArgumentParser(description='Train: AWS CLI IAM/User Management')

parser.add_argument('-c', metavar='<user>',
                    help='Create IAM/User',
                    required=False)

parser.add_argument('-d', metavar='<user>',
                    help='Delete AWS user',
                    required=False)

parser.add_argument('-l',
                    help='List all users',
                    action='store_true', required=False)

args = parser.parse_args()

def process():
    """Execute command/flags"""

    if args.c:
        users.create_user(conn, args.c)
    if args.d:
        users.delete_user(conn, args.d)
    if args.l:
        users.list_users(conn)

if __name__ == '__main__':
    if len(sys.argv)==1:
        parser.print_help()
        sys.exit(1)

    process()


import collections
import re
from abc import abstractmethod

from docutils import core, nodes
from docutils.parsers.rst import Parser, Directive, directives
from docutils.writers import UnfilteredWriter

class Question(nodes.General, nodes.Element):
    id = None
    name = None
    header = None
    type = None
    language = None
    answer = None
    multiple = None
    limit = None

class Box(nodes.General, nodes.Element):
    type = None
    content = None
    maxchars = None
    lines = None
    language = None

class Choice(nodes.General, nodes.Element):
    text = None
    valid = None

class BaseDirective(Directive):
    has_content = True

    @abstractmethod
    def get_node(self):
        return None

    def run(self):
        node = self.get_node()
        self.state.nested_parse(self.content, self.content_offset, node)
        return [node]

class QuestionDirective(BaseDirective):
    required_arguments = 1
    option_spec = {
        'type': str,
        'language': str,
        'answer': str,
        'multiple': bool,
        'limit': int
    }

    def get_node(self):
        return Question()

    def run(self):
        node = BaseDirective.run(self)[0]
        node.id = self.arguments[0]
        node.header = '\n'.join(self.content)
        match = re.search(r'\.\.[ \t]+(positive|negative|box)::', node.header)
        if match:
            node.header = node.header[:match.start()].strip()
        else:
            node.header = node.header.strip()
        for option, value in list(self.options.items()):
            setattr(node, option, value)
        return [node]

class BoxDirective(Directive):
    has_content = True
    option_spec = {
        'type': str,
        'maxchars': int,
        'lines': int,
        'language': str
    }

    def run(self):
        node = Box()
        for option, value in list(self.options.items()):
            setattr(node, option, value)
        node.content = '\n'.join(self.content)
        return [node]

class PosNegDirective(Directive):
    has_content = True

    # This has to be replaced in subclasses
    valid = None

    def run(self):
        node = Choice()
        node.text = '\n'.join(self.content)
        node.valid = self.valid
        return [node]

class PositiveDirective(PosNegDirective):
    valid = True

class NegativeDirective(PosNegDirective):
    valid = False

class TitleParser(Parser):
    symbols = r'[!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~]'
    context = None

    def parse(self, inputstring, document):
        pattern = (r'(?:' + TitleParser.symbols + r'+\s)?.+\s' + TitleParser.symbols
                   + r'+\s+(?:(?::.+:.*\s)*)((?:.*\s)*?)(?:'
                   + TitleParser.symbols + r'+\s)?.+\s' + TitleParser.symbols + r'+')
        self.context = re.search(pattern, inputstring).group(1).strip('\n\r')
        Parser(self).parse(inputstring, document)

class Writer(UnfilteredWriter):
    docinfo_types = {
        'context': str,
        'order': int,
        'name': str,
        'accessible': str,
        'limit-time': int,
        'limit-memory': int,
        'limit-output': int,
        'environment': str
    }

    parser = None
    output = {}

    def translate(self):
        self.validate()
        self.docinfo()
        title = self.document.next_node(nodes.title)
        if title:
            self.output['name'] = title.astext()
        if self.parser.context and len(self.parser.context) > 0:
            self.output['context'] = self.parser.context
        self.process_questions()

    def validate(self):
        docinfo = self.document.next_node(nodes.docinfo)
        if docinfo:
            for field in docinfo.traverse(nodes.field):
                field_name = field.next_node(nodes.field_name).astext()
                field_body = field.next_node(nodes.field_body).astext()
                try:
                    Writer.docinfo_types[field_name](field_body)
                except KeyError:
                    raise StructureError('Invalid document option: ' + field_name + '.')
                except ValueError:
                    raise StructureError('Invalid value for ' + field_name + ' option: ' + field_body + '.')
        questions = self.document.traverse(Question)
        if len(questions) == 0:
            raise StructureError('There must be at least one question in your document.')
        for question in questions:
            qtype = get_type(question.type)
            qtype.validate(question)

    def docinfo(self):
        docinfo = self.document.next_node(nodes.docinfo)
        if not docinfo:
            return
        author = docinfo.next_node(nodes.author)
        if author:
            self.output['author'] = [s.strip() for s in author.astext().split(',')]
            if len(self.output['author']) == 1:
                self.output['author'] = self.output['author'][0]
        self.output['limits'] = {}
        for field in docinfo.traverse(nodes.field):
            field_name = field.next_node(nodes.field_name).astext()
            field_body = field.next_node(nodes.field_body).astext()
            if field_name == 'accessible':
                if field_body == 'true':
                    self.output['accessible'] = True
                    continue
                if field_body == 'false':
                    self.output['accessible'] = False
                    continue
            match = re.match('^limit-(.*)$', field_name)
            if match:
                self.output['limits'][match.group(1)] = Writer.docinfo_types[field_name](field_body)
            else:
                self.output[field_name] = Writer.docinfo_types[field_name](field_body)

    def process_questions(self):
        self.output['problems'] = collections.OrderedDict()
        for question in self.document.traverse(Question):
            name = question.parent.next_node(nodes.title)
            if name:
                question.name = name.astext()
            infos = {}
            for option in QuestionDirective.option_spec:
                value = getattr(question, option)
                if value:
                    infos[option] = value
            if question.name:
                infos['name'] = question.name
            if question.header and len(question.header) > 0:
                infos['header'] = question.header
            self.process_boxes(question, infos)
            self.process_choices(question, infos)
            self.output['problems'][question.id] = infos

    def process_boxes(self, question, infos):
        boxes = collections.OrderedDict()
        bid = 1
        for box in question.traverse(Box):
            boxId = 'boxId' + str(bid)
            boxes[boxId] = {}
            for option in BoxDirective.option_spec:
                value = getattr(box, option)
                if option == 'maxchars':
                    option = 'maxChars'
                if value:
                    boxes[boxId][option] = value
                if box.content:
                    boxes[boxId]['content'] = box.content
            bid += 1
        if len(boxes) > 0:
            infos['boxes'] = boxes

    def process_choices(self, question, infos):
        choices = []
        for choice in question.traverse(Choice):
            choices.append({
                'text': choice.text,
                'valid': choice.valid
            })
        if len(choices) > 0:
            infos['choices'] = choices

def get_type(ttype):
    if ttype == 'code':
        return Code()
    if ttype == 'code-single-line':
        return CodeSingleLine()
    if ttype == 'match':
        return Match()
    if ttype == "multiple-choice":
        return MultipleChoice()
    return UnknownType()

class StructureError(Exception):
    pass

class Type(object):
    def validate(self, question):
        pass

class Code(Type):
    def validate(self, question):
        for box in question.traverse(Box):
            if not box.type:
                raise StructureError('Every box directive must have a type option.')
            if box.type == 'text' and not box.content:
                raise StructureError('A box directive with a text type must have a content option.')

class CodeSingleLine(Type):
    pass

class Match(Type):
    def validate(self, question):
        if not question.answer:
            raise StructureError('A match type question must have an answer option.')

class MultipleChoice(Type):
    def validate(self, question):
        for choice in question.traverse(Choice):
            if not choice.text or len(choice.text) == 0:
                raise StructureError('Every positive and negative directive must have a content.')

class UnknownType(Type):
    def validate(self, question):
        raise StructureError('Unknown type for the question directive.')

def rst2dict(rst_string):
    directives.register_directive('question', QuestionDirective)
    directives.register_directive('box', BoxDirective)
    directives.register_directive('positive', PositiveDirective)
    directives.register_directive('negative', NegativeDirective)
    parser = TitleParser()
    writer = Writer()
    writer.parser = parser
    return core.publish_string(source=rst_string, parser=parser, writer=writer)


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

import copy
from collections import deque
import random
from collections import namedtuple
import numpy as np
import pandas as pd

import sys

from machine import Machine
from GymMachEnv import MachineEnv

Transition = namedtuple('Transition', ('state', 'next_state', 'action', 'reward', 'mask'))

class Memory(object):
    def __init__(self, capacity):
        self.memory = []
        self.capacity = capacity
        self.position = 0

    def push(self, state, next_state, action, reward, mask):
        """Saves a transition."""
        if len(self.memory) < self.capacity:
            self.memory.append(Transition(state, next_state, action, reward, mask))
        self.memory[self.position] = Transition(state, next_state, action, reward, mask)
        self.position = (self.position + 1) % self.capacity

    def sample(self, batch_size):
        transitions = random.sample(self.memory, batch_size)
        batch = Transition(*zip(*transitions))
        return batch

    def __len__(self):
        return len(self.memory)

class DoubleDQNet(nn.Module):
    def __init__(self, num_inputs, num_outputs):
        super(DoubleDQNet, self).__init__()
        self.num_inputs = num_inputs
        self.num_outputs = num_outputs

        self.fc1 = nn.Linear(num_inputs, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, num_outputs)

        for m in self.modules():
            if isinstance(m, nn.Linear):
                nn.init.xavier_uniform_(m.weight)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        qvalue = self.fc3(x)
        return qvalue

    @classmethod
    def train_model(cls, online_net, target_net, optimizer, batch, gamma):
        states = torch.stack(batch.state)
        next_states = torch.stack(batch.next_state)
        actions = torch.Tensor(batch.action).float()
        rewards = torch.Tensor(batch.reward)
        masks = torch.Tensor(batch.mask)

        pred = online_net(states).squeeze(1)
        _, action_from_online_net = online_net(next_states).squeeze(1).max(1)
        next_pred = target_net(next_states).squeeze(1)

        pred = torch.sum(pred.mul(actions), dim=1)

        target = rewards + masks * gamma * next_pred.gather(1, action_from_online_net.unsqueeze(1)).squeeze(1)

        loss = F.mse_loss(pred, target.detach())
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        return loss

    def get_action(self, input):
        qvalue = self.forward(input)
        _, action = torch.max(qvalue, 1)
        return action.numpy()[0]

def get_action(state, target_net, epsilon, env):
    if np.random.rand() <= epsilon:
        return env.action_space.sample()
    else:
        return target_net.get_action(state)

def update_target_model(online_net, target_net):
    # Target -> Net
    target_net.load_state_dict(online_net.state_dict())

def compute_avg_return(environment, policy, num_episodes):
    total_return = 0.0
    for _ in range(num_episodes):
        state = torch.Tensor(environment.reset())
        state = state.unsqueeze(0)
        episode_return = 0.0
        while not environment.done:
            action = get_action(state, policy, 0.1, environment)
            next_state, reward, done, _ = environment.step(action)
            next_state = torch.Tensor(next_state)
            next_state = next_state.unsqueeze(0)
            state = next_state
            episode_return += reward
        total_return += episode_return
    avg_return = total_return / num_episodes
    return avg_return# Evaluate the agent's policy once before training.

def gen_param_array(l16_array):
    full = []
    for row in range(len(l16_array)):
        x = l16_array[row]
        arr_params = []

        for col in range(len(x)):
            list_params = list(params.values())[col]
            value = list_params[x[col]]
            arr_params.append(value)
        print(arr_params)
        full.append(arr_params)
    return full

def evaluate_and_test(params,trial_number,folder): #trial function that trains and stores results into array

    max_episodes = 20000

    #Train Env
    machine = Machine()
    machine.curr_state = 0
    env = MachineEnv(machine)

    #Eval Env
    machine2 = Machine()
    machine2.curr_state = 0
    env2 = MachineEnv(machine2)

    online_net = DoubleDQNet(4, 2)
    target_net = DoubleDQNet(4, 2)
    update_target_model(online_net, target_net)

    optimizer = optim.Adam(online_net.parameters(), lr=params[0])
    online_net.train()
    target_net.train()
    memory = Memory(10000)

    #start_time = datetime.now().replace(microsecond=0)

    running_score = 0
    epsilon = 1.0
    steps = 0
    loss = 0
    initial_exploration = 1000
    log_interval = 10

    tracker = [[0,0]]

    for e in range(max_episodes):
        done = False

        score = 0
        state = env.reset()
        state = torch.Tensor(state)
        state = state.unsqueeze(0)
        while not done:
            steps += 1
            action = get_action(state, target_net, epsilon, env)
            next_state, reward, done, _ = env.step(action)

            next_state = torch.Tensor(next_state)
            next_state = next_state.unsqueeze(0)

            mask = 0 if done else 1
            #reward = reward if not done or score == 499 else -1
            action_one_hot = np.zeros(2)
            action_one_hot[action] = 1
            memory.push(state, next_state, action_one_hot, reward, mask)

            score += reward
            state = next_state

            if steps > initial_exploration:
                epsilon -= params[2]
                epsilon = max(epsilon, 0.1)

                batch = memory.sample(64)
                loss = DoubleDQNet.train_model(online_net, target_net, optimizer, batch,params[1])

                if steps % params[3] == 0:
                    update_target_model(online_net, target_net)

        if e % log_interval == 0:
            if e == 0: continue
            eval_score = compute_avg_return(env2,online_net,20)
            tracker.append([eval_score,e])

    #end_time = datetime.now().replace(microsecond=0)
    #print("Total training time  : ", end_time - start_time)
    np.savetxt(f'{folder}/trial_{trial_number}.txt', tracker, delimiter=',',fmt='%s')
    torch.save(online_net,f'{folder}/trial_{trial_number}_dqn_agent_.pt')
    return np.array(tracker)

def train(params_array,folder_name):
    trial = 0
    for sets in params_array:
        print("trial ",trial)
#         if trial in [0,1,2]:
#             trial+=1
#             continue
        evaluate_and_test(sets,trial,folder_name)
        trial+=1
    return

def main(args):
    folder_name = args[0]

    params = {
     'lr' : [1e-04,1e-03,1e-02,1e-01],
     'gamma' : [0.80,0.90,0.95,0.99],
     'epsilon_decay': [1e-05,1e-04,1e-03,1e-02],
     'update_freq' : [50,100,150,200]
    }

    config_array = np.array(pd.read_csv('L16.txt',header=None, sep='\t'))
    params_array = gen_param_array(config_array)
    train(params_array,folder_name)

    return

if __name__ == "__main__":
    '''
    Arguments:
    1. Folder name eg. run_1

    '''

    main(sys.argv[1:])


# this python file intends to copy the experiment proposed by Shaobo Xue
# the experiment refers to the paper:"基于持续增量模型的低速端口扫描检测算法"
# the main purpose of this experiment is to verify the precision of the algorithm which is
# mentioned in the above paper. Plus, some deficiency of this algorithm should be reveal
# during this experiment(such as some special slow port scan were not detected under the
# purposed algorithm).

import pandas as pd
import time
import numpy as np
import csv

class Host(object):
    def __init__(self, ip, pt):
        self.ip = ip
        self.pt = []
        self.pt.append(pt)

class Detect_Unit(object):

    def __init__(self, ip, dpt, dip):
        self.ip = ip
        self.dip = []
        self.dpt = []
        self.dip.append(dip)
        self.dpt.append(dpt)

        self.cusum_x1 = 0
        self.cusum_x2 = 0

        self.alarm = False

        self.live = True

        self.destination = []

        self.x1 = []
        self.x2 = []
        # self.x1.append(0)
        # self.x2.append(0)

    def similarity(self, host1, host2):
        summery = 0
        i = 0
        while i < len(host1.pt):
            if host1.pt[i] in host2.pt:
                summery = summery + 1
            i = i + 1
        m = len(host1.pt)
        n = len(host2.pt)
        if m < n:
            m = n
        return summery / m

    def calculateX2(self):
        if len(self.destination) <= 1:
            return 0
        sum = 0
        i = j = k = 0
        while i < len(self.destination):
            j = i + 1
            while j < len(self.destination):
                sum = sum + self.similarity(host1=self.destination[i], host2=self.destination[j])
                k = k + 1
                j = j + 1
            i = i + 1

        return sum / k

    def addDestination(self, dip, dpt):
        if len(self.destination) == 0:
            self.destination.append(Host(dip, dpt))
            return
        else:
            j = 0
            isNew = True
            while j < len(self.destination):
                if dip == self.destination[j].ip:
                    if dpt not in self.destination[j].pt:
                        self.destination[j].pt.append(dpt)
                    isNew = False
                    break
                j = j + 1
            if isNew:
                self.destination.append(Host(dip, dpt))
        return

    def addDip(self, dip):
        if dip not in self.dip:
            self.dip.append(dip)

    def addDpt(self, dpt):
        if dpt not in self.dpt:
            self.dpt.append(dpt)

def calculate_precision(timewindow, group):
    abnormal_count = 0
    abnormal_right = 0
    normal_count = 0
    normal_wrong = 0

    present = len(timewindow) - 1

    i = 0
    while i < len(timewindow[present]):
        if timewindow[present][i][12] != "normal":
            abnormal_count = abnormal_count + 1
            j = 0
            while j < len(group):
                if group[j].alarm:
                    if timewindow[present][i][5] == group[j].ip:
                        abnormal_right = abnormal_right + 1
                        break
                    if timewindow[present][i][3] == group[j].ip:
                        abnormal_right = abnormal_right + 1
                        break
                j = j + 1

        if timewindow[present][i][12] == "normal":
            normal_count = normal_count + 1

            j = 0
            while j < len(group):
                if group[j].alarm:
                    if timewindow[present][i][3] == group[j].ip:
                        '''print("--------------")
                        print(timewindow[present][i])
                        print(present,
                              i,
                              group[j].ip,
                              group[j].dip,
                              len(group[j].destination),
                              group[j].cusum_x1,
                              group[j].cusum_x2,
                              group[j].x1,
                              group[j].x2)
                        print("--------------")'''
                        normal_wrong = normal_wrong + 1
                        break

                    if timewindow[present][i][5] == group[j].ip:
                        '''print("--------------")
                        print(timewindow[present][i])
                        print(present,
                              i,
                              group[j].ip,
                              group[j].dip,
                              len(group[j].destination),
                              group[j].cusum_x1,
                              group[j].cusum_x2,
                              group[j].x1,
                              group[j].x2)
                        print("--------------")'''
                        normal_wrong = normal_wrong + 1
                        break
                j = j + 1
        i = i + 1

    return abnormal_count, abnormal_right, normal_count, normal_wrong

def predict(series):
    value = 0
    n = len(series)
    last = value
    i = 1
    while i < n:
        value = ((1 - (1 / i)) * last) + ((1 / i) * series[i])
        last = value
        i = i + 1
    return value

def cumulative_sum(group):
    if len(group) == 0:
        return
    else:
        j = 0
        while j < len(group):
            length = len(group[j].x1)
            yn = group[j].x1[length - 1] - predict(group[j].x1)
            m = 0
            n = group[j].cusum_x1 + yn
            if m > n:
                k = m
            else:
                k = n
            group[j].cusum_x1 = k

            length = len(group[j].x2)
            yn = group[j].x2[length - 1] - predict(group[j].x2)
            m = 0
            n = group[j].cusum_x2 + yn
            if m > n:
                k = m
            else:
                k = n
            group[j].cusum_x2 = k

            if group[j].cusum_x1 > threshold_x1 and group[j].cusum_x2 > threshold_x2:
                group[j].alarm = True
                # print(group[j].x1,group[j].x2)
            j = j + 1

    return

def create_statistic(group):
    if len(group) == 0:
        return
    else:
        j = 0
        while j < len(group):
            # print(group[j].x1,group[j].x2)
            if group[j].live:
                if (len(group[j].dip) / len(group[j].dpt)) > (len(group[j].dpt) / len(group[j].dip)):
                    k = (len(group[j].dip) / len(group[j].dpt))
                else:
                    k = (len(group[j].dpt) / len(group[j].dip))
                group[j].x1.append(k)
                group[j].x2.append(group[j].calculateX2())
            else:
                group[j].x1.append(-200)
                group[j].x2.append(-200)
            j = j + 1

    return

def mark_destination(timewindow, group):
    present = len(timewindow) - 1

    i = 0
    while i < len(timewindow[present]):
        j = 0
        while j < len(group):
            if group[j].ip == timewindow[present][i][3]:
                group[j].addDestination(dip=timewindow[present][i][5],
                                        dpt=timewindow[present][i][6])
            j = j + 1
        i = i + 1

    return

def mark_source_ip(timewindow, group):
    present = len(timewindow) - 1

    j = 0
    while j < len(group):
        group[j].dip.clear()
        group[j].dpt.clear()
        group[j].destination.clear()
        group[j].live = True
        j = j + 1

    i = 0
    while i < len(timewindow[present]):
        j = 0
        while j < len(group):
            if group[j].ip == timewindow[present][i][3] or group[j].ip == timewindow[present][i][5]:
                if group[j].alarm:
                    timewindow[present].__delitem__(i)
                    i = i - 1
                    break
            j = j + 1
        i = i + 1

    i = 0
    while i < len(timewindow[present]):
        isNew = True
        j = 0
        while j < len(group):
            if group[j].ip == timewindow[present][i][3]:
                group[j].addDip(dip=timewindow[present][i][5])
                group[j].addDpt(dpt=timewindow[present][i][6])
                isNew = False
                break
            j = j + 1
        if isNew:
            new = Detect_Unit(ip=timewindow[present][i][3],
                              dip=timewindow[present][i][5],
                              dpt=timewindow[present][i][6])
            group.append(new)
        i = i + 1

    j = 0
    while j < len(group):
        if len(group[j].dip) == 0 or len(group[j].dpt) == 0:
            group[j].live = False
        j = j + 1

    return

filepath = "D:\Python\Python37\myexperiment\portScanningDetection\CIDDS-001\\traffic\OpenStack\CIDDS-001-internal-week1.csv"

# open the original csv data file
file = csv.reader(open(filepath, 'r'))

# timewindow contains five[which is given by windownum below and the specific number is decided by
# the method given in paper] item and each item is refers to 2 min flow data
timewindow = []
# timing is used to print the timestamp of flow data which is under the present calculation.
timing = 0
threshold_x1 = 0
threshold_x2 = 0

totaldetect = 0
rightdetect = 0
normaldetect = 0
wrongdetect = 0

group = []
# handle the first and second row
isFirstrow = True
head = next(file)
firstrow = next(file)
timeArray = time.strptime(firstrow[0], "%Y-%m-%d %H:%M:%S.%f")
timeStamp = float(time.mktime(timeArray))
start = timeStamp
index = 0
for row in file:

    if isFirstrow:
        timewindow.append([])
        timewindow[index].append(firstrow)
        isFirstrow = False

    timeArray = time.strptime(row[0], "%Y-%m-%d %H:%M:%S.%f")
    timeStamp = float(time.mktime(timeArray))
    end = timeStamp

    if timeArray.tm_hour > timing:
        print(str(timeArray.tm_hour) + "AM")
        timing = timing + 1
    elif timeArray.tm_hour < 0:
        continue
    elif timeArray.tm_hour >= 13:
        print("considered abnormal(actually abnormal):" + str(rightdetect) + "\ttotal abnormal:" + str(totaldetect))
        print("considered abnormal(actually abnormal)/total abnormal:" + str(rightdetect / totaldetect))
        print("considered abnormal(actually normal):" + str(wrongdetect) + "\ttotal normal:" + str(normaldetect))
        print("considered abnormal(actually normal)/total normal:" + str(wrongdetect / normaldetect))
        exit(0)

    timewindow[index].append(row)

    if end - start > 180:
        mark_source_ip(timewindow=timewindow, group=group)
        mark_destination(timewindow=timewindow, group=group)
        create_statistic(group=group)
        cumulative_sum(group=group)
        (t, r, n, w) = calculate_precision(timewindow=timewindow, group=group)
        totaldetect = totaldetect + t
        rightdetect = rightdetect + r
        normaldetect = normaldetect + n
        wrongdetect = wrongdetect + w

        start = end
        timewindow.append([])
        index = index + 1


import unittest
import os
import pandas as pd
import numpy as np
from tradeframework.api.core import Asset
from tradeframework.environments import SandboxEnvironment
from tradeframework.api.insights import InsightManager
import tradeframework.operations.utils as utils
import tradeframework.operations.trader as trader

dir = os.path.dirname(os.path.abspath(__file__))

class SignalsTest(unittest.TestCase):

    def setUp(self):
        marketData = pd.read_csv(dir + "/data/testData3.csv")
        marketData = marketData \
            .reset_index() \
            .assign(Date_Time=lambda x: pd.to_datetime(x['Date_Time'])) \
            .set_index("Date_Time") \
            [["Open", "High", "Low", "Close"]]
        self.marketData = marketData.tz_convert("US/Eastern", level="Date_Time")

    def test_signals(self):

        # Create portfolio
        env = SandboxEnvironment("TradeFair")
        asset = env.createAsset("DOW", self.marketData)

        p = env.setPortfolio(
            env.createDerivative("MyPortfolio", weightGenerator=env.createOptimizer("EqualWeightsOptimizer"))
            .addAsset(
                env.createDerivative("TestModel", weightGenerator=env.createModel("TrendFollowing", opts={"start": "15:00", "end": "16:00", "barOnly": True}))
                .addAsset(asset)
            )
        )

        env.refresh()

        #signal = trader.getCurrentSignal(p, capital=10000)

        im = InsightManager(p)
        im.addInsightGenerator(im.createInsightGenerator("Signals", opts={"capital": 10000}))
        signal = im.generateInsights(display=False)["Signals"]

        # Jan'23: Bug: Original value here was based on date that missed July 1st 2013 data!
        # Jan'23: Bug: To ensure test_predictions (below) works, the time series needs to run to 2pm on 2013-07-10
        self.assertTrue(np.allclose(signal["value"], 0.9912554640452014))

    def test_predict(self):

        # Create portfolio
        env = SandboxEnvironment("TradeFair")
        asset = env.createAsset("DOW", self.marketData)

        p = env.setPortfolio(
            env.createDerivative("MyPortfolio", weightGenerator=env.createOptimizer("EqualWeightsOptimizer"))
            .addAsset(
                env.createDerivative("TestModel", weightGenerator=env.createModel("TrendFollowing", opts={"start": "15:00", "end": "16:00", "barOnly": True}))
                .addAsset(asset)
            )
        )

        env.refresh()

        possibles = []
        for i in range(-10, 10):
            ohlc = [[15274.38 + i, np.nan, np.nan, np.nan]]
            index = pd.DatetimeIndex(['2013-07-10 15:00:00'], tz='US/Eastern')
            possibles.append(utils.createAssetFromOHLC(index, ohlc, "DOW"))

        #signals = trader.predictSignals(p, possibles)

        im = InsightManager(p)
        im.addInsightGenerator(im.createInsightGenerator("Predictions", opts={"prices": possibles}))
        signals = im.generateInsights(display=False)["Predictions"]

        self.assertEqual(signals[9][0]["markets"][0]["signal"], "SELL")
        self.assertEqual(signals[10][0]["markets"][0]["signal"], "HOLD")
        self.assertEqual(signals[11][0]["markets"][0]["signal"], "BUY")

if __name__ == '__main__':
    unittest.main()


import csv
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from pandas import DataFrame

def graph_max_by_year():

    max_2011 = max_2012 = max_2013 = max_2014 = max_2015 = 0

    df = pd.read_csv('D:\Python_Project_Compilers/xwra_2011_d_xl.csv', encoding='latin1')
    for row in range(len(df)):
        if max_2011 < float(df.iloc[row, 3]):
            max_2011 = float(df.iloc[row, 3])
            nation_max_2011 = df.iloc[row, 1]

    df = pd.read_csv('xwra_2012_d_xl.csv', encoding='latin1')
    for row in range(len(df)):
        if max_2012 < float(df.iloc[row, 3]):
            max_2012 = float(df.iloc[row, 3])
            nation_max_2012 = df.iloc[row, 1]

    df = pd.read_csv('xwra_2013_d_xl.csv', encoding='latin1')
    for row in range(len(df)):
        if max_2013 < float(df.iloc[row, 3]):
            max_2013 = float(df.iloc[row, 3])
            nation_max_2013 = df.iloc[row, 1]

    df = pd.read_csv('xwra_2014_d_xl.csv', encoding='latin1')
    for row in range(len(df)):
        if max_2014 < float(df.iloc[row, 3]):
            max_2014 = float(df.iloc[row, 3])
            nation_max_2014 = df.iloc[row, 1]

    df = pd.read_csv('xwra_2015_d_xl.csv', encoding='latin1')
    for row in range(len(df)):
        if max_2015 < float(df.iloc[row, 3]):
            max_2015 = float(df.iloc[row, 3])
            nation_max_2015 = df.iloc[row, 1]

    # set width of bar
    barWidth = 0.25

    # set height of bar
    bars_max = [max_2011, max_2012, max_2013, max_2014, max_2015]

    # Set position of bar on X axis
    r1 = np.arange(len(bars_max))

    # Make the plot
    plt.bar(r1, bars_max, color='#7f6d5f', width=barWidth, edgecolor='white')  # label=nation_max_2011)

    # Add xticks on the middle of the group bars
    plt.xlabel('Most Valuable Nations', fontweight='bold')
    plt.xticks([r + barWidth for r in range(len(bars_max))],
               ["2011: \n" + str(nation_max_2011), "2012: \n" + str(nation_max_2012),
                "2013: \n" + str(nation_max_2013),
                "2014: \n" + str(nation_max_2014), "2015: \n" + str(nation_max_2015)])

    # Create legend & Show graphic
    plt.legend()
    plt.show()

    return bars_max


#소프트맥스 오버플로우 개선
import numpy as np
def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a-c)
    sum_exp_a = np.sum(exp_a)
    y = exp_a/sum_exp_a
    return y

a = np.array([1010,1000,990])
#print(np.exp(a)/np.sum(np.exp(a))) -> 오버플로우 발생

c = np.max(a)
print(np.exp(a-c)/np.sum(np.exp(a-c)))
print(softmax(a))
print("==============")
#소프트맥스 함수의 특징
b = np.array([0.3,2.9,4.0])
y = softmax(b)
print(y)
print(np.sum(y))


import sqlite3
import tempfile
from pathlib import Path

class MaxScoreCounter():
    def __init__(self):
        self.__connection = sqlite3.connect(str(Path(tempfile.gettempdir(), "HarryPotter.db")))
        self.__cursor = self.__connection.cursor()

        self.__cursor.execute("CREATE TABLE if not exists scores (id int, score int)")
        self.__connection.commit()

    def updateMaxScore(self, score):
        self.__cursor.execute("SELECT score FROM scores WHERE id = 1")
        scores = self.__cursor.fetchall()

        if len(scores) == 0:
            self.__cursor.execute("INSERT INTO scores VALUES (?, ?)", (1, score))
            self.__connection.commit()
            return

        maxScore = scores[0][0]
        if score > maxScore:
            self.__cursor.execute("UPDATE scores SET score = (?) WHERE id = 1", (score,))
            self.__connection.commit()

    def getMaxScore(self):
        self.__cursor.execute("SELECT score FROM scores WHERE id = 1")
        scores = self.__cursor.fetchall()
        return str(scores[0][0] if len(scores) > 0 else 0)


##Given two strings S and T,
# return if they are equal when both are typed into empty text editors.
# #means a backspace character.
# Example 1:
# Input: S = "ab#c", T = "ad#c"
# Output: true
# Explanation: Both S and T become "ac".
# Example 2:
# Input: S = "ab##", T = "c#d#"
# Output: true
# Explanation: Both S and T become "".
# Example 3:
# Input: S = "a##c", T = "#a#c"
# Output: true
# Explanation: Both S and T become "c".
# Example 4:
# Input: S = "a#c", T = "b"
# Output: false
# Explanation: S becomes "c" while T becomes "b".
# Note:
# 1 <= S.length <= 200
# 1 <= T.length <= 200
# S and T only contain lowercase letters and '#' characters.
# Follow up:
# Can you solve it in O(N) time and O(1) space?
class Solution:
    def backspaceCompare(self, S: str, T: str):
        i = len(S) - 1
        j = len(T) - 1
        k = 0
        m = 0
        while i >= 0 or j >= 0:
            while i >= 0 and (S[i] == "#" or k > 0):
                if S[i] == "#":
                    k += 1
                else:
                    k -= 1
                i -= 1
            while j >= 0 and (T[j] == "#" or m > 0):
                if T[j] == "#":
                    m += 1
                else:
                    m -= 1
                j -= 1
            if i < 0 or j < 0:
                break
            if S[i] != T[j]:
                return False
            i -= 1
            j -= 1
        while i >= 0 and (S[i] == "#" or k > 0):
            if S[i] == "#":
                k += 1
            else:
                k -= 1
            i -= 1
        if i >= 0 and S[i] != "#":
            return False
        while j >= 0 and (T[j] == "#" or m > 0):
            if T[j] == "#":
                m += 1
            else:
                m -= 1
            j -= 1
        if j >= 0 and S[j] != "#":
            return False
        return True

a = "ab##"
b = "c#d#"
s = Solution()
print(s.backspaceCompare(a, b))


import numpy as np
import scipy.linalg as linalg
from typing import Tuple

class ThoulessModel:
    h_0: float
    delta_0: float
    t_0: float
    period: float
    # The number of sites.
    sites: int

    def __init__(self, h_0: float, delta_0: float, t_0: float, period: float, sites: int):
        self.h_0 = h_0
        self.delta_0 = delta_0
        self.t_0 = t_0
        self.period = period
        self.sites = sites
        assert sites > 0 and sites % 2 == 0

    '''
    Return the cosine part of J1/J2.
    '''

    def delta(self, t: float) -> float:
        return self.delta_0 * np.sin(2 * np.pi * t / self.period)

    '''
    Return the staggered on-site energy offset.
    '''

    def h_st(self, t: float) -> float:
        return self.h_0 * np.cos(2 * np.pi * t / self.period)

    '''
    Return the Hamiltonian of this model, in form of matrix, in time t.
    '''

    def single_hamiltonian(self, t: float) -> np.ndarray:
        hamiltonian = np.zeros((self.sites, self.sites))
        # Fill the diagonal elements.
        for i in range(0, self.sites):
            hamiltonian[i, i] = (-1) ** i * self.h_st(t)
        # Fill the non-diagonal elements.
        for i in range(0, self.sites - 1):
            hamiltonian[i, i + 1] = (self.t_0 + self.delta(t) * (-1) ** i)
            hamiltonian[i + 1, i] = np.conj(hamiltonian[i, i + 1])
        return hamiltonian

    '''
    Diagonalize the single-hamiltonian matrix.
    Return a Tuple containing energy_levels(eigenvalues) and vectors(eigenvectors).
    '''

    def single_exact_diagonalization(self, t: float) -> Tuple[np.ndarray, np.ndarray]:
        single_hamiltonian: np.ndarray = self.single_hamiltonian(t)
        energy_levels, vectors = linalg.eigh(single_hamiltonian)
        return energy_levels, vectors.T

    '''
    Return the bulk-space hamiltonian matrix
    '''
    def bulk_hamiltonian(self, k, t):
        omega = 2 * np.pi * t / self.period
        matrix = np.zeros((2, 2), dtype=complex)
        # Fill the diagonal elements.
        matrix[0, 1] = 2 * 1j * self.delta_0 * np.sin(omega) * np.sin(k) + 2 * 1 * np.cos(k)
        matrix[1, 0] = -2 * 1j * self.delta_0 * np.sin(omega) * np.sin(k) +  2 * 1 * np.cos(k)
        matrix[0, 0] = self.h_0 * np.cos(omega)
        matrix[1, 1] = -self.h_0 * np.cos(omega)
        return matrix

    '''
    Calculate bulk levels, and return them in form of a two-dimensional array: [E+_array, E-_array].
    '''

    def bulk_levels(self, t: float) -> np.ndarray:
        k_points = np.linspace(-np.pi, np.pi, self.sites // 2 + 1)
        levels = np.sqrt(self.h_st(t) ** 2 + self.delta(t) ** 2 *
                         np.sin(k_points / 2) ** 2 + self.t_0 ** 2 * np.cos(k_points / 2) ** 2)
        return np.concatenate(
            (levels, -levels)
        )