from os import mkdir, path, walk

from yaml import safe_dump, safe_load

base_folder = "assets/deck"

if not path.exists(path.join(base_folder, "cleaned")):
    mkdir(path.join(base_folder, "cleaned"))

files = [file for file in list(walk(base_folder))[0][2] if file.endswith(".yaml")]
for file in files:
    with open(path.join(base_folder, file)) as f:
        content = f.read()
        total_words = len(content.split("\n"))
        print(f"> Reading '{file}': {total_words} words")
        words = {str(word): taboo for word, taboo in safe_load(content).items()}
        words_capitalize = {
            word[0].upper() + word[1:]: taboo for word, taboo in words.items()
        }
    with open(path.join(base_folder, "cleaned", file), "w+") as new_file:
        safe_dump(words_capitalize, new_file)
        print(f"> Cleaned '{file}': {len(words_capitalize)} words")
    taboo_n = dict()
    for taboo in words_capitalize.values():
        taboo_n[len(taboo)] = taboo_n.get(len(taboo), 0) + 1
    print(f"  # stats {taboo_n}")
    print("-" * 10)


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

def tokens(str1):
    import re
    return re.findall('[a-zA-Z]+', str1)

def ngrams(words):
    for length in range(1, 5 + 1):
        for ngram in zip(*(words[i:] for i in range(length))):
            yield ngram

def mapper(files):
    import fileinput
    from nltk.tokenize import word_tokenize
    from collections import Counter
    ngram_counter = Counter()
    for line in fileinput.input(files):
        line = line.decode('iso-8859-1')
        words = tokens(line.lower())
        # words = word_tokenize(line.lower())
        ngram_counter.update(ngrams(words))

    for ngram, count in ngram_counter.iteritems():
        print (u' '.join(ngram) + u'\t' + unicode(count)).encode('utf-8')

def line_to_ngram(line):
    line = line.decode('iso-8859-1')
    return line.split(u'\t', 1)[0]

def line_to_count(line):
    line = line.decode('iso-8859-1')
    return int(line.split(u'\t', 1)[1])

def reducer(files):
    import fileinput
    from itertools import groupby, imap

    for ngram, lines in groupby(fileinput.input(files), key=line_to_ngram):
        count = sum(imap(line_to_count, lines))
        if count>=3:
            print (ngram + u'\t' + unicode(count)).encode('utf-8')

if __name__ == '__main__':
    import argparse
    import sys
    parser = argparse.ArgumentParser(description='N-gram counter')
    parser.add_argument(
        '-r', '--reducer', action='store_true', help='reducer mode')
    parser.add_argument(
        '-m', '--mapper', action='store_true', help='mapper mode')
    parser.add_argument('files', metavar='FILE', type=str, nargs='*',
                        help='input files')

    args = parser.parse_args()

    if (args.mapper and args.reducer
            or
            not args.mapper and not args.reducer):
        parser.print_help()
        sys.exit(1)

    if args.mapper:
        mapper(args.files)
    elif args.reducer:
        reducer(args.files)


from fastapi.exceptions import HTTPException
from sqlalchemy.orm.session import Session
from starlette import status
from blog import models, schemas

def getall(db: Session):
    blogs = db.query(models.Blog).all()
    return blogs

def create_blog(request: schemas.Blog, db: Session):
    new_blog = models.Blog(title= request.title, body= request.body, user_id= 1)
    db.add(new_blog)
    db.commit()
    db.refresh(new_blog)
    return new_blog

def get_blog_by_id(id, db: Session):
        blog = db.query(models.Blog).filter(models.Blog.id == id).first()
        if not blog:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail= f'The blog with the id: {id} was not found')
        return blog

def update_blog(id, request:  schemas.Blog, db: Session):
    blog=  db.query(models.Blog).filter(models.Blog.id == id)
    if not blog.first():
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The blog qith the id {id} was not found')
    blog.update({'title': request.title,'body':request.body})
    db.commit()
    return 'updated'

def delete_blog(id, db: Session):
    blog = db.query(models.Blog).filter(models.Blog.id==id)
    if not blog.first():
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The blog qith the id {id} was not found')
    blog.delete(synchronize_session=False)
    db.commit()
    return 'Done'


import sys

from utils import log
from interp import build_surf
from wave import build_wave
from api import build_api

def main() -> None:
    """
    Simple build script for the project that drops the CMake build into a directory
    Build configuration can be passed either as 'Debug' or 'Release'

    Examples
    --------
    python surf.py surf
    python surf.py wave debug
    python surf.py api
    """
    usage = "usage: surf.py <project> <optional_build_cfg>"
    if len(sys.argv) <= 1:
        log(usage)
        return

    project_name = sys.argv[1].lower()
    if project_name == "surf":
        build_surf()
    elif project_name == "wave":
        build_wave()
    elif project_name == "api":
        build_api()
    else:
        log(f"invalid project - {usage}")

if __name__ == '__main__':
    main()


import csv
import os
import pytest
from deduce_uces.algs.indexed_seq import IndexedSeq
import tempfile

from hypothesis import given
from hypothesis.strategies import composite, integers, lists, text

from deduce_uces.algs.merge_doa import CoreKmer, generate_contig_sequences_indexed
from deduce_uces.algs.uce_params import UCEParams, get_uce_max_gap

@composite
def contig_data(draw, fasta=text(min_size=3, alphabet=["A", "C", "G", "T"])):
    fa = draw(fasta)
    core_kmer_len = draw(integers(min_value=3, max_value=len(fa)))

    core_kmer_positions = draw(
        lists(
            integers(min_value=0, max_value=len(fa) - core_kmer_len), unique=True
        ).map(sorted)
    )

    core_kmers = sorted(
        [
            CoreKmer(
                id=0,
                genome=0,
                contig="chr",
                position=pos,
            )
            for pos in core_kmer_positions
        ]
    )

    min_len = draw(integers(min_value=core_kmer_len, max_value=len(fa)))

    return fa, core_kmers, min_len, core_kmer_len

# Ensure that the sequences generated are always present in the FASTA
@given(contig_data())
def test_generate_contig_sequences_seqs_in_fasta(data):
    fa, core_kmers, min_len, core_kmer_len = data

    params = UCEParams(
        uce_min_length=min_len,
        uce_min_homology=1,
        core_kmer_len=core_kmer_len,
        uce_min_support=1,
        uce_max_gap=get_uce_max_gap(1, min_len, 0),
        core_kmer_mismatches=0,
    )

    with tempfile.NamedTemporaryFile() as fasta:
        fasta.writelines([b">chr\n", fa.encode()])
        fasta.flush()

        index = IndexedSeq(fasta.name, build_index=True)

        assert all(
            s in fa
            for s in generate_contig_sequences_indexed(
                (ck for ck in core_kmers),
                min_len=min_len,
                uce_params=params,
                index=index,
            )
        )

def get_contig_sequence_dataset(filename):
    input_path = os.path.join(os.path.split(__file__)[0], "data", "merge", filename)
    with open(input_path, "r") as f:
        reader = csv.reader(f)
        return [CoreKmer(int(line[0]), 0, "chr1", int(line[0])) for line in reader]

GENERATE_CONTIG_SEQUENCE_TEST_CASES = [
    (11, ["ATCCCCAAATA"]),
    (10, ["ATCCCCAAAT", "TCCCCAAATA"]),
    (
        6,
        [
            "AGGGTT",
            "GGGTTC",
            "GGTTCA",
            "GTTCAG",
            "CCGTAG",
            "CGTAGT",
            "GTAGTA",
            "TAGTAC",
            "ATCCCC",
            "TCCCCA",
            "CCCCAA",
            "CCCAAA",
            "CCAAAT",
            "CAAATA",
        ],
    ),
]

TEST_SEQ = "AGGGTTCAGCGAAAAAGGCCGTAGTACCCCATCCCCAAATA"

@pytest.mark.parametrize(
    "min_len,expected",
    GENERATE_CONTIG_SEQUENCE_TEST_CASES,
)
def test_generate_contig_sequences(min_len, expected):
    contig_sequences = get_contig_sequence_dataset("contig_sequences.csv")

    with tempfile.NamedTemporaryFile() as fasta:
        fasta.writelines([b">chr1\n", TEST_SEQ.encode()])
        fasta.flush()

        index = IndexedSeq(fasta.name, build_index=True)

        params = UCEParams(
            uce_min_length=min_len,
            uce_min_homology=1,
            core_kmer_len=5,
            uce_min_support=1,
            uce_max_gap=get_uce_max_gap(1, min_len, 0),
            core_kmer_mismatches=0,
        )

        assert (
            list(
                generate_contig_sequences_indexed(
                    (x for x in contig_sequences),
                    min_len=min_len,
                    uce_params=params,
                    index=index,
                )
            )
            == expected
        )


def block(matrix, row, column):
    matrix[row-1][column-1] = 'b'

#domenii
def domenii(matrix):
    domenii = dict()
    list2 = []

    for j in range(len(matrix[0])):
        list1 = []
        for i in range(len(matrix)):
            if(matrix[i][j] != 'b'):
                list1.append(i+1)
        list2.append(list1)

    counter = 0
    for elem in list2:
        counter = counter + 1
        domenii['X' + str(counter)] = elem
    return domenii

#restrictie
def verificaDiagonalaSus(matrice, row, column):
    iterRow = row
    iterCol = column
    while iterCol >= 0 and iterRow >= 0:
        if matrice[iterRow][iterCol] == 1:
            return False
        iterCol -= 1
        iterRow -= 1
    return True

#restrictie
def verificaDiagonalaJos(matrice, row, column):
    iterRow = row
    iterCol = column
    while iterCol >= 0 and iterRow < len(matrice):
        if matrice[iterRow][iterCol] == 1:
            return False
        iterRow += 1
        iterCol -= 1
    return True

#restrictie
def unicDiagonala(matrice, row, column):
    return verificaDiagonalaSus(matrice, row, column) and verificaDiagonalaJos(matrice, row, column)

#restrictie
def unicRand(matrice, row):
    for col in range(len(matrice)):
        if matrice[row][col] == 1:
            return False
    return True

#restrictie
def unicColoana(matrice, column):
    for row in range(len(matrice)):
        if matrice[row][column] == 1:
            return False
    return True

#restrictie
def isCorrect(matrice, row, column):
    return unicRand(matrice, row) and unicColoana(matrice, column) and unicDiagonala(matrice, row, column)

def ForwardChecking(matrice, regine):
    if len(matrice) == regine:
        for i in matrice:
            print(i)
        return True
    rowsProposition = getRowsProposition(matrice, regine)
    for row in rowsProposition:
        matrice[row][regine] = 1
        domainWipeOut = False
        for variable in getFromConstraint(matrice, regine):
            if fc(matrice, variable.row, variable.column):
                domainWipeOut = True
                break
        if not domainWipeOut:
            if ForwardChecking(matrice, regine + 1):
                return True
        matrice[row][regine] = 0

def fc(matrice, row, regine):
    actualDomain = getRowsProposition(matrice, regine)
    tempDomain = list(actualDomain)
    for propositionRow in actualDomain:
        if not isCorrect(matrice, propositionRow, regine):
            tempDomain.remove(propositionRow)
    return len(tempDomain) == 0

def getFromConstraint(matrice, regine):
    result = []
    for row in range(len(matrice)):
        for col in range(regine + 1, len(matrice)):
            if matrice[row][col] == 0 and isCorrect(matrice, row, col):
                result.append(Unassigned(row, col))
    return result

def getRowsProposition(matrice, regine):
    rows = []
    for row in range(len(matrice)):
        if isCorrect(matrice, row, regine):
            rows.append(row)
    return rows

def ForwardCheckingOrder(grid, queen):
    if len(grid) == queen:
        for i in grid:
            print(i)
        return True
    rowsProposition = getHeuristicRowsProposition(grid, queen)
    for row in rowsProposition:
        grid[row.row][queen] = 1
        domainWipeOut = False
        for variable in getUnassignedFromConstraint(grid, queen):
            if fc(grid, variable.row, variable.column):
                domainWipeOut = True
                break
        if not domainWipeOut:
            if ForwardCheckingOrder(grid, queen + 1):
                return True
        grid[row.row][queen] = 0

def getHeuristicRowsProposition(grid, queen):
    rows = []
    for row in range(len(grid)):
        if isCorrect(grid, row, queen):
            tempGrid = grid.copy()
            tempGrid[row][queen] = 1
            rows.append(HeuristicRow(row, queen, rateForHeuristic(tempGrid, queen + 1)))
    rows.sort(key=lambda x: x.rate)
    return rows

def rateForHeuristic(grid, queen):
    return len(getRowsProposition(grid, queen))

class HeuristicRow:

    def __init__(self, row, column, rate):
        self.row = row
        self.column = column
        self.rate = rate

    def __eq__(self, other):
        return self.row == other.row and self.column == other.column

    def __hash__(self):
        return hash(self.row) ^ hash(self.column)

class Unassigned:

    def __init__(self, row, column):
        self.row = row
        self.column = column

    def __eq__(self, other):
        return self.row == other.row and self.column == other.column

    def __hash__(self):
        return hash(self.row) ^ hash(self.column)

matrix = [[0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 0]]

print("Original ", matrix)
block(matrix,1,1), block(matrix,2,2), block(matrix,4,3)
print("With blocks ", matrix)
print("Domenii", domenii(matrix))

print("Forward checking")
print(ForwardChecking(matrix, 0))


# 도로 건설

t = int(input())
for tc in range(t):
    W, H = map(int, input().split())
    map_li = [list(map(int, input().split())) for _ in range(H)]
    road = []
    # 가로 확인
    for i in range(H):
        if map_li[i].count(1) == 0:
            road.append([[i, j] for j in range(W)])
    # 세로 확인
    for j in range(W):
        for i in range(H):
            if map_li[i][j] == 1:
                break
        else:
            road.append([[k, j] for k in range(H)])
    # 대각 확인
    for i in range(H-1):
        tmp = []
        for j in range(H-i):
            if j + i >= H or j >= W:
                continue
            if map_li[j+i][j] == 1:
                break
            tmp.append([j+i, j])
        else:
            road.append(tmp)

    for i in range(W-1):
        tmp = []
        for j in range(W-i):
            if j + i >= W or j >= H:
                continue
            if map_li[j][j+i] == 1:
                break
            tmp.append([j, j+i])
        else:
            road.append(tmp)

    for i in range(H-1):
        tmp = []
        for j in range(H-i):
            if H-(j+i)-1 < 0 or j >= W:
                continue
            if map_li[H-(j+i)-1][j] == 1:
                break
            tmp.append([H-(j+i)-1, j])
        else:
            road.append(tmp)

    for i in range(W-1):
        tmp = []
        for j in range(W-i):
            if H-(j+i)-1 < 0 or j >= H:
                continue
            if map_li[j][W-(j+i)-1] == 1:
                break
            tmp.append([j, W-(j+i)-1])
        else:
            road.append(tmp)

    if not road:
        print('#{} -1' .format(tc+1))
    else:
        homes = []
        min_val = 1000
        for i in range(H):
            for j in range(W):
                if map_li[i][j] == 1:
                    homes.append([i, j])

        for ro in road:
            home_min = [1000] * len(homes)
            for i in range(len(homes)):
                for j in range(len(ro)):
                    dis = abs(homes[i][0] - ro[j][0]) + abs(homes[i][1] - ro[j][1])
                    if dis < home_min[i]:
                        home_min[i] = dis
            if min_val > max(home_min):
                min_val = max(home_min)
        print('#{} {}'.format(tc + 1, min_val))


"""
Rabin Karp Algorithm for String Matching

The concept of rabin karp is hashing, if two values are same they will have
same hash values and same digits, so rabin karp first computes hashes and
if they match then it moves forward to check digits otherwise skips it.
Let assume was have a string P of length m and a substring S of length n
The hashes can be computed in O(m) time with the help of ROLLING HASHES,
here the hash values of most significant digit is substracted and that
of the next digit is added.

Time Complexity:
Best Case: O(m - n + 1)
Average Case: O(m + n)* amortized
Worst Case: O(mn)

Usage:
```
>>> RabinKarp.search('hello', 'll')
True
>> RabinKarp.search('qwerty', 'abcd')
False
```
"""

class RabinKarp:
    """
    Rabin Karp Algorithm
    """

    @staticmethod
    def get_value(char):
        """
        Returns value of character in decimal system where a =1, z=26
        :param: char -> integer
        :return: integer
        """
        return ord(char) - ord('a') + 1

    @staticmethod
    def check_digits(index, string, sub_string):
        """Checks for equal strings and substring from index of string"""
        return string[index:index+len(sub_string)] == sub_string

    @staticmethod
    def search(string, sub_string, prime=10**7, d=26):
        """
        Returns True if the substring is present
        int the string otherwise returns False
        :param: string -> string
        :param: sub_string -> string
        :param: prime -> a prime number, the larger the better
        :param: d -> number of digits possible in strings |#s|
        :return: Boolean
        """
        l_s = len(string)
        l_sub = len(sub_string)
        if l_s < l_sub:
            return False

        hash_sub = 0
        hash_t = 0

        for i in range(l_sub):
            hash_sub += (RabinKarp.get_value(sub_string[i])
                         * (d ** (l_sub - i - 1))) % prime
            hash_t += (RabinKarp.get_value(string[i])
                       * (d ** (l_sub - i - 1))) % prime

        if hash_sub == hash_t:
            if RabinKarp.check_digits(0, string, sub_string):
                return True

        for i in range(1, l_s - l_sub + 1):
            # Calculate Rolling Hash
            hash_t = (d * (hash_t - (RabinKarp.get_value(string[i - 1]) * d**(
                l_sub - 1))) + RabinKarp.get_value(string[i + l_sub - 1])) \
                % prime

            if hash_sub == hash_t:
                if RabinKarp.check_digits(i, string, sub_string):
                    return True
        return False

if __name__ == '__main__':
    assert RabinKarp.get_value('a') == 1, 'Check Get Value Method'
    assert RabinKarp.get_value('z') == 26, 'Check Get Value Method'

    assert RabinKarp.search('hello', 'll') is True, 'Check Search Method'
    assert RabinKarp.search(
        'abcdefghjikl', 'aa') is False, 'Check Search Method'

    from random import randint

    for i in range(100):
        string = ''.join([chr(97 + randint(0, 26)) for _ in range(100)])
        substring = ''.join([chr((97) + randint(0, 26)) for _ in range(5)])
        assert (substring in string) == (RabinKarp.search(
            string, substring)), 'Check Search Method'

    print("All test cases passed")


# -*- coding: UTF-8 -*-
# 1.计算从1到1000以内所有奇数的和并输出
# solution 1
sum = 0
for num in range(1,1001):
    # print(num)
    if num%2:
        sum += num

print('\nThe sum of odd integers ranging from 1 to 1000 is:', sum)

# solution 2
sum = 0
n = 1000 - 1
while n > 0:
    sum = sum + n
    n = n - 2
print('\nThe sum of odd integers ranging from 1 to 1000 is:', sum)

print()


from pytest import mark
from pages.heroku.heroku import Heroku

@mark.heroku
def test_heroku_dropdown_option(driver):
  heroku = Heroku(driver)
  heroku.homepage()
  heroku.dropdown.click()
  assert heroku.dropdown_list.current_page_url() == 'http://the-internet.herokuapp.com/dropdown'
  heroku.dropdown_list.go_to_element('Option 2')
  assert heroku.second_option.text() == 'Option 2'
  assert heroku.dropdown_list.attribute('value') == '2'

@mark.parallel
def test_find_qux_button(driver):
  heroku = Heroku(driver)
  heroku.homepage()
  heroku.challenging_dom.click()
  assert heroku.dropdown_list.current_page_url() == 'http://the-internet.herokuapp.com/challenging_dom'
  heroku.buttons.click_second_button()
  heroku.button_qux.find()
  assert heroku.button_qux.text() == 'qux', "Button 'qux' not displayed"

@mark.parallel
def test_find_foo_button(driver):
  heroku = Heroku(driver)
  heroku.homepage()
  heroku.challenging_dom.click()
  assert heroku.button_foo.text() == 'foo', "Button 'foo' not displayed"

@mark.parallel
def test_find_definebas1(driver):
  heroku = Heroku(driver)
  heroku.homepage()
  heroku.challenging_dom.click()
  assert heroku.dropdown_list.current_page_url() == 'http://the-internet.herokuapp.com/challenging_dom'
  heroku.find_table_cell.find()
  assert heroku.find_table_cell.text() == 'Definiebas1'

@mark.parallel
def test_find_delete(driver):
  heroku = Heroku(driver)
  heroku.homepage()
  heroku.challenging_dom.click()
  assert heroku.dropdown_list.current_page_url() == 'http://the-internet.herokuapp.com/challenging_dom'
  heroku.find_table_cell.find()
  assert heroku.find_cell_in_row.text() == 'delete'


import os
import time
import signal
import threading

class BarComponent:
    interval = None

    def __init__(self, sign_no, update_func):
        self.value = ''
        self.pid = os.getpid()
        self.sign_no = sign_no
        self.update_func = update_func

        signal.signal(signal.SIGUSR1 + self.sign_no, self.handle_signal)

        if self.interval:
            thread = threading.Thread(target=self.set_interval)
            thread.start()

    def set_interval(self):
        while True:
            time.sleep(self.interval)
            os.kill(self.pid, signal.SIGUSR1 + self.sign_no)

    def handle_signal(self, sign_no, stack):
        self.update_value()
        self.update_func(self, self.value)

    def update_value(self):
        """ Must return the value """
        return self.value


import chess
import atexit
from threading import Thread
from datetime import datetime

from ai import AI_handler, AI_player
from board_player import Board_player, Schrobot
from computer_player import Computer_player
from lichess_player import Lichess_player, Stockfish_player

import rendering

class Game:
	player_ids = {
		"bp": Board_player,
		"li": Lichess_player,
		"stockfish": Stockfish_player,
		"cp": Computer_player,
		"ai": AI_player,
	}

	def quit(self):
		self.pl1.quit()
		self.pl2.quit()

		rendering.quit()

	def __init__(self):
		self.running = True

		self.clicked = False
		self.hovered_square = None
		self.highlighted_square = None
		self.move_dests = []

		self.info = ""

		self.last_move = None
		self.state = None
		self.check_preventing = []
		self.pinned = []

		self.li_time = 10
		self.li_incr = 3

		print('\n'.join([f"{key}: {self.player_ids[key]}" for key in self.player_ids]))

		short1 = input("white player > ")
		short2 = input("black player > ")

		self.pl1 = self.player_ids[short1.lower()](self, 1)
		print(f"White plays from {self.pl1.name}")

		self.pl2 = self.player_ids[short2.lower()](self, 0)
		print(f"Black plays from {self.pl2.name}")

		self.player = [self.pl2, self.pl1]

		rendering.setup()

		atexit.register(self.quit)

		self.board = chess.Board()

		self.AI = AI_handler()
		self.schrobot = Schrobot()

	def get_possible_moves(self, sq1):
		self.move_dests = self.AI.get_possible_moves(sq1)

	def do_move(self):
		pl = self.player[ self.board.turn ]
		print(f"waiting for {pl.name}")
		mv = pl.await_move()
		if not mv:
			self.running = False
			return
		print(f'\033[F \033[K{mv.uci()}')

		self.board.push(mv)
		self.last_move = mv

		self.AI.push(mv.uci())
		self.schrobot.push(mv.from_square, mv.to_square, self.board.piece_at(mv.from_square))
		self.player[ self.board.turn ].push_move(mv)

		self.AI.get_evaluation(self)
		if self.state == "mate" or self.state == "stalemate":
			self.running = False

def move_loop(game):
	while game.running:
		game.do_move()

def main():
	game = Game()

	move_thr = Thread(target=move_loop, args=(game,))
	move_thr.daemon = True
	move_thr.start()

	while game.running:
		window = rendering.show(game)

	if len(game.board.move_stack) > 8:
		path = f"/Users/Jakob/Documents/C++/chess/logs/{datetime.today().strftime('%d.%b_%H-%Muhr')}#{game.pl1.name}Vs{game.pl2.name}.log"
		with open(path, "w") as file:
			file.write(f"{game.state}\n")
			for i, mv in enumerate(game.board.move_stack):
				if (i+1)%2:
					file.write(f"{i//2+1}. {mv.uci()} \t")
				else:
					file.write(f"{mv.uci()}\n")

	while rendering.show(game) and window: pass
	print('')

if __name__ == "__main__":
    main()


# # Qustion 1 Solution
def hello_name(user_name):
    print("hello_" + user_name +"!")

hello_name("Wei")
hello_name("Maui")

# Qustion 1 Input Solution
# def hello_names():
#     name = input("Enter Name: ")
#     print("hello_" + name +"!")

# hello_names()

# Question 2: Write a python function,
# first_odds that prints the odd numbers from 1-100 and returns nothing def first_odds():

def first_odds():
    for x in range(1, 101):
        if(x % 2 == 1):
            print(x)
first_odds()

# Question 3: Please write a Python function,
# max_num_in_list to return the max number of a given list.
# The first line of the code has been defined as below. def max_num_in_list(a_list):

def max_num_in_list(a_list):
    LowestNum = a_list[0]
    for x in a_list:
        print(x)
        if (x < LowestNum):
            LowestNum = x
    return LowestNum

print (max_num_in_list([50, 1, 41, 100]))

# Question 4: Write a function to return if the given year is a leap year.
# A leap year is divisible by 4, but not divisible by 100 unless it is also divisible by 400.
# The return should be boolean Type (true/false). def is_leap_year(a_year):

# def is_leap_year(a_year):

#     if(a_year == )


import sys
inputs = sys.stdin.readline

# kmp 함수
def kmp(s,p,table):

    j = 0
    for i in range(len(s)):
        while j > 0 and s[i] != p[j]:
            j = table[j-1]

        if s[i] == p[j]:
            j += 1

        if j == len(p):
            return 1

    return 0

s = inputs().rstrip()
p = inputs().rstrip()

table = [0]*len(p)  # 패턴에서 같은 문자열 체크

j = 0
for i in range(1,len(p)):
    while j > 0 and p[i] != p[j]:
        j = 0

    if p[i] == p[j]:    # 같으면 j ++ / table 갱신
        j += 1
        table[i] = j
ans = kmp(s,p,table)
print(ans)


import turtle
n = int(input('Quantidade de lados do polígono: '))
lado = int(input('Tamanho do lado: '))
main = turtle.Screen()
caneta = turtle.Turtle()

for _ in range(n):
    caneta.forward(lado)
    caneta.right(360 / n)

while True:
    main.update()


__author__ = "Prabhu Ramachandran <prabhu_r@users.sf.net>"
__version__ = "$Revision: 1.4 $"
__date__ = "$Date: 2005/08/02 18:26:25 $"

import PolyDataNormals
import Common
import vtk

debug = Common.debug

# derived from PolyDataNormals since it implements exactly what we need.
class WarpScalar (PolyDataNormals.PolyDataNormals):

    """ This wraps the vtkWarpScalar filter.  vtkWarpScalar is a
    filter that modifies point coordinates by moving points along
    point normals by the scalar amount times the scale factor.  Useful
    for creating carpet or x-y-z plots.  """

    def initialize (self):
        debug ("In WarpScalar::initialize ()")
        self.fil = vtk.vtkWarpScalar ()
        self._set_input ()
        self.fil.Update ()


from collections import deque

def read_input():
    with open('input', 'r') as f:
        raw_input = f.read()
    p1, p2 = raw_input.split('\n\n')
    p1_cards = deque([int(x) for x in p1.split('\n')[1:]])
    p2_cards = deque([int(x) for x in p2.split('\n')[1:]])
    return p1_cards, p2_cards

p1, p2 = read_input()

while p1 and p2:
    c1 = p1.popleft()
    c2 = p2.popleft()
    if c1 > c2:
        p1.extend([c1, c2])
    elif c1 < c2:
        p2.extend([c2, c1])

score = sum(x * idx for idx, x in enumerate(reversed(p1 + p2), start=1))
print(score)


from model_training import *
from sklearn.linear_model import Lasso
from sklearn.ensemble import RandomForestRegressor, ExtraTreesRegressor
from xgboost.sklearn import XGBRegressor
from sklearn.tree import DecisionTreeRegressor
import xgboost as xgb
import time
import lightgbm as ltb
from datetime import date
from math import sqrt
from sklearn.metrics import mean_squared_error, r2_score

#Building models
models = [
           ['DecisionTreeRegressor: ', DecisionTreeRegressor()],
           ['Lasso:', Lasso(alpha =0.0005, random_state=1, max_iter = 100000, normalize = True)],
           ['RandomForest ',RandomForestRegressor()],
           ['ExtraTreeRegressor :',ExtraTreesRegressor()],
           ['LGBMRegressor:',ltb.LGBMRegressor(objective='regression',num_leaves=5,
                              learning_rate=0.05, n_estimators=720,
                              max_bin = 55, bagging_fraction = 0.8,
                              bagging_freq = 5, feature_fraction = 0.2319,
                              feature_fraction_seed=9, bagging_seed=9,
                              min_data_in_leaf =6, min_sum_hessian_in_leaf = 11)],
           ['XGBRegressor: ', xgb.XGBRegressor(colsample_bytree=0.4603, gamma=0.0468,
                             learning_rate=0.05, max_depth=3,
                             min_child_weight=1.7817, n_estimators=2200,
                             reg_alpha=0.4640, reg_lambda=0.8571,
                             subsample=0.5213, silent=1,
                             random_state =7, nthread = -1)]
         ]

#Model's metrics
model_data = []
for name,curr_model in models :
    curr_model_data = {}
    curr_model.random_state = 42
    curr_model_data["Name"] = name
    start = time.time()
    curr_model.fit(X_train,y_train)
    end = time.time()
    curr_model_data["Train_Time"] = end - start
    curr_model_data["Train_R2_Score"] = r2_score(y_train,curr_model.predict(X_train))
    curr_model_data["Test_R2_Score"] = r2_score(y_test,curr_model.predict(X_test))
    curr_model_data["Train_RMSE_Score"] = np.sqrt(mean_squared_error(y_train,curr_model.predict(X_train)))
    curr_model_data["Test_RMSE_Score"] = np.sqrt(mean_squared_error(y_test,curr_model.predict(X_test)))
    model_data.append(curr_model_data)

results_df = pd.DataFrame(model_data)
print(results_df)

cur_model = ltb.LGBMRegressor(objective='regression',num_leaves=5,
                              learning_rate=0.05, n_estimators=720,
                              max_bin = 55, bagging_fraction = 0.8,
                              bagging_freq = 5, feature_fraction = 0.2319,
                              feature_fraction_seed=9, bagging_seed=9,
                              min_data_in_leaf =6, min_sum_hessian_in_leaf = 11)
cur_model.fit(X_train,y_train)
prediction = cur_model.predict(X_predict_test)
print(prediction)


import boto3, json
from botocore.errorfactory import ClientError
from src import (
    ConfigurationHandler as cgh,
    Models as models,
    DataclassConversions
)
import mypy_boto3_s3.service_resource as s3_stubs

class S3Utilities:
    settings: cgh.S3Settings

    def __init__(self, settings: cgh.S3Settings) -> None:
        self.settings = settings

    def get_s3_file_object(self, filename: str) -> s3_stubs.Object:
        session = boto3.Session()
        s3: s3_stubs.S3ServiceResource = session.resource('s3')

        return s3.Object(self.settings.S3_BucketName,filename)

    def fetch_s3_contents(self, filename: str, default_contents: str = '') -> str:
        try:
            cloud_cube_object = self.get_s3_file_object(filename).get()

        except ClientError as e:
            if e.response['ResponseMetadata']['HTTPStatusCode'] == 404:
                return default_contents

            else:
                raise e

        return cloud_cube_object['Body'].read().decode('utf-8')

    def fetch_post_history_from_bucket(self) -> models.SubmissionListForMultipleSources:
        PostHistory_json = json.loads(self.fetch_s3_contents(
                self.settings.PostHistoryFullFileName,
                "{}"
            )
        )
        return DataclassConversions.convert_post_history_json_to_submission_model(PostHistory_json)

    def push_post_history_to_bucket(self, post_history: models.SubmissionListForMultipleSources) -> None:
        post_history_json : dict = DataclassConversions.convert_post_history_model_to_json(post_history)

        self.get_s3_file_object(self.settings.PostHistoryFullFileName).put(
            Body=json.dumps(post_history_json).encode('utf-8')
            )


import cv2
import argparse
import requests
import util
import simplejson

def draw_face_rects(image, api_key):
    # Connect to Microsoft-api and provide key, content-type and image file
    microsoft_detect_url = "https://northeurope.api.cognitive.microsoft.com/face/v1.0/detect"
    headers = {"Content-Type": "application/octet-stream", "Ocp-Apim-Subscription-Key": api_key}
    r = requests.post(microsoft_detect_url, open(image_path, "rb"), headers=headers)

    # Load the result into a JSON-dictionary
    json = simplejson.loads(r.text)

    # If the JSON only has one key then it failed
    if len(json) is 1:
        # Print error message and quit
        print("Error: " + json["error"]["message"])
        exit(1)

    for face in json:
        image = util.draw_rect_copy(image, face["faceRectangle"])

    return image

if __name__ == "__main__":
    # Define input arguments for the script
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--image_path", type=str, help="Path to image file")
    parser.add_argument("-k", "--api_key", type=str, help="API key for Microsoft Azure Face API")

    # Parse the arguments
    args = parser.parse_args()
    image_path = args.image_path
    microsoft_key = args.api_key

    # Validate the input arguments and quit if invalid
    util.quit_if_file_arg_is_invalid(image_path, "Must provide a valid image file")

    # Load image
    input_image = cv2.imread(image_path)

    util.show_image("Detect faces: Microsoft", draw_face_rects(input_image, microsoft_key))


# Licensed under a 3-clause BSD style license - see LICENSE.rst

from abc import abstractmethod
from astropy import log, units
import numpy as np
import re

from sofia_redux.scan.coordinate_systems.grid.grid import Grid
from sofia_redux.scan.coordinate_systems.coordinate_2d import Coordinate2D
from sofia_redux.scan.coordinate_systems.coordinate_2d1 import Coordinate2D1
from sofia_redux.scan.coordinate_systems.horizontal_coordinates import \
    HorizontalCoordinates
from sofia_redux.scan.coordinate_systems.equatorial_coordinates import \
    EquatorialCoordinates
from sofia_redux.scan.coordinate_systems.ecliptic_coordinates import \
    EclipticCoordinates
from sofia_redux.scan.coordinate_systems.galactic_coordinates import \
    GalacticCoordinates
from sofia_redux.scan.coordinate_systems.super_galactic_coordinates import \
    SuperGalacticCoordinates
from sofia_redux.scan.utilities.utils import round_values

__all__ = ['Grid2D']

class Grid2D(Grid):

    def __init__(self):
        """
        Initialize a 2-dimensional abstract grid.

        The grid is used to convert from 2D coordinates to offsets in relation
        to a specified reference onto a regular grid, and the reverse
        operation.

        Forward transform: grid projection -> offsets -> coordinates
        Reverse transform: coordinates -> offsets -> grid projection
        """
        super().__init__()
        self._projection = None
        self._reference_index = Coordinate2D(np.zeros(2, dtype=float))
        self.m = None
        self.i = None
        self.set_defaults()

    def copy(self):
        """
        Return a copy of the Grid2D.

        Returns
        -------
        Grid2D
        """
        return super().copy()

    def __eq__(self, other):
        """
        Check if this grid is equal to another.

        Parameters
        ----------
        other : Grid2D

        Returns
        -------
        equal : bool
        """
        if self is other:
            return True
        if not super().__eq__(other):
            return False
        if self.projection != other.projection:
            return False
        if self.reference_index != other.reference_index:
            return False
        # The uncovered statements are covered, but not picked up by coverage
        if self.m is not None:
            if other.m is None:  # pragma: no cover
                return False
            if not np.allclose(self.m, other.m):
                return False
        elif other.m is not None:  # pragma: no cover
            return False
        if self.i is not None:
            if other.i is None:  # pragma: no cover
                return False
            if not np.allclose(self.i, other.i):
                return False
        elif other.i is not None:  # pragma: no cover
            return False
        return True

    def get_dimensions(self):
        """
        Return the number of grid dimensions.

        Returns
        -------
        n_dimensions : int
        """
        return 2

    def set_defaults(self):
        """
        Set the default values for the grid.

        Returns
        -------
        None
        """
        self.m = np.eye(2, dtype=float)
        self.i = np.eye(2, dtype=float)
        self.reference_index.zero()

    @property
    def reference_index(self):
        """
        Return the reference index for the grid.

        Returns
        -------
        Coordinate2D
        """
        return self.get_reference_index()

    @reference_index.setter
    def reference_index(self, value):
        """
        Set the reference index for the grid.

        Parameters
        ----------
        value : Coordinate2D

        Returns
        -------
        None
        """
        self.set_reference_index(value)

    @property
    def projection(self):
        """
        Return the grid projection.

        Returns
        -------
        Projection2D
        """
        return self.get_projection()

    @projection.setter
    def projection(self, value):
        """
        Set the grid projection.

        Parameters
        ----------
        value : Projection2D

        Returns
        -------
        None
        """
        self.set_projection(value)

    @property
    def transform(self):
        """
        Return the transform matrix for the grid.

        Returns
        -------
        m : numpy.ndarray or units.Quantity
        """
        return self.get_transform()

    @property
    def inverse_transform(self):
        """
        Return the inverse transform matrix for the grid.

        Returns
        -------
        i : numpy.ndarray or units.Quantity
        """
        return self.get_inverse_transform()

    @property
    def rectilinear(self):
        """
        Return whether the grid is rectilinear.

        Returns
        -------
        bool
        """
        return self.m[0, 1] == 0 and self.m[1, 0] == 0

    @property
    def x_axis(self):
        """
        Return the x-axis of the grid.

        Returns
        -------
        CoordinateAxis
        """
        return self.coordinate_system.axes[0]

    @property
    def y_axis(self):
        """
        Return the y-axis of the grid.

        Returns
        -------
        CoordinateAxis
        """
        return self.coordinate_system.axes[1]

    @property
    def fits_x_unit(self):
        """
        Return the unit for the X axis data.

        Returns
        -------
        units.Unit
        """
        return self.x_axis.unit

    @property
    def fits_y_unit(self):
        """
        Return the unit for the Y axis data.

        Returns
        -------
        units.Unit
        """
        return self.y_axis.unit

    def __str__(self):
        """
        Return a string representation of the grid.

        Returns
        -------
        str
        """
        return self.to_string()

    def __repr__(self):
        """
        Return a representation of the grid and underlying object.

        Returns
        -------
        str
        """
        return f'{object.__repr__(self)}\n{self.to_string()}'

    @staticmethod
    def to_coordinate2d(value):
        """
        Convert a value to a Coordinate2D object.

        Parameters
        ----------
        value : int or float or numpy.ndarray or units.Quantity or Coordinate2D

        Returns
        -------
        Coordinate2D
        """
        if not isinstance(value, Coordinate2D):
            if isinstance(value, (units.Quantity, np.ndarray)):
                value = np.atleast_1d(value)
                if value.size == 1:
                    if isinstance(value, units.Quantity):
                        value = np.full(
                            2, value[0].value, dtype=float) * value.unit
                    else:
                        value = np.full(2, value[0])
            else:
                value = np.full(2, value)

            value = Coordinate2D(value)
        return value

    @classmethod
    def get_coordinate_instance_for(cls, name):
        """
        Return a coordinate instance for the given name.

        Parameters
        ----------
        name : str

        Returns
        -------
        Coordinate2D
        """
        return Coordinate2D.get_instance(name)

    # @classmethod
    # def get_default_unit(cls):
    #     """
    #     Return the default unit for the grid.
    #
    #     Returns
    #     -------
    #     None or units.Unit
    #     """
    #     return None

    def get_default_unit(self):
        """
        Return the default unit for the grid.

        Returns
        -------
        None or units.Unit
        """
        unit = None
        resolution = self.resolution
        if isinstance(resolution, Coordinate2D):
            unit = resolution.unit
        elif isinstance(resolution, Coordinate2D1):
            unit = resolution.xy_unit
        elif isinstance(resolution, units.Quantity):  # pragma: no cover
            unit = resolution.unit

        if unit is None:
            return units.Unit('pixel')
        else:
            return unit

    @classmethod
    def get_default_coordinate_instance(cls):
        """
        Return a coordinate for the dimensions of the grid.

        Returns
        -------
        Coordinate2D
        """
        return Coordinate2D()

    @classmethod
    def from_header(cls, header, alt=''):
        """
        Create a grid instance from a header.

        Parameters
        ----------
        header : fits.Header
            The FITS header from which to create the grid.
        alt : str, optional
            The alternate coordinate system designation.

        Returns
        -------
        Grid2D
        """
        ctype_1 = header.get(f'CTYPE1{alt}')
        ctype_2 = header.get(f'CTYPE2{alt}')

        grid = cls.get_grid_2d_instance_for(ctype_1, ctype_2)
        grid.parse_header(header)
        return grid

    @classmethod
    def get_grid_2d_instance_for(cls, ctype_1, ctype_2):
        """
        Return a Grid2D instance for the given FITS coordinate types.

        A suitable grid instance will be returned depending on the provided
        CTYPE values.  If any CTYPE value is not recognized, a FlatGrid2D
        instance will be returned.  In cases where a spherical system is
        recognized, a SphericalGrid will be returned.

        CTYPE values should be 8 characters in length, divided into 2 segments
        of 4 characters each.  The first set should give the type of world
        coordinates, and the second set should provide the type of projection
        geometry.  The first set is left justified, with hyphens filling in any
        blank characters to the right, and the second set should be right
        justified with hyphens filling in any blank characters to the left.
        For example, 'RA---TAN' or 'GLON-AIT'.

        Note that in addition to the standard FITS CTYPE standards, the LON and
        LAT coordinate systems are also recognized.  E.g., 'LAT--TAN'.
        xLON, xyLN, xLAT, xyLT coordinate systems are also recognized, where
        x and y indicate arbitrary (but matching across longitude and latitude)
        characters.

        Parameters
        ----------
        ctype_1 : str or None
            The type of the first world coordinate axis.
        ctype_2 : str or None
            The type of the second world coordinate axis.

        Returns
        -------
        Grid2D
        """
        if ctype_1 is None or ctype_2 is None:
            return cls.get_grid_instance('flat_grid_2d')
        elif len(ctype_1) < 6 or len(ctype_2) < 6:
            return cls.get_grid_instance('flat_grid_2d')

        tokens_x = re.split(r'[-]+', ctype_1.lower())
        tokens_y = re.split(r'[-]+', ctype_2.lower())
        if len(tokens_x) != 2 or len(tokens_y) != 2:
            return cls.get_grid_instance('flat_grid_2d')

        x_type, proj_x = tokens_x
        y_type, proj_y = tokens_y

        if (x_type, y_type) in [('ra', 'dec'), ('dec', 'ra'),
                                ('lon', 'lat'), ('lat', 'lon')]:
            return cls.get_grid_instance('spherical_grid')

        if x_type[0] != y_type[0]:
            return cls.get_grid_instance('flat_grid_2d')

        # Check for things like GLON, GLAT
        x_type, y_type = x_type[1:], y_type[1:]
        if (x_type, y_type) in [('lat', 'lon'), ('lon', 'lat')]:
            return cls.get_grid_instance('spherical_grid')

        if x_type[0] != y_type[0]:
            return cls.get_grid_instance('flat_grid_2d')

        # Check for things like ..LN, ..LT
        x_type, y_type = x_type[1:], y_type[1:]
        if (x_type, y_type) in [('lt', 'ln'), ('ln', 'lt')]:
            return cls.get_grid_instance('spherical_grid')

        return cls.get_grid_instance('flat_grid_2d')

    def to_string(self):
        """
        Return a string representation of the grid.

        Returns
        -------
        str
        """
        projection_name = self.reference.__class__.__name__.split(
            'Coordinates')[0]
        reference_str = f'{projection_name}: {self.reference}'
        projection_str = (f'{self.projection.get_full_name()} '
                          f'({self.projection.get_fits_id()})')
        dx, dy = self.resolution.coordinates
        if isinstance(dx, units.Quantity):
            dx = dx.value
        spacing_str = f'{dx} x {dy}'
        crpix_str = f'{self.reference_index} C-style, 0-based'
        return (f'{reference_str}\n'
                f'Projection: {projection_str}\n'
                f'Grid Spacing: {spacing_str}\n'
                f'Reference Pixel: {crpix_str}')

    def for_resolution(self, resolution):
        """
        Return a Grid2D for a given resolution.

        Parameters
        ----------
        resolution : astropy.units.Quantity or numpy.ndarray or Coordinate2D

        Returns
        -------
        grid : Grid2D
        """
        resolution = self.to_coordinate2d(resolution)
        grid = self.copy()
        grid.set_resolution(resolution)
        x_factor = self.resolution.x / resolution.x
        y_factor = self.resolution.y / resolution.y
        if isinstance(x_factor, units.Quantity):
            x_factor = x_factor.decompose().value
            y_factor = y_factor.decompose().value

        grid.reference_index.scale_x(x_factor)
        grid.reference_index.scale_y(y_factor)
        return grid

    def get_pixel_area(self):
        """
        Return the area of one pixel on the grid.

        Returns
        -------
        area : float or units.Quantity
        """
        return np.abs(np.linalg.det(self.m))

    def set_resolution(self, resolution):
        """
        Set the grid resolution.

        Parameters
        ----------
        resolution : Coordinate2D or float or numpy.ndarray or units.Quantity
            The resolution to set.

        Returns
        -------
        None
        """
        resolution = self.to_coordinate2d(resolution)
        dx, dy = resolution.x, resolution.y
        if isinstance(dx, units.Quantity):
            unit = dx.unit
            dx, dy = dx.value, dy.value
        else:
            unit = None
        self.m = np.array([[dx, 0.0], [0.0, dy]])
        if unit is not None:
            self.m = self.m * unit
        self.calculate_inverse_transform()

    def calculate_inverse_transform(self):
        """
        Calculate the inverse transform for the grid (calculate i from m).

        Returns
        -------
        None
        """
        if np.isnan(self.m).any():
            self.i = np.zeros_like(self.m)
        else:
            self.i = np.linalg.pinv(self.m)

    def get_transform(self):
        """
        Return the transform matrix for the grid.

        Returns
        -------
        m : numpy.ndarray or units.Quantity
        """
        return self.m.copy()

    def set_transform(self, m):
        """
        Set the transform matrix for the grid.

        Parameters
        ----------
        m : numpy.ndarray or units.Quantity

        Returns
        -------
        None
        """
        if m.shape != (2, 2):
            raise ValueError("Coordinate transform should have shape (2, 2).")
        self.m = m.copy()
        self.calculate_inverse_transform()

    def get_inverse_transform(self):
        """
        Return the inverse transform matrix for the grid.

        Returns
        -------
        i : numpy.ndarray or units.Quantity
        """
        return self.i.copy()

    def is_horizontal(self):
        """
        Return whether the reference coordinate is a horizontal coordinate.

        Returns
        -------
        horizontal : bool
        """
        return isinstance(self.reference, HorizontalCoordinates)

    def is_equatorial(self):
        """
        Return whether the reference coordinate is an equatorial coordinate.

        Returns
        -------
        equatorial : bool
        """
        return isinstance(self.reference, EquatorialCoordinates)

    def is_ecliptic(self):
        """
        Return whether the reference coordinate is an ecliptic coordinate.

        Returns
        -------
        ecliptic : bool
        """
        return isinstance(self.reference, EclipticCoordinates)

    def is_galactic(self):
        """
        Return whether the reference coordinate is a Galactic coordinate.

        Returns
        -------
        galactic : bool
        """
        return isinstance(self.reference, GalacticCoordinates)

    def is_super_galactic(self):
        """
        Return whether the reference coordinate is a super Galactic coordinate.

        Returns
        -------
        super_galactic : bool
        """
        return isinstance(self.reference, SuperGalacticCoordinates)

    def local_affine_transform(self, grid_indices):
        """
        Perform a local affine transform using the forward m matrix.

        The transformed coordinates are of the form:

        new = (m @ coordinates) - reference_index

        Parameters
        ----------
        grid_indices: Coordinate2D

        Returns
        -------
        transformed_indices : numpy.ndarray or units.Quantity
        """
        if isinstance(self.m, units.Quantity):
            if grid_indices.unit is None:
                raise ValueError("Grid indices should be quantities.")
            m = self.m.to(grid_indices.unit).value
        else:
            m = self.m

        if grid_indices.singular:
            coordinates = grid_indices.coordinates[..., None]
        else:
            coordinates = grid_indices.coordinates

        transformed = (m @ coordinates)
        transformed[0] -= self.reference_index.x
        transformed[1] -= self.reference_index.y
        if grid_indices.singular:
            tx, ty = transformed[:, 0]
        else:
            tx, ty = transformed

        t_indices = grid_indices.empty_copy()
        t_indices.set_x(tx)
        t_indices.set_y(ty)
        return t_indices

    def get_resolution(self):
        """
        Return the grid resolution in (x, y).

        Returns
        -------
        resolution : Coordinate2D
        """
        return Coordinate2D(np.diag(self.m))

    def get_pixel_size(self):
        """
        Return the pixel size in (x, y).

        Returns
        -------
        resolution : Coordinate2D
        """
        return self.get_resolution()

    def get_pixel_size_x(self):
        """
        Return the pixel size in the x-direction.

        Returns
        -------
        size : float or units.Quantity
        """
        return self.m[0, 0]

    def get_pixel_size_y(self):
        """
        Return the pixel size in the y-direction.

        Returns
        -------
        size : float or units.Quantity
        """
        return self.m[1, 1]

    def rotate(self, angle):
        """
        Rotate the grid by a given angle.

        This effectively rotates the transformation matrices (m and i).

        Parameters
        ----------
        angle : units.Quantity
            The angle of rotation.

        Returns
        -------
        None
        """
        c = np.cos(angle)
        s = np.sin(angle)
        if isinstance(angle, units.Quantity):
            c, s = c.value, s.value

        a = self.m.copy()
        self.m[0, 0] = (c * a[0, 0]) - (s * a[1, 0])
        self.m[0, 1] = (c * a[0, 1]) - (s * a[1, 1])
        self.m[1, 0] = (s * a[0, 0]) + (c * a[1, 0])
        self.m[1, 1] = (s * a[0, 1]) + (c * a[1, 1])
        self.calculate_inverse_transform()

    def is_reverse_x(self):
        """
        Returns if the x-axis is reversed.

        Returns
        -------
        bool
        """
        return self.x_axis.reverse

    def is_reverse_y(self):
        """
        Returns if the y-axis is reversed.

        Returns
        -------
        bool
        """
        return self.y_axis.reverse

    def parse_header(self, header):
        """
        Parse a FITS header and apply to the grid.

        Parameters
        ----------
        header : fits.Header

        Returns
        -------
        None
        """
        alt = self.fits_id
        c_type = header.get(f'CTYPE1{alt}')
        try:
            self.parse_projection(header)
        except Exception as err:  # pragma: no cover
            log.warning(f'Unknown projection {c_type}')
            log.error(err)

        default_unit = self.get_default_unit()
        x_unit = header.get(f'CUNIT1{alt}')
        y_unit = header.get(f'CUNIT2{alt}')
        if x_unit is None:
            x_unit = 1.0 if default_unit is None else default_unit
        else:
            x_unit = units.Unit(x_unit)
        if y_unit is None:
            y_unit = 1.0 if default_unit is None else default_unit
        else:
            y_unit = units.Unit(y_unit)

        if isinstance(x_unit, units.UnitBase):
            self.x_axis.unit = x_unit
        if isinstance(y_unit, units.UnitBase):
            self.y_axis.unit = y_unit

        cd_keys = [f'CD1_1{alt}', f'CD1_2{alt}', f'CD2_1{alt}', f'CD2_2{alt}']
        for key in cd_keys:
            if key not in header:
                dx = float(header.get(f'CDELT1{alt}', 1.0)) * x_unit
                dy = float(header.get(f'CDELT2{alt}', 1.0)) * y_unit
                m11 = float(header.get(f'PC1_1{alt}', 1.0)) * dx
                m12 = float(header.get(f'PC1_2{alt}', 0.0)) * dx
                m21 = float(header.get(f'PC2_1{alt}', 0.0)) * dy
                m22 = float(header.get(f'PC2_2{alt}', 1.0)) * dy
                break
        else:
            m11 = float(header.get(f'CD1_1{alt}')) * x_unit
            m12 = float(header.get(f'CD1_2{alt}')) * x_unit
            m21 = float(header.get(f'CD2_1{alt}')) * y_unit
            m22 = float(header.get(f'CD2_2{alt}')) * y_unit

        self.m = np.empty((2, 2), dtype=float) * x_unit
        self.m[0, 0] = m11
        self.m[0, 1] = m12
        self.m[1, 0] = m21
        self.m[1, 1] = m22

        # The rotation of the latitude axis.
        if f'CROTA2{alt}' in header:
            self.rotate(header[f'CROTA2{alt}'] * units.Unit('degree'))

        if self.is_reverse_x():
            self.m[:, 0] *= -1
        if self.is_reverse_y():
            self.m[0, 0] *= -1
            self.m[1, 1] *= -1

        reference_index = self.reference_index

        if isinstance(reference_index, Coordinate2D1):
            one = Coordinate2D1([1.0, 1.0, 1.0])  # FITS origin is at (1, 1)
        else:
            one = Coordinate2D([1.0, 1.0])

        reference_index.parse_header(
            header, key_stem='CRPIX', alt='', default=one)
        reference_index.subtract(one)
        self.reference_index = reference_index

        reference = self.get_coordinate_instance_for(c_type)
        if isinstance(reference, Coordinate2D1):
            reference.xy_coordinates.parse_header(
                header, key_stem='CRVAL', alt=alt,
                default=Coordinate2D([0.0, 0.0]))

        else:
            reference.parse_header(header, key_stem='CRVAL', alt=alt,
                                   default=Coordinate2D([0.0, 0.0]))
        self.set_reference(reference)
        self.calculate_inverse_transform()

    def edit_header(self, header):
        """
        Edit a FITS header with the grid information.

        Parameters
        ----------
        header : fits.Header

        Returns
        -------
        None
        """
        alt = self.get_fits_id()
        self.projection.edit_header(header, alt=alt)
        header[f'CRPIX1{alt}'] = (self.reference_index.x + 1,
                                  "Reference grid index")
        header[f'CRPIX2{alt}'] = (self.reference_index.y + 1,
                                  "Reference grid index")
        self.projection.reference.edit_header(header,
                                              key_stem='CRVAL', alt=alt)

        # Change from native to apparent for reversed axes.
        a = self.m.copy()
        if self.is_reverse_x():
            a[0] *= -1
        if self.is_reverse_y():
            a[1] *= -1

        nd = units.dimensionless_unscaled

        fits_x_unit = self.fits_x_unit
        fits_y_unit = self.fits_y_unit
        unit = a.unit if isinstance(a, units.Quantity) else None
        if unit == nd:
            a = a.value
            unit = None

        if fits_x_unit == nd or fits_x_unit is None:
            fits_x_unit = unit
        if fits_y_unit == nd or fits_y_unit is None:
            fits_y_unit = unit

        if unit is None and fits_x_unit is not None:
            a = a * fits_x_unit
            unit = fits_x_unit

        x_unit = f' ({fits_x_unit})' if fits_x_unit is not None else ''
        y_unit = f' ({fits_y_unit})' if fits_y_unit is not None else ''

        if unit is not None:
            a00, a01 = a[0].to(fits_x_unit).value
            a10, a11 = a[1].to(fits_y_unit).value
        else:
            a00, a01, a10, a11 = a.ravel()

        if self.m[0, 1] == 0 and self.m[1, 0] == 0:
            header[f'CDELT1{alt}'] = a00, f'Grid spacing{x_unit}'
            header[f'CDELT2{alt}'] = a11, f'Grid spacing{y_unit}'
        else:
            header[f'CD1_1{alt}'] = a00, 'Transformation matrix element'
            header[f'CD1_2{alt}'] = a01, 'Transformation matrix element'
            header[f'CD2_1{alt}'] = a10, 'Transformation matrix element'
            header[f'CD2_2{alt}'] = a11, 'Transformation matrix element'

        if x_unit != '':
            header[f'CUNIT1{alt}'] = (fits_x_unit.name, 'Coordinate axis unit')
            header[f'CUNIT2{alt}'] = (fits_y_unit.name, 'Coordinate axis unit')

    def index_of(self, coordinates, grid_indices=None):
        """
        Return the index of a coordinate on the grid.

        Parameters
        ----------
        coordinates : Coordinate2D
            The "true" coordinates.
        grid_indices : Coordinate2D, optional
            The output coordinates that will hold the result.

        Returns
        -------
        grid_indices : Coordinate2D
        """
        if grid_indices is None:
            grid_indices = Coordinate2D()
        # Convert to offsets
        grid_indices = self.projection.project(
            coordinates, projected=grid_indices)
        grid_indices = self.offset_to_index(grid_indices, in_place=True)
        return grid_indices

    def offset_to_index(self, offset, in_place=False):
        """
        Convert an offset to a grid location.

        Parameters
        ----------
        offset : Coordinate2D
        in_place : bool, optional
            If `True`, updates `offset` in-place.  Otherwise, a new instance is
            returned.

        Returns
        -------
        index : Coordinate2D
        """
        if isinstance(self.i, units.Quantity):
            if offset.unit is None:
                raise ValueError("Offsets should be quantities.")
            im = self.i.to(1 / offset.unit).value
        else:
            im = self.i

        if offset.singular:
            coordinates = offset.coordinates[..., None]
            singular = True
        else:
            coordinates = offset.coordinates
            singular = False
        singular &= self.reference_index.singular
        if isinstance(self.i, units.Quantity):
            coordinates = coordinates.value

        i00, i01, i10, i11 = im.ravel()
        rx, ry = self.reference_index.x, self.reference_index.y
        ix = (i00 * coordinates[0]) + (i01 * coordinates[1]) + rx
        iy = (i10 * coordinates[0]) + (i11 * coordinates[1]) + ry

        if singular:
            ix, iy = ix[0], iy[0]

        if not in_place:
            indices = Coordinate2D()
        else:
            indices = offset
            indices.unit = None
            indices.coordinates = None

        indices.set([ix, iy])
        return indices

    def index_to_offset(self, grid_indices, in_place=False):
        """
        Convert grid indices to offset positions.

        Parameters
        ----------
        grid_indices : Coordinate2D
        in_place : bool, optional
            If `True`, updates `offset` in-place.  Otherwise, a new instance is
            returned.

        Returns
        -------
        offset : Coordinate2D
        """
        m = self.m

        if grid_indices.singular:
            indices = grid_indices.coordinates[..., None]
        else:
            indices = grid_indices.coordinates

        di = indices[0] - self.reference_index.x
        dj = indices[1] - self.reference_index.y
        x = (m[0, 0] * di) + (m[0, 1] * dj)
        y = (m[1, 0] * di) + (m[1, 1] * dj)
        if grid_indices.singular and self.reference_index.singular:
            x, y = x[0], y[0]

        if in_place:
            offset = grid_indices
            offset.coordinates = None
            offset.unit = None
        else:
            offset = Coordinate2D()
        offset.set([x, y])
        return offset

    def coordinates_at(self, grid_indices, coordinates=None):
        """
        Return the coordinates at given grid indices.

        Parameters
        ----------
        grid_indices : Coordinate2D
            The grid indices for which to find coordinates.
        coordinates : Coordinate2D, optional
            Optional output coordinates to hold the result.

        Returns
        -------
        Coordinate2D
        """
        if coordinates is None:
            coordinates = self.projection.get_coordinate_instance()
        offset = self.index_to_offset(grid_indices, in_place=False)
        return self.projection.deproject(offset, coordinates=coordinates)

    def get_reference(self):
        """
        Return the reference position of the grid.

        Returns
        -------
        reference : Coordinate2D
        """
        if self.projection is None:
            return None
        return self.projection.get_reference()

    def set_reference(self, value):
        """
        Set the reference position of the grid.

        Parameters
        ----------
        value : Coordinate2D
            The reference coordinate to set.

        Returns
        -------
        None
        """
        self.projection.set_reference(value)

    def get_reference_index(self):
        """
        Return the reference index of the reference position on the grid.

        Returns
        -------
        index : Coordinate2D
        """
        return self._reference_index

    def set_reference_index(self, value):
        """
        Set the reference index of the reference position on the grid.

        Parameters
        ----------
        value : Coordinate2D

        Returns
        -------
        None
        """
        self._reference_index = value

    def get_projection(self):
        """
        Return the grid projection.

        Returns
        -------
        projection : Projection2D
        """
        return self._projection

    def set_projection(self, value):
        """
        Set the grid projection.

        Parameters
        ----------
        value : Projection2D

        Returns
        -------
        None
        """
        self._projection = value

    def get_coordinate_index(self, coordinates, indices=None):
        """
        Get the indices of the given coordinates.

        Parameters
        ----------
        coordinates : Coordinate2D
            The coordinates for which to find grid indices.
        indices : Coordinate2D, optional
            Optional output coordinates to return.  If not created, a fresh
            Coordinate2D instance will be used.

        Returns
        -------
        indices : Coordinate2D
            The grid indices.
        """
        indices = self.projection.project(coordinates, projected=indices)
        return self.offset_to_index(indices, in_place=True)

    def get_offset_index(self, offsets, indices=None):
        """
        Get the grid indices of the given offsets.

        Parameters
        ----------
        offsets : Coordinate2D
            The offsets for which to find indices.
        indices : Coordinate2D
            Optional coordinates in which to place the results.

        Returns
        -------
        indices : Coordinate2D
            The grid indices.
        """
        offset_indices = self.offset_to_index(offsets, in_place=False)
        i_xy = round_values(np.stack([offset_indices.x, offset_indices.y]))
        if indices is None:
            indices = Coordinate2D()
        indices.set(i_xy)
        return indices

    def get_coordinates(self, indices, coordinates=None):
        """
        Get the coordinates at the given grid indices.

        Parameters
        ----------
        indices : Coordinate2D
        coordinates : Coordinate2D, optional
            Optional coordinates in which to store the output coordinates.

        Returns
        -------
        coordinates : Coordinates2D
        """
        if coordinates is None:
            coordinates = self.projection.get_coordinate_instance()
        index_offsets = self.index_to_offset(indices, in_place=False)
        return self.projection.deproject(index_offsets,
                                         coordinates=coordinates)

    def get_offset(self, indices, offset=None):
        """
        Get coordinate offsets from the given grid indices.

        Parameters
        ----------
        indices : Coordinate2D
            The grid indices.
        offset : Coordinate2D, optional
            Optional coordinates in which to store the results.

        Returns
        -------
        offset : Coordinate2D
        """
        if offset is None:
            offset = Coordinate2D()
        offset.copy_coordinates(indices)
        return self.index_to_offset(offset, in_place=True)

    def toggle_native(self, offset, in_place=True):
        """
        Reverse the x and y axis of native offsets if axes are reversed.

        Scales reversed axis by -1.

        Parameters
        ----------
        offset : Coordinate2D
        in_place : bool, optional
            If `True`, toggle in-place, otherwise return a copy.

        Returns
        -------
        Coordinate2D
        """
        if not in_place:
            offset = offset.copy()
        if self.is_reverse_x():
            offset.scale_x(-1)
        if self.is_reverse_y():
            offset.scale_y(-1)
        return offset

    @abstractmethod
    def parse_projection(self, header):  # pragma: no cover
        """
        Parse the projection from the header.

        Parameters
        ----------
        header : fits.Header

        Returns
        -------
        None
        """
        pass


#!/usr/bin/env python3
import sys
import cv2
import rospy
import numpy as np
import os
import time

from darkflow.net.build import TFNet

from std_msgs.msg import Bool, String

from PySide2.QtWidgets import (QLineEdit, QPushButton, QApplication, QAction,
    QVBoxLayout, QDialog, QMainWindow, QGraphicsScene, QGraphicsPixmapItem)
from PySide2.QtGui import QPixmap, QImage, QKeySequence, QColor
from PySide2.QtCore import QThread, Signal, Slot, QEvent

from main_ui import Ui_Form

from py_pkg import (Create_Map, camera_thread, map_reader_thread,
                    srv_thread, load_thread, book_search_thread)

def fixpath(path):
    return os.path.abspath(os.path.expanduser(path))

class MainWindow(QMainWindow):
#////////////////////////// MainWindow Init Start //////////////////////////////
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.Form.installEventFilter(self)
        self.ui.statusbar.showMessage('Ready', 5000)
        self.camera_flag = 0
        self.loading_flag = True
        self.map_load_flag = False
        self.map_create_flag = False

#========================== Auto Control Button init ===========================
        self.ui.Auto_Fineder_Start_BTN.clicked.connect(self.auto_Start)
        self.ui.Auto_Fineder_Stop_BTN.clicked.connect(self.auto_Stop)

#========================== Map Control Button init ============================
        self.ui.Map_Reader_BTN.clicked.connect(self.read_Map)
        self.ui.Map_Delete_BTN.clicked.connect(self.delete_Map)
        self.ui.Map_Save_BTN.clicked.connect(self.save_Map)
        self.ui.Map_Create_BTN.clicked.connect(self.create_Map)

#========================== Camera Control Button init =========================
        self.ui.Camera_Toggle_BTN.clicked.connect(self.Camera_Toggle_BTN)

#========================== Thread init ========================================
        self.th_camera = camera_thread.Worker(parent = self, tfnet = tfnet)
        self.th_camera.send_camera_view.connect(self.camera_View_Update)

        self.th_map = map_reader_thread.Mapper(parent = self)

        self.th_srv = srv_thread.Server(parent = self)

        self.th_load = load_thread.Loader(parent = self)

        self.th_book = book_search_thread.Book_search(parent = self)

#========================== Publisher Define ===================================
        self.camera_pub = rospy.Publisher("/camera_toggle",
                                          Bool,
                                          queue_size = 1)

        self.launch_select_pub = rospy.Publisher("/launch_select",
                                          String,
                                          queue_size = 1)

#========================== Etc Class init =====================================
        self.CM = Create_Map.create_map()

#========================== Show Mainwindow ====================================
        self.show()

#////////////////////////// MainWindow Init End ////////////////////////////////

#========================== Auto Control Slot Def ==============================
    @Slot()
    def auto_Start(self):
        try:
            print(self.ui.listwidget.count())
            if(not self.ui.listwidget.count() == 0):
                self.th_book.sub.unregister()
                self.th_book.quit()
                self.ui.listwidget.clear()

            print(self.ui.listwidget.count())
            self.ui.statusbar.showMessage('Auto Drive Start')
            self.launch_select_pub.publish("auto_Start")
            self.th_book.start()
            self.ui.Map_View.setFocus()
        except:
            pass
    @Slot()
    def auto_Stop(self):
        try:

            self.ui.statusbar.showMessage('Auto Drive End', 5000)
            self.launch_select_pub.publish("auto_Stop")

        except:
            pass

#========================== Camera Control Slot Def ============================
    @Slot()
    def Camera_Toggle_BTN(self):
        try:
            if (self.camera_flag == 0):
                self.camera_on()
            else:
                self.camera_off()
        except:
            pass

#========================== Map Control Slot Def ===============================
    @Slot()
    def read_Map(self):
        if(self.map_load_flag == False):
            self.map_load_flag = True
            self.th_load.loading_flag = True

            self.ui.Map_View.installEventFilter(self)
            self.ui.Map_View.setFocus()

            self.th_load.loading.connect(self.loading_map)
            self.th_map.send_map_view.connect(self.map_View_Update)
            self.launch_select_pub.publish("load_map_mode")

            self.th_load.start()
            self.th_map.start()

    @Slot()
    def delete_Map(self):
        if(self.map_load_flag == True):
            self.th_map.send_map_view.disconnect()
        self.map_load_flag = False
        self.map_create_flag = False
        self.th_load.loading_flag = False

        self.ui.Map_View.removeEventFilter(self)

        self.th_map.stop()
        self.th_map.quit()

        self.th_load.quit()

        time.sleep(0.1)
        self.launch_select_pub.publish("load_map_mode_close")
        self.ui.Map_View.setScene(self.view_Clear())
        self.ui.Map_View.show()

        self.camera_off()

    @Slot()
    def create_Map(self):
        if(self.map_create_flag == False):
            self.map_create_flag = True
            self.th_load.loading_flag = True

            self.th_load.loading.connect(self.loading_map)
            self.th_map.send_map_view.connect(self.map_View_Update)
            self.launch_select_pub.publish("create_map_mode")
            self.ui.Map_View.installEventFilter(self)

            self.th_load.start()
            self.th_map.start()

    @Slot()
    def save_Map(self):
        if(self.map_create_flag == True):
            self.th_map.stop()
            self.th_map.quit()

            self.ui.Map_View.removeEventFilter(self)

            self.launch_select_pub.publish("load_map_mode_close")
            self.ui.Map_View.setScene(self.view_Clear())
            self.ui.Map_View.show()

            self.th_load.loading_flag = False
            self.th_srv.send_server_data.connect(self.srv_Server)
            self.th_srv.start()
            self.camera_off()

#========================== Thread Data Req, Res Slot Def ======================
    @Slot(object)
    def map_View_Update(self, msg):
        if (self.th_load.loading_flag == True):

            self.th_load.loading_flag = False
            self.th_load.loading.disconnect()
            self.camera_on()
        try:
            scene = self.image2Qpixmap(msg)
            self.ui.Map_View.setScene(scene)
            self.ui.Map_View.show()
        except:
            pass

    @Slot(object)
    def camera_View_Update(self, msg):
        try:
            scene = self.image2Qpixmap(msg)
            self.ui.Camera_View.setScene(scene)
            self.ui.Camera_View.show()
        except:
            pass

    @Slot(object)
    def srv_Server(self):
        try:
            self.map_create_flag = False
            self.launch_select_pub.publish("create_map_mode_save")
            self.th_map.send_map_view.disconnect()
            self.th_map.stop()
            self.th_map.quit()
            self.ui.Map_View.setScene(self.view_Clear())
            self.ui.Map_View.show()
        except:
            pass

    @Slot(object)
    def loading_map(self, msg):
        try:
            scene = self.image2Qpixmap(msg)
            self.ui.Map_View.setScene(scene)
            self.ui.Map_View.show()
        except:
            pass
#========================== Event Filter =======================================
    def eventFilter(self, obj, event):
        if event.type() == QEvent.Close:
            print ("================ User has clicked the red x on the main window =================\n\n\n")

            #del self.CM
            if(self.th_load.isRunning()):
                self.th_load.loading_flag = False
                self.th_load.quit()
                self.th_load.wait(2)
            self.launch_select_pub.publish("auto_Stop")
            self.launch_select_pub.publish("load_map_mode_close")

            event.accept()
            print("============================= End Mainwindow ===================================\n\n\n")

            return True
        elif obj == self.ui.Map_View:
            if event.type() == QEvent.KeyPress and not event.isAutoRepeat():
                self.CM.keyEvent(event)
                return True
            elif event.type() == QEvent.KeyRelease and not event.isAutoRepeat():
                self.CM.keyEvent(event)
                return True
            else:
                return False
        else:
            # pass the event on to the parent class
            return QMainWindow.eventFilter(self, obj, event)

#    def closeEvent(self, event): # Click the Window X Button, Calling this Event

#========================== Etc Function =======================================

    def view_Clear(self):
        try:
            clear = QPixmap(1, 1)
            clear.fill(QColor("white"))
            clear = QGraphicsPixmapItem(clear)
            scene = QGraphicsScene()
            scene.addItem(clear)
            return scene
        except:
            pass

    def image2Qpixmap(self, data):
        pixmap = QPixmap.fromImage(data)
        item = QGraphicsPixmapItem(pixmap)
        scene = QGraphicsScene()
        scene.addItem(item)
        return scene

    def camera_on(self):
        if (self.camera_flag == 0):
            self.ui.statusbar.showMessage('Camera On')
            self.th_camera.send_camera_view.connect(self.camera_View_Update)
            self.th_camera.start()
            self.camera_flag = 1
            self.camera_pub.publish(self.camera_flag)
            self.ui.Camera_Toggle_BTN.setText("카메라 Off")
            #print("카메라 On")

    def camera_off(self):
        if (self.camera_flag == 1):
            self.ui.statusbar.showMessage('Camera Off', 5000)

            self.th_camera.send_camera_view.disconnect()
            self.th_camera.stop()
            self.camera_flag = 0
            self.camera_pub.publish(self.camera_flag)
            self.ui.Camera_Toggle_BTN.setText("카메라 On")
            #print("카메라 Off")
            time.sleep(0.1)
            self.ui.Camera_View.setScene(self.view_Clear())
            self.ui.Camera_View.show()

if __name__ == '__main__':

    options = {"pbLoad" : fixpath("~/catkin_ws/src/bitproject/built_graph/book_2class_yolo2.pb"),
               "metaLoad" : fixpath("~/catkin_ws/src/bitproject/built_graph/book_2class_yolo2.meta"),
               "threshold" : 0.25
               }

    tfnet = TFNet(options)
    rospy.init_node('main_program', anonymous=True)
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())


#!/usr/bin/env python3

"""
Download XML tarball files from NCBI website.
"""

from contextlib import closing
import os
from pathlib import Path
import shutil
import urllib.request as request

from utils import set_read_only, updater_log

pmc_open_access_url = "ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/oa_bulk/"

def ftp_download(url, destination):
    """
    Download a single file that's hosted on an FTP server.
    Code is based on: https://stackoverflow.com/questions/11768214/
    """

    updater_log(f"Downloading {url} ...")
    with closing(request.urlopen(url)) as resp, open(destination, 'wb') as fh:
            shutil.copyfileobj(resp, fh)

def download_xml_files(download_dir):
    """
    Download all *.xml.tar.gz" files from NCBI FTP server.
    """

    # Grab file list on ftp server
    response = request.urlopen(f"{pmc_open_access_url}")
    files = response.read().decode("utf-8").splitlines()
    tar_files = [
        f.split(" ")[-1] for f in files if f.endswith(".xml.tar.gz")
    ]

    for f in tar_files:
        url = pmc_open_access_url + f
        destination = Path(download_dir, f)
        ftp_download(url, destination)
        set_read_only(destination)  # set downloaded file read-only

# Test harness
if __name__ == '__main__':
    download_dir = '/tmp/xml-tarball'
    download_xml_files(download_dir)


from math import gcd
from functools import lru_cache

@lru_cache(maxsize=None)
def func(x, g):
    while x != 1:
        gx = gcd(x, g)
        if gx == 1:
            break
        x //= gx
    return x == 1

def same(a, b):
    g = gcd(a, b)
    return func(a, g) and func(b, g)

def solution(A, B):
    res = 0
    for a, b in zip(A, B):
        res += same(a, b)
    return res

print(solution([15, 10, 9], [75, 30, 5]))


import random
from time import sleep

response = ["Yes", "No", "Maybe", "Only if you believe in God", "To die", "In two years", "At the age of 50"]

def bulk():
    question = input("Ask me any question: ")
    print("Processing...")
    sleep(2.5)
    print(random.choice(response))
bulk()

sleep(1)

restart = input("Would you like to ask another question? ")
if restart == "yes" or restart == "Yes":
    bulk()
if restart == "no" or restart == "No":
    print("Ok")


from django.urls import path

from .views import add_subject, subject_list, mark_entry, mark_table, edit_subject, mark_result, my_subjects, teacher_result, student_result, students_list, student_results_list, approve_students_result, result_view_list, student_result_view, student_subject_result

urlpatterns = [
    path('add-subject', add_subject, name='add-subject'),
    path('subject-list', subject_list, name='subject-list'),
    path('subject-edit/<id>', edit_subject, name='subject-edit'),
    path('mark-entry', mark_entry, name='mark-entry'),
    path('mark-result', mark_result, name='mark-result'),
    path('mark-table/<subject>', mark_table, name='mark-table'),
    path('my-subjects', my_subjects, name='my_subjects'),
    path('teacher-result/<subject_code>', teacher_result, name='teacher_result'),
    path('student-result/<registration_no>', student_result, name='student_result'),
    path('student-list', students_list, name='result_student_list'),
    path('student-results/<registration_no>', student_results_list, name='student_results'),
    path('approve-results', approve_students_result, name='view_student_result'),
    path('student-result-list', result_view_list, name='student_result_view'),
    path('student-result-view/<id>', student_result_view, name='student_view_result'),
    path('student-subject-result/<name>/<registration_no>', student_subject_result, name='student_subject_result')
]


import os
import re
import glob
import time
import psutil
import pathlib
import subprocess

class Util:

    @staticmethod
    def findInList(lst, key):
        for x in lst:
            if key(x):
                return x
        return None

    @staticmethod
    def checkListUnique(lst, key=None):
        if key is None:
            keyList = lst
        else:
            keyList = [key(x) for x in lst]
        return len(keyList) == len(set(keyList))

    @staticmethod
    def globDirRecursively(dirpath, excludeSelf=False):
        # glob.glob("/a/**", recursive=True) returns ["/a/", "/a/a", "/a/a/a", ...]
        # the first element sucks, normalize it
        ret = glob.glob(os.path.join(dirpath, "**"), recursive=True)
        assert ret[0] == dirpath + "/"
        if excludeSelf:
            ret.pop(0)
        else:
            ret[0] = dirpath
        return ret

    @staticmethod
    def getBlkDevUuid(devPath):
        """UUID is also called FS-UUID, only device containing a file system has it, note that all btrfs device has same UUID"""

        ret = Util.cmdCall("/sbin/blkid", devPath)
        m = re.search(r'\bUUID="(\S*)"\B', ret, re.M)
        if m is not None:
            return m.group(1)
        return None

    @staticmethod
    def getBlkDevByUuid(uuid):
        path = os.path.join("/dev", "disk", "by-uuid", uuid)
        if not os.path.exists(path):
            return None
        return os.path.realpath(path)

    @staticmethod
    def getBlkDevSubUuid(devPath):
        """UUID_SUB is special UUID for btrfs device"""

        ret = Util.cmdCall("/sbin/blkid", devPath)
        m = re.search(r'\bUUID_SUB="(\S*)"\B', ret, re.M)
        if m is not None:
            return m.group(1)
        return None

    @staticmethod
    def getBlkDevBySubUuid(uuid):
        devName = None
        for line in Util.cmdCall("blkid", "-o", "export").split("\n"):
            m = re.fullmatch("DEVNAME=(\\S+)", line)
            if m is not None:
                devName = m.group(1)
                continue
            m = re.fullmatch("UUID_SUB=(\\S+)", line)
            if m is not None and m.group(1) == uuid:
                break
        return devName

    @staticmethod
    def getBlkDevPartUuid(devPath):
        """only disk partition has PARTUUID"""

        ret = Util.cmdCall("/sbin/blkid", devPath)
        m = re.search(r'\bPARTUUID="(\S*)"\B', ret, re.M)
        if m is not None:
            return m.group(1)
        return None

    @staticmethod
    def getBlkDevByPartUuid(uuid):
        path = os.path.join("/dev", "disk", "by-partuuid", uuid)
        if not os.path.exists(path):
            return None
        return os.path.realpath(path)

    @staticmethod
    def splitToTuple(s, d, count):
        ret = s.split(d)
        assert len(ret) == count
        return tuple(ret)

    @staticmethod
    def isValidKernelArch(archStr):
        return True

    @staticmethod
    def isValidKernelVer(verStr):
        return True

    @staticmethod
    def readListFile(filename):
        ret = []
        with open(filename, "r") as f:
            for line in f.read().split("\n"):
                line = line.strip()
                if line != "" and not line.startswith("#"):
                    ret.append(line)
        return ret

    @staticmethod
    def addItemToListFile(item, filename):
        with open(filename, "a") as f:
            f.write("\n")
            f.write(item)
            f.write("\n")

    @staticmethod
    def compareVerstr(verstr1, verstr2):
        """eg: 3.9.11-gentoo-r1 or 3.10.7-gentoo"""

        partList1 = verstr1.split("-")
        partList2 = verstr2.split("-")

        verList1 = partList1[0].split(".")
        verList2 = partList2[0].split(".")
        assert len(verList1) == 3 and len(verList2) == 3

        ver1 = int(verList1[0]) * 10000 + int(verList1[1]) * 100 + int(verList1[2])
        ver2 = int(verList2[0]) * 10000 + int(verList2[1]) * 100 + int(verList2[2])
        if ver1 > ver2:
            return 1
        elif ver1 < ver2:
            return -1

        if len(partList1) >= 2 and len(partList2) == 1:
            return 1
        elif len(partList1) == 1 and len(partList2) >= 2:
            return -1

        p1 = "-".join(partList1[1:])
        p2 = "-".join(partList2[1:])
        if p1 > p2:
            return 1
        elif p1 < p2:
            return -1

        return 0

    @staticmethod
    def cmdCall(cmd, *kargs):
        # call command to execute backstage job
        #
        # scenario 1, process group receives SIGTERM, SIGINT and SIGHUP:
        #   * callee must auto-terminate, and cause no side-effect
        #   * caller must be terminated by signal, not by detecting child-process failure
        # scenario 2, caller receives SIGTERM, SIGINT, SIGHUP:
        #   * caller is terminated by signal, and NOT notify callee
        #   * callee must auto-terminate, and cause no side-effect, after caller is terminated
        # scenario 3, callee receives SIGTERM, SIGINT, SIGHUP:
        #   * caller detects child-process failure and do appopriate treatment

        ret = subprocess.run([cmd] + list(kargs),
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                             universal_newlines=True)
        if ret.returncode > 128:
            # for scenario 1, caller's signal handler has the oppotunity to get executed during sleep
            time.sleep(1.0)
        if ret.returncode != 0:
            print(ret.stdout)
            ret.check_returncode()
        return ret.stdout.rstrip()

    @staticmethod
    def cmdCallTestSuccess(cmd, *kargs):
        ret = subprocess.run([cmd] + list(kargs),
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                             universal_newlines=True)
        if ret.returncode > 128:
            time.sleep(1.0)
        return (ret.returncode == 0)

    @staticmethod
    def shellCall(cmd):
        # call command with shell to execute backstage job
        # scenarios are the same as Util.cmdCall

        ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                             shell=True, universal_newlines=True)
        if ret.returncode > 128:
            # for scenario 1, caller's signal handler has the oppotunity to get executed during sleep
            time.sleep(1.0)
        if ret.returncode != 0:
            print(ret.stdout)
            ret.check_returncode()
        return ret.stdout.rstrip()

    @staticmethod
    def shellCallWithRetCode(cmd):
        ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                             shell=True, universal_newlines=True)
        if ret.returncode > 128:
            time.sleep(1.0)
        return (ret.returncode, ret.stdout.rstrip())

    @staticmethod
    def bcachefsGetUuid(slaveDevPathList):
        ret = None
        for devPath in slaveDevPathList:
            out = Util.cmdCall("file", "-sb", devPath)
            m = re.search("^bcachefs, UUID=(\\S+),", out)
            if ret is None:
                ret = m.group(1)
            else:
                assert ret == m.group(1)
        return ret

    @staticmethod
    def btrfsGetUuid(mountPoint):
        out = Util.cmdCall("btrfs", "filesystem", "show", mountPoint)
        m = re.search("uuid: (\\S+)", out, re.M)
        return m.group(1)

    @staticmethod
    def btrfsGetSlavePathList(mountPoint):
        ret = []
        out = Util.cmdCall("btrfs", "filesystem", "show", mountPoint)
        for m in re.finditer("path (\\S+)", out, re.M):
            ret.append(m.group(1))
        return ret

    @staticmethod
    def bcacheGetSlaveDevPathList(bcacheDevPath):
        """Last element in the returned list is the backing device, others are cache device"""

        retList = []

        slavePath = "/sys/block/" + os.path.basename(bcacheDevPath) + "/slaves"
        for slaveDev in os.listdir(slavePath):
            retList.append(os.path.join("/dev", slaveDev))

        bcachePath = os.path.realpath("/sys/block/" + os.path.basename(bcacheDevPath) + "/bcache")
        backingDev = os.path.basename(os.path.dirname(bcachePath))
        backingDevPath = os.path.join("/dev", backingDev)

        retList.remove(backingDevPath)
        retList.append(backingDevPath)
        return retList

    @staticmethod
    def scsiGetHostControllerName(devPath):
        devName = os.path.basename(os.path.realpath(devPath))       # XXX -> /dev/sda => sda
        sysfsPath = os.path.join("/sys", "block", devName)          # sda => /sys/block/sda
        hostPath = os.path.realpath(sysfsPath)                      # /sys/block/sda -> /sys/block/devices/pci0000:00/0000:00:17.0/ata3/host2/target2:0:0/2:0:0:0/block/sda
        while True:
            m = re.search("^host[0-9]+$", os.path.basename(hostPath), re.M)
            if m is not None:
                hostControllerNameFile = os.path.join("/sys", "class", "scsi_host", m.group(0), "proc_name")
                return pathlib.Path(hostControllerNameFile).read_text().rstrip()
            hostPath = os.path.dirname(hostPath)
            assert hostPath != "/"

    @staticmethod
    def getBlkDevLvmInfo(devPath):
        """Returns (vg-name, lv-name)
           Returns None if the device is not lvm"""

        rc, out = Util.shellCallWithRetCode("dmsetup info %s" % (devPath))
        if rc == 0:
            m = re.search("^Name: *(\\S+)$", out, re.M)
            assert m is not None
            ret = m.group(1).split(".")
            if len(ret) == 2:
                return ret
            ret = m.group(1).split("-")         # compatible with old lvm version
            if len(ret) == 2:
                return ret

        m = re.fullmatch("(/dev/mapper/\\S+)-(\\S+)", devPath)          # compatible with old lvm version
        if m is not None:
            return Util.getBlkDevLvmInfo("%s-%s" % (m.group(1), m.group(2)))

        return None

    @staticmethod
    def lvmGetSlaveDevPathList(vgName):
        ret = []
        out = Util.cmdCall("/sbin/lvm", "pvdisplay", "-c")
        for m in re.finditer("^\\s*(\\S+):%s:.*" % (vgName), out, re.M):
            if m.group(1) == "[unknown]":
                raise Exception("volume group %s not fully loaded" % (vgName))
            ret.append(m.group(1))
        return ret

    @staticmethod
    def getBlkDevFsType(devPath):
        # FIXME: blkid doesn't support bcachefs yet, use file instead
        ret = Util.cmdCall("file", "-sb", devPath)
        if re.search("^bcachefs, UUID=", ret) is not None:
            return "bcachefs"

        # use blkid to get fstype
        ret = Util.cmdCall("blkid", "-o", "export", devPath)
        m = re.search("^TYPE=(\\S+)$", ret, re.M)
        if m is not None:
            return m.group(1).lower()

        return ""

    @staticmethod
    def libUsed(binFile):
        """Return a list of the paths of the shared libraries used by binFile"""

        LDD_STYLE1 = re.compile(r'^\t(.+?)\s\=\>\s(.+?)?\s\(0x.+?\)$')
        LDD_STYLE2 = re.compile(r'^\t(.+?)\s\(0x.+?\)$')

        try:
            raw_output = Util.cmdCall("/usr/bin/ldd", "--", binFile)
        except subprocess.CalledProcessError as e:
            if 'not a dynamic executable' in e.output:
                raise Exception("not a dynamic executable")
            else:
                raise

        # We can expect output like this:
        # [tab]path1[space][paren]0xaddr[paren]
        # or
        # [tab]path1[space+]=>[space+]path2?[paren]0xaddr[paren]
        # path1 can be ignored if => appears
        # path2 could be empty

        if 'statically linked' in raw_output:
            return []

        result = []
        for line in raw_output.splitlines():
            match = LDD_STYLE1.match(line)
            if match is not None:
                if match.group(2):
                    result.append(match.group(2))
                continue

            match = LDD_STYLE2.match(line)
            if match is not None:
                result.append(match.group(1))
                continue

            assert False

        result.remove("linux-vdso.so.1")
        return result

    @staticmethod
    def devPathPartitionToDiskAndPartitionId(partitionDevPath):
        m = re.fullmatch("(/dev/sd[a-z])([0-9]+)", partitionDevPath)
        if m is not None:
            return (m.group(1), int(m.group(2)))
        m = re.fullmatch("(/dev/xvd[a-z])([0-9]+)", partitionDevPath)
        if m is not None:
            return (m.group(1), int(m.group(2)))
        m = re.fullmatch("(/dev/vd[a-z])([0-9]+)", partitionDevPath)
        if m is not None:
            return (m.group(1), int(m.group(2)))
        m = re.fullmatch("(/dev/nvme[0-9]+n[0-9]+)p([0-9]+)", partitionDevPath)
        if m is not None:
            return (m.group(1), int(m.group(2)))
        assert False

    @staticmethod
    def devPathPartitionToDisk(partitionDevPath):
        return Util.devPathPartitionToDiskAndPartitionId(partitionDevPath)[0]

    @staticmethod
    def devPathPartitionOrDiskToDisk(devPath):
        if re.fullmatch(".*[0-9]+", devPath):
            return Util.devPathPartitionToDiskAndPartitionId(devPath)[0]
        else:
            return devPath

class TempChdir:

    def __init__(self, dirname):
        self.olddir = os.getcwd()
        os.chdir(dirname)

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        os.chdir(self.olddir)

class PhysicalDiskMounts:

    """This class is a better psutil.disk_partitions()"""

    class Entry:

        def __init__(self, p):
            self._p = p

        @property
        def device(self):
            return self._p.device

        @property
        def mountpoint(self):
            return self._p.mountpoint

        @property
        def fstype(self):
            return self._p.fstype

        @property
        def opts(self):
            return self._p.opts

        @property
        def mnt_opt_list(self):
            return self._p.opts.split(",")

        def __repr__(self):
            return "<%s %r>" % (self.__class__.__name__, self.__dict__)

    class NotFoundError(Exception):
        pass

    @classmethod
    def get_entries(cls):
        return [cls.Entry(p) for p in psutil.disk_partitions()]

    @classmethod
    def find_root_entry(cls):
        ret = cls.find_entry_by_mount_point("/")
        if ret is None:
            raise cls.NotFoundError("no rootfs mount point")
        else:
            return ret

    @classmethod
    def find_entry_by_mount_point(cls, mount_point_path):
        for p in psutil.disk_partitions():
            if p.mountpoint == mount_point_path:
                return cls.Entry(p)
        return None